Compare commits
868 commits
1.3.0-beta
...
1.20.2
Author | SHA1 | Date | |
---|---|---|---|
|
a006373619 | ||
|
43fab8916b | ||
|
f1ea3cacb6 | ||
|
e0255c0e9b | ||
|
762c1125a3 | ||
|
36eb042ffa | ||
|
652802b844 | ||
|
378cb34f83 | ||
|
895a7bff60 | ||
|
a43f5d2022 | ||
|
fd65e7db17 | ||
|
93299feae6 | ||
|
f1ddb2381d | ||
|
7ecf4b1367 | ||
|
cab9b517c2 | ||
|
49847d1479 | ||
|
83048f2a6b | ||
|
02b62372cf | ||
|
adf81b9b51 | ||
|
7302bd5632 | ||
|
e317df4bf9 | ||
|
b61ef575fb | ||
|
c877016ac7 | ||
|
c89f7209e9 | ||
|
add128cbee | ||
|
04a0506582 | ||
|
2ad3f48f15 | ||
|
5a900e8601 | ||
|
68820924bf | ||
|
c0d9200101 | ||
|
62679897b2 | ||
|
2b979d4fe4 | ||
|
4f4ac3f809 | ||
|
4cfb8d835f | ||
|
c32bf4c099 | ||
|
a987e9612a | ||
|
17b014939a | ||
|
c7c8e0971b | ||
|
c7a0c7b527 | ||
|
36a8a9d018 | ||
|
bee81cae74 | ||
|
95da98b8c3 | ||
|
797e2101b5 | ||
|
1ff0e89724 | ||
|
4cd2809f40 | ||
|
f8018cb6fc | ||
|
5b443f118d | ||
|
c75b4b36b8 | ||
|
89124eb146 | ||
|
e8649aca7d | ||
|
469aaeecd1 | ||
|
92ad502fa7 | ||
|
420f78eaaf | ||
|
dc33678062 | ||
|
2016b7dd84 | ||
|
37a7b08e45 | ||
|
3f9d26f4b4 | ||
|
72615aac95 | ||
|
68146c4f8c | ||
|
ac1ac5d903 | ||
|
55a57c3d1b | ||
|
a3d5670f7a | ||
|
2458471fdd | ||
|
7b5a7682c4 | ||
|
8c560e3ff3 | ||
|
956dbd26b9 | ||
|
aa7c4511e9 | ||
|
9424a3f2ba | ||
|
512ae4d126 | ||
|
1b2f0ebd6b | ||
|
fe39258cff | ||
|
9d03ad7576 | ||
|
6ac22e36a1 | ||
|
1c52237568 | ||
|
d6286c7a00 | ||
|
7c779eb2e3 | ||
|
6f9af46060 | ||
|
0ba3fd64a7 | ||
|
2046ca3029 | ||
|
b53a51173c | ||
|
b3068780ae | ||
|
fab6e7b3dd | ||
|
5b3a8bee95 | ||
|
7fed38331a | ||
|
fab4924021 | ||
|
33b01f4eaa | ||
|
8caf619418 | ||
|
8bf6d53a48 | ||
|
0077b44d8c | ||
|
74fae35865 | ||
|
3e05fbe027 | ||
|
5a087d88e3 | ||
|
7cc1aeb7a5 | ||
|
1636bf18f8 | ||
|
c869e0b5e1 | ||
|
7f866a5af8 | ||
|
5756cad2ab | ||
|
883332b415 | ||
|
ff677f17ff | ||
|
a9d7e15659 | ||
|
dc6f39df45 | ||
|
1838118290 | ||
|
ff6b55e4c9 | ||
|
5e27ffc7bb | ||
|
5f26d6cb63 | ||
|
bedc298bd8 | ||
|
c91c0feb75 | ||
|
7fa2363979 | ||
|
2a0c28cec5 | ||
|
d5fb4d4640 | ||
|
05e399ad84 | ||
|
c740cbd908 | ||
|
dc894af0c2 | ||
|
995fe3645d | ||
|
6e88b51889 | ||
|
c7a2e4bc1e | ||
|
44709daaf1 | ||
|
636c84db3b | ||
|
ebbb87a0b8 | ||
|
cc8bc28432 | ||
|
6eb2464d78 | ||
|
74a08b4820 | ||
|
6d1f703cf1 | ||
|
b0c721fd7f | ||
|
85e906c1ae | ||
|
0c8f0f2b01 | ||
|
953124d66f | ||
|
62f19409a9 | ||
|
7e80227305 | ||
|
2914b3d4e6 | ||
|
30994885a7 | ||
|
a6b16ec09f | ||
|
f6668eff72 | ||
|
d4e3feacee | ||
|
bf5a29e8d5 | ||
|
86b0530f45 | ||
|
302a033710 | ||
|
498ec2bca0 | ||
|
e2f2b83003 | ||
|
626cfcfa3d | ||
|
6c1690e222 | ||
|
81ff753bc0 | ||
|
701d0707c6 | ||
|
6a5d847fce | ||
|
44eef98079 | ||
|
fd85ccd8c8 | ||
|
9ee81c961c | ||
|
b30e9c5f1f | ||
|
4dd3b2fb26 | ||
|
92d2bc229f | ||
|
53b996c47c | ||
|
6d0b02989b | ||
|
f7c167bfc9 | ||
|
9d4651a14b | ||
|
80bce449ac | ||
|
cfe3d2c51e | ||
|
bb473acd0d | ||
|
759cf9ae0a | ||
|
56bcfc143e | ||
|
aaea2bfbc1 | ||
|
66d0dc8750 | ||
|
baae2630ef | ||
|
36f3a6e161 | ||
|
b1a4820156 | ||
|
e3fb4856c3 | ||
|
99e00b802f | ||
|
24eec6c618 | ||
|
738410a07d | ||
|
1f714b3ed0 | ||
|
2883b68210 | ||
|
d5d187c273 | ||
|
86481ec90f | ||
|
4e6e37f8f5 | ||
|
214adcc645 | ||
|
49ca7d331d | ||
|
0277c6dee5 | ||
|
5207f7fefb | ||
|
9efe49afbd | ||
|
98714556a0 | ||
|
ce48d86fd6 | ||
|
cf4d98078c | ||
|
c510c727fa | ||
|
6e5d631f78 | ||
|
153f95a2de | ||
|
a25d8b7a2c | ||
|
2edf2c6989 | ||
|
e12fe95be8 | ||
|
bb4d5b325f | ||
|
d716d2e00b | ||
|
7937604c41 | ||
|
e9114f9e12 | ||
|
6057d8ea3b | ||
|
ab6ac8b143 | ||
|
a6a19a4d4b | ||
|
8ba83934a3 | ||
|
0b3f49e7fe | ||
|
81db96d8a2 | ||
|
1e3560fc04 | ||
|
30ade1417d | ||
|
8114806a89 | ||
|
445e8da053 | ||
|
6af136def0 | ||
|
0b2423c9f3 | ||
|
83759d9418 | ||
|
4cc8bc2cea | ||
|
37080957f0 | ||
|
c61e74141c | ||
|
79d97adf0b | ||
|
7219baa36d | ||
|
ab29c9e6c5 | ||
|
aa7984c1bb | ||
|
d1b3e8702a | ||
|
7bffeb0e1a | ||
|
1e382c85e2 | ||
|
b924502d20 | ||
|
23eb781316 | ||
|
1f3bc89dd9 | ||
|
c6e3d04f0f | ||
|
7649868bb3 | ||
|
6175605069 | ||
|
e22f181f41 | ||
|
98f612cd13 | ||
|
c61f2ce834 | ||
|
d909ee47f1 | ||
|
14084e270b | ||
|
1ecb28e511 | ||
|
8a093a8a8b | ||
|
77de42dd09 | ||
|
575c1f7438 | ||
|
dc0e0ff100 | ||
|
2910b8d29c | ||
|
6e368f613a | ||
|
fde89f7336 | ||
|
823a29e943 | ||
|
306e9d285f | ||
|
3bfc2637d9 | ||
|
580f06d9e4 | ||
|
6536a470f4 | ||
|
e23cbcdd1c | ||
|
ca361049f5 | ||
|
9e2135fde3 | ||
|
d824d5d701 | ||
|
2f0adac616 | ||
|
88cf90842f | ||
|
771da650c4 | ||
|
c1bcaaa78e | ||
|
4bac633a23 | ||
|
b9015c9220 | ||
|
f8f60a8d3d | ||
|
9f407dfb76 | ||
|
d38a02dcd4 | ||
|
1f2df6daf5 | ||
|
faf5fc3ff7 | ||
|
7560df438c | ||
|
87b1063318 | ||
|
ad3ee994da | ||
|
7a08b58c14 | ||
|
be3e76352c | ||
|
3719f3b633 | ||
|
2633b564e9 | ||
|
d28204afc7 | ||
|
80b885514f | ||
|
e819678307 | ||
|
a1ed8e5319 | ||
|
a42aaeefc0 | ||
|
b4126b839b | ||
|
5d4c0d0dd0 | ||
|
648f1838e7 | ||
|
aae0fceb27 | ||
|
715519e1f1 | ||
|
2cdce6504c | ||
|
c09b02d8c8 | ||
|
0c9c3caae2 | ||
|
6f486c4550 | ||
|
fec05ecb09 | ||
|
1790f746fd | ||
|
bc2f96ef56 | ||
|
d0bbb9400e | ||
|
ada9ccd557 | ||
|
e78bf19c34 | ||
|
8a3abf5622 | ||
|
95ffe5b0b5 | ||
|
1d15630566 | ||
|
21f2764d20 | ||
|
e053539d1b | ||
|
04298eefcf | ||
|
8c4de84b3c | ||
|
4ad8dff9a2 | ||
|
1bf1fd54d1 | ||
|
3ec7da172a | ||
|
55c7bbe64c | ||
|
cb6ba5931f | ||
|
0459efa732 | ||
|
e6ec2083ef | ||
|
6a8c0d82ee | ||
|
56b25ea98d | ||
|
b7368c9773 | ||
|
096e988586 | ||
|
a26c72a481 | ||
|
54f7ab3277 | ||
|
c454932a00 | ||
|
26f55bf556 | ||
|
faf489511d | ||
|
fffbee84e3 | ||
|
2fdd5b2730 | ||
|
151f3604e6 | ||
|
59bdba6437 | ||
|
f2a4a5f114 | ||
|
09cecef68e | ||
|
f0b57a2bbf | ||
|
11d36a3523 | ||
|
89196c1adc | ||
|
6812acb5f7 | ||
|
ec8cf37917 | ||
|
dd4c3f4d75 | ||
|
28e5a49315 | ||
|
2d28bed961 | ||
|
68025e4642 | ||
|
dcaaca149b | ||
|
da38726bc0 | ||
|
a67935c634 | ||
|
cda4e5b0b6 | ||
|
f84ef86546 | ||
|
498577294e | ||
|
e830268253 | ||
|
119eafbbc7 | ||
|
a48dffcf3a | ||
|
d83a3b0239 | ||
|
80b5c4a5dc | ||
|
cda7ec1d9e | ||
|
0be4aa1b4f | ||
|
fb216459b5 | ||
|
a1d59b48bf | ||
|
03f4b4004e | ||
|
1545210efa | ||
|
e51d82f37e | ||
|
96b14aa1c3 | ||
|
bdedeeece4 | ||
|
19f67c23c6 | ||
|
22d6874102 | ||
|
2749bab863 | ||
|
f68be46b0c | ||
|
afad14682f | ||
|
701c08a1bd | ||
|
e20c4260f6 | ||
|
22eaf9997c | ||
|
d0cf4cea82 | ||
|
ff1ec2fc73 | ||
|
f221d0be12 | ||
|
06b009af25 | ||
|
8f7c87f18d | ||
|
4eabfb456f | ||
|
2bd8e26114 | ||
|
d7a57318ee | ||
|
fb909e1009 | ||
|
a563fa0a29 | ||
|
a15114db30 | ||
|
27685aacd7 | ||
|
824377ca03 | ||
|
e99ef2e8d4 | ||
|
877fc9e113 | ||
|
04404cb9d8 | ||
|
77a2ed3e42 | ||
|
05f9429ddf | ||
|
e625f68e5e | ||
|
de475de405 | ||
|
80b812d052 | ||
|
a891cb0dd1 | ||
|
a274f9d72f | ||
|
84383aa052 | ||
|
65e845b396 | ||
|
fd8a2f3f32 | ||
|
136267f439 | ||
|
0a5ec3da03 | ||
|
86faeeaa43 | ||
|
3489c47d63 | ||
|
3bfc656dd0 | ||
|
b739978701 | ||
|
408c9d11c0 | ||
|
76405a8f48 | ||
|
b99c6b6c29 | ||
|
6c04d866b5 | ||
|
69a55c097e | ||
|
ffbeb78283 | ||
|
c21e6a271a | ||
|
6fcaf4dd04 | ||
|
5d0c7b23dd | ||
|
9c744eb3eb | ||
|
7a67232890 | ||
|
59fbd177a2 | ||
|
c78abf58be | ||
|
97bfb714e0 | ||
|
6c0eaff6c1 | ||
|
7abe3e4260 | ||
|
58b26c90fe | ||
|
2216b9d3d5 | ||
|
04fa39bd65 | ||
|
3df738c560 | ||
|
5b41458025 | ||
|
944f4f1ca6 | ||
|
078e1c9354 | ||
|
e2ae3ab95a | ||
|
045769c7a8 | ||
|
9cd1b7055d | ||
|
146eef39ff | ||
|
1914c90d1b | ||
|
99f6ae0a13 | ||
|
b92db6dd32 | ||
|
ce1ac6aed4 | ||
|
58d435f03d | ||
|
b517651dc3 | ||
|
c089aec00f | ||
|
4418f360c8 | ||
|
20cb6349f3 | ||
|
c157d64d61 | ||
|
a17310f41a | ||
|
7e680549c7 | ||
|
4a94c63e9b | ||
|
ca935ce224 | ||
|
59d20f9e0f | ||
|
b8e2db12f0 | ||
|
1cab1bd16a | ||
|
12748f5c6e | ||
|
d5e4b69aec | ||
|
51d67d5215 | ||
|
bd8c2f39fe | ||
|
04f8827e28 | ||
|
a8f0796ad7 | ||
|
4cb06bcc92 | ||
|
281e2ba26d | ||
|
978b5e9854 | ||
|
b84f1f046b | ||
|
d6d6984955 | ||
|
e465a21839 | ||
|
12bc0b6973 | ||
|
835834a468 | ||
|
b81e03a489 | ||
|
ea12ca7f24 | ||
|
ca2be7ae85 | ||
|
7140ce6d0e | ||
|
34bdd7f135 | ||
|
9219b07aff | ||
|
5529382e71 | ||
|
8c83647004 | ||
|
926b8088cf | ||
|
d6e1a6c3b8 | ||
|
56e91629b1 | ||
|
eeded18c36 | ||
|
171c786dec | ||
|
734e75f8c8 | ||
|
4f613ebb91 | ||
|
a87257de83 | ||
|
3bc1628fd4 | ||
|
77d1d62494 | ||
|
7d63797d4d | ||
|
a81336ef88 | ||
|
ec9a12bdf9 | ||
|
ea9c3bfaf9 | ||
|
1503cb5773 | ||
|
2784627adc | ||
|
f0b2a8a550 | ||
|
1fd1782051 | ||
|
f500956760 | ||
|
f8ff162d6c | ||
|
e65838b943 | ||
|
3bab3c4f56 | ||
|
10dc8ce6d7 | ||
|
5109b67de2 | ||
|
11f0bbc4e4 | ||
|
82b74ecb18 | ||
|
74a11086d1 | ||
|
6b3b5c7c86 | ||
|
101a560a01 | ||
|
3ff7466a54 | ||
|
fbe444b56c | ||
|
93d11531d6 | ||
|
ff47703140 | ||
|
7cf32cce52 | ||
|
c0a64a80f1 | ||
|
e931be3388 | ||
|
e02c6f57a0 | ||
|
f84f45c47c | ||
|
2ae28c72d3 | ||
|
dd8bf650d5 | ||
|
4a630dfcf9 | ||
|
5cfebba12e | ||
|
692db5a070 | ||
|
b4a847e4b5 | ||
|
2dd7fbbb55 | ||
|
9e329ac2f9 | ||
|
54cbf2c238 | ||
|
29502e7529 | ||
|
0f681b07b3 | ||
|
380c35fcc6 | ||
|
2ac6970e04 | ||
|
f0c5cdb156 | ||
|
fd03dabdd6 | ||
|
c91b5ac985 | ||
|
a6b8e6fe93 | ||
|
9ef3a946f6 | ||
|
ac5aedb488 | ||
|
c59b9366f6 | ||
|
a266253d53 | ||
|
b3be98f664 | ||
|
aa1973181f | ||
|
a4fb5e7ae7 | ||
|
d0d17a3eed | ||
|
f67ab25a54 | ||
|
01b9e11e2d | ||
|
7c48486956 | ||
|
bc90a96e44 | ||
|
64fb0ecc07 | ||
|
e3afab9858 | ||
|
07c8170652 | ||
|
a3c1248e9f | ||
|
c608a33aea | ||
|
1e8b6ebaab | ||
|
7d59e1e0bf | ||
|
3b4639d5da | ||
|
2dffb92e54 | ||
|
599dfea711 | ||
|
f7534f9f84 | ||
|
cef8ef15ce | ||
|
1f2d6c0411 | ||
|
095b10802f | ||
|
1922c02f5b | ||
|
ffc66293fd | ||
|
672dd72d62 | ||
|
7bad93044d | ||
|
731de7572f | ||
|
00b625815c | ||
|
e07377f91e | ||
|
7d1d2f45da | ||
|
9d59c89ac2 | ||
|
86cc754a7d | ||
|
e859c71e4f | ||
|
16b68d43ba | ||
|
620e5622f1 | ||
|
54db20a623 | ||
|
956b55dc30 | ||
|
9db67f6727 | ||
|
1bf698cf5d | ||
|
bdc41c58c4 | ||
|
5360274ed3 | ||
|
5180c2ca5b | ||
|
0ffedcf688 | ||
|
4d4647a385 | ||
|
1c878be324 | ||
|
53f7e34e59 | ||
|
f06dad53fc | ||
|
e5f2f696ba | ||
|
0e067e2a24 | ||
|
dce29e46a6 | ||
|
a36a654a09 | ||
|
0e45d9379b | ||
|
9eb0a0028b | ||
|
7d48821770 | ||
|
385c412a9d | ||
|
5348e12aca | ||
|
308cb721cd | ||
|
3165f3cd2a | ||
|
2d2a6e9b32 | ||
|
e1df02bdf7 | ||
|
3a44b9605f | ||
|
829a57d00d | ||
|
e03fa2f564 | ||
|
53984c3346 | ||
|
89aeb3903f | ||
|
713fde35f0 | ||
|
75d41c1468 | ||
|
1e02de30c4 | ||
|
58b134577f | ||
|
f4b607346a | ||
|
b6f71400a9 | ||
|
2f74a90afc | ||
|
06015ee10b | ||
|
df0cc6d225 | ||
|
d408f82785 | ||
|
f0f02b478f | ||
|
975f49d390 | ||
|
e21cffcf7d | ||
|
aa00b1a9b0 | ||
|
e03fb016d5 | ||
|
9c71272def | ||
|
ba2e673de7 | ||
|
8a2463d0a8 | ||
|
5d7227f547 | ||
|
850aa8a9fd | ||
|
58561a5eea | ||
|
1c88d47e7b | ||
|
0ba987159f | ||
|
f9711b9043 | ||
|
450eee5fe6 | ||
|
3f475c693b | ||
|
07bf99fcac | ||
|
3606c5b0f2 | ||
|
4b66dd517f | ||
|
a11f8d33eb | ||
|
672807e343 | ||
|
a5132859ab | ||
|
5acebc270c | ||
|
00a20fbdc7 | ||
|
53497c70d6 | ||
|
703c8e6d39 | ||
|
cdfc4babb4 | ||
|
de016d30dd | ||
|
0560ff5556 | ||
|
d07b7bd5a2 | ||
|
2abeff5767 | ||
|
5c8ee9c0ff | ||
|
c924d81331 | ||
|
e9092aaf4e | ||
|
4351644ced | ||
|
a0ace5ea1f | ||
|
013a75fccb | ||
|
4edde4d479 | ||
|
0e1d7e8a51 | ||
|
4dcc919d5e | ||
|
a12c70a67e | ||
|
cef99f4a67 | ||
|
ae8068ccb4 | ||
|
c0cff59963 | ||
|
1c2560c910 | ||
|
1c32d71d46 | ||
|
e69749300d | ||
|
e7e88c4805 | ||
|
9b3cb7944a | ||
|
91b8b827a6 | ||
|
e1d4b229ff | ||
|
4593648974 | ||
|
336c1c320a | ||
|
92fd22668e | ||
|
2754d41ee9 | ||
|
a072317f31 | ||
|
1b424a1445 | ||
|
e97adc8841 | ||
|
db53f4906e | ||
|
cdcbfea8dc | ||
|
ceb98f6fab | ||
|
bb661da35e | ||
|
6465d99e3e | ||
|
ae5464b758 | ||
|
46dcf0802b | ||
|
f2bc32a90b | ||
|
a9db2490f5 | ||
|
80c31b4a1d | ||
|
0de1847392 | ||
|
623d231f2f | ||
|
ae0179be8f | ||
|
4644092120 | ||
|
18f2865264 | ||
|
989d1df294 | ||
|
65b468507c | ||
|
f8b4238822 | ||
|
ded8499e9f | ||
|
9599d0044b | ||
|
09abc30c2d | ||
|
6586e7625d | ||
|
dd804c872e | ||
|
34566b560e | ||
|
5e099aeea5 | ||
|
1b688ac9f4 | ||
|
5cc612ca3a | ||
|
5ed68fca7f | ||
|
400bc19d08 | ||
|
c4ab7e1bdf | ||
|
17cd097d88 | ||
|
a0d6c41088 | ||
|
4aa088ec1b | ||
|
2d7eca4d5b | ||
|
6fd124ed81 | ||
|
adb07cc586 | ||
|
660973371d | ||
|
476d779b3d | ||
|
b467aae7b2 | ||
|
7b78cbc49c | ||
|
36e22f1ead | ||
|
5fb54aa2fd | ||
|
2b2fab2303 | ||
|
8d736befa5 | ||
|
1fdf88dce7 | ||
|
2f68d4409a | ||
|
afe44d0ca1 | ||
|
c30ef7e9c1 | ||
|
f3f38aae7b | ||
|
4e8f683737 | ||
|
1b5910aab1 | ||
|
4e57272470 | ||
|
2a6d7932c7 | ||
|
aba0526acd | ||
|
3d5292c7f3 | ||
|
a29a4eb05e | ||
|
e48b7bd244 | ||
|
ad484ee74d | ||
|
3b0a64326e | ||
|
1181399977 | ||
|
141b67884f | ||
|
7435eed8a9 | ||
|
b9b2dac114 | ||
|
5af0f73f5c | ||
|
c7a23a19d9 | ||
|
73d4975bf4 | ||
|
2d00b3ad77 | ||
|
4a081f0c9c | ||
|
09343e25c7 | ||
|
ec1fcdb41d | ||
|
cfd2d7d42b | ||
|
d7dda76ebd | ||
|
ac9428668a | ||
|
fef9c2bdde | ||
|
cd6047ba8e | ||
|
40975732ce | ||
|
1bd3723539 | ||
|
353b0626d9 | ||
|
1529fa4dd0 | ||
|
f97c7b17bd | ||
|
408cb8c4a7 | ||
|
9209b5dbd3 | ||
|
4230518d08 | ||
|
b9266b047e | ||
|
da42cadad0 | ||
|
b356d1f888 | ||
|
ae730ce8fc | ||
|
26fc8f9823 | ||
|
8454ccedd7 | ||
|
466ba09072 | ||
|
38892ffde4 | ||
|
eb4c70de2f | ||
|
ad1784b417 | ||
|
5a5ec8b24c | ||
|
38e2a1c035 | ||
|
8fd97223ed | ||
|
28e64eebe1 | ||
|
a0ebfbacce | ||
|
82428f77b7 | ||
|
7cb8e9c859 | ||
|
8804fa0aba | ||
|
e1f4d77580 | ||
|
2e938633e9 | ||
|
fbe859dcc7 | ||
|
b194f720ef | ||
|
72b5b3d50c | ||
|
e85bb4b3a5 | ||
|
a36aa10085 | ||
|
dc6bc9fe9e | ||
|
d08de6fae8 | ||
|
e15d64ff3d | ||
|
d4e698fa56 | ||
|
78dbc800ae | ||
|
8af82ade1c | ||
|
7c1eaf8736 | ||
|
4eec169f5a | ||
|
fcad058e3a | ||
|
31850a0f5c | ||
|
e06ae63077 | ||
|
e385eb5640 | ||
|
80500a74c8 | ||
|
da3aec8d83 | ||
|
cd9597f117 | ||
|
8b7a55d764 | ||
|
7c7ea1e555 | ||
|
0910ad72ca | ||
|
4151b66e99 | ||
|
bbe9eb0068 | ||
|
885bf6d1c4 | ||
|
4c821a521c | ||
|
1a17ff7dd0 | ||
|
a19637a8e4 | ||
|
5356c5c7ec | ||
|
8785a3f5aa | ||
|
fce8623f44 | ||
|
56e1f5ffeb | ||
|
e1cc467b05 | ||
|
eb1b767319 | ||
|
edb1e024d6 | ||
|
225c67d558 | ||
|
34aa3b8ced | ||
|
39672e5028 | ||
|
dd9bec2a0c | ||
|
e1d9faa223 | ||
|
8cb3ba298d | ||
|
134db120cd | ||
|
9510b83c72 | ||
|
e09ade57b1 | ||
|
3827deb235 | ||
|
7fb9543dbe | ||
|
b3a7d338d2 | ||
|
81070be4b3 | ||
|
e017fb1b89 | ||
|
7b1f5ce0db | ||
|
35536e6e4a | ||
|
69985e50f9 | ||
|
ab3ac8cb0d | ||
|
d22dd3bdf9 | ||
|
5d2478604c | ||
|
08e1702a1a | ||
|
e5236e5802 | ||
|
f2b817d635 | ||
|
d47a1a52f5 | ||
|
ae6e7a0337 | ||
|
c7a161e114 | ||
|
dde64153dd | ||
|
0c26827790 | ||
|
5ac68a3df9 | ||
|
54381cf673 | ||
|
f3ab86ed74 | ||
|
5867e987f3 | ||
|
4e9966055f | ||
|
18111ae6e0 | ||
|
9c9afe798d | ||
|
f568552462 | ||
|
117c68c8c6 | ||
|
144f00c207 | ||
|
0ca19ba07c | ||
|
fc23e16d43 | ||
|
d9bebf0b0f | ||
|
facbbe2d26 | ||
|
ddd217c53d | ||
|
1c751aca0e | ||
|
0e40c10c43 | ||
|
e572c2c1ea | ||
|
073d411e90 | ||
|
0372592a79 | ||
|
d4a3a274e2 | ||
|
383cefa915 | ||
|
2d87fd5099 | ||
|
5196c9bf17 | ||
|
19831a635f | ||
|
6eea0944d2 | ||
|
80225bf1e7 | ||
|
99fc4ea904 | ||
|
cdb77e5fa3 | ||
|
9b92155bf0 | ||
|
5af1557664 | ||
|
988d5d8ce1 | ||
|
24868633a5 | ||
|
17b437a060 | ||
|
ab0b412945 | ||
|
cc5e39aebb | ||
|
bad793aabf | ||
|
c1c37881eb | ||
|
e361e7e83d | ||
|
0ab31bf3ac | ||
|
ea813c3dcb | ||
|
f8fc9467be | ||
|
6cfb00eeac | ||
|
3c179c2450 | ||
|
3c7df8fd98 | ||
|
48e724a021 | ||
|
fd0919b482 | ||
|
87b2a39632 | ||
|
0719b14e2c | ||
|
7f6b440265 | ||
|
6e96e7a58c | ||
|
219cd16e5f | ||
|
e87d18346b | ||
|
a1f91a591a | ||
|
5f545745be | ||
|
ec151ad092 | ||
|
012cc2aee3 | ||
|
1a2efb5016 | ||
|
91b11c84cc | ||
|
f767e6a6ae | ||
|
ef5e26124e | ||
|
7c9071a321 | ||
|
44bde9fd16 | ||
|
c3c2ba461a | ||
|
24f1f4bdcd |
38
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
|
@ -0,0 +1,38 @@
|
|||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: "[BUG]"
|
||||
labels: bug
|
||||
assignees: Sollace
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Steps to reproduce**
|
||||
Help us figure out what you did to get this issue
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Version Information:**
|
||||
- Minecraft Version: [e.g. 1.20.5]
|
||||
- Mine Little Pony Version:
|
||||
|
||||
**Mod Loader:**
|
||||
- [ ] Fabric
|
||||
- [ ] Quilt
|
||||
- [ ] Neoforge (with connector)
|
||||
|
||||
**Client/Server Logs**
|
||||
If applicable, add log files by uploading them as attachments or put them below.
|
||||
|
||||
<details>
|
||||
```
|
||||
**Paste logs here**
|
||||
```
|
||||
</details>
|
26
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
|
@ -0,0 +1,26 @@
|
|||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: enhancement
|
||||
assignees: Sollace
|
||||
|
||||
---
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Version Information:**
|
||||
- Minecraft Version: [e.g. 1.20.5]
|
||||
- Mine Little Pony Version:
|
||||
|
||||
**Mod Loader:**
|
||||
- [ ] Fabric
|
||||
- [ ] Quilt
|
||||
- [ ] Neoforge (with connector)
|
4
.github/workflows/gradle-publish.yml
vendored
|
@ -17,6 +17,10 @@ jobs:
|
|||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 17
|
||||
- name: Prepare Datagen
|
||||
uses: eskatos/gradle-command-action@v1
|
||||
with:
|
||||
arguments: rundatagen
|
||||
- name: Publish Modrinth Jar
|
||||
env:
|
||||
MODRINTH_KEY: ${{ secrets.MODRINTH_KEY }}
|
||||
|
|
3
.gitignore
vendored
|
@ -3,6 +3,7 @@
|
|||
bin/
|
||||
build/
|
||||
run/
|
||||
generated/
|
||||
.classpath
|
||||
.project
|
||||
*.launch
|
||||
|
@ -15,4 +16,4 @@ ideas
|
|||
*.iml
|
||||
classes/
|
||||
out/
|
||||
jars/
|
||||
jars/
|
||||
|
|
3
.gitmodules
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
[submodule "BlockusAddon"]
|
||||
path = BlockusAddon
|
||||
url = https://github.com/Sollace/Unicopia-Blockus-Addon
|
1
BlockusAddon
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 94ff5babb976911f46d7efcdad2586652fb33047
|
|
@ -3,7 +3,7 @@
|
|||
[](README_RU.md)
|
||||
[](README_CN.md)
|
||||
|
||||
When starting a new world you're given the choice of which tribe to join. One of Unicorn, Pegasus, Earth, Bat, or Changeling.
|
||||
When starting a new world you're given the choice of which tribe to join. You can choose from _Unicorn_, _Pegasus_, _Earth Pony_, _Batpony_, or _Changeling_.
|
||||
|
||||
Depending on which race you pick, you're given different abilities, displayed on your HUD in a series of circular elements.
|
||||
To activate an ability, simply press and hold the key corresponding to that ability. Some take longer than others, and certain abilities
|
||||
|
@ -17,7 +17,7 @@ also respond to quick, short single-taps, or double-taps.
|
|||
|
||||
For unicorns, casting spells is done through gems, which you can obtain whilst mining. You first need to craft a spellbook using a gem, and then
|
||||
in the spellbook you can discover the magical traits of different items and recipes to combine them to create different spells, as well
|
||||
as modify existing one.
|
||||
as modify existing ones.
|
||||
|
||||
Once you have a gem with a spell you want to use, you can equip it to your main-hand or off-hand slot by right-clicking with a gem in
|
||||
one of either hand, then to activate it you us your primary ability. You can also cast spells directly from a gem by using the ability
|
||||
|
@ -34,7 +34,7 @@ also respond to quick, short single-taps, or double-taps.
|
|||
### Earth Ponies
|
||||
- Kicking & Stomping
|
||||
|
||||
Earth ponies kick good.
|
||||
*Earth ponies kick good*.
|
||||
|
||||
If Mine Little Pony is installed, and you have the appearance of a pony, kicking will target the block behind you, so twirl that rump!
|
||||
Kicking blocks will incrementally mine them, and kicking trees will shake items loose from their branches. Kicking a tree _too much_ might destroy it,
|
||||
|
@ -47,7 +47,7 @@ also respond to quick, short single-taps, or double-taps.
|
|||
|
||||
- Bracing
|
||||
|
||||
Earth ponies can brace themselves by sneaking! It, uh, makes you harder to push! yeah!
|
||||
Earth ponies can brace themselves by sneaking! It, uh, makes you harder to push! Yeah!
|
||||
|
||||
### Pegasi / Bat Ponies
|
||||
|
||||
|
@ -99,7 +99,7 @@ also respond to quick, short single-taps, or double-taps.
|
|||
|
||||
- Hanging of Ceilings
|
||||
|
||||
Ever just want to hang out? Well bat ponies can, _literally_! All the cool kids are doing.
|
||||
Ever just want to hang out? Well bat ponies can, _literally_! All the cool kids are doing it!
|
||||
|
||||
- Mangoes
|
||||
|
||||
|
@ -121,6 +121,12 @@ also respond to quick, short single-taps, or double-taps.
|
|||
|
||||
Changelings can turn into damn near anything, even other players! And blocks! And hostile mobs!
|
||||
Careful about turning into skeletons, though, because they hate the sun even more than bat ponies.
|
||||
|
||||
- Crawling
|
||||
|
||||
Changelings can crawl on Ceilings, which is very useful for lining up your shot, when attempting to shoot somepony in a cave,
|
||||
while disguised as a stone block. Or is that just me? Anyways, they can only crawl along flat surfaces, meaning that if you go off the edge of a block,
|
||||
you will fall off.
|
||||
|
||||
## Special Items, Plants, Tools
|
||||
|
||||
|
@ -135,7 +141,7 @@ Fighting too close together with them may cause you some knockback.
|
|||
|
||||
Zap Apple Trees occur naturally in the world and are the only way to obtain zap apples in survival. They can appear in one of several different states:
|
||||
|
||||
Hybernating, Flowering, Fruiting, or Withering
|
||||
*Hibernating, Flowering, Fruiting, or Withering*
|
||||
|
||||
They cycle through these states throughout the lunar cycle, so if you find one, and it's not in the state you want, wait around another few days and it
|
||||
will eventually bear fruit, but don't try to harvest the apples before they're ripe, because they will zap you!
|
||||
|
@ -144,4 +150,6 @@ If you're able to obtain the wood and leaves, it also makes the perfect deterant
|
|||
|
||||
### Muffins
|
||||
|
||||
They're bouncy and delicious, and pigs absolutely love them!
|
||||
They're bouncy and delicious, and pigs absolutely love them!
|
||||
|
||||
<!-- https://media.tenor.com/GTYRNMAuLIUAAAAC/muffin-button-muffins.gif -->
|
|
@ -13,9 +13,9 @@
|
|||
|
||||
- 魔法
|
||||
|
||||
独角兽需要魔法宝石来施法,没有魔法的普通宝石可以从挖矿活动中取得。一开始,您需要用一颗宝石和一本书合成魔法书,魔法书将助力您解析各物品中含有的要素并辅助您用这些要素开发各类魔咒配方,同样可以用于修饰已有配方。
|
||||
独角兽需要魔法晶石来施法,没有魔法的普通晶石可以从挖矿活动中取得。一开始,您需要用一颗晶石和一本书合成魔法书,魔法书将助力您解析各物品中含有的要素并辅助您用这些要素开发各类魔法配方,同样可以用于修饰已有配方。
|
||||
|
||||
当您做出了所需的魔法宝石后,您可以拿着它右键以将其中的魔法导入到主槽位或是副槽位(按下潜行键)中 ,这些魔咒将可以以您的主技能形式激活。您也可以直接拿着魔法宝石释放其中的魔力。
|
||||
当您做出了所需的魔法晶石后,您可以拿着它右键以将其中的魔法导入到主槽位或是副槽位(按下潜行键)中 ,这些魔法将可以以您的主技能形式激活。您也可以直接拿着魔法晶石释放其中的魔力。
|
||||
|
||||
- 瞬移
|
||||
|
||||
|
@ -84,7 +84,7 @@
|
|||
|
||||
(夜骐会在阴暗的地方重生)
|
||||
|
||||
- 倒挂于天花板
|
||||
- 倒悬
|
||||
|
||||
想开挂吗?夜骐是可以 _字面意义上_ 开挂的!大哥都喜欢这么玩。
|
||||
|
||||
|
@ -124,6 +124,6 @@
|
|||
这些状态是按周期循环的,如果您发现的果树不是您想要的状态,可以在它旁边等待几天直到结果,但请不要在魔虹苹果成熟前收获它们,否则它们会把您电得酥脆!
|
||||
如果您设法获取到了魔虹苹果的木头和叶子,那它们也可以充当威慑滋事者的完美屏障。
|
||||
|
||||
### 马芬
|
||||
### 玛芬
|
||||
|
||||
香软可口,猪猪最爱。
|
30
README.md
|
@ -1,15 +1,18 @@
|
|||
# Unicopia
|
||||
# 
|
||||
|
||||
[](https://github.com/Sollace/Unicopia/actions/workflows/gradle-build.yml)
|
||||
[](https://github.com/Sollace/Unicopia/releases/latest)
|
||||
[](https://crowdin.com/project/unicopia)
|
||||

|
||||
|
||||
[](README_RU.md)
|
||||
[](README_CN.md)
|
||||
|
||||
[Wiki](https://github.com/Sollace/Unicopia/wiki)
|
||||
|
||||
Bringing the magic of friendship to Minecraft!
|
||||
|
||||
What started as a humble utility to make playing as a unicorn a little more emersive has grown into a full-blown pony
|
||||
What started as a humble utility to make playing as a unicorn a little more immersive has grown into a full-blown pony
|
||||
conversion experience that brings new magic, mechanics and experience to the world of Minecraft to make it truly feel like you've
|
||||
entered the world of Equestria!
|
||||
|
||||
|
@ -22,13 +25,13 @@ Unicorns, Pegasi, Earth Ponies, and even Changelings get their own special abili
|
|||
- *Play as a unicorn* and learn to use magic! Craft your first spellbook and experiment, finding the different spells you can
|
||||
make and what they do, or simply delve into the lore to learn more about the past of this mysterious world!
|
||||
|
||||
Besides casting spells, such as a shield to protect themselves, of fire a bolt of magic to incinerate your foes,
|
||||
Besides casting spells, such as a shield to protect themselves, or a bolt of magic to incinerate your foes,
|
||||
Unicorns can also teleport to get around obstacles or simply reach those hard to reach places.
|
||||
|
||||
- *Play as a pegasus* and dominate the skies! Besides the ability to fly, pegasi can also perform rainbooms, control the weather by shoving them into jars,
|
||||
- *Play as a pegasus* and dominate the skies! Besides the ability to fly, pegasi can also perform sonic rainbooms, control the weather by shoving them into jars,
|
||||
and have a greater reach distance and speed than other races.
|
||||
|
||||
- *Play as a humble background pony*! Earth Ponies are tougher and heavier than the other races. They also have the nify ability to
|
||||
- *Play as a humble background pony*! Earth Ponies are tougher and heavier than the other races. They also have the nifty ability to
|
||||
kick trees to get food and hasten the growth of crops. You'll never go hungry if you're an earth pony.
|
||||
|
||||
Feeling like going over to the dark side?
|
||||
|
@ -41,7 +44,7 @@ Unicorns, Pegasi, Earth Ponies, and even Changelings get their own special abili
|
|||
|
||||
### Manage your diet
|
||||
|
||||
Playing as a pony isn't all just kicking and zapping, though! As herbivores your food options open up to include
|
||||
Playing as a pony isn't all just kicking and zapping, though! As herbivores, your food options open up to include
|
||||
a lot of items normal players don't usually get to eat. Feeling peckish? Try for some flowers from the meadow,
|
||||
or some hay! I hear the hay burgers of good, if you can find some oats.
|
||||
|
||||
|
@ -55,21 +58,24 @@ Unicorns, Pegasi, Earth Ponies, and even Changelings get their own special abili
|
|||
### Natural Stuff
|
||||
|
||||
- Airflow is simulated (badly)
|
||||
Pegasi, beware about flying during storms! It can get dangerous out there!
|
||||
|
||||
Pegasi, beware of flying during storms! It can get dangerous out there!
|
||||
If you're playing as a flying species, or just like having nice things, try building a weather vein.
|
||||
|
||||
It shows the actual, totally real and not simulated badly, wind direction of your minecraft world. Just beware
|
||||
that the direction and strength is situational (and bad), and will be different depending where you are and
|
||||
that the direction and strength are situational (and bad), and will be different depending on where you are and
|
||||
how high up you are.
|
||||
|
||||
- Hot air Rises
|
||||
|
||||
No, it's not a bad Star Wars movie, it's an actual mechanic. Sand and lava will give flying species extra lift. Water does the opposite.
|
||||
Try it! Actually don't, I don't want you to drown.
|
||||
|
||||
### Magic Items And Artifacts
|
||||
|
||||
- Craft and build s shrine for the Crystal Heart to provide valuable support to your friends
|
||||
- Or give out bangles of comradery to your non-unicorn buddies so they can share in your powers,
|
||||
or just so you can laugh when you teleport and they end up coming witht
|
||||
- Craft and build a shrine for the Crystal Heart to provide valuable support to your friends
|
||||
- Or give out bangles of comradery to your non-unicorn buddies, so they can share in your powers,
|
||||
or just so you can laugh when you teleport and they end up coming with
|
||||
- Send and receive items using the Dragon's Breath Scroll
|
||||
- Possibly more I'm forgetting about (or am I? OoOoOooOOoo...Spooky surprise mechanics)
|
||||
|
||||
|
@ -86,7 +92,7 @@ View the HOW_TO_PLAY.md file for more details.
|
|||
### 1.19.3 Only
|
||||
|
||||
This project uses reach-entity-attributes, which may not be updated at the time of this writing.
|
||||
If you building for 1.19.3, you may follow these steps to make sure it's available to git:
|
||||
If you're building for 1.19.3, you may follow these steps to make sure it's available to git:
|
||||
|
||||
`git clone https://github.com/Sollace/reach-entity-attributes`
|
||||
`cd reach-entity-attributes`
|
||||
|
|
|
@ -16,9 +16,9 @@
|
|||
|
||||
独角兽,天马,陆马,甚至幻形灵都有其独特的能力
|
||||
|
||||
- *成为独角兽,* 学习使用魔法!制成您的第一本魔法书并开展实验。既可研究不同魔咒的配方与功效,亦可潜心研究历史传说,揭开这奇幻世界过往的面纱!
|
||||
- *成为独角兽,* 学习使用魔法!制成您的第一本魔法书并开展实验。既可研究不同魔法的配方与功效,亦可潜心研究历史传说,揭开这奇幻世界过往的面纱!
|
||||
|
||||
除了施放保护自己的防护罩,用魔法镭射焚烧敌人的魔咒外,独角兽还可利用瞬移法术免去翻山越岭的苦恼,直接传送到难以到达的地方。
|
||||
除了施放保护自己的防护罩,用魔法镭射焚烧敌人的魔法外,独角兽还可利用瞬移法术免去翻山越岭的苦恼,直接传送到难以到达的地方。
|
||||
|
||||
- *成为天马,*统治天空!除了能飞以外,天马还可以制造彩虹音爆、用罐子收容坏天气,相比于其他种族可触距离更远,跑得更快。
|
||||
|
||||
|
|
17
README_RU.md
|
@ -1,4 +1,4 @@
|
|||
# Unicopia
|
||||
# 
|
||||
|
||||
[](https://github.com/Sollace/Unicopia/actions/workflows/gradle-build.yml)
|
||||
[](https://github.com/Sollace/Unicopia/releases/latest)
|
||||
|
@ -6,6 +6,8 @@
|
|||
|
||||
[](README.md)
|
||||
|
||||
[Вики (англ.)](https://github.com/Sollace/Unicopia/wiki)
|
||||
|
||||
Привнесите магию дружбы в Minecraft!
|
||||
|
||||
То, что начиналось как скромная утилита, позволяющая сделать игру за единорога немного более увлекательной,
|
||||
|
@ -46,19 +48,22 @@
|
|||
|
||||
### Понифицированные картины
|
||||
|
||||
Ведь что это был бы за пони-мод, если бы в нём не было этого? У каждой расы есть хотя бы один рисунок, представляющий её,
|
||||
Ведь что это был бы за пони-мод, если бы в нём _не_ было этого? У каждой расы есть хотя бы один рисунок, представляющий её,
|
||||
так что покажите свою гордость и поднимите флаг!
|
||||
|
||||
Дисклеймер: Радужных флагов нет (пока)
|
||||
Дисклеймер: Радужных флагов (пока) нет
|
||||
|
||||
### Природные явления
|
||||
|
||||
- Воздушный поток (плохо) влияет на пегасов, остерегайтесь летать во время грозы! Там может быть опасно!
|
||||
Если вы играете за летающий вид или просто любите приятные вещи, попробуйте построить метеорологическую жилу.
|
||||
- Воздушный поток
|
||||
|
||||
Пегасы, остерегайтесь полётов во время грозы! Это может быть опасно!
|
||||
Если вы играете за летающий вид или просто любите приятные вещи, попробуйте построить погодную жилу.
|
||||
Она показывает фактическое, абсолютно реальное, а не плохо смоделированное направление ветра в вашем мире Minecraft. Только учтите,
|
||||
что направление и сила ветра ситуативны (и плохи), и будут отличаться в зависимости от того, где вы находитесь и на какой высоте.
|
||||
что направление и сила ветра ситуативны, и будут отличаться в зависимости от того, где вы находитесь и на какой высоте.
|
||||
|
||||
- Горячий воздух поднимает
|
||||
|
||||
Нет, это не плохой фильм про "Звездные войны", это реальная механика. Песок и лава придают летающим видам дополнительную подъёмную силу.
|
||||
Вода - наоборот. Попробуйте! А вообще, не стоит, я не хочу чтобы вы утонули.
|
||||
|
||||
|
|
80
assets/accretion_disk.svg
Normal file
|
@ -0,0 +1,80 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="793.70081"
|
||||
height="1122.5197"
|
||||
viewBox="0 0 210 297"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
sodipodi:docname="accretion_disk.svg"
|
||||
inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)">
|
||||
<defs
|
||||
id="defs2">
|
||||
<filter
|
||||
inkscape:collect="always"
|
||||
style="color-interpolation-filters:sRGB"
|
||||
id="filter1006"
|
||||
x="-0.047823932"
|
||||
width="1.0956479"
|
||||
y="-0.048177369"
|
||||
height="1.0963547">
|
||||
<feGaussianBlur
|
||||
inkscape:collect="always"
|
||||
stdDeviation="11.80918"
|
||||
id="feGaussianBlur1008" />
|
||||
</filter>
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="0.65297002"
|
||||
inkscape:cx="638.40178"
|
||||
inkscape:cy="466.56457"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
objecttolerance="1"
|
||||
inkscape:window-width="2048"
|
||||
inkscape:window-height="1076"
|
||||
inkscape:window-x="-4"
|
||||
inkscape:window-y="4"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:pagecheckerboard="true"
|
||||
units="px" />
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<path
|
||||
style="fill:#d98282;stroke:#000000;stroke-width:5.90000009;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1;filter:url(#filter1006);stroke-miterlimit:4;stroke-dasharray:none"
|
||||
d="M 273.33203 61.957031 C 218.19856 132.07255 244.67649 272.3247 300.8125 327.65625 C 212.65683 342.56237 117.8187 290.41151 96.970703 214.49609 C 106.48046 303.18347 223.38426 385.06833 302.34375 385.77344 C 250.43451 458.78189 146.3945 488.61281 78.105469 449.44141 C 147.35021 505.66464 287.99747 481.38179 344.34961 426.17578 C 358.39121 514.5561 305.1554 608.79183 229.00586 628.76758 C 317.79645 620.27585 401.01904 504.31983 402.66211 425.35938 C 475.15092 478.02297 503.88024 582.37041 463.99023 650.24219 C 520.94121 581.59474 498.14594 440.69846 443.26758 384.42969 C 531.7397 373.62573 624.38067 429.5873 642.12695 506.28711 C 636.22847 417.28661 522.7479 330.71796 443.91992 326.89844 C 498.97294 256.29628 604.20699 230.99439 670.73828 273.08203 C 603.98948 213.9172 462.42095 232.0939 402.21289 284.1875 C 386.71456 195.15366 439.99868 100.94561 516.1582 81.007812 C 427.36338 89.45531 344.08309 205.36983 342.04102 283.99023 C 267.83445 232.87989 235.23336 130.85029 273.33203 61.957031 z M 371.38086 289.78711 A 64.321476 64.321476 0 0 1 435.70117 354.10742 A 64.321476 64.321476 0 0 1 371.38086 418.42969 A 64.321476 64.321476 0 0 1 307.05859 354.10742 A 64.321476 64.321476 0 0 1 371.38086 289.78711 z "
|
||||
transform="scale(0.26458333)"
|
||||
id="path828"
|
||||
inkscape:export-xdpi="37.806454"
|
||||
inkscape:export-ydpi="37.806454" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.6 KiB |
BIN
assets/models/body.png
Normal file
After Width: | Height: | Size: 220 B |
BIN
assets/models/bulb_angry.png
Normal file
After Width: | Height: | Size: 42 KiB |
BIN
assets/models/bulb_idle.png
Normal file
After Width: | Height: | Size: 42 KiB |
|
@ -1,50 +0,0 @@
|
|||
// Made with Blockbench 4.8.3
|
||||
// Exported for Minecraft version 1.17 or later with Mojang mappings
|
||||
// Paste this class into your mod and generate all required imports
|
||||
|
||||
|
||||
public class cloud_bed<T extends Entity> extends EntityModel<T> {
|
||||
// This layer location should be baked with EntityRendererProvider.Context in the entity renderer and passed into this model's constructor
|
||||
public static final ModelLayerLocation LAYER_LOCATION = new ModelLayerLocation(new ResourceLocation("modid", "cloud_bed"), "main");
|
||||
private final ModelPart head;
|
||||
private final ModelPart foot;
|
||||
|
||||
public cloud_bed(ModelPart root) {
|
||||
this.head = root.getChild("head");
|
||||
this.foot = root.getChild("foot");
|
||||
}
|
||||
|
||||
public static LayerDefinition createBodyLayer() {
|
||||
MeshDefinition meshdefinition = new MeshDefinition();
|
||||
PartDefinition partdefinition = meshdefinition.getRoot();
|
||||
|
||||
PartDefinition head = partdefinition.addOrReplaceChild("head", CubeListBuilder.create(), PartPose.offset(0.0F, 24.0F, 0.0F));
|
||||
|
||||
PartDefinition main_r1 = head.addOrReplaceChild("main_r1", CubeListBuilder.create().texOffs(0, 0).addBox(-8.0F, -21.0F, -9.0F, 16.0F, 13.0F, 6.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(0.0F, 0.0F, -16.0F, -1.5708F, 0.0F, 0.0F));
|
||||
|
||||
PartDefinition head_board = head.addOrReplaceChild("head_board", CubeListBuilder.create().texOffs(52, 24).addBox(7.0F, -13.0F, -3.0F, 2.0F, 13.0F, 3.0F, new CubeDeformation(0.0F))
|
||||
.texOffs(0, 43).addBox(-6.0F, -15.0F, -2.0F, 13.0F, 15.0F, 3.0F, new CubeDeformation(0.0F))
|
||||
.texOffs(52, 24).addBox(-8.0F, -13.0F, -3.0F, 2.0F, 13.0F, 3.0F, new CubeDeformation(0.0F)), PartPose.offset(-0.5F, 0.0F, 7.0F));
|
||||
|
||||
PartDefinition foot = partdefinition.addOrReplaceChild("foot", CubeListBuilder.create(), PartPose.offset(0.0F, 24.0F, 0.0F));
|
||||
|
||||
PartDefinition main_r2 = foot.addOrReplaceChild("main_r2", CubeListBuilder.create().texOffs(0, 22).addBox(-8.0F, -8.0F, -9.0F, 16.0F, 15.0F, 6.0F, new CubeDeformation(0.0F)), PartPose.offsetAndRotation(0.0F, 0.0F, 0.0F, -1.5708F, 0.0F, 0.0F));
|
||||
|
||||
PartDefinition head_board2 = foot.addOrReplaceChild("head_board2", CubeListBuilder.create().texOffs(52, 40).addBox(6.0F, -13.0F, -2.0F, 3.0F, 10.0F, 3.0F, new CubeDeformation(0.0F))
|
||||
.texOffs(0, 43).addBox(-6.0F, -15.0F, -3.0F, 13.0F, 11.0F, 3.0F, new CubeDeformation(0.0F))
|
||||
.texOffs(52, 40).addBox(-8.0F, -13.0F, -2.0F, 3.0F, 10.0F, 3.0F, new CubeDeformation(0.0F)), PartPose.offset(-0.5F, 3.0F, -7.0F));
|
||||
|
||||
return LayerDefinition.create(meshdefinition, 64, 64);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupAnim(T entity, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderToBuffer(PoseStack poseStack, VertexConsumer vertexConsumer, int packedLight, int packedOverlay, float red, float green, float blue, float alpha) {
|
||||
head.render(poseStack, vertexConsumer, packedLight, packedOverlay, red, green, blue, alpha);
|
||||
foot.render(poseStack, vertexConsumer, packedLight, packedOverlay, red, green, blue, alpha);
|
||||
}
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
// Made with Blockbench 4.8.3
|
||||
// Exported for Minecraft version 1.17+ for Yarn
|
||||
// Paste this class into your mod and generate all required imports
|
||||
public class cloud_chest extends EntityModel<Entity> {
|
||||
private final ModelPart lid;
|
||||
private final ModelPart lock_r1;
|
||||
private final ModelPart bb_main;
|
||||
public cloud_chest(ModelPart root) {
|
||||
this.lid = root.getChild("lid");
|
||||
this.bb_main = root.getChild("bb_main");
|
||||
}
|
||||
public static TexturedModelData getTexturedModelData() {
|
||||
ModelData modelData = new ModelData();
|
||||
ModelPartData modelPartData = modelData.getRoot();
|
||||
ModelPartData lid = modelPartData.addChild("lid", ModelPartBuilder.create().uv(0, 0).cuboid(-1.0F, -2.0F, 13.8F, 2.0F, 4.0F, 1.0F, new Dilation(0.0F))
|
||||
.uv(0, 0).cuboid(-1.0F, -1.0F, 14.0F, 2.0F, 2.0F, 1.0F, new Dilation(0.0F))
|
||||
.uv(0, 0).cuboid(-7.0F, -5.0F, 0.0F, 14.0F, 5.0F, 14.0F, new Dilation(0.3F)), ModelTransform.of(0.0F, 16.0F, -7.0F, 1.0908F, 0.0F, 0.0F));
|
||||
|
||||
ModelPartData lock_r1 = lid.addChild("lock_r1", ModelPartBuilder.create().uv(0, 0).cuboid(-2.0F, -4.0F, -0.5F, 2.0F, 4.0F, 1.0F, new Dilation(0.0F)), ModelTransform.of(-2.0F, 1.0F, 14.3F, 0.0F, 0.0F, 1.5708F));
|
||||
|
||||
ModelPartData bb_main = modelPartData.addChild("bb_main", ModelPartBuilder.create().uv(0, 19).cuboid(-7.0F, -10.0F, -7.0F, 14.0F, 10.0F, 14.0F, new Dilation(0.0F)), ModelTransform.pivot(0.0F, 24.0F, 0.0F));
|
||||
return TexturedModelData.of(modelData, 64, 64);
|
||||
}
|
||||
@Override
|
||||
public void setAngles(Entity entity, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch) {
|
||||
}
|
||||
@Override
|
||||
public void render(MatrixStack matrices, VertexConsumer vertexConsumer, int light, int overlay, float red, float green, float blue, float alpha) {
|
||||
lid.render(matrices, vertexConsumer, light, overlay, red, green, blue, alpha);
|
||||
bb_main.render(matrices, vertexConsumer, light, overlay, red, green, blue, alpha);
|
||||
}
|
||||
}
|
BIN
assets/models/cork.png
Normal file
After Width: | Height: | Size: 136 B |
1
assets/models/hanging_sandbag.bbmodel
Normal file
33
assets/models/hanging_sandbag.java
Normal file
|
@ -0,0 +1,33 @@
|
|||
// Made with Blockbench 4.9.4
|
||||
// Exported for Minecraft version 1.17+ for Yarn
|
||||
// Paste this class into your mod and generate all required imports
|
||||
public class hanging_sandbag extends EntityModel<Entity> {
|
||||
private final ModelPart root;
|
||||
private final ModelPart bag;
|
||||
private final ModelPart cube_r1;
|
||||
private final ModelPart cube_r2;
|
||||
public hanging_sandbag(ModelPart root) {
|
||||
this.root = root.getChild("root");
|
||||
}
|
||||
public static TexturedModelData getTexturedModelData() {
|
||||
ModelData modelData = new ModelData();
|
||||
ModelPartData modelPartData = modelData.getRoot();
|
||||
ModelPartData root = modelPartData.addChild("root", ModelPartBuilder.create().uv(16, 19).cuboid(-0.5F, 0.0F, -0.5F, 1.0F, 9.0F, 1.0F, new Dilation(0.0F)), ModelTransform.pivot(0.0F, 24.0F, 0.0F));
|
||||
|
||||
ModelPartData bag = root.addChild("bag", ModelPartBuilder.create().uv(0, 0).cuboid(-3.0F, 1.0F, -3.0F, 6.0F, 7.0F, 6.0F, new Dilation(0.0F))
|
||||
.uv(12, 14).cuboid(-2.0F, 0.0F, -2.0F, 4.0F, 1.0F, 4.0F, new Dilation(0.0F))
|
||||
.uv(0, 13).cuboid(-2.0F, 8.0F, -2.0F, 4.0F, 1.0F, 4.0F, new Dilation(0.0F)), ModelTransform.pivot(0.0F, 9.0F, 0.0F));
|
||||
|
||||
ModelPartData cube_r1 = bag.addChild("cube_r1", ModelPartBuilder.create().uv(0, 14).cuboid(0.0F, 8.0F, -2.0F, 0.0F, 4.0F, 4.0F, new Dilation(0.0F)), ModelTransform.of(0.0F, 1.0F, 0.0F, 0.0F, -0.7854F, 0.0F));
|
||||
|
||||
ModelPartData cube_r2 = bag.addChild("cube_r2", ModelPartBuilder.create().uv(0, 14).cuboid(0.0F, 8.0F, -2.0F, 0.0F, 4.0F, 4.0F, new Dilation(0.0F)), ModelTransform.of(0.0F, 1.0F, 0.0F, 0.0F, 0.7854F, 0.0F));
|
||||
return TexturedModelData.of(modelData, 32, 32);
|
||||
}
|
||||
@Override
|
||||
public void setAngles(Entity entity, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch) {
|
||||
}
|
||||
@Override
|
||||
public void render(MatrixStack matrices, VertexConsumer vertexConsumer, int light, int overlay, float red, float green, float blue, float alpha) {
|
||||
root.render(matrices, vertexConsumer, light, overlay, red, green, blue, alpha);
|
||||
}
|
||||
}
|
BIN
assets/models/hanging_sandbag.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
1
assets/models/hay_bale.bbmodel
Normal file
1
assets/models/ignimious_bulb.bbmodel
Normal file
1
assets/models/jar.bbmodel
Normal file
|
@ -0,0 +1 @@
|
|||
{"meta":{"format_version":"4.9","model_format":"java_block","box_uv":false},"name":"jar","parent":"","ambientocclusion":true,"front_gui_light":false,"visible_box":[1,1,0],"variable_placeholders":"","variable_placeholder_buttons":[],"unhandled_root_fields":{},"resolution":{"width":16,"height":16},"elements":[{"name":"cube","box_uv":false,"rescale":false,"locked":false,"render_order":"default","allow_mirror_modeling":true,"from":[4,0,4],"to":[12,12,12],"autouv":0,"color":3,"origin":[0,0,0],"faces":{"north":{"uv":[0,0,8,12],"texture":0},"east":{"uv":[0,0,8,12],"texture":0},"south":{"uv":[0,0,8,12],"texture":0},"west":{"uv":[0,0,8,12],"texture":0},"up":{"uv":[8,0,16,8],"texture":0},"down":{"uv":[8,0,16,8],"texture":0}},"type":"cube","uuid":"c02d32c0-74ac-27ba-627e-83de2a9500f7"},{"name":"cube","box_uv":false,"rescale":false,"locked":false,"render_order":"default","allow_mirror_modeling":true,"from":[6,13,6],"to":[10,16,10],"autouv":0,"color":3,"origin":[0,0,0],"faces":{"north":{"uv":[0,4,4,7],"texture":1},"east":{"uv":[0,4,4,7],"texture":1},"south":{"uv":[0,4,4,7],"texture":1},"west":{"uv":[0,4,4,7],"texture":1},"up":{"uv":[0,0,4,4],"texture":1},"down":{"uv":[4,0,8,4],"texture":1}},"type":"cube","uuid":"147c96d5-ae15-7e40-dcb7-c635e6e80eed"},{"name":"cube","box_uv":false,"rescale":false,"locked":false,"render_order":"default","allow_mirror_modeling":true,"from":[5,13,5],"to":[11,14,11],"autouv":0,"color":3,"origin":[0,0,0],"faces":{"north":{"uv":[0,0,8,1],"texture":0},"east":{"uv":[0,0,8,1],"texture":0},"south":{"uv":[0,0,8,1],"texture":0},"west":{"uv":[0,0,8,1],"texture":0},"up":{"uv":[8,0,16,8],"texture":0},"down":{"uv":[8,0,16,8],"texture":0}},"type":"cube","uuid":"7642fef8-ce7e-d79f-f450-01de2526fca5"},{"name":"cube","box_uv":false,"rescale":false,"locked":false,"render_order":"default","allow_mirror_modeling":true,"from":[6,12,6],"to":[10,13,10],"autouv":0,"color":3,"origin":[0,0,0],"faces":{"north":{"uv":[0,0,8,1],"texture":0},"east":{"uv":[0,0,8,1],"texture":0},"south":{"uv":[0,0,8,1],"texture":0},"west":{"uv":[0,0,8,1],"texture":0},"up":{"uv":[8,0,16,8],"texture":0},"down":{"uv":[8,0,16,8],"texture":0}},"type":"cube","uuid":"e1e878a3-7fdb-79f6-e2c8-b591a94cec41"}],"outliner":["c02d32c0-74ac-27ba-627e-83de2a9500f7","7642fef8-ce7e-d79f-f450-01de2526fca5","e1e878a3-7fdb-79f6-e2c8-b591a94cec41","147c96d5-ae15-7e40-dcb7-c635e6e80eed"],"textures":[{"path":"","name":"body","folder":"block","namespace":"","id":"0","width":16,"height":16,"uv_width":16,"uv_height":16,"particle":true,"layers_enabled":false,"sync_to_project":"","render_mode":"default","render_sides":"auto","frame_time":1,"frame_order_type":"loop","frame_order":"","frame_interpolate":false,"visible":true,"internal":true,"saved":false,"uuid":"c3fc3ff5-2bb6-a5d1-88ff-7d0d48a4200c","source":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAKxJREFUOE/Nk70NxCAMhe0qiCKCCRiA/UdhAFgARIGg8sknJbpI/CS6K47Sz/54fggkIoLJCSHAvu+glLp0pZQg5wwYYyStNfYYrHGdhxHx0sMXM+QEHIVPGAN6w8dlPHMCek4eAUYrLB1478kYM8zga8AyxJkD1hgwfcYVYLTekRk658ha281gpv0WUEqBWiu01t7gbdtACAFSShi5Ox3M/sEdrbv7ncH/cfACoGWX3cV5e7AAAAAASUVORK5CYII="},{"path":"","name":"cork","folder":"block","namespace":"","id":"1","width":16,"height":16,"uv_width":16,"uv_height":16,"particle":false,"layers_enabled":false,"sync_to_project":"","render_mode":"default","render_sides":"auto","frame_time":1,"frame_order_type":"loop","frame_order":"","frame_interpolate":false,"visible":true,"internal":true,"saved":false,"uuid":"1faf1369-230e-ed4a-f210-037c1820f194","source":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAFJJREFUOE9jXDwj8z8DHhCbMZ0RnzwjyABRYW6wmtdvv4JpZD59DKDICztWl6CEgUdoD14/o1sGDgNkQUJ+pr4B+PxPjBxJ/sVm4KgBDAzDIAwAlBIoEQohE0IAAAAASUVORK5CYII="}]}
|
BIN
assets/models/jar_body.png
Normal file
After Width: | Height: | Size: 220 B |
1
assets/models/jar_cloud.bbmodel
Normal file
BIN
assets/models/jar_cork.png
Normal file
After Width: | Height: | Size: 136 B |
1
assets/models/jar_lightning.bbmodel
Normal file
|
@ -0,0 +1 @@
|
|||
{"meta":{"format_version":"4.9","model_format":"java_block","box_uv":false},"name":"jar","parent":"","ambientocclusion":true,"front_gui_light":false,"visible_box":[1,1,0],"variable_placeholders":"","variable_placeholder_buttons":[],"unhandled_root_fields":{},"resolution":{"width":16,"height":16},"elements":[{"name":"cube","box_uv":false,"rescale":true,"locked":false,"render_order":"default","allow_mirror_modeling":true,"from":[6,1,7.5],"to":[11,11,7.5],"autouv":0,"color":5,"rotation":[0,-45,0],"origin":[8,5,7],"faces":{"north":{"uv":[3,0,13,16],"texture":0},"east":{"uv":[0,0,0,8],"texture":0},"south":{"uv":[3,0,13,16],"texture":0},"west":{"uv":[0,0,0,8],"texture":0},"up":{"uv":[0,0,6,0],"texture":0},"down":{"uv":[0,0,6,0],"texture":0}},"type":"cube","uuid":"52fdb109-7055-1f3c-d1a1-788daf976643"},{"name":"cube","box_uv":false,"rescale":true,"locked":false,"render_order":"default","allow_mirror_modeling":true,"from":[5,1,7.5],"to":[10,11,7.5],"autouv":0,"color":5,"rotation":[0,45,0],"origin":[8,5,7],"faces":{"north":{"uv":[3,0,13,16],"texture":0},"east":{"uv":[0,0,0,8],"texture":0},"south":{"uv":[3,0,13,16],"texture":0},"west":{"uv":[0,0,0,8],"texture":0},"up":{"uv":[0,0,6,0],"rotation":180,"texture":0},"down":{"uv":[0,0,6,0],"rotation":180,"texture":0}},"type":"cube","uuid":"67ba2407-52e4-4b13-579c-0e7675265bb9"}],"outliner":["52fdb109-7055-1f3c-d1a1-788daf976643","67ba2407-52e4-4b13-579c-0e7675265bb9"],"textures":[{"path":"/home/sollace/Documents/GitRepos/minecraft_mods/Unicopia/src/main/resources/assets/unicopia/textures/block/lightning_jar_filling.png","name":"lightning_jar_filling.png","folder":"block","namespace":"unicopia","id":"2","width":16,"height":16,"uv_width":16,"uv_height":16,"particle":false,"layers_enabled":false,"sync_to_project":"","render_mode":"default","render_sides":"auto","frame_time":1,"frame_order_type":"loop","frame_order":"","frame_interpolate":false,"visible":true,"internal":true,"saved":true,"uuid":"2c8fdd18-9bd4-2276-cdc1-d86d0605d22d","relative_path":"../../../src/main/resources/assets/unicopia/textures/block/lightning_jar_filling.png","source":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAN9JREFUOE9jZCASOH7T/L+f6zojunIMAWzmObxR/c/IxcJAlgE+3/X+f/j7l4GV6R/pBnh/0vv/59d/hl9cf7BqBrkWrxdABnxj+Y1TM14DQJq//vrOwMfLz7CJ/QxOi7BKgEKc5wcLw3u2fwxHeK6C1YDEuP6wMqC7CKcB2GIDZMBWvksoejAMANmErBnkEhD4zP6bgZGRESM88BoA1/zvBzi8D4jcwp+QkG0HJRrfd7pg14DCgqh0ADMApBnEZvsGcT5Z6QBXqBOVF9C9gi+/4Y1GbJmHoAuQw4GYnA4AMBBxEZobGUEAAAAASUVORK5CYII="}]}
|
1
assets/models/jar_storm.bbmodel
Normal file
1
assets/models/jar_zap.bbmodel
Normal file
|
@ -0,0 +1 @@
|
|||
{"meta":{"format_version":"4.9","model_format":"java_block","box_uv":false},"name":"jar","parent":"","ambientocclusion":true,"front_gui_light":false,"visible_box":[1,1,0],"variable_placeholders":"","variable_placeholder_buttons":[],"unhandled_root_fields":{},"resolution":{"width":16,"height":16},"elements":[{"name":"cube","box_uv":false,"rescale":false,"locked":false,"render_order":"default","allow_mirror_modeling":true,"from":[4,0,4],"to":[12,10,12],"autouv":0,"color":4,"inflate":-0.09999999999999964,"origin":[0,0,0],"faces":{"north":{"uv":[0,2,8,12],"texture":2},"east":{"uv":[0,6,8,16],"texture":2},"south":{"uv":[8,6,16,16],"texture":2},"west":{"uv":[8,0,16,10],"texture":2},"up":{"uv":[4,3,12,11],"texture":2},"down":{"uv":[8,4,16,12],"texture":2}},"type":"cube","uuid":"e15b3907-6195-1f3b-0c48-23c6b4642fc6"}],"outliner":["e15b3907-6195-1f3b-0c48-23c6b4642fc6"],"textures":[{"path":"/home/sollace/Documents/GitRepos/minecraft_mods/Unicopia/assets/models/body.png","name":"body.png","folder":"","namespace":"","id":"0","width":16,"height":16,"uv_width":16,"uv_height":16,"particle":true,"layers_enabled":false,"sync_to_project":"","render_mode":"default","render_sides":"auto","frame_time":1,"frame_order_type":"loop","frame_order":"","frame_interpolate":false,"visible":true,"internal":true,"saved":true,"uuid":"c3fc3ff5-2bb6-a5d1-88ff-7d0d48a4200c","relative_path":"../body.png","source":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAKxJREFUOE/Nk70NxCAMhe0qiCKCCRiA/UdhAFgARIGg8sknJbpI/CS6K47Sz/54fggkIoLJCSHAvu+glLp0pZQg5wwYYyStNfYYrHGdhxHx0sMXM+QEHIVPGAN6w8dlPHMCek4eAUYrLB1478kYM8zga8AyxJkD1hgwfcYVYLTekRk658ha281gpv0WUEqBWiu01t7gbdtACAFSShi5Ox3M/sEdrbv7ncH/cfACoGWX3cV5e7AAAAAASUVORK5CYII="},{"path":"/home/sollace/Documents/GitRepos/minecraft_mods/Unicopia/assets/models/cork.png","name":"cork.png","folder":"","namespace":"","id":"1","width":16,"height":16,"uv_width":16,"uv_height":16,"particle":false,"layers_enabled":false,"sync_to_project":"","render_mode":"default","render_sides":"auto","frame_time":1,"frame_order_type":"loop","frame_order":"","frame_interpolate":false,"visible":true,"internal":true,"saved":true,"uuid":"1faf1369-230e-ed4a-f210-037c1820f194","relative_path":"../cork.png","source":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAFJJREFUOE9jXDwj8z8DHhCbMZ0RnzwjyABRYW6wmtdvv4JpZD59DKDICztWl6CEgUdoD14/o1sGDgNkQUJ+pr4B+PxPjBxJ/sVm4KgBDAzDIAwAlBIoEQohE0IAAAAASUVORK5CYII="},{"path":"/home/sollace/Documents/GitRepos/minecraft_mods/Unicopia/src/main/resources/assets/unicopia/textures/item/jar_filling_zap.png","name":"jar_filling_zap.png","folder":"item","namespace":"unicopia","id":"2","width":16,"height":16,"uv_width":16,"uv_height":16,"particle":false,"layers_enabled":false,"sync_to_project":"","render_mode":"default","render_sides":"auto","frame_time":1,"frame_order_type":"loop","frame_order":"","frame_interpolate":false,"visible":true,"internal":true,"saved":false,"uuid":"62c06d20-77c5-befb-bb95-8e5da5394d9c","source":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAudJREFUOE8dkUlrXWUYgJ/3G849J7dJSxZuG2s6aMDaUsWWNjVpBS2luHDtyp1UcOhfEKTZ1LYIURQXjQYkEkwduhVd6S8oxUXAJpCBeO/NGb7hlfgPnkHOmvfUiMepBwJ3ph0ej3YRPew5+9UnSN9CY4gnL0FpcBo5vzjCeEHOmA9UJaBJuTftKHAUGeoqc/7BPTgUyPsgJ+boTEEkU6rj3OJTysIiZ/37moPly5mSnjEgBYN2n5d/+RSXgAQ5QDw5R2GFQWOZ/WIL6Ql2lJFz9iNdfM4zsg3jFAy6louP7kMRyZ2AgfqZWXAlRlsuLw7wpdDEQH10Ffnj+C31PY+2LT4Lp79fgBIkQZICfeEyQSsYNlxZ3mX4b83EkYqm6Rge/wn569SHqjZRq+fC6gK66Vgff5ep9A3MzLLTBY5UgVcXa1KKRBImQH5xDVGH/Pn8LTUkXvr5M1I0uKbj73yTZ48/IfmEsZFXvt6jGAniDYOwTz72A9rvQzbI76c+1gs/3icMa/wERAE3dYOailwPmFvbxu5kJBz0F0ZnVkl1S9Xr0wWD6GOUCCogCvnYWxjfgkZeX27Y3tzDO0cMGTPzkNh3tHVNUULvtbtIfoKKeNLUVYwYJEW6kePGbyM2Hm9RVI5oDGlqhewMgsWKoXd1gUiH1GFeSyvQjJGrhjeWO/55uoVTh+9bjGTs9K80YmhDTRk69PodnPW0MSIarimu4NrKiO31baJP9IqCHJV4Yol8gC8lsR5Qjo1Tzt2mIRNjwHhF3vzuinaaECvs7uxgjaE6+pCNPGRsYpxcJ9QbNAYmr37Org7pmTFaavyB8vzSrDpbsbe5RVNF3NEVovXQtPjeIVpa3t7cYO2dbzHqyKYhqSekfUpXIReXLqlJke3JB7geqHdIryDWSmkjxlYcnr/NXmhIVrCq/H/NZBwVcvrRunYSKLGkImOi4LynDcrk9bsMm33koIFrKUIP1Y7sWqz0ydLyH7DGczPZHbGfAAAAAElFTkSuQmCC","relative_path":"../../../src/main/resources/assets/unicopia/textures/item/jar_filling_zap.png"}]}
|
1
assets/models/mimic.bbmodel
Normal file
66
assets/models/mimic.java
Normal file
|
@ -0,0 +1,66 @@
|
|||
// Made with Blockbench 4.9.4
|
||||
// Exported for Minecraft version 1.17+ for Yarn
|
||||
// Paste this class into your mod and generate all required imports
|
||||
|
||||
package com.example.mod;
|
||||
|
||||
public class mimic extends EntityModel<Entity> {
|
||||
private final ModelPart lid;
|
||||
private final ModelPart tongue_r1;
|
||||
private final ModelPart upper_teeth;
|
||||
private final ModelPart cube_r1;
|
||||
private final ModelPart lower_teeth;
|
||||
private final ModelPart cube_r2;
|
||||
private final ModelPart right_leg;
|
||||
private final ModelPart left_leg;
|
||||
public mimic(ModelPart root) {
|
||||
this.lid = root.getChild("lid");
|
||||
this.lower_teeth = root.getChild("lower_teeth");
|
||||
this.right_leg = root.getChild("right_leg");
|
||||
this.left_leg = root.getChild("left_leg");
|
||||
}
|
||||
public static TexturedModelData getTexturedModelData() {
|
||||
ModelData modelData = new ModelData();
|
||||
ModelPartData modelPartData = modelData.getRoot();
|
||||
ModelPartData lid = modelPartData.addChild("lid", ModelPartBuilder.create(), ModelTransform.of(0.0F, 17.0F, -7.0F, -0.829F, 0.0F, -3.1416F));
|
||||
|
||||
ModelPartData tongue_r1 = lid.addChild("tongue_r1", ModelPartBuilder.create().uv(11, 34).cuboid(-3.0F, -10.0F, 1.0F, 6.0F, 1.0F, 8.0F, new Dilation(0.0F)), ModelTransform.of(0.0F, 7.0F, 7.0F, 0.5236F, 0.0F, 0.0F));
|
||||
|
||||
ModelPartData upper_teeth = lid.addChild("upper_teeth", ModelPartBuilder.create().uv(0, 0).cuboid(-1.0F, -8.0F, 5.0F, 2.0F, 4.0F, 1.0F, new Dilation(0.0F))
|
||||
.uv(0, 0).cuboid(-4.0F, -8.0F, 5.0F, 2.0F, 4.0F, 1.0F, new Dilation(0.0F))
|
||||
.uv(0, 0).cuboid(2.0F, -8.0F, 5.0F, 2.0F, 4.0F, 1.0F, new Dilation(0.0F)), ModelTransform.pivot(0.0F, 7.0F, 7.0F));
|
||||
|
||||
ModelPartData cube_r1 = upper_teeth.addChild("cube_r1", ModelPartBuilder.create().uv(0, 0).cuboid(-6.0F, -1.0F, -6.0F, 2.0F, 4.0F, 1.0F, new Dilation(0.0F))
|
||||
.uv(0, 0).cuboid(-9.0F, -1.0F, -6.0F, 2.0F, 4.0F, 1.0F, new Dilation(0.0F))
|
||||
.uv(0, 0).cuboid(-12.0F, -1.0F, -6.0F, 2.0F, 4.0F, 1.0F, new Dilation(0.0F))
|
||||
.uv(0, 0).cuboid(-6.0F, -1.0F, 5.0F, 2.0F, 4.0F, 1.0F, new Dilation(0.0F))
|
||||
.uv(0, 0).cuboid(-9.0F, -1.0F, 5.0F, 2.0F, 4.0F, 1.0F, new Dilation(0.0F))
|
||||
.uv(0, 0).cuboid(-12.0F, -1.0F, 5.0F, 2.0F, 4.0F, 1.0F, new Dilation(0.0F)), ModelTransform.of(0.0F, -7.0F, -7.0F, 0.0F, 1.5708F, 0.0F));
|
||||
|
||||
ModelPartData lower_teeth = modelPartData.addChild("lower_teeth", ModelPartBuilder.create().uv(0, 0).cuboid(-1.0F, -1.0F, 12.0F, 2.0F, 4.0F, 1.0F, new Dilation(0.0F))
|
||||
.uv(0, 0).cuboid(-4.0F, -1.0F, 12.0F, 2.0F, 4.0F, 1.0F, new Dilation(0.0F))
|
||||
.uv(0, 0).cuboid(2.0F, -1.0F, 12.0F, 2.0F, 4.0F, 1.0F, new Dilation(0.0F)), ModelTransform.pivot(0.0F, 16.0F, -7.0F));
|
||||
|
||||
ModelPartData cube_r2 = lower_teeth.addChild("cube_r2", ModelPartBuilder.create().uv(0, 0).cuboid(-6.0F, -1.0F, -6.0F, 2.0F, 4.0F, 1.0F, new Dilation(0.0F))
|
||||
.uv(0, 0).cuboid(-9.0F, -1.0F, -6.0F, 2.0F, 4.0F, 1.0F, new Dilation(0.0F))
|
||||
.uv(0, 0).cuboid(-12.0F, -1.0F, -6.0F, 2.0F, 4.0F, 1.0F, new Dilation(0.0F))
|
||||
.uv(0, 0).cuboid(-6.0F, -1.0F, 5.0F, 2.0F, 4.0F, 1.0F, new Dilation(0.0F))
|
||||
.uv(0, 0).cuboid(-9.0F, -1.0F, 5.0F, 2.0F, 4.0F, 1.0F, new Dilation(0.0F))
|
||||
.uv(0, 0).cuboid(-12.0F, -1.0F, 5.0F, 2.0F, 4.0F, 1.0F, new Dilation(0.0F)), ModelTransform.of(0.0F, 0.0F, 0.0F, 0.0F, 1.5708F, 0.0F));
|
||||
|
||||
ModelPartData right_leg = modelPartData.addChild("right_leg", ModelPartBuilder.create().uv(7, 30).cuboid(-2.5F, -1.5F, -3.0F, 5.0F, 7.0F, 6.0F, new Dilation(0.0F)), ModelTransform.pivot(3.5F, 25.5F, 1.0F));
|
||||
|
||||
ModelPartData left_leg = modelPartData.addChild("left_leg", ModelPartBuilder.create().uv(7, 30).mirrored().cuboid(-9.5F, -1.5F, -3.0F, 5.0F, 7.0F, 6.0F, new Dilation(0.0F)).mirrored(false), ModelTransform.pivot(3.5F, 25.5F, 1.0F));
|
||||
return TexturedModelData.of(modelData, 64, 64);
|
||||
}
|
||||
@Override
|
||||
public void setAngles(Entity entity, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch) {
|
||||
}
|
||||
@Override
|
||||
public void render(MatrixStack matrices, VertexConsumer vertexConsumer, int light, int overlay, float red, float green, float blue, float alpha) {
|
||||
lid.render(matrices, vertexConsumer, light, overlay, red, green, blue, alpha);
|
||||
lower_teeth.render(matrices, vertexConsumer, light, overlay, red, green, blue, alpha);
|
||||
right_leg.render(matrices, vertexConsumer, light, overlay, red, green, blue, alpha);
|
||||
left_leg.render(matrices, vertexConsumer, light, overlay, red, green, blue, alpha);
|
||||
}
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
{
|
||||
"parent": "minecraft:block/cube_all",
|
||||
"textures": {
|
||||
"all": "unicopia:block/slime_pustule",
|
||||
"particle": "unicopia:block/slime_pustule"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"from": [7, 14.9, 7],
|
||||
"to": [12, 16, 12],
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0, 6, 1.1], "texture": "#all"},
|
||||
"east": {"uv": [0, 0, 6, 1.1], "texture": "#all"},
|
||||
"south": {"uv": [0, 0, 6, 1.1], "texture": "#all"},
|
||||
"west": {"uv": [0, 0, 6, 1.1], "texture": "#all"},
|
||||
"up": {"uv": [0, 0, 6, 6], "texture": "#all"},
|
||||
"down": {"uv": [0, 0, 6, 6], "texture": "#all"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [3, 15, 4],
|
||||
"to": [9, 16, 10],
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0, 6, 1], "texture": "#all"},
|
||||
"east": {"uv": [0, 0, 6, 1], "texture": "#all"},
|
||||
"south": {"uv": [0, 0, 6, 1], "texture": "#all"},
|
||||
"west": {"uv": [0, 0, 6, 1], "texture": "#all"},
|
||||
"up": {"uv": [0, 0, 6, 6], "texture": "#all"},
|
||||
"down": {"uv": [0, 0, 6, 6], "texture": "#all"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "rope",
|
||||
"from": [7, 10, 7],
|
||||
"to": [9, 15, 9],
|
||||
"faces": {
|
||||
"north": {"uv": [1, 7, 5, 13], "texture": "#all"},
|
||||
"east": {"uv": [1, 7, 5, 13], "texture": "#all"},
|
||||
"south": {"uv": [1, 7, 5, 13], "texture": "#all"},
|
||||
"west": {"uv": [1, 7, 5, 13], "texture": "#all"},
|
||||
"up": {"uv": [2, 2, 4, 4], "texture": "#all"},
|
||||
"down": {"uv": [2, 2, 4, 4], "texture": "#all"}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,137 +0,0 @@
|
|||
{
|
||||
"parent": "minecraft:block/cube_all",
|
||||
"textures": {
|
||||
"all": "unicopia:block/slime_pustule",
|
||||
"particle": "unicopia:block/slime_pustule"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"name": "rope",
|
||||
"from": [7.5, 0, 7.5],
|
||||
"to": [8.5, 16, 8.5],
|
||||
"faces": {
|
||||
"north": {"uv": [12, 0, 13, 16], "texture": "#all"},
|
||||
"east": {"uv": [13, 0, 14, 16], "texture": "#all"},
|
||||
"south": {"uv": [15, 0, 16, 16], "texture": "#all"},
|
||||
"west": {"uv": [14, 0, 15, 16], "texture": "#all"},
|
||||
"up": {"uv": [13, 0, 14, 1], "texture": "#all"},
|
||||
"down": {"uv": [12, 0, 13, 1], "texture": "#all"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [7, 14.9, 7],
|
||||
"to": [12, 16, 12],
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0, 6, 1.1], "texture": "#all"},
|
||||
"east": {"uv": [0, 0, 6, 1.1], "texture": "#all"},
|
||||
"south": {"uv": [0, 0, 6, 1.1], "texture": "#all"},
|
||||
"west": {"uv": [0, 0, 6, 1.1], "texture": "#all"},
|
||||
"up": {"uv": [0, 0, 6, 6], "texture": "#all"},
|
||||
"down": {"uv": [0, 0, 6, 6], "texture": "#all"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"from": [3, 15, 4],
|
||||
"to": [9, 16, 10],
|
||||
"faces": {
|
||||
"north": {"uv": [0, 0, 6, 1], "texture": "#all"},
|
||||
"east": {"uv": [0, 0, 6, 1], "texture": "#all"},
|
||||
"south": {"uv": [0, 0, 6, 1], "texture": "#all"},
|
||||
"west": {"uv": [0, 0, 6, 1], "texture": "#all"},
|
||||
"up": {"uv": [0, 0, 6, 6], "texture": "#all"},
|
||||
"down": {"uv": [0, 0, 6, 6], "texture": "#all"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "rope",
|
||||
"from": [7, 10, 7],
|
||||
"to": [9, 15, 9],
|
||||
"faces": {
|
||||
"north": {"uv": [1, 7, 5, 13], "texture": "#all"},
|
||||
"east": {"uv": [1, 7, 5, 13], "texture": "#all"},
|
||||
"south": {"uv": [1, 7, 5, 13], "texture": "#all"},
|
||||
"west": {"uv": [1, 7, 5, 13], "texture": "#all"},
|
||||
"up": {"uv": [2, 2, 4, 4], "texture": "#all"},
|
||||
"down": {"uv": [2, 2, 4, 4], "texture": "#all"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "rope",
|
||||
"from": [7, 15, 7],
|
||||
"to": [9, 20, 9],
|
||||
"faces": {
|
||||
"north": {"uv": [2, 7, 4, 13], "texture": "#all"},
|
||||
"east": {"uv": [2, 7, 4, 13], "texture": "#all"},
|
||||
"south": {"uv": [2, 7, 4, 13], "texture": "#all"},
|
||||
"west": {"uv": [2, 7, 4, 13], "texture": "#all"},
|
||||
"up": {"uv": [2, 2, 4, 4], "texture": "#all"},
|
||||
"down": {"uv": [2, 2, 4, 4], "texture": "#all"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "drop",
|
||||
"from": [5, 10, 5],
|
||||
"to": [11, 13, 11],
|
||||
"faces": {
|
||||
"north": {"uv": [0, 6, 6, 9], "texture": "#all"},
|
||||
"east": {"uv": [0, 6, 6, 9], "texture": "#all"},
|
||||
"south": {"uv": [0, 6, 6, 9], "texture": "#all"},
|
||||
"west": {"uv": [0, 6, 6, 9], "texture": "#all"},
|
||||
"up": {"uv": [0, 0, 6, 6], "texture": "#all"},
|
||||
"down": {"uv": [0, 0, 6, 6], "texture": "#all"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "drop",
|
||||
"from": [6, 13, 6],
|
||||
"to": [10, 15, 10],
|
||||
"faces": {
|
||||
"north": {"uv": [0, 6, 6, 8], "texture": "#all"},
|
||||
"east": {"uv": [0, 6, 6, 8], "texture": "#all"},
|
||||
"south": {"uv": [0, 6, 6, 8], "texture": "#all"},
|
||||
"west": {"uv": [0, 6, 6, 8], "texture": "#all"},
|
||||
"up": {"uv": [0, 0, 6, 6], "texture": "#all"},
|
||||
"down": {"uv": [0, 0, 6, 6], "texture": "#all"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "drop",
|
||||
"from": [5, 0, 5],
|
||||
"to": [11, 1, 11],
|
||||
"faces": {
|
||||
"north": {"uv": [0, 13, 6, 14], "texture": "#all"},
|
||||
"east": {"uv": [0, 13, 6, 14], "texture": "#all"},
|
||||
"south": {"uv": [0, 13, 6, 14], "texture": "#all"},
|
||||
"west": {"uv": [0, 13, 6, 14], "texture": "#all"},
|
||||
"up": {"uv": [0, 0, 6, 6], "texture": "#all"},
|
||||
"down": {"uv": [0, 0, 6, 6], "texture": "#all"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "drop",
|
||||
"from": [4, 1, 4],
|
||||
"to": [12, 10, 12],
|
||||
"faces": {
|
||||
"north": {"uv": [0, 6, 6, 14], "texture": "#all"},
|
||||
"east": {"uv": [0, 6, 6, 14], "texture": "#all"},
|
||||
"south": {"uv": [0, 6, 6, 14], "texture": "#all"},
|
||||
"west": {"uv": [0, 6, 6, 14], "texture": "#all"},
|
||||
"up": {"uv": [0, 0, 6, 6], "texture": "#all"},
|
||||
"down": {"uv": [0, 0, 6, 6], "texture": "#all"}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "drop",
|
||||
"from": [5, 2, 5],
|
||||
"to": [11, 9, 11],
|
||||
"faces": {
|
||||
"north": {"uv": [7, 7, 11, 13], "texture": "#all"},
|
||||
"east": {"uv": [7, 7, 11, 13], "texture": "#all"},
|
||||
"south": {"uv": [7, 7, 11, 13], "texture": "#all"},
|
||||
"west": {"uv": [7, 7, 11, 13], "texture": "#all"},
|
||||
"up": {"uv": [7, 1, 11, 5], "texture": "#all"},
|
||||
"down": {"uv": [7, 1, 11, 5], "texture": "#all"}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
1
assets/models/tentacle.bbmodel
Normal file
BIN
assets/models/tentacle.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
assets/spectral_clock_0.xcf
Normal file
BIN
assets/zap_planks.xcf
Normal file
66
build.gradle
|
@ -1,15 +1,14 @@
|
|||
buildscript {
|
||||
dependencies {
|
||||
classpath 'com.github.dexman545:Outlet:1.3.10'
|
||||
classpath 'com.github.dexman545:Outlet:1.6.1'
|
||||
}
|
||||
}
|
||||
plugins {
|
||||
id 'java-library'
|
||||
id 'fabric-loom' version '0.12-SNAPSHOT'
|
||||
id 'fabric-loom' version '1.5-SNAPSHOT'
|
||||
id 'com.modrinth.minotaur' version '2.+'
|
||||
id 'org.ajoberstar.reckon' version '0.13.0'
|
||||
id 'org.ajoberstar.reckon' version '0.13.1'
|
||||
}
|
||||
apply plugin: 'dex.plugins.outlet'
|
||||
apply plugin: 'io.github.dexman545.outlet'
|
||||
|
||||
java {
|
||||
toolchain {
|
||||
|
@ -30,6 +29,12 @@ loom {
|
|||
accessWidenerPath = file('src/main/resources/unicopia.aw')
|
||||
}
|
||||
|
||||
fabricApi {
|
||||
configureDataGeneration {
|
||||
modId = 'unicopia'
|
||||
}
|
||||
}
|
||||
|
||||
reckon {
|
||||
scopeFromProp()
|
||||
stageFromProp 'beta', 'rc', 'final'
|
||||
|
@ -38,12 +43,17 @@ reckon {
|
|||
repositories {
|
||||
mavenLocal()
|
||||
flatDir { dirs 'lib' }
|
||||
maven { name 'entity-reach-attributes'; url 'https://maven.jamieswhiteshirt.com/libs-release' }
|
||||
maven { name 'entity-reach-attributes'; url 'https://maven.jamieswhiteshirt.com/libs-release'; content { includeGroup "com.jamieswhiteshirt" } }
|
||||
maven { name 'trinkets'; url 'https://maven.ladysnake.org/releases' }
|
||||
maven { name 'mod-menu'; url 'https://maven.terraformersmc.com/' }
|
||||
maven { name 'minelp-snapshot'; url 'https://repo.minelittlepony-mod.com/maven/snapshot' }
|
||||
maven { name 'minelp-releases'; url 'https://repo.minelittlepony-mod.com/maven/release' }
|
||||
maven { name 'TerraformersMC'; url 'https://maven.terraformersmc.com/' }
|
||||
maven { name 'Nodium'; url 'https://maven.cafeteria.dev/releases/' }
|
||||
maven { name 'Greenhouse Maven For Farmers delight'; url 'https://maven.greenhouseteam.dev/releases/' }
|
||||
maven { name 'Porting Lib For Farmers delight'; url = 'https://mvn.devos.one/releases/' }
|
||||
maven { name 'Modrinth'; url 'https://api.modrinth.com/maven' }
|
||||
maven { name 'JitPack'; url 'https://jitpack.io'; content { includeGroup "com.github.Virtuoel" } }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
@ -67,22 +77,49 @@ dependencies {
|
|||
include "com.sollace:Romanizer:Romanizer:1.0.2"
|
||||
|
||||
modCompileOnly "com.terraformersmc:modmenu:${project.modmenu_version}"
|
||||
modCompileOnly "dev.emi:trinkets:${project.trinkets_version}"
|
||||
|
||||
if (project.use_trinkets == '1') {
|
||||
modCompileOnly "dev.emi:trinkets:${project.trinkets_version}"
|
||||
modCompileOnly "dev.onyxstudios.cardinal-components-api:cardinal-components-base:5.3.0"
|
||||
modCompileOnly "dev.onyxstudios.cardinal-components-api:cardinal-components-entity:5.3.0"
|
||||
} else {
|
||||
modCompileOnly "dev.emi:trinkets-dummy:${project.trinkets_version}"
|
||||
}
|
||||
|
||||
modImplementation "com.terraformersmc.terraform-api:terraform-wood-api-v1:${project.terraformer_api_version}"
|
||||
include "com.terraformersmc.terraform-api:terraform-wood-api-v1:${project.terraformer_api_version}"
|
||||
|
||||
modImplementation "me.luligabi:NoIndium:${project.nodium_version}"
|
||||
include "me.luligabi:NoIndium:${project.nodium_version}"
|
||||
|
||||
//modImplementation "vectorwing:FarmersDelight-Refabricated:${project.farmers_delight_version}", {
|
||||
// exclude group: "net.fabricmc"
|
||||
//}
|
||||
if (project.use_pehkui == '1') {
|
||||
modCompileOnly "maven.modrinth:pehkui:${project.pehkui_version}", { exclude group: "net.fabricmc.fabric-api" }
|
||||
modCompileOnly "com.github.Virtuoel:KanosConfig:0.4.1", { exclude group: "net.fabricmc.fabric-api" }
|
||||
}
|
||||
|
||||
if (project.use_sodium == '1') {
|
||||
modCompileOnly "maven.modrinth:indium:${project.indium_version}", { exclude group: "net.fabricmc.fabric-api" }
|
||||
modCompileOnly "maven.modrinth:sodium:${project.sodium_version}", { exclude group: "net.fabricmc.fabric-api" }
|
||||
if (project.use_iris == '1') {
|
||||
modCompileOnly "maven.modrinth:iris:${project.iris_version}", { exclude group: "net.fabricmc.fabric-api" }
|
||||
modImplementation "org.anarres:jcpp:1.4.14"
|
||||
modImplementation "org.antlr:antlr4-runtime:4.13.1"
|
||||
modImplementation "io.github.douira:glsl-transformer:2.0.1"
|
||||
}
|
||||
}
|
||||
|
||||
if (project.tmi_type == 'emi') {
|
||||
modCompileOnly "dev.emi:emi-fabric:${project.emi_version}"
|
||||
} else {
|
||||
modCompileOnly "dev.emi:emi-fabric-dummy:${project.emi_version}"
|
||||
}
|
||||
}
|
||||
|
||||
if (project.tmi_type == 'rei') {
|
||||
// TODO:
|
||||
} else {
|
||||
// TODO:
|
||||
}
|
||||
remapJar {
|
||||
addNestedDependencies = true
|
||||
}
|
||||
|
||||
processResources {
|
||||
|
@ -121,6 +158,9 @@ modrinth {
|
|||
gameVersions.add ver
|
||||
}
|
||||
dependencies {
|
||||
required.project '9K7RJlvM'
|
||||
required.project 'P7dR8mSH'
|
||||
optional.project '5aaWibi9'
|
||||
optional.project 'JBjInUXM'
|
||||
optional.project 'fRiHVvU7'
|
||||
}
|
||||
}
|
||||
|
|
3
crowdin.yml
Normal file
|
@ -0,0 +1,3 @@
|
|||
files:
|
||||
- source: src/main/resources/assets/unicopia/lang/en_us.json
|
||||
translation: /%original_path%/%locale_with_underscore%.%file_extension%
|
|
@ -3,10 +3,10 @@ org.gradle.daemon=false
|
|||
|
||||
# Fabric Properties
|
||||
# check these on https://fabricmc.net/develop
|
||||
minecraft_version=1.20.1
|
||||
yarn_mappings=1.20.1+build.9
|
||||
loader_version=0.14.21
|
||||
fabric_version=0.85.0+1.20.1
|
||||
minecraft_version=1.20.2
|
||||
yarn_mappings=1.20.2+build.4
|
||||
loader_version=0.15.7
|
||||
fabric_version=0.91.6+1.20.2
|
||||
|
||||
# Mod Properties
|
||||
group=com.minelittlepony
|
||||
|
@ -15,19 +15,32 @@ org.gradle.daemon=false
|
|||
description=Magical Abilities for Mine Little Pony!
|
||||
|
||||
# Publishing
|
||||
minecraft_version_range=>=1.20.1
|
||||
minecraft_version_range=1.20.2
|
||||
modrinth_loader_type=fabric
|
||||
modrinth_project_id=9K7RJlvM
|
||||
|
||||
# Dependencies
|
||||
fabwork_version=1.2.0
|
||||
modmenu_version=7.0.0-beta.2
|
||||
minelp_version=4.10.1+1.20
|
||||
kirin_version=1.15.4+1.20
|
||||
reach_attributes_version=2.3.3
|
||||
trinkets_version=3.7.1
|
||||
terraformer_api_version=7.0.0-beta.1
|
||||
fabwork_version=1.3.0+1.20.2
|
||||
modmenu_version=8.0.0-beta.1
|
||||
minelp_version=4.11.6+1.20.2
|
||||
kirin_version=1.16.1+1.20.2
|
||||
reach_attributes_version=2.3.4
|
||||
trinkets_version=3.8.0
|
||||
terraformer_api_version=8.0.0-beta.1
|
||||
nodium_version=1.1.0+1.20
|
||||
|
||||
# Testing
|
||||
use_trinkets=1
|
||||
use_pehkui=0
|
||||
use_sodium=0
|
||||
use_iris=1
|
||||
|
||||
farmers_delight_version=1.20.1-2.0.9
|
||||
pehkui_version=3.7.8+1.14.4-1.20.2
|
||||
iris_version=1.6.17+1.20.2
|
||||
sodium_version=mc1.20.2-0.5.5
|
||||
indium_version=1.0.30+mc1.20.4
|
||||
|
||||
# TMI Testing
|
||||
tmi_type=emi
|
||||
emi_version=1.0.19+1.20.1
|
||||
emi_version=1.0.21+1.20.2
|
||||
|
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
|
@ -1,5 +1,5 @@
|
|||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
|
BIN
lib/emi-fabric-dummy-1.0.20+1.20.1.jar
Normal file
BIN
lib/reach-entity-attributes-2.3.4.jar
Normal file
BIN
lib/trinkets-dummy-3.8.0.jar
Normal file
|
@ -1,12 +1,20 @@
|
|||
package com.minelittlepony.unicopia;
|
||||
|
||||
import net.minecraft.util.Formatting;
|
||||
import java.util.Locale;
|
||||
|
||||
public enum Affinity {
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.Formatting;
|
||||
import net.minecraft.util.StringIdentifiable;
|
||||
import net.minecraft.util.Util;
|
||||
|
||||
public enum Affinity implements StringIdentifiable {
|
||||
GOOD(Formatting.BLUE, -1, 0),
|
||||
NEUTRAL(Formatting.LIGHT_PURPLE, 0, 0.5F),
|
||||
BAD(Formatting.RED, 1, 1);
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public static final EnumCodec<Affinity> CODEC = StringIdentifiable.createCodec(Affinity::values);
|
||||
|
||||
private final Formatting color;
|
||||
|
||||
private final int corruption;
|
||||
|
@ -14,10 +22,18 @@ public enum Affinity {
|
|||
|
||||
public static final Affinity[] VALUES = values();
|
||||
|
||||
private final String translationKey;
|
||||
|
||||
Affinity(Formatting color, int corruption, float alignment) {
|
||||
this.color = color;
|
||||
this.corruption = corruption;
|
||||
this.alignment = alignment;
|
||||
this.translationKey = Util.createTranslationKey("affinity", Unicopia.id(name().toLowerCase(Locale.ROOT)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String asString() {
|
||||
return name().toLowerCase(Locale.ROOT);
|
||||
}
|
||||
|
||||
public Formatting getColor() {
|
||||
|
@ -25,7 +41,11 @@ public enum Affinity {
|
|||
}
|
||||
|
||||
public String getTranslationKey() {
|
||||
return this == BAD ? "curse" : "spell";
|
||||
return translationKey;
|
||||
}
|
||||
|
||||
public Text getDisplayName() {
|
||||
return Text.translatable(getTranslationKey()).formatted(getColor());
|
||||
}
|
||||
|
||||
public int getCorruption() {
|
||||
|
|
57
src/main/java/com/minelittlepony/unicopia/AllowList.java
Normal file
|
@ -0,0 +1,57 @@
|
|||
package com.minelittlepony.unicopia;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public class AllowList {
|
||||
public static final AllowList INSTANCE = new AllowList();
|
||||
|
||||
public AllowList() {
|
||||
|
||||
}
|
||||
|
||||
public boolean disable() {
|
||||
if (!isEnabled()) {
|
||||
return false;
|
||||
}
|
||||
Unicopia.getConfig().speciesWhiteList.get().clear();
|
||||
Unicopia.getConfig().save();
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return !Unicopia.getConfig().speciesWhiteList.get().isEmpty();
|
||||
}
|
||||
|
||||
public boolean add(Race race) {
|
||||
if (race.isUnset() || race.isHuman()) {
|
||||
return false;
|
||||
}
|
||||
Set<String> values = Unicopia.getConfig().speciesWhiteList.get();
|
||||
boolean added = values.add(race.getId().toString());
|
||||
Unicopia.getConfig().save();
|
||||
return added;
|
||||
}
|
||||
|
||||
public boolean remove(Race race) {
|
||||
Set<String> values = Unicopia.getConfig().speciesWhiteList.get();
|
||||
if (values.isEmpty()) {
|
||||
for (Race r : Race.REGISTRY) {
|
||||
if (!r.isUnset() && r != race) {
|
||||
values.add(r.getId().toString());
|
||||
}
|
||||
}
|
||||
Unicopia.getConfig().save();
|
||||
return true;
|
||||
}
|
||||
boolean removed = values.remove(race.getId().toString());
|
||||
Unicopia.getConfig().save();
|
||||
return removed;
|
||||
}
|
||||
|
||||
public boolean permits(Race race) {
|
||||
return race.isUnset()
|
||||
|| race.isHuman()
|
||||
|| !isEnabled()
|
||||
|| Unicopia.getConfig().speciesWhiteList.get().contains(race.getId().toString());
|
||||
}
|
||||
}
|
|
@ -1,10 +1,24 @@
|
|||
package com.minelittlepony.unicopia;
|
||||
|
||||
public enum Availability {
|
||||
import java.util.Locale;
|
||||
|
||||
import net.minecraft.util.StringIdentifiable;
|
||||
|
||||
public enum Availability implements StringIdentifiable {
|
||||
DEFAULT,
|
||||
COMMANDS,
|
||||
NONE;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public static final EnumCodec<Availability> CODEC = StringIdentifiable.createCodec(Availability::values);
|
||||
|
||||
private final String name = name().toLowerCase(Locale.ROOT);
|
||||
|
||||
@Override
|
||||
public String asString() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public boolean isSelectable() {
|
||||
return this == DEFAULT;
|
||||
}
|
||||
|
|
|
@ -15,9 +15,11 @@ public class Config extends com.minelittlepony.common.util.settings.Config {
|
|||
.addComment("whilst any ones left off are not permitted")
|
||||
.addComment("An empty list disables whitelisting entirely.");
|
||||
|
||||
@Deprecated
|
||||
public final Setting<Set<String>> wantItNeedItEntityExcludelist = value("server", "wantItNeedItEntityExcludelist", (Set<String>)new HashSet<>(Set.of("minecraft:creeper")))
|
||||
.addComment("A list of entity types that are immune to the want it need it spell's effects");
|
||||
|
||||
@Deprecated
|
||||
public final Setting<Set<String>> dimensionsWithoutAtmosphere = value("server", "dimensionsWithoutAtmosphere", (Set<String>)new HashSet<String>())
|
||||
.addComment("A list of dimensions ids that do not have an atmosphere, and thus shouldn't allow pegasi to fly.");
|
||||
|
||||
|
@ -34,6 +36,9 @@ public class Config extends com.minelittlepony.common.util.settings.Config {
|
|||
.addComment("If true Mine Little Pony will not be considered when determining the race to use")
|
||||
.addComment("The result will always be what is set by this config file.");
|
||||
|
||||
public final Setting<Boolean> toggleAbilityKeys = value("client", "toggleAbilityKeys", false)
|
||||
.addComment("If true the ability keybinds will function as toggle keys rather than hold keys");
|
||||
|
||||
public final Setting<Integer> hudPage = value("client", "hudActivePage", 0)
|
||||
.addComment("The page of abilities currently visible in the HUD. You can change this in-game using the PG_UP and PG_DWN keys (configurable)");
|
||||
|
||||
|
@ -45,9 +50,26 @@ public class Config extends com.minelittlepony.common.util.settings.Config {
|
|||
.addComment("Removes butterflies from spawning in your world")
|
||||
.addComment("Turn this ON if you have another mod that adds butterflies.");
|
||||
|
||||
public final Setting<Boolean> simplifiedPortals = value("compatibility", "simplifiedPortals", false)
|
||||
.addComment("Disables dynamic portal rendering");
|
||||
|
||||
public final Setting<Boolean> disableShaders = value("compatibility", "disableShaders", false)
|
||||
.addComment("Disables post-effect shaders used by the corruption mechanic");
|
||||
|
||||
public final Setting<Long> fancyPortalRefreshRate = value("client", "fancyPortalRefreshRate", -1L)
|
||||
.addComment("Sets the refresh rate of portals when using fancy portal rendering")
|
||||
.addComment("Set to -1 (default) for unlimited");
|
||||
|
||||
public final Setting<Integer> maxPortalRecursion = value("client", "maxPortalRecursion", 2)
|
||||
.addComment("Sets the maximum depth to reach when rendering portals through portals");
|
||||
|
||||
public Config() {
|
||||
super(new HeirarchicalJsonConfigAdapter(new GsonBuilder()
|
||||
.registerTypeAdapter(Race.class, RegistryTypeAdapter.of(Race.REGISTRY))
|
||||
), GamePaths.getConfigDirectory().resolve("unicopia.json"));
|
||||
}
|
||||
|
||||
public SyncedConfig toSynced() {
|
||||
return new SyncedConfig(wantItNeedItEntityExcludelist.get(), dimensionsWithoutAtmosphere.get());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,33 +1,35 @@
|
|||
package com.minelittlepony.unicopia;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits;
|
||||
import com.minelittlepony.unicopia.entity.mob.AirBalloonEntity;
|
||||
import com.minelittlepony.unicopia.entity.mob.UEntities;
|
||||
|
||||
import net.minecraft.entity.vehicle.BoatEntity;
|
||||
import net.minecraft.registry.Registries;
|
||||
import net.minecraft.registry.tag.TagKey;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.dimension.DimensionTypes;
|
||||
|
||||
public interface Debug {
|
||||
boolean SPELLBOOK_CHAPTERS = Boolean.getBoolean("unicopia.debug.spellbookChapters");
|
||||
boolean CHECK_GAME_VALUES = Boolean.getBoolean("unicopia.debug.checkGameValues");
|
||||
boolean CHECK_TRAIT_COVERAGE = Boolean.getBoolean("unicopia.debug.checkTraitCoverage");
|
||||
|
||||
boolean[] TESTS_COMPLETE = {false};
|
||||
AtomicReference<World> LAST_TESTED_WORLD = new AtomicReference<>(null);
|
||||
|
||||
static void runTests(World world) {
|
||||
if (!CHECK_GAME_VALUES || TESTS_COMPLETE[0]) {
|
||||
if (!CHECK_GAME_VALUES || !world.getDimensionKey().getValue().equals(DimensionTypes.OVERWORLD_ID) || (LAST_TESTED_WORLD.getAndSet(world) == world)) {
|
||||
return;
|
||||
}
|
||||
TESTS_COMPLETE[0] = true;
|
||||
|
||||
try {
|
||||
Registries.ITEM.getEntrySet().forEach(entry -> {
|
||||
if (SpellTraits.of(entry.getValue()).isEmpty()) {
|
||||
// Unicopia.LOGGER.warn("No traits registered for item {}", entry.getKey());
|
||||
}
|
||||
});
|
||||
} catch (Throwable t) {
|
||||
throw new IllegalStateException("Tests failed", t);
|
||||
if (CHECK_TRAIT_COVERAGE) {
|
||||
testTraitCoverage();
|
||||
}
|
||||
|
||||
try {
|
||||
|
@ -40,4 +42,30 @@ public interface Debug {
|
|||
throw new IllegalStateException("Tests failed", t);
|
||||
}
|
||||
}
|
||||
|
||||
private static void testTraitCoverage() {
|
||||
Registries.ITEM.getEntrySet().stream().collect(Collectors.toMap(
|
||||
entry -> entry.getKey().getValue().getNamespace(),
|
||||
Set::of,
|
||||
Sets::union
|
||||
)).forEach((namespace, entries) -> {
|
||||
@SuppressWarnings("deprecation")
|
||||
var unregistered = entries.stream()
|
||||
.filter(entry -> !entry.getValue().getRegistryEntry().isIn(UTags.Items.HAS_NO_TRAITS) && SpellTraits.of(entry.getValue()).isEmpty())
|
||||
.map(entry -> {
|
||||
String id = entry.getKey().getValue().toString();
|
||||
|
||||
return id + "(" + Registries.ITEM.streamTags()
|
||||
.filter(entry.getValue().getRegistryEntry()::isIn)
|
||||
.map(TagKey::id)
|
||||
.map(Identifier::toString)
|
||||
.collect(Collectors.joining(", ")) + ")";
|
||||
})
|
||||
.toList();
|
||||
|
||||
if (!unregistered.isEmpty()) {
|
||||
Unicopia.LOGGER.warn("No traits registered for {} items in namepsace {} {}", unregistered.size(), namespace, String.join(",\r\n", unregistered));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ public interface EntityConvertable<E extends Entity> extends WorldConvertable {
|
|||
* Gets the center position where this caster is located.
|
||||
*/
|
||||
default Vec3d getOriginVector() {
|
||||
return asEntity().getPos();
|
||||
return asEntity().getPos().add(0, asEntity().getHeight() * 0.5F, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -22,14 +22,19 @@ public interface EquineContext {
|
|||
}
|
||||
|
||||
default boolean collidesWithClouds() {
|
||||
return getCompositeRace().any(Race::canInteractWithClouds);
|
||||
return getCompositeRace().canInteractWithClouds() || getCloudWalkingStrength() >= 1;
|
||||
}
|
||||
|
||||
default boolean hasFeatherTouch() {
|
||||
return false;
|
||||
}
|
||||
|
||||
static EquineContext of(ShapeContext context) {
|
||||
if (context == ShapeContext.absent()) {
|
||||
return Unicopia.SIDE.getPony().map(EquineContext.class::cast).orElse(ABSENT);
|
||||
return InteractionManager.getInstance().getEquineContext();
|
||||
}
|
||||
return context instanceof EquineContext c ? c : ABSENT;
|
||||
EquineContext result = context instanceof Container c ? c.get() : ABSENT;
|
||||
return result == null ? ABSENT : result;
|
||||
}
|
||||
|
||||
static EquineContext of(ItemUsageContext context) {
|
||||
|
@ -42,4 +47,8 @@ public interface EquineContext {
|
|||
}
|
||||
return MoreObjects.firstNonNull(Equine.of(entity).orElse(null), ABSENT);
|
||||
}
|
||||
|
||||
interface Container {
|
||||
EquineContext get();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,8 @@ import com.minelittlepony.unicopia.item.enchantment.WantItNeedItEnchantment;
|
|||
import net.minecraft.entity.*;
|
||||
import net.minecraft.entity.decoration.AbstractDecorationEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.projectile.ProjectileEntity;
|
||||
import net.minecraft.entity.vehicle.BoatEntity;
|
||||
import net.minecraft.predicate.entity.EntityPredicates;
|
||||
|
||||
public interface EquinePredicates {
|
||||
|
@ -18,7 +20,7 @@ public interface EquinePredicates {
|
|||
Predicate<Entity> BAT = physicalRaceMatches(Race.BAT::equals);
|
||||
Predicate<Entity> CHANGELING = physicalRaceMatches(Race.CHANGELING::equals);
|
||||
|
||||
Predicate<Entity> RACE_INTERACT_WITH_CLOUDS = raceMatches(Race::canInteractWithClouds);
|
||||
Predicate<Entity> RACE_CAN_INFLUENCE_WEATHER = raceMatches(Race::canInfluenceWeather);
|
||||
Predicate<Entity> RAGING = IS_PLAYER.and(SpellType.RAGE::isOn);
|
||||
|
||||
Predicate<Entity> PLAYER_EARTH = IS_PLAYER.and(ofRace(Race.EARTH));
|
||||
|
@ -26,14 +28,19 @@ public interface EquinePredicates {
|
|||
Predicate<Entity> PLAYER_UNICORN = IS_PLAYER.and(raceMatches(Race::canCast));
|
||||
Predicate<Entity> PLAYER_CHANGELING = IS_PLAYER.and(ofRace(Race.CHANGELING));
|
||||
Predicate<Entity> PLAYER_KIRIN = IS_PLAYER.and(ofRace(Race.KIRIN));
|
||||
Predicate<Entity> PLAYER_PEGASUS = IS_PLAYER.and(e -> ((PlayerEntity)e).getAbilities().creativeMode || RACE_INTERACT_WITH_CLOUDS.test(e));
|
||||
Predicate<Entity> PLAYER_SEAPONY = IS_PLAYER.and(raceMatches(Race::isFish));
|
||||
|
||||
Predicate<Entity> PLAYER_CAN_USE_EARTH = IS_PLAYER.and(raceMatches(Race::canUseEarth));
|
||||
Predicate<Entity> IS_CASTER = e -> !e.isRemoved() && (e instanceof Caster || IS_PLAYER.test(e));
|
||||
Predicate<Entity> IS_PLACED_SPELL = e -> e instanceof Caster && !e.isRemoved();
|
||||
|
||||
Predicate<Entity> IS_MAGIC_IMMUNE = e -> (e instanceof MagicImmune || !(e instanceof LivingEntity)) && !(e instanceof ItemEntity);
|
||||
Predicate<Entity> IS_MAGIC_IMMUNE = EntityPredicates.VALID_ENTITY.negate()
|
||||
.or(EntityPredicates.EXCEPT_CREATIVE_OR_SPECTATOR.negate()
|
||||
.or(e -> (e instanceof MagicImmune || !(e instanceof LivingEntity))
|
||||
&& !(e instanceof ItemEntity)
|
||||
&& !(e instanceof ExperienceOrbEntity)
|
||||
&& !(e instanceof BoatEntity)
|
||||
&& !(e instanceof ProjectileEntity)));
|
||||
Predicate<Entity> EXCEPT_MAGIC_IMMUNE = IS_MAGIC_IMMUNE.negate();
|
||||
Predicate<Entity> VALID_LIVING_AND_NOT_MAGIC_IMMUNE = EntityPredicates.VALID_LIVING_ENTITY.and(EXCEPT_MAGIC_IMMUNE);
|
||||
|
||||
|
|
|
@ -1,15 +1,28 @@
|
|||
package com.minelittlepony.unicopia;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.sound.SoundEvent;
|
||||
import net.minecraft.util.StringIdentifiable;
|
||||
|
||||
public enum FlightType {
|
||||
public enum FlightType implements StringIdentifiable {
|
||||
UNSET,
|
||||
NONE,
|
||||
AVIAN,
|
||||
INSECTOID,
|
||||
ARTIFICIAL;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public static final EnumCodec<FlightType> CODEC = StringIdentifiable.createCodec(FlightType::values);
|
||||
|
||||
private final String name = name().toLowerCase(Locale.ROOT);
|
||||
|
||||
@Override
|
||||
public String asString() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public boolean isGrounded() {
|
||||
return this == NONE;
|
||||
}
|
||||
|
|
|
@ -2,21 +2,23 @@ package com.minelittlepony.unicopia;
|
|||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Stack;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.minelittlepony.unicopia.ability.magic.CasterView;
|
||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
import com.minelittlepony.unicopia.entity.player.dummy.DummyPlayerEntity;
|
||||
import com.minelittlepony.unicopia.server.world.Ether;
|
||||
import com.minelittlepony.unicopia.particle.ParticleSpawner;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.world.BlockView;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class InteractionManager {
|
||||
|
@ -31,17 +33,23 @@ public class InteractionManager {
|
|||
|
||||
public static final int SCREEN_DISPELL_ABILITY = 0;
|
||||
|
||||
public static InteractionManager INSTANCE = new InteractionManager();
|
||||
private static InteractionManager INSTANCE = new InteractionManager();
|
||||
|
||||
public static InteractionManager instance() {
|
||||
@Nullable
|
||||
private SyncedConfig config;
|
||||
|
||||
private final Stack<EquineContext> equineContext = new Stack<>();
|
||||
|
||||
public static InteractionManager getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
public Optional<CasterView> getCasterView(BlockView view) {
|
||||
if (view instanceof ServerWorld world) {
|
||||
return Optional.of(Ether.get(world));
|
||||
}
|
||||
return Optional.empty();
|
||||
public InteractionManager() {
|
||||
INSTANCE = this;
|
||||
}
|
||||
|
||||
public ParticleSpawner createBoundParticle(UUID id) {
|
||||
return ParticleSpawner.EMPTY;
|
||||
}
|
||||
|
||||
public Map<Identifier, ?> readChapters(PacketByteBuf buf) {
|
||||
|
@ -92,4 +100,49 @@ public class InteractionManager {
|
|||
public PlayerEntity createPlayer(World world, GameProfile profile) {
|
||||
return new DummyPlayerEntity(world, profile);
|
||||
}
|
||||
|
||||
public void sendPlayerLookAngles(PlayerEntity player) {
|
||||
|
||||
}
|
||||
|
||||
public void addBlockBreakingParticles(BlockPos pos, Direction direction) {
|
||||
|
||||
}
|
||||
|
||||
public void setEquineContext(EquineContext context) {
|
||||
equineContext.push(context);
|
||||
}
|
||||
|
||||
public void clearEquineContext() {
|
||||
if (!equineContext.isEmpty()) {
|
||||
equineContext.pop();
|
||||
}
|
||||
}
|
||||
|
||||
public EquineContext getEquineContext() {
|
||||
return getClientPony().map(EquineContext.class::cast).orElseGet(this::getPathingEquineContext);
|
||||
}
|
||||
|
||||
public EquineContext getPathingEquineContext() {
|
||||
return equineContext.isEmpty() ? EquineContext.ABSENT : equineContext.peek();
|
||||
}
|
||||
|
||||
public Optional<Pony> getClientPony() {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
public final Race getClientSpecies() {
|
||||
return getClientPony().map(Pony::getSpecies).orElse(Race.HUMAN);
|
||||
}
|
||||
|
||||
public void setSyncedConfig(SyncedConfig config) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
public SyncedConfig getSyncedConfig() {
|
||||
if (config == null) {
|
||||
config = Unicopia.getConfig().toSynced();
|
||||
}
|
||||
return config;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,8 @@ import java.util.UUID;
|
|||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.minelittlepony.unicopia.item.FriendshipBraceletItem;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
|
||||
/**
|
||||
|
@ -27,18 +29,31 @@ public interface Owned<E extends Entity> {
|
|||
* Since {@link Owned#getMaster()} will only return if the owner is loaded, use this to perform checks
|
||||
* in the owner's absence.
|
||||
*/
|
||||
default Optional<UUID> getMasterId() {
|
||||
return Optional.of(getMaster()).map(Entity::getUuid);
|
||||
Optional<UUID> getMasterId();
|
||||
|
||||
default boolean isOwnerOrFriend(Entity target) {
|
||||
return isFriend(target) || isOwnerOrVehicle(target);
|
||||
}
|
||||
|
||||
default boolean isFriend(Entity target) {
|
||||
return FriendshipBraceletItem.isComrade(this, target);
|
||||
}
|
||||
|
||||
default boolean isOwnerOrVehicle(@Nullable Entity target) {
|
||||
if (isOwnedBy(target)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Entity owner = getMaster();
|
||||
return target != null && owner != null && owner.isConnectedThroughVehicle(target);
|
||||
}
|
||||
|
||||
default boolean isOwnedBy(@Nullable Object owner) {
|
||||
return owner instanceof Entity e
|
||||
&& getMasterId().isPresent()
|
||||
&& e.getUuid().equals(getMasterId().get());
|
||||
return owner instanceof Entity e && e.getUuid().equals(getMasterId().orElse(null));
|
||||
}
|
||||
|
||||
default boolean hasCommonOwner(Owned<?> sibling) {
|
||||
return getMasterId().isPresent() && getMasterId().equals(sibling.getMasterId());
|
||||
return getMasterId().equals(sibling.getMasterId());
|
||||
}
|
||||
|
||||
interface Mutable<E extends Entity> {
|
||||
|
|
|
@ -1,72 +1,113 @@
|
|||
package com.minelittlepony.unicopia;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.spongepowered.include.com.google.common.base.Objects;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.base.Suppliers;
|
||||
import com.minelittlepony.unicopia.ability.Abilities;
|
||||
import com.minelittlepony.unicopia.ability.Ability;
|
||||
import com.minelittlepony.unicopia.ability.magic.Affine;
|
||||
import com.minelittlepony.unicopia.network.track.TrackableDataType;
|
||||
import com.minelittlepony.unicopia.util.RegistryUtils;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import com.mojang.brigadier.exceptions.DynamicCommandExceptionType;
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
|
||||
import net.minecraft.command.argument.RegistryKeyArgumentType;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.server.command.ServerCommandSource;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.Util;
|
||||
import net.minecraft.registry.Registry;
|
||||
import net.minecraft.registry.RegistryKey;
|
||||
|
||||
public record Race (Supplier<Composite> compositeSupplier, Availability availability, boolean canCast, FlightType flightType, boolean canUseEarth, boolean isNocturnal, boolean canHang) implements Affine {
|
||||
public record Race (
|
||||
List<Ability<?>> abilities,
|
||||
Affinity affinity,
|
||||
Availability availability,
|
||||
FlightType flightType,
|
||||
boolean canCast,
|
||||
boolean hasIronGut,
|
||||
boolean canUseEarth,
|
||||
boolean isNocturnal,
|
||||
boolean canHang,
|
||||
boolean isFish,
|
||||
boolean canInfluenceWeather,
|
||||
boolean canInteractWithClouds
|
||||
) implements Affine {
|
||||
public static final String DEFAULT_ID = "unicopia:unset";
|
||||
public static final Registry<Race> REGISTRY = RegistryUtils.createDefaulted(Unicopia.id("race"), DEFAULT_ID);
|
||||
public static final Registry<Race> COMMAND_REGISTRY = RegistryUtils.createDefaulted(Unicopia.id("race/grantable"), DEFAULT_ID);
|
||||
public static final TrackableDataType<Race> TRACKABLE_TYPE = TrackableDataType.RACE;
|
||||
public static final RegistryKey<? extends Registry<Race>> REGISTRY_KEY = REGISTRY.getKey();
|
||||
private static final DynamicCommandExceptionType UNKNOWN_RACE_EXCEPTION = new DynamicCommandExceptionType(id -> Text.translatable("race.unknown", id));
|
||||
private static final DynamicCommandExceptionType UNKNOWN_RACE_EXCEPTION = new DynamicCommandExceptionType(id -> Text.translatable("commands.race.fail", id));
|
||||
private static final Function<Race, Composite> COMPOSITES = Util.memoize(race -> new Composite(race, null, null));
|
||||
|
||||
public static Race register(String name, Availability availability, boolean magic, FlightType flight, boolean earth, boolean nocturnal, boolean canHang) {
|
||||
return register(Unicopia.id(name), availability, magic, flight, earth, nocturnal, canHang);
|
||||
}
|
||||
|
||||
public static Race register(Identifier id, Availability availability, boolean magic, FlightType flight, boolean earth, boolean nocturnal, boolean canHang) {
|
||||
Race race = Registry.register(REGISTRY, id, new Race(Suppliers.memoize(() -> new Composite(REGISTRY.get(id), null, null)), availability, magic, flight, earth, nocturnal, canHang));
|
||||
if (availability.isGrantable()) {
|
||||
Registry.register(COMMAND_REGISTRY, id, race);
|
||||
}
|
||||
return race;
|
||||
}
|
||||
|
||||
public static RegistryKeyArgumentType<Race> argument() {
|
||||
return RegistryKeyArgumentType.registryKey(COMMAND_REGISTRY.getKey());
|
||||
}
|
||||
public static final Codec<Race> CODEC = RecordCodecBuilder.create(i -> i.group(
|
||||
Abilities.REGISTRY.getCodec().listOf().fieldOf("abilities").forGetter(Race::abilities),
|
||||
Affinity.CODEC.fieldOf("affinity").forGetter(Race::affinity),
|
||||
Availability.CODEC.fieldOf("availability").forGetter(Race::availability),
|
||||
FlightType.CODEC.fieldOf("flight").forGetter(Race::flightType),
|
||||
Codec.BOOL.fieldOf("magic").forGetter(Race::canCast),
|
||||
Codec.BOOL.fieldOf("can_forage").forGetter(Race::hasIronGut),
|
||||
Codec.BOOL.fieldOf("earth_pony_strength").forGetter(Race::canUseEarth),
|
||||
Codec.BOOL.fieldOf("nocturnal").forGetter(Race::isNocturnal),
|
||||
Codec.BOOL.fieldOf("hanging").forGetter(Race::canHang),
|
||||
Codec.BOOL.fieldOf("aquatic").forGetter(Race::isFish),
|
||||
Codec.BOOL.fieldOf("weather_magic").forGetter(Race::canInfluenceWeather),
|
||||
Codec.BOOL.fieldOf("cloud_magic").forGetter(Race::canInteractWithClouds)
|
||||
).apply(i, Race::new));
|
||||
|
||||
/**
|
||||
* The default, unset race.
|
||||
* This is used if there are no other races.
|
||||
*/
|
||||
public static final Race UNSET = register("unset", Availability.COMMANDS, false, FlightType.NONE, false, false, false);
|
||||
public static final Race HUMAN = register("human", Availability.COMMANDS, false, FlightType.NONE, false, false, false);
|
||||
public static final Race EARTH = register("earth", Availability.DEFAULT, false, FlightType.NONE, true, false, false);
|
||||
public static final Race UNICORN = register("unicorn", Availability.DEFAULT, true, FlightType.NONE, false, false, false);
|
||||
public static final Race PEGASUS = register("pegasus", Availability.DEFAULT, false, FlightType.AVIAN, false, false, false);
|
||||
public static final Race BAT = register("bat", Availability.DEFAULT, false, FlightType.AVIAN, false, true, true);
|
||||
public static final Race ALICORN = register("alicorn", Availability.COMMANDS, true, FlightType.AVIAN, true, false, false);
|
||||
public static final Race CHANGELING = register("changeling", Availability.DEFAULT, false, FlightType.INSECTOID, false, false, true);
|
||||
public static final Race KIRIN = register("kirin", Availability.DEFAULT, true, FlightType.NONE, false, false, false);
|
||||
public static final Race HIPPOGRIFF = register("hippogriff", Availability.DEFAULT, false, FlightType.AVIAN, false, false, false);
|
||||
public static final Race SEAPONY = register("seapony", Availability.NONE, false, FlightType.NONE, false, false, false);
|
||||
public static final Race UNSET = register("unset", new Builder().availability(Availability.COMMANDS));
|
||||
public static final Race HUMAN = register("human", new Builder());
|
||||
public static final Race EARTH = register("earth", new Builder().foraging().earth()
|
||||
.abilities(Abilities.HUG, Abilities.STOMP, Abilities.KICK, Abilities.GROW)
|
||||
);
|
||||
public static final Race UNICORN = register("unicorn", new Builder().foraging().magic()
|
||||
.abilities(Abilities.TELEPORT, Abilities.CAST, Abilities.GROUP_TELEPORT, Abilities.SHOOT, Abilities.DISPELL)
|
||||
);
|
||||
public static final Race PEGASUS = register("pegasus", new Builder().foraging().flight(FlightType.AVIAN).weatherMagic().cloudMagic()
|
||||
.abilities(Abilities.TOGGLE_FLIGHT, Abilities.RAINBOOM, Abilities.CAPTURE_CLOUD, Abilities.CARRY)
|
||||
);
|
||||
public static final Race BAT = register("bat", new Builder().foraging().flight(FlightType.AVIAN).canHang().cloudMagic().nocturnal()
|
||||
.abilities(Abilities.TOGGLE_FLIGHT, Abilities.CARRY, Abilities.HANG, Abilities.EEEE)
|
||||
);
|
||||
public static final Race ALICORN = register("alicorn", new Builder().foraging().availability(Availability.COMMANDS).flight(FlightType.AVIAN).earth().magic().weatherMagic().cloudMagic()
|
||||
.abilities(
|
||||
Abilities.TELEPORT, Abilities.GROUP_TELEPORT, Abilities.CAST, Abilities.SHOOT, Abilities.DISPELL,
|
||||
Abilities.TOGGLE_FLIGHT, Abilities.RAINBOOM, Abilities.CAPTURE_CLOUD, Abilities.CARRY,
|
||||
Abilities.HUG, Abilities.STOMP, Abilities.KICK, Abilities.GROW,
|
||||
Abilities.TIME
|
||||
)
|
||||
);
|
||||
public static final Race CHANGELING = register("changeling", new Builder().foraging().affinity(Affinity.BAD).flight(FlightType.INSECTOID).canHang()
|
||||
.abilities(Abilities.DISPELL, Abilities.TOGGLE_FLIGHT, Abilities.FEED, Abilities.DISGUISE, Abilities.CARRY)
|
||||
);
|
||||
public static final Race KIRIN = register("kirin", new Builder().foraging().magic()
|
||||
.abilities(Abilities.DISPELL, Abilities.RAGE, Abilities.NIRIK_BLAST, Abilities.KIRIN_CAST)
|
||||
);
|
||||
public static final Race HIPPOGRIFF = register("hippogriff", new Builder().foraging().flight(FlightType.AVIAN).cloudMagic()
|
||||
.abilities(Abilities.TOGGLE_FLIGHT, Abilities.SCREECH, Abilities.PECK, Abilities.DASH, Abilities.CARRY)
|
||||
);
|
||||
public static final Race SEAPONY = register("seapony", new Builder().availability(Availability.COMMANDS).foraging().fish()
|
||||
.abilities(Abilities.SONAR_PULSE)
|
||||
);
|
||||
|
||||
public static void bootstrap() {}
|
||||
|
||||
public Composite composite() {
|
||||
return compositeSupplier.get();
|
||||
return COMPOSITES.apply(this);
|
||||
}
|
||||
|
||||
public Composite composite(@Nullable Race pseudo, @Nullable Race potential) {
|
||||
|
@ -75,11 +116,7 @@ public record Race (Supplier<Composite> compositeSupplier, Availability availabi
|
|||
|
||||
@Override
|
||||
public Affinity getAffinity() {
|
||||
return this == CHANGELING ? Affinity.BAD : Affinity.NEUTRAL;
|
||||
}
|
||||
|
||||
public boolean hasIronGut() {
|
||||
return !isHuman() && this != CHANGELING;
|
||||
return affinity;
|
||||
}
|
||||
|
||||
public boolean isUnset() {
|
||||
|
@ -90,12 +127,8 @@ public record Race (Supplier<Composite> compositeSupplier, Availability availabi
|
|||
return !isHuman();
|
||||
}
|
||||
|
||||
public boolean isFish() {
|
||||
return this == SEAPONY;
|
||||
}
|
||||
|
||||
public boolean isHuman() {
|
||||
return this == UNSET || this == HUMAN;
|
||||
return isUnset() || this == HUMAN;
|
||||
}
|
||||
|
||||
public boolean isDayurnal() {
|
||||
|
@ -106,8 +139,12 @@ public record Race (Supplier<Composite> compositeSupplier, Availability availabi
|
|||
return !flightType().isGrounded();
|
||||
}
|
||||
|
||||
public boolean canInteractWithClouds() {
|
||||
return canFly() && this != CHANGELING && this != BAT && this != HIPPOGRIFF;
|
||||
public boolean hasPersistentWeatherMagic() {
|
||||
return canInfluenceWeather();
|
||||
}
|
||||
|
||||
public boolean canUse(Ability<?> ability) {
|
||||
return abilities.contains(ability);
|
||||
}
|
||||
|
||||
public Identifier getId() {
|
||||
|
@ -123,30 +160,24 @@ public record Race (Supplier<Composite> compositeSupplier, Availability availabi
|
|||
}
|
||||
|
||||
public String getTranslationKey() {
|
||||
Identifier id = getId();
|
||||
return String.format("%s.race.%s", id.getNamespace(), id.getPath().toLowerCase());
|
||||
return Util.createTranslationKey("race", getId());
|
||||
}
|
||||
|
||||
public Identifier getIcon() {
|
||||
Identifier id = getId();
|
||||
return new Identifier(id.getNamespace(), "textures/gui/race/" + id.getPath() + ".png");
|
||||
return getId().withPath(p -> "textures/gui/race/" + p + ".png");
|
||||
}
|
||||
|
||||
public boolean isPermitted(@Nullable PlayerEntity sender) {
|
||||
Set<String> whitelist = Unicopia.getConfig().speciesWhiteList.get();
|
||||
|
||||
return isUnset()
|
||||
|| whitelist.isEmpty()
|
||||
|| whitelist.contains(getId().toString());
|
||||
return AllowList.INSTANCE.permits(this);
|
||||
}
|
||||
|
||||
public Race validate(PlayerEntity sender) {
|
||||
if (!isPermitted(sender)) {
|
||||
if (this == EARTH) {
|
||||
return HUMAN;
|
||||
Race alternative = this == EARTH ? HUMAN : EARTH.validate(sender);
|
||||
if (alternative != this && sender instanceof ServerPlayerEntity spe) {
|
||||
spe.sendMessageToClient(Text.translatable("respawn.reason.illegal_race", getDisplayName()), false);
|
||||
}
|
||||
|
||||
return EARTH.validate(sender);
|
||||
return alternative;
|
||||
}
|
||||
|
||||
return this;
|
||||
|
@ -156,16 +187,6 @@ public record Race (Supplier<Composite> compositeSupplier, Availability availabi
|
|||
return isEquine() ? this : other;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return getId().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return o instanceof Race race && Objects.equal(race.getId(), getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Race{ " + getId().toString() + " }";
|
||||
|
@ -190,13 +211,29 @@ public record Race (Supplier<Composite> compositeSupplier, Availability availabi
|
|||
return def;
|
||||
}
|
||||
|
||||
public static Race fromName(String name) {
|
||||
return fromName(name, EARTH);
|
||||
public static Race register(String name, Builder builder) {
|
||||
return register(Unicopia.id(name), builder);
|
||||
}
|
||||
|
||||
public static Race register(Identifier id, Builder builder) {
|
||||
Race race = Registry.register(REGISTRY, id, builder.build());
|
||||
if (race.availability().isGrantable()) {
|
||||
Registry.register(COMMAND_REGISTRY, id, race);
|
||||
}
|
||||
return race;
|
||||
}
|
||||
|
||||
public static RegistryKeyArgumentType<Race> argument() {
|
||||
return RegistryKeyArgumentType.registryKey(COMMAND_REGISTRY.getKey());
|
||||
}
|
||||
|
||||
public static Race fromArgument(CommandContext<ServerCommandSource> context, String name) throws CommandSyntaxException {
|
||||
Identifier id = context.getArgument(name, RegistryKey.class).getValue();
|
||||
return REGISTRY.getOrEmpty(id).orElseThrow(() -> UNKNOWN_RACE_EXCEPTION.create(id));
|
||||
final Identifier idf = id;
|
||||
if (id.getNamespace() == Identifier.DEFAULT_NAMESPACE && !REGISTRY.containsId(id)) {
|
||||
id = new Identifier(REGISTRY_KEY.getValue().getNamespace(), id.getPath());
|
||||
}
|
||||
return REGISTRY.getOrEmpty(id).orElseThrow(() -> UNKNOWN_RACE_EXCEPTION.create(idf));
|
||||
}
|
||||
|
||||
public static Set<Race> allPermitted(PlayerEntity player) {
|
||||
|
@ -228,6 +265,22 @@ public record Race (Supplier<Composite> compositeSupplier, Availability availabi
|
|||
return any(Race::canCast);
|
||||
}
|
||||
|
||||
public boolean canUse(Ability<?> ability) {
|
||||
return any(r -> r.canUse(ability));
|
||||
}
|
||||
|
||||
public boolean canInteractWithClouds() {
|
||||
return any(Race::canInteractWithClouds);
|
||||
}
|
||||
|
||||
public boolean canInfluenceWeather() {
|
||||
return any(Race::canInfluenceWeather);
|
||||
}
|
||||
|
||||
public boolean hasPersistentWeatherMagic() {
|
||||
return any(Race::hasPersistentWeatherMagic);
|
||||
}
|
||||
|
||||
public FlightType flightType() {
|
||||
if (pseudo() == null) {
|
||||
return physical().flightType();
|
||||
|
@ -235,6 +288,85 @@ public record Race (Supplier<Composite> compositeSupplier, Availability availabi
|
|||
return physical().flightType().or(pseudo().flightType());
|
||||
}
|
||||
}
|
||||
|
||||
public static final class Builder {
|
||||
private final List<Ability<?>> abilities = new ArrayList<>();
|
||||
private Affinity affinity = Affinity.NEUTRAL;
|
||||
private Availability availability = Availability.DEFAULT;
|
||||
private boolean canCast;
|
||||
private boolean hasIronGut;
|
||||
private FlightType flightType = FlightType.NONE;
|
||||
private boolean canUseEarth;
|
||||
private boolean isNocturnal;
|
||||
private boolean canHang;
|
||||
private boolean isFish;
|
||||
private boolean canInfluenceWeather;
|
||||
private boolean canInteractWithClouds;
|
||||
|
||||
public Builder abilities(Ability<?>...abilities) {
|
||||
this.abilities.addAll(List.of(abilities));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder foraging() {
|
||||
hasIronGut = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder affinity(Affinity affinity) {
|
||||
this.affinity = affinity;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder availability(Availability availability) {
|
||||
this.availability = availability;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder flight(FlightType flight) {
|
||||
flightType = flight;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder magic() {
|
||||
canCast = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder earth() {
|
||||
canUseEarth = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder nocturnal() {
|
||||
isNocturnal = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder canHang() {
|
||||
canHang = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder fish() {
|
||||
isFish = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder weatherMagic() {
|
||||
canInfluenceWeather = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder cloudMagic() {
|
||||
canInteractWithClouds = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Race build() {
|
||||
return new Race(List.copyOf(abilities), affinity, availability, flightType, canCast, hasIronGut, canUseEarth, isNocturnal, canHang, isFish, canInfluenceWeather, canInteractWithClouds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
package com.minelittlepony.unicopia;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public record SyncedConfig (
|
||||
Set<String> wantItNeedItExcludeList,
|
||||
Set<String> dimensionsWithoutAtmosphere) {
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
package com.minelittlepony.unicopia;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.registry.RegistryKeys;
|
||||
import net.minecraft.registry.tag.TagKey;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
public interface UConventionalTags {
|
||||
interface Blocks {
|
||||
TagKey<Block> CONCRETE_POWDERS = block("concrete_powders");
|
||||
TagKey<Block> CONCRETES = block("concretes");
|
||||
TagKey<Block> GLAZED_TERRACOTTAS = block("glazed_terracottas");
|
||||
TagKey<Block> CORAL_BLOCKS = block("coral_blocks");
|
||||
TagKey<Block> CORAL_FANS = block("coral_fans");
|
||||
TagKey<Block> CORALS = block("corals");
|
||||
|
||||
private static TagKey<Block> block(String name) {
|
||||
return TagKey.of(RegistryKeys.BLOCK, new Identifier("c", name));
|
||||
}
|
||||
}
|
||||
|
||||
interface Items {
|
||||
TagKey<Item> CONCRETE_POWDERS = item("concrete_powders");
|
||||
TagKey<Item> CONCRETES = item("concretes");
|
||||
TagKey<Item> GLAZED_TERRACOTTAS = item("glazed_terracottas");
|
||||
TagKey<Item> CORAL_BLOCKS = item("coral_blocks");
|
||||
TagKey<Item> CORAL_FANS = item("coral_fans");
|
||||
TagKey<Item> CORALS = item("corals");
|
||||
|
||||
TagKey<Item> APPLES = item("apples");
|
||||
TagKey<Item> ACORNS = item("acorns");
|
||||
TagKey<Item> PINECONES = item("pinecones");
|
||||
TagKey<Item> PINEAPPLES = item("pineapples");
|
||||
TagKey<Item> BANANAS = item("bananas");
|
||||
TagKey<Item> STICKS = item("sticks");
|
||||
TagKey<Item> SEEDS = item("seeds");
|
||||
TagKey<Item> GRAIN = item("grain");
|
||||
TagKey<Item> NUTS = item("nuts");
|
||||
TagKey<Item> MUSHROOMS = item("mushrooms");
|
||||
TagKey<Item> MUFFINS = item("muffins");
|
||||
TagKey<Item> MANGOES = item("mangoes");
|
||||
TagKey<Item> OATMEALS = item("oatmeals");
|
||||
TagKey<Item> COOKIES = item("cookies");
|
||||
|
||||
TagKey<Item> FRUITS = item("fruits");
|
||||
TagKey<Item> WORMS = item("worms");
|
||||
TagKey<Item> ROCKS = item("rocks");
|
||||
TagKey<Item> GEMS = item("gems");
|
||||
|
||||
TagKey<Item> RAW_INSECT = item("raw_insect");
|
||||
TagKey<Item> COOKED_INSECT = item("cooked_insect");
|
||||
TagKey<Item> ROTTEN_INSECT = item("rotten_insect");
|
||||
|
||||
TagKey<Item> RAW_FISH = item("raw_fish");
|
||||
TagKey<Item> COOKED_FISH = item("cooked_fish");
|
||||
TagKey<Item> ROTTEN_FISH = item("rotten_fish");
|
||||
TagKey<Item> RAW_MEAT = item("raw_meat");
|
||||
TagKey<Item> COOKED_MEAT = item("cooked_meat");
|
||||
TagKey<Item> ROTTEN_MEAT = item("rotten_meat");
|
||||
TagKey<Item> DESSERTS = item("desserts");
|
||||
TagKey<Item> CANDY = item("candy");
|
||||
|
||||
TagKey<Item> CROPS_PEANUTS = item("crops/peanuts");
|
||||
TagKey<Item> TOOL_KNIVES = item("tools/knives");
|
||||
|
||||
private static TagKey<Item> item(String name) {
|
||||
return TagKey.of(RegistryKeys.ITEM, new Identifier("c", name));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,7 +11,7 @@ public interface UGameEvents {
|
|||
|
||||
static GameEvent register(String name, int range) {
|
||||
Identifier id = Unicopia.id(name);
|
||||
return Registry.register(Registries.GAME_EVENT, id, new GameEvent(id.toString(), range));
|
||||
return Registry.register(Registries.GAME_EVENT, id, new GameEvent(range));
|
||||
}
|
||||
|
||||
static void bootstrap() {
|
||||
|
|
|
@ -1,16 +1,78 @@
|
|||
package com.minelittlepony.unicopia;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import com.minelittlepony.unicopia.mixin.MixinPointOfInterestType;
|
||||
import com.minelittlepony.unicopia.mixin.PointOfInterestTypesAccessor;
|
||||
|
||||
import net.fabricmc.fabric.api.event.registry.DynamicRegistrySetupCallback;
|
||||
import net.fabricmc.fabric.api.event.registry.RegistryEntryAddedCallback;
|
||||
import net.fabricmc.fabric.api.object.builder.v1.world.poi.PointOfInterestHelper;
|
||||
import net.minecraft.block.AbstractChestBlock;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.ChestBlock;
|
||||
import net.minecraft.registry.Registries;
|
||||
import net.minecraft.registry.RegistryKey;
|
||||
import net.minecraft.registry.RegistryKeys;
|
||||
import net.minecraft.registry.entry.RegistryEntry;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.world.poi.PointOfInterestType;
|
||||
import net.minecraft.world.poi.PointOfInterestTypes;
|
||||
|
||||
public interface UPOIs {
|
||||
PointOfInterestType CHESTS = PointOfInterestHelper.register(Unicopia.id("chests"), 1, 64, Registries.BLOCK.getEntrySet().stream()
|
||||
.map(entry -> entry.getValue())
|
||||
.filter(b -> b instanceof AbstractChestBlock)
|
||||
.toArray(Block[]::new));
|
||||
Set<RegistryKey<PointOfInterestType>> CHEST_POINTS_OF_INTEREST = new HashSet<>();
|
||||
RegistryKey<PointOfInterestType> CHESTS = register(Unicopia.id("chests"), 1, 64, () -> {
|
||||
return Registries.BLOCK.getEntrySet().stream()
|
||||
.map(entry -> entry.getValue())
|
||||
.filter(b -> b instanceof AbstractChestBlock)
|
||||
.flatMap(block -> {
|
||||
List<BlockState> states = block.getStateManager().getStates();
|
||||
List<RegistryKey<PointOfInterestType>> existingTypes = states.stream()
|
||||
.flatMap(state -> PointOfInterestTypes.getTypeForState(state).stream())
|
||||
.flatMap(entry -> entry.getKey().stream())
|
||||
.toList();
|
||||
|
||||
static void bootstrap() { }
|
||||
if (!existingTypes.isEmpty()) {
|
||||
CHEST_POINTS_OF_INTEREST.addAll(existingTypes);
|
||||
return Stream.empty();
|
||||
}
|
||||
return states.stream();
|
||||
})
|
||||
.distinct();
|
||||
});
|
||||
|
||||
static RegistryKey<PointOfInterestType> register(Identifier id, int ticketCount, int searchDistance, Supplier<Stream<BlockState>> states) {
|
||||
PointOfInterestType type = PointOfInterestHelper.register(id, ticketCount, searchDistance, List.of());
|
||||
((MixinPointOfInterestType)(Object)type).setStates(new HashSet<>());
|
||||
DynamicRegistrySetupCallback.EVENT.register(registries -> {
|
||||
if (type.blockStates().isEmpty()) {
|
||||
type.blockStates().addAll(states.get().collect(Collectors.toSet()));
|
||||
PointOfInterestTypesAccessor.registerStates(Registries.POINT_OF_INTEREST_TYPE.entryOf(CHESTS), type.blockStates());
|
||||
}
|
||||
});
|
||||
return RegistryKey.of(RegistryKeys.POINT_OF_INTEREST_TYPE, id);
|
||||
}
|
||||
|
||||
static boolean isChest(RegistryEntry<PointOfInterestType> type) {
|
||||
return type.getKey().filter(CHEST_POINTS_OF_INTEREST::contains).isPresent();
|
||||
}
|
||||
|
||||
static void bootstrap() {
|
||||
CHEST_POINTS_OF_INTEREST.add(CHESTS);
|
||||
Registries.POINT_OF_INTEREST_TYPE.getEntrySet().forEach(poi -> {
|
||||
if (poi.getValue().blockStates().stream().anyMatch(state -> state.getBlock() instanceof ChestBlock)) {
|
||||
CHEST_POINTS_OF_INTEREST.add(poi.getKey());
|
||||
}
|
||||
});
|
||||
RegistryEntryAddedCallback.event(Registries.POINT_OF_INTEREST_TYPE).register((raw, key, value) -> {
|
||||
if (value.blockStates().stream().anyMatch(state -> state.getBlock() instanceof ChestBlock)) {
|
||||
CHEST_POINTS_OF_INTEREST.add(RegistryKey.of(RegistryKeys.POINT_OF_INTEREST_TYPE, key));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ import static net.minecraft.sound.SoundEvents.*;
|
|||
public interface USounds {
|
||||
SoundEvent ENTITY_GENERIC_BUTTER_FINGERS = BLOCK_HONEY_BLOCK_SLIDE;
|
||||
|
||||
SoundEvent ENTITY_PLAYER_CORRUPTION = PARTICLE_SOUL_ESCAPE;
|
||||
SoundEvent ENTITY_PLAYER_CORRUPTION = register("entity.player.corrupt");
|
||||
SoundEvent ENTITY_PLAYER_BATPONY_SCREECH = register("entity.player.batpony.screech");
|
||||
SoundEvent ENTITY_PLAYER_HIPPOGRIFF_SCREECH = register("entity.player.hippogriff.screech");
|
||||
SoundEvent ENTITY_PLAYER_HIPPOGRIFF_PECK = ENTITY_CHICKEN_STEP;
|
||||
|
@ -62,11 +62,18 @@ public interface USounds {
|
|||
SoundEvent ENTITY_SOMBRA_AMBIENT = register("entity.sombra.ambient");
|
||||
SoundEvent ENTITY_SOMBRA_LAUGH = register("entity.sombra.laugh");
|
||||
SoundEvent ENTITY_SOMBRA_SNICKER = register("entity.sombra.snicker");
|
||||
SoundEvent ENTITY_SOMBRA_SCARY = USounds.Vanilla.ENTITY_GHAST_AMBIENT;
|
||||
SoundEvent ENTITY_SOMBRA_SCARY = ENTITY_GHAST_AMBIENT;
|
||||
|
||||
SoundEvent ENTITY_CRYSTAL_SHARDS_AMBIENT = BLOCK_AMETHYST_BLOCK_HIT;
|
||||
SoundEvent ENTITY_CRYSTAL_SHARDS_JOSTLE = BLOCK_AMETHYST_BLOCK_BREAK;
|
||||
|
||||
SoundEvent ENTITY_IGNIMEOUS_BULB_HURT = ENTITY_WARDEN_HURT;
|
||||
SoundEvent ENTITY_IGNIMEOUS_BULB_DEATH = ENTITY_WARDEN_DEATH;
|
||||
|
||||
SoundEvent ENTITY_TENTACLE_ROAR = ENTITY_RAVAGER_ROAR;
|
||||
SoundEvent ENTITY_TENTACLE_AMBIENT = BLOCK_CONDUIT_AMBIENT_SHORT;
|
||||
SoundEvent ENTITY_TENTACLE_DIG = ENTITY_WARDEN_DIG;
|
||||
|
||||
SoundEvent ITEM_AMULET_CHARGING = register("item.amulet.charging");
|
||||
SoundEvent ITEM_AMULET_RECHARGE = register("item.amulet.recharge");
|
||||
|
||||
|
@ -90,6 +97,8 @@ public interface USounds {
|
|||
SoundEvent ITEM_STAFF_STRIKE = ENTITY_PLAYER_ATTACK_CRIT;
|
||||
SoundEvent ITEM_MAGIC_STAFF_CHARGE = ENTITY_GUARDIAN_ATTACK;
|
||||
|
||||
SoundEvent ITEM_CURING_JOKE_CURE = BLOCK_AMETHYST_BLOCK_BREAK;
|
||||
|
||||
SoundEvent ITEM_ROCK_LAND = BLOCK_STONE_HIT;
|
||||
RegistryEntry.Reference<SoundEvent> ITEM_MUFFIN_BOUNCE = BLOCK_NOTE_BLOCK_BANJO;
|
||||
|
||||
|
|
|
@ -11,70 +11,141 @@ import net.minecraft.util.Identifier;
|
|||
import net.minecraft.world.dimension.DimensionType;
|
||||
|
||||
public interface UTags {
|
||||
TagKey<Item> APPLES = item("apples");
|
||||
TagKey<Item> FRESH_APPLES = item("fresh_apples");
|
||||
interface Items {
|
||||
TagKey<Item> ZAP_LOGS = item("zap_logs");
|
||||
TagKey<Item> WAXED_ZAP_LOGS = item("waxed_zap_logs");
|
||||
TagKey<Item> PALM_LOGS = item("palm_logs");
|
||||
TagKey<Item> CLOUD_BEDS = item("cloud_beds");
|
||||
TagKey<Item> CLOUD_SLABS = item("cloud_slabs");
|
||||
TagKey<Item> CLOUD_STAIRS = item("cloud_stairs");
|
||||
TagKey<Item> CLOUD_BLOCKS = item("cloud_blocks");
|
||||
TagKey<Item> CHITIN_BLOCKS = item("chitin_blocks");
|
||||
|
||||
TagKey<Item> FALLS_SLOWLY = item("falls_slowly");
|
||||
TagKey<Item> PIES = item("pies");
|
||||
TagKey<Item> CAN_CUT_PIE = item("can_cut_pie");
|
||||
TagKey<Item> FRESH_APPLES = item("fresh_apples");
|
||||
|
||||
TagKey<Item> MAGIC_FEATHERS = item("magic_feathers");
|
||||
TagKey<Item> FALLS_SLOWLY = item("falls_slowly");
|
||||
TagKey<Item> PIES = item("pies");
|
||||
TagKey<Item> CAN_CUT_PIE = item("can_cut_pie");
|
||||
|
||||
TagKey<Item> SHADES = item("shades");
|
||||
TagKey<Item> CHANGELING_EDIBLE = item("food_types/changeling_edible");
|
||||
TagKey<Item> SPOOKED_MOB_DROPS = item("spooked_mob_drops");
|
||||
TagKey<Item> IS_DELIVERED_AGGRESSIVELY = item("is_delivered_aggressively");
|
||||
TagKey<Item> FLOATS_ON_CLOUDS = item("floats_on_clouds");
|
||||
TagKey<Item> COOLS_OFF_KIRINS = item("cools_off_kirins");
|
||||
TagKey<Item> MAGIC_FEATHERS = item("magic_feathers");
|
||||
|
||||
TagKey<Item> POLEARMS = item("polearms");
|
||||
TagKey<Item> HORSE_SHOES = item("horse_shoes");
|
||||
TagKey<Item> APPLE_SEEDS = item("apple_seeds");
|
||||
TagKey<Item> SHADES = item("shades");
|
||||
TagKey<Item> SPOOKED_MOB_DROPS = item("spooked_mob_drops");
|
||||
TagKey<Item> HAS_NO_TRAITS = item("has_no_traits");
|
||||
TagKey<Item> IS_DELIVERED_AGGRESSIVELY = item("is_delivered_aggressively");
|
||||
TagKey<Item> CONTAINER_WITH_LOVE = item("container_with_love");
|
||||
TagKey<Item> FLOATS_ON_CLOUDS = item("floats_on_clouds");
|
||||
TagKey<Item> COOLS_OFF_KIRINS = item("cools_off_kirins");
|
||||
TagKey<Item> LOOT_BUG_COMMON_DROPS = item("loot_bug_common_drops");
|
||||
TagKey<Item> LOOT_BUG_RARE_DROPS = item("loot_bug_rare_drops");
|
||||
TagKey<Item> LOOT_BUG_EPIC_DROPS = item("loot_bug_epic_drops");
|
||||
|
||||
TagKey<Item> ACORNS = item("acorns");
|
||||
TagKey<Item> BASKETS = item("baskets");
|
||||
TagKey<Item> SHELLS = item("shells");
|
||||
TagKey<Item> SPECIAL_SHELLS = item("special_shells");
|
||||
TagKey<Item> ROCK_STEWS = item("rock_stews");
|
||||
TagKey<Item> BAKED_GOODS = item("baked_goods");
|
||||
|
||||
TagKey<Block> GLASS_PANES = block("glass_panes");
|
||||
TagKey<Block> GLASS_BLOCKS = block("glass_blocks");
|
||||
TagKey<Block> FRAGILE = block("fragile");
|
||||
TagKey<Block> INTERESTING = block("interesting");
|
||||
TagKey<Block> CATAPULT_IMMUNE = block("catapult_immune");
|
||||
TagKey<Item> HIGH_QUALITY_SEA_VEGETABLES = item("food_types/high_quality_sea_vegetables");
|
||||
TagKey<Item> LOW_QUALITY_SEA_VEGETABLES = item("food_types/low_quality_sea_vegetables");
|
||||
|
||||
TagKey<Block> CRYSTAL_HEART_BASE = block("crystal_heart_base");
|
||||
TagKey<Block> CRYSTAL_HEART_ORNAMENT = block("crystal_heart_ornament");
|
||||
TagKey<Item> POLEARMS = item("polearms");
|
||||
TagKey<Item> HORSE_SHOES = item("horse_shoes");
|
||||
TagKey<Item> APPLE_SEEDS = item("apple_seeds");
|
||||
|
||||
TagKey<Block> POLEARM_MINEABLE = block("mineable/polearm");
|
||||
TagKey<Item> BASKETS = item("baskets");
|
||||
TagKey<Item> BADGES = item("badges");
|
||||
TagKey<Item> WOOL_BED_SHEETS = item("wool_bed_sheets");
|
||||
TagKey<Item> BED_SHEETS = item("bed_sheets");
|
||||
TagKey<Item> CLOUD_JARS = item("cloud_jars");
|
||||
|
||||
TagKey<EntityType<?>> TRANSFORMABLE_ENTITIES = entity("transformable");
|
||||
TagKey<Item> GROUP_FORAGING = item("groups/foraging");
|
||||
TagKey<Item> GROUP_EARTH_PONY = item("groups/earth_pony");
|
||||
TagKey<Item> GROUP_UNICORN = item("groups/unicorn");
|
||||
TagKey<Item> GROUP_PEGASUS = item("groups/pegasus");
|
||||
TagKey<Item> GROUP_BAT_PONY = item("groups/bat_pony");
|
||||
TagKey<Item> GROUP_SEA_PONY = item("groups/sea_pony");
|
||||
TagKey<Item> GROUP_CHANGELING = item("groups/changeling");
|
||||
|
||||
TagKey<StatusEffect> PINEAPPLE_EFFECTS = effect("pineapple_effects");
|
||||
TagKey<Item> FORAGE_BLINDING = item("forage/blinding");
|
||||
TagKey<Item> FORAGE_DANGEROUS = item("forage/dangerous");
|
||||
TagKey<Item> FORAGE_FILLING = item("forage/filling");
|
||||
TagKey<Item> FORAGE_SAFE = item("forage/safe");
|
||||
TagKey<Item> FORAGE_NAUSEATING = item("forage/nauseating");
|
||||
TagKey<Item> FORAGE_PRICKLY = item("forage/prickly");
|
||||
TagKey<Item> FORAGE_GLOWING = item("forage/glowing");
|
||||
TagKey<Item> FORAGE_RISKY = item("forage/risky");
|
||||
TagKey<Item> FORAGE_STRENGHENING = item("forage/strenghtening");
|
||||
TagKey<Item> FORAGE_SEVERE_NAUSEATING = item("forage/severe/nauseating");
|
||||
TagKey<Item> FORAGE_SEVERE_PRICKLY = item("forage/severe/prickly");
|
||||
|
||||
TagKey<DamageType> BREAKS_SUNGLASSES = damage("breaks_sunglasses");
|
||||
TagKey<DamageType> SPELLBOOK_IMMUNE_TO = damage("spellbook_immune_to");
|
||||
|
||||
TagKey<DimensionType> HAS_NO_ATMOSPHERE = dimension("has_no_atmosphere");
|
||||
|
||||
static TagKey<Item> item(String name) {
|
||||
return TagKey.of(RegistryKeys.ITEM, Unicopia.id(name));
|
||||
private static TagKey<Item> item(String name) {
|
||||
return TagKey.of(RegistryKeys.ITEM, Unicopia.id(name));
|
||||
}
|
||||
}
|
||||
|
||||
static TagKey<Block> block(String name) {
|
||||
return TagKey.of(RegistryKeys.BLOCK, Unicopia.id(name));
|
||||
interface Blocks {
|
||||
TagKey<Block> ZAP_LOGS = block("zap_logs");
|
||||
TagKey<Block> WAXED_ZAP_LOGS = block("waxed_zap_logs");
|
||||
TagKey<Block> PALM_LOGS = block("palm_logs");
|
||||
TagKey<Block> CLOUD_BEDS = block("cloud_beds");
|
||||
TagKey<Block> CLOUD_SLABS = block("cloud_slabs");
|
||||
TagKey<Block> CLOUD_STAIRS = block("cloud_stairs");
|
||||
TagKey<Block> CLOUD_BLOCKS = block("cloud_blocks");
|
||||
TagKey<Block> CHITIN_BLOCKS = block("chitin_blocks");
|
||||
|
||||
TagKey<Block> FRAGILE = block("fragile");
|
||||
TagKey<Block> INTERESTING = block("interesting");
|
||||
TagKey<Block> CATAPULT_IMMUNE = block("catapult_immune");
|
||||
TagKey<Block> JARS = block("jars");
|
||||
|
||||
TagKey<Block> CRYSTAL_HEART_BASE = block("crystal_heart_base");
|
||||
TagKey<Block> CRYSTAL_HEART_ORNAMENT = block("crystal_heart_ornament");
|
||||
TagKey<Block> UNAFFECTED_BY_GROW_ABILITY = block("unaffected_by_grow_ability");
|
||||
TagKey<Block> KICKS_UP_DUST = block("kicks_up_dust");
|
||||
|
||||
TagKey<Block> POLEARM_MINEABLE = block("mineable/polearm");
|
||||
TagKey<Block> MIMIC_CHESTS = block("mimic_chests");
|
||||
|
||||
TagKey<Block> BUTTERFLIES_SPAWNABLE_ON = block("butterflies_spawn_on");
|
||||
TagKey<Block> ANGERS_GUARDIANS = block("angers_guardians");
|
||||
|
||||
private static TagKey<Block> block(String name) {
|
||||
return TagKey.of(RegistryKeys.BLOCK, Unicopia.id(name));
|
||||
}
|
||||
}
|
||||
|
||||
static TagKey<EntityType<?>> entity(String name) {
|
||||
return TagKey.of(RegistryKeys.ENTITY_TYPE, Unicopia.id(name));
|
||||
interface Entities {
|
||||
TagKey<EntityType<?>> TRANSFORMABLE = entity("transformable");
|
||||
|
||||
private static TagKey<EntityType<?>> entity(String name) {
|
||||
return TagKey.of(RegistryKeys.ENTITY_TYPE, Unicopia.id(name));
|
||||
}
|
||||
}
|
||||
|
||||
static TagKey<StatusEffect> effect(String name) {
|
||||
return TagKey.of(RegistryKeys.STATUS_EFFECT, Unicopia.id(name));
|
||||
interface DamageTypes {
|
||||
TagKey<DamageType> BREAKS_SUNGLASSES = damage("breaks_sunglasses");
|
||||
TagKey<DamageType> SPELLBOOK_IMMUNE_TO = damage("spellbook_immune_to");
|
||||
TagKey<DamageType> FROM_ROCKS = damage("from_rocks");
|
||||
TagKey<DamageType> FROM_HORSESHOES = damage("from_horseshoes");
|
||||
|
||||
private static TagKey<DamageType> damage(String name) {
|
||||
return TagKey.of(RegistryKeys.DAMAGE_TYPE, Unicopia.id(name));
|
||||
}
|
||||
}
|
||||
|
||||
static TagKey<DamageType> damage(String name) {
|
||||
return TagKey.of(RegistryKeys.DAMAGE_TYPE, Unicopia.id(name));
|
||||
interface DimensionTypes {
|
||||
TagKey<DimensionType> HAS_NO_ATMOSPHERE = dimension("has_no_atmosphere");
|
||||
|
||||
private static TagKey<DimensionType> dimension(String name) {
|
||||
return TagKey.of(RegistryKeys.DIMENSION_TYPE, new Identifier("c", name));
|
||||
}
|
||||
}
|
||||
|
||||
static TagKey<DimensionType> dimension(String name) {
|
||||
return TagKey.of(RegistryKeys.DIMENSION_TYPE, new Identifier("c", name));
|
||||
interface StatusEffects {
|
||||
TagKey<StatusEffect> PINEAPPLE_EFFECTS = effect("pineapple_effects");
|
||||
|
||||
private static TagKey<StatusEffect> effect(String name) {
|
||||
return TagKey.of(RegistryKeys.STATUS_EFFECT, Unicopia.id(name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,15 +2,13 @@ package com.minelittlepony.unicopia;
|
|||
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
|
||||
import net.fabricmc.fabric.api.event.player.PlayerBlockBreakEvents;
|
||||
import net.fabricmc.fabric.api.resource.ResourceManagerHelper;
|
||||
import net.minecraft.resource.ResourceType;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import com.minelittlepony.unicopia.ability.Abilities;
|
||||
import com.minelittlepony.unicopia.ability.data.tree.TreeTypeLoader;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType;
|
||||
|
@ -25,14 +23,15 @@ import com.minelittlepony.unicopia.container.UScreenHandlers;
|
|||
import com.minelittlepony.unicopia.diet.DietsLoader;
|
||||
import com.minelittlepony.unicopia.diet.affliction.AfflictionType;
|
||||
import com.minelittlepony.unicopia.entity.damage.UDamageTypes;
|
||||
import com.minelittlepony.unicopia.entity.effect.SeaponyGraceStatusEffect;
|
||||
import com.minelittlepony.unicopia.entity.effect.UPotions;
|
||||
import com.minelittlepony.unicopia.entity.mob.UEntities;
|
||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
import com.minelittlepony.unicopia.item.UItems;
|
||||
import com.minelittlepony.unicopia.item.enchantment.UEnchantments;
|
||||
import com.minelittlepony.unicopia.network.Channel;
|
||||
import com.minelittlepony.unicopia.particle.UParticles;
|
||||
import com.minelittlepony.unicopia.server.world.BlockDestructionManager;
|
||||
import com.minelittlepony.unicopia.server.world.Ether;
|
||||
import com.minelittlepony.unicopia.server.world.NocturnalSleepManager;
|
||||
import com.minelittlepony.unicopia.server.world.UGameRules;
|
||||
import com.minelittlepony.unicopia.server.world.UWorldGen;
|
||||
|
@ -43,8 +42,6 @@ public class Unicopia implements ModInitializer {
|
|||
public static final String DEFAULT_NAMESPACE = "unicopia";
|
||||
public static final Logger LOGGER = LogManager.getLogger();
|
||||
|
||||
public static SidedAccess SIDE = Optional::empty;
|
||||
|
||||
private static Config CONFIG;
|
||||
|
||||
public static Config getConfig() {
|
||||
|
@ -69,12 +66,13 @@ public class Unicopia implements ModInitializer {
|
|||
UCriteria.bootstrap();
|
||||
UEntities.bootstrap();
|
||||
Commands.bootstrap();
|
||||
TrinketsDelegate.getInstance().bootstrap();
|
||||
TrinketsDelegate.getInstance(null).bootstrap();
|
||||
|
||||
ServerTickEvents.END_WORLD_TICK.register(w -> {
|
||||
((BlockDestructionManager.Source)w).getDestructionManager().tick();
|
||||
ZapAppleStageStore.get(w).tick();
|
||||
WeatherConditions.get(w).tick();
|
||||
Ether.get(w).tick();
|
||||
if (Debug.SPELLBOOK_CHAPTERS) {
|
||||
SpellbookChapterLoader.INSTANCE.sendUpdate(w.getServer());
|
||||
}
|
||||
|
@ -82,6 +80,7 @@ public class Unicopia implements ModInitializer {
|
|||
Debug.runTests(w);
|
||||
}
|
||||
});
|
||||
PlayerBlockBreakEvents.AFTER.register(SeaponyGraceStatusEffect::processBlockChange);
|
||||
NocturnalSleepManager.bootstrap();
|
||||
|
||||
registerServerDataReloaders(ResourceManagerHelper.get(ResourceType.SERVER_DATA));
|
||||
|
@ -111,12 +110,4 @@ public class Unicopia implements ModInitializer {
|
|||
registry.registerReloadListener(SpellbookChapterLoader.INSTANCE);
|
||||
registry.registerReloadListener(new DietsLoader());
|
||||
}
|
||||
|
||||
public interface SidedAccess {
|
||||
Optional<Pony> getPony();
|
||||
|
||||
default Race.Composite getPlayerSpecies() {
|
||||
return getPony().map(Pony::getCompositeRace).orElse(Race.HUMAN.composite());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,6 +38,9 @@ public class UnicopiaMixinPlugin implements IMixinConfigPlugin {
|
|||
if (mixinClassName.indexOf("minelp") != -1) {
|
||||
return FabricLoader.getInstance().isModLoaded("minelp");
|
||||
}
|
||||
if (mixinClassName.indexOf("forgified") != -1) {
|
||||
return FabricLoader.getInstance().isModLoaded("connectormod");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -42,8 +42,8 @@ public interface WeaklyOwned<E extends Entity> extends Owned<E>, WorldConvertabl
|
|||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
default void setMaster(Owned<? extends E> sibling) {
|
||||
if (sibling instanceof WeaklyOwned) {
|
||||
getMasterReference().copyFrom(((WeaklyOwned<E>)sibling).getMasterReference());
|
||||
if (sibling instanceof WeaklyOwned w) {
|
||||
getMasterReference().copyFrom(w.getMasterReference());
|
||||
} else {
|
||||
setMaster(sibling.getMaster());
|
||||
}
|
||||
|
|
|
@ -68,7 +68,9 @@ public interface Ability<T extends Hit> {
|
|||
* Checks if the given race is permitted to use this ability
|
||||
* @param playerSpecies The player's species
|
||||
*/
|
||||
boolean canUse(Race playerSpecies);
|
||||
default boolean canUse(Race race) {
|
||||
return race.canUse(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when an ability is about to be triggered. This event occurs on both the client and server so check {@code Pony#isClient} if you need to know which one you're on.
|
||||
|
@ -81,6 +83,15 @@ public interface Ability<T extends Hit> {
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether this ability has any special actions for the given activation type.
|
||||
* <p>
|
||||
* The default is to only respond to press-and-hold actions.
|
||||
*/
|
||||
default boolean acceptsQuickAction(Pony player, ActivationType type) {
|
||||
return type == ActivationType.NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called on the client to get any data required for the quick action.
|
||||
*
|
||||
|
|
|
@ -172,6 +172,16 @@ public class AbilityDispatcher implements Tickable, NbtSerialisable {
|
|||
}
|
||||
|
||||
public void tick() {
|
||||
Optional<Ability<?>> activeAbility = getActiveAbility();
|
||||
|
||||
if (activeAbility.isEmpty()) {
|
||||
if (warmup > 0) {
|
||||
warmup--;
|
||||
}
|
||||
if (cooldown > 0) {
|
||||
cooldown--;
|
||||
}
|
||||
}
|
||||
getActiveAbility().ifPresent(ability -> {
|
||||
if (warmup > 0) {
|
||||
warmup--;
|
||||
|
@ -209,6 +219,7 @@ public class AbilityDispatcher implements Tickable, NbtSerialisable {
|
|||
warmup = 0;
|
||||
|
||||
if (data.isPresent()) {
|
||||
InteractionManager.getInstance().sendPlayerLookAngles(player.asEntity());
|
||||
Channel.CLIENT_PLAYER_ABILITY.sendToServer(new MsgPlayerAbility<>(ability, data, ActivationType.NONE));
|
||||
} else {
|
||||
player.asEntity().playSound(USounds.GUI_ABILITY_FAIL, 1, 1);
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package com.minelittlepony.unicopia.ability;
|
||||
|
||||
import com.minelittlepony.unicopia.*;
|
||||
import com.minelittlepony.unicopia.ability.data.Hit;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.effect.CustomisedSpellType;
|
||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
|
@ -11,17 +10,11 @@ import net.minecraft.util.ActionResult;
|
|||
import net.minecraft.util.TypedActionResult;
|
||||
|
||||
abstract class AbstractSpellCastingAbility implements Ability<Hit> {
|
||||
|
||||
@Override
|
||||
public int getCooldownTime(Pony player) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canUse(Race race) {
|
||||
return race.canCast() && race != Race.KIRIN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Text getName(Pony player) {
|
||||
CustomisedSpellType<?> spell = player.getCharms().getEquippedSpell(player.getCharms().getHand());
|
||||
|
|
|
@ -18,6 +18,10 @@ public enum ActivationType {
|
|||
return ordinal();
|
||||
}
|
||||
|
||||
public boolean isResult() {
|
||||
return this != NONE;
|
||||
}
|
||||
|
||||
public static ActivationType of(int id) {
|
||||
return VALUES[MathHelper.clamp(id, 0, VALUES.length)];
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package com.minelittlepony.unicopia.ability;
|
||||
|
||||
import com.minelittlepony.unicopia.AwaitTickQueue;
|
||||
import com.minelittlepony.unicopia.Race;
|
||||
import com.minelittlepony.unicopia.USounds;
|
||||
import com.minelittlepony.unicopia.advancement.UCriteria;
|
||||
import com.minelittlepony.unicopia.entity.damage.UDamageTypes;
|
||||
|
@ -16,11 +15,6 @@ import net.minecraft.world.event.GameEvent;
|
|||
public class BatEeeeAbility extends ScreechAbility {
|
||||
public static final int SELF_SPOOK_PROBABILITY = 20000;
|
||||
|
||||
@Override
|
||||
public boolean canUse(Race race) {
|
||||
return race == Race.BAT;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void playSounds(Pony player, Random rng, float strength) {
|
||||
int count = 1 + rng.nextInt(10) + (int)(strength * 10);
|
||||
|
@ -31,7 +25,7 @@ public class BatEeeeAbility extends ScreechAbility {
|
|||
1.6F + (rng.nextFloat() - 0.5F)
|
||||
);
|
||||
}
|
||||
player.asWorld().emitGameEvent(player.asEntity(), GameEvent.ENTITY_ROAR, player.asEntity().getEyePos());
|
||||
player.asWorld().emitGameEvent(player.asEntity(), GameEvent.ENTITY_ACTION, player.asEntity().getEyePos());
|
||||
for (int j = 0; j < (int)(strength * 2); j++) {
|
||||
for (int k = 0; k < count; k++) {
|
||||
AwaitTickQueue.scheduleTask(player.asWorld(), w -> {
|
||||
|
@ -39,7 +33,7 @@ public class BatEeeeAbility extends ScreechAbility {
|
|||
(0.9F + (rng.nextFloat() - 0.5F) / 2F) * strength,
|
||||
1.6F + (rng.nextFloat() - 0.5F)
|
||||
);
|
||||
player.asWorld().emitGameEvent(player.asEntity(), GameEvent.ENTITY_ROAR, player.asEntity().getEyePos());
|
||||
player.asWorld().emitGameEvent(player.asEntity(), GameEvent.ENTITY_ACTION, player.asEntity().getEyePos());
|
||||
}, rng.nextInt(3));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@ package com.minelittlepony.unicopia.ability;
|
|||
|
||||
import java.util.Optional;
|
||||
|
||||
import com.minelittlepony.unicopia.Race;
|
||||
import com.minelittlepony.unicopia.ability.data.Multi;
|
||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
import com.minelittlepony.unicopia.util.TraceHelper;
|
||||
|
@ -30,11 +29,6 @@ public class BatPonyHangAbility implements Ability<Multi> {
|
|||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canUse(Race race) {
|
||||
return race == Race.BAT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Multi> prepare(Pony player) {
|
||||
|
||||
|
@ -43,7 +37,7 @@ public class BatPonyHangAbility implements Ability<Multi> {
|
|||
}
|
||||
|
||||
return TraceHelper.findBlock(player.asEntity(), 5, 1)
|
||||
.map(BlockPos::down)
|
||||
.map(pos -> pos.down(player.getPhysics().getGravitySignum()))
|
||||
.filter(player.getAcrobatics()::canHangAt)
|
||||
.map(pos -> new Multi(pos, 1));
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ import java.util.UUID;
|
|||
import java.util.stream.StreamSupport;
|
||||
|
||||
import com.minelittlepony.unicopia.EquinePredicates;
|
||||
import com.minelittlepony.unicopia.Race;
|
||||
import com.minelittlepony.unicopia.ability.data.Hit;
|
||||
import com.minelittlepony.unicopia.entity.Living;
|
||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
|
@ -37,11 +36,6 @@ public class CarryAbility implements Ability<Hit> {
|
|||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canUse(Race race) {
|
||||
return race.canFly();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Hit> prepare(Pony player) {
|
||||
return Hit.INSTANCE;
|
||||
|
@ -69,6 +63,11 @@ public class CarryAbility implements Ability<Hit> {
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptsQuickAction(Pony player, ActivationType type) {
|
||||
return type == ActivationType.NONE || type == ActivationType.TAP;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Pony iplayer, Hit data) {
|
||||
PlayerEntity player = iplayer.asEntity();
|
||||
|
|
|
@ -9,8 +9,11 @@ import org.jetbrains.annotations.Nullable;
|
|||
import com.minelittlepony.unicopia.Race;
|
||||
import com.minelittlepony.unicopia.USounds;
|
||||
import com.minelittlepony.unicopia.ability.data.Hit;
|
||||
import com.minelittlepony.unicopia.advancement.UCriteria;
|
||||
import com.minelittlepony.unicopia.compat.trinkets.TrinketsDelegate;
|
||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
import com.minelittlepony.unicopia.item.FriendshipBraceletItem;
|
||||
import com.minelittlepony.unicopia.item.UItems;
|
||||
|
||||
import net.minecraft.particle.ParticleTypes;
|
||||
import net.minecraft.sound.SoundCategory;
|
||||
|
@ -72,13 +75,19 @@ public class ChangeFormAbility implements Ability<Hit> {
|
|||
|
||||
List<Pony> targets = getTargets(player).toList();
|
||||
player.subtractEnergyCost(5 * targets.size());
|
||||
TrinketsDelegate.EquippedStack amulet = UItems.PEARL_NECKLACE.getForEntity(player.asEntity());
|
||||
if (!amulet.stack().isEmpty()) {
|
||||
amulet.stack().damage(1, player.asEntity(), amulet.breakStatusSender());
|
||||
}
|
||||
|
||||
boolean isTransforming = player.getSuppressedRace().isUnset();
|
||||
targets.forEach(target -> {
|
||||
Race supressed = target.getSuppressedRace();
|
||||
if (target == player || supressed.isUnset() == isTransforming) {
|
||||
Race actualRace = target.getSpecies();
|
||||
Race actualRace = isTransforming ? target.getSpecies() : Race.UNSET;
|
||||
target.setSpecies(supressed.or(player.getCompositeRace().potential()));
|
||||
target.setSuppressedRace(isTransforming ? actualRace : Race.UNSET);
|
||||
target.setSuppressedRace(actualRace);
|
||||
UCriteria.SEAPONY_TRANSITION.trigger(target.asEntity());
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ public class ChangelingDisguiseAbility extends ChangelingFeedAbility {
|
|||
|
||||
player.getEntityWorld().playSound(null, player.getBlockPos(), USounds.ENTITY_PLAYER_CHANGELING_TRANSFORM, SoundCategory.PLAYERS, 1.4F, 0.4F);
|
||||
|
||||
Disguise currentDisguise = iplayer.getSpellSlot().get(SpellType.CHANGELING_DISGUISE, true)
|
||||
Disguise currentDisguise = iplayer.getSpellSlot().get(SpellType.CHANGELING_DISGUISE)
|
||||
.orElseGet(() -> SpellType.CHANGELING_DISGUISE.withTraits().apply(iplayer, CastingMethod.INNATE));
|
||||
|
||||
if (currentDisguise.isOf(looked)) {
|
||||
|
@ -64,7 +64,6 @@ public class ChangelingDisguiseAbility extends ChangelingFeedAbility {
|
|||
}
|
||||
|
||||
player.calculateDimensions();
|
||||
iplayer.setDirty();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,26 +2,21 @@ package com.minelittlepony.unicopia.ability;
|
|||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.minelittlepony.unicopia.Race;
|
||||
import com.minelittlepony.unicopia.USounds;
|
||||
import com.minelittlepony.unicopia.ability.data.Hit;
|
||||
import com.minelittlepony.unicopia.entity.damage.UDamageTypes;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.ChangelingFeedingSpell;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType;
|
||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
import com.minelittlepony.unicopia.particle.FollowingParticleEffect;
|
||||
import com.minelittlepony.unicopia.particle.ParticleUtils;
|
||||
import com.minelittlepony.unicopia.particle.UParticles;
|
||||
import com.minelittlepony.unicopia.util.TraceHelper;
|
||||
import com.minelittlepony.unicopia.util.VecHelper;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.entity.damage.DamageSource;
|
||||
import net.minecraft.entity.effect.StatusEffectInstance;
|
||||
import net.minecraft.entity.effect.StatusEffects;
|
||||
import net.minecraft.entity.mob.HostileEntity;
|
||||
import net.minecraft.entity.passive.CowEntity;
|
||||
import net.minecraft.entity.passive.MerchantEntity;
|
||||
|
@ -34,6 +29,13 @@ import net.minecraft.particle.ParticleTypes;
|
|||
* Changeling ability to restore health from mobs
|
||||
*/
|
||||
public class ChangelingFeedAbility implements Ability<Hit> {
|
||||
private static final Predicate<Entity> TARGET_PREDICATE = e -> (e instanceof LivingEntity)
|
||||
&& (e instanceof CowEntity
|
||||
|| e instanceof MerchantEntity
|
||||
|| e instanceof PlayerEntity
|
||||
|| e instanceof SheepEntity
|
||||
|| e instanceof PigEntity
|
||||
|| e instanceof HostileEntity);
|
||||
|
||||
@Override
|
||||
public int getWarmupTime(Pony player) {
|
||||
|
@ -42,33 +44,13 @@ public class ChangelingFeedAbility implements Ability<Hit> {
|
|||
|
||||
@Override
|
||||
public int getCooldownTime(Pony player) {
|
||||
return canFeed(player) ? 15 : 80;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canUse(Race race) {
|
||||
return race == Race.CHANGELING;
|
||||
return !SpellType.FEED.isOn(player) && ChangelingFeedingSpell.canFeed(player) ? 15 : 80;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Optional<Hit> prepare(Pony player) {
|
||||
return Hit.of(canFeed(player) && !getTargets(player).isEmpty());
|
||||
}
|
||||
|
||||
private boolean canFeed(Pony player) {
|
||||
return player.asEntity().getHealth() < player.asEntity().getMaxHealth()
|
||||
|| player.asEntity().canConsume(false);
|
||||
}
|
||||
|
||||
private boolean canDrain(Entity e) {
|
||||
return (e instanceof LivingEntity)
|
||||
&& (e instanceof CowEntity
|
||||
|| e instanceof MerchantEntity
|
||||
|| e instanceof PlayerEntity
|
||||
|| e instanceof SheepEntity
|
||||
|| e instanceof PigEntity
|
||||
|| e instanceof HostileEntity);
|
||||
return Hit.of(ChangelingFeedingSpell.canFeed(player) && !getTargets(player).findAny().isEmpty());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -76,16 +58,6 @@ public class ChangelingFeedAbility implements Ability<Hit> {
|
|||
return Hit.SERIALIZER;
|
||||
}
|
||||
|
||||
protected List<LivingEntity> getTargets(Pony player) {
|
||||
List<Entity> list = VecHelper.findInRange(player.asEntity(), player.asWorld(), player.getOriginVector(), 3, this::canDrain);
|
||||
|
||||
TraceHelper.<LivingEntity>findEntity(player.asEntity(), 17, 1,
|
||||
looked -> looked instanceof LivingEntity && !list.contains(looked) && canDrain(looked))
|
||||
.ifPresent(list::add);
|
||||
|
||||
return list.stream().map(i -> (LivingEntity)i).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getCostEstimate(Pony player) {
|
||||
return 0;
|
||||
|
@ -93,7 +65,7 @@ public class ChangelingFeedAbility implements Ability<Hit> {
|
|||
|
||||
@Override
|
||||
public boolean apply(Pony iplayer, Hit data) {
|
||||
if (!canFeed(iplayer)) {
|
||||
if (!ChangelingFeedingSpell.canFeed(iplayer)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -103,64 +75,25 @@ public class ChangelingFeedAbility implements Ability<Hit> {
|
|||
int maximumFoodGain = player.canConsume(false) ? (20 - player.getHungerManager().getFoodLevel()) : 0;
|
||||
|
||||
if (maximumHealthGain > 0 || maximumFoodGain > 0) {
|
||||
List<LivingEntity> targets = getTargets(iplayer).map(LivingEntity.class::cast).toList();
|
||||
|
||||
float healAmount = 0;
|
||||
if (targets.size() > 0) {
|
||||
new ChangelingFeedingSpell(targets, maximumHealthGain, maximumFoodGain).apply(iplayer);
|
||||
|
||||
for (LivingEntity i : getTargets(iplayer)) {
|
||||
healAmount += drainFrom(iplayer, i);
|
||||
iplayer.playSound(USounds.ENTITY_PLAYER_CHANGELING_FEED, 0.1F, iplayer.getRandomPitch());
|
||||
return true;
|
||||
}
|
||||
|
||||
int foodAmount = (int)Math.floor(Math.min(healAmount / 3, maximumFoodGain));
|
||||
|
||||
if (foodAmount > 0) {
|
||||
healAmount -= foodAmount;
|
||||
}
|
||||
player.getHungerManager().add(Math.max(1, foodAmount), 0.125f);
|
||||
|
||||
player.heal(Math.max(1, Math.min(healAmount, maximumHealthGain)));
|
||||
}
|
||||
|
||||
|
||||
if (!canFeed(iplayer)) {
|
||||
iplayer.playSound(USounds.Vanilla.ENTITY_PLAYER_BURP, 1, (float)player.getWorld().random.nextTriangular(1F, 0.2F));
|
||||
} else {
|
||||
iplayer.playSound(USounds.ENTITY_PLAYER_CHANGELING_FEED, 0.1F, iplayer.getRandomPitch());
|
||||
}
|
||||
|
||||
iplayer.playSound(USounds.Vanilla.ENTITY_PLAYER_BURP, 1, (float)player.getWorld().random.nextTriangular(1F, 0.2F));
|
||||
return true;
|
||||
}
|
||||
|
||||
public float drainFrom(Pony changeling, LivingEntity living) {
|
||||
|
||||
DamageSource d = changeling.damageOf(UDamageTypes.LOVE_DRAINING, changeling);
|
||||
|
||||
float damage = living.getHealth()/2;
|
||||
|
||||
if (damage > 0) {
|
||||
living.damage(d, damage);
|
||||
}
|
||||
|
||||
ParticleUtils.spawnParticles(UParticles.CHANGELING_MAGIC, living, 7);
|
||||
ParticleUtils.spawnParticles(new FollowingParticleEffect(UParticles.HEALTH_DRAIN, changeling.asEntity(), 0.2F), living, 1);
|
||||
|
||||
if (changeling.asEntity().hasStatusEffect(StatusEffects.NAUSEA)) {
|
||||
StatusEffectInstance effect = changeling.asEntity().getStatusEffect(StatusEffects.NAUSEA);
|
||||
changeling.asEntity().removeStatusEffect(StatusEffects.NAUSEA);
|
||||
living.addStatusEffect(effect);
|
||||
} else if (changeling.asWorld().random.nextInt(2300) == 0) {
|
||||
living.addStatusEffect(new StatusEffectInstance(StatusEffects.WITHER, 20, 1));
|
||||
}
|
||||
|
||||
if (living instanceof PlayerEntity) {
|
||||
damage ++;
|
||||
damage *= 1.6F;
|
||||
|
||||
if (!changeling.asEntity().hasStatusEffect(StatusEffects.HEALTH_BOOST)) {
|
||||
changeling.asEntity().addStatusEffect(new StatusEffectInstance(StatusEffects.HEALTH_BOOST, 13000, 1));
|
||||
}
|
||||
}
|
||||
|
||||
return damage;
|
||||
protected Stream<Entity> getTargets(Pony player) {
|
||||
return Stream.concat(
|
||||
VecHelper.findInRange(player.asEntity(), player.asWorld(), player.getOriginVector(), 3, TARGET_PREDICATE).stream(),
|
||||
TraceHelper.findEntity(player.asEntity(), 17, 1, TARGET_PREDICATE).stream()
|
||||
).distinct();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,22 +1,37 @@
|
|||
package com.minelittlepony.unicopia.ability;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import com.minelittlepony.unicopia.Race;
|
||||
import java.util.function.DoubleSupplier;
|
||||
import java.util.function.Supplier;
|
||||
import com.minelittlepony.unicopia.USounds;
|
||||
import com.minelittlepony.unicopia.UTags;
|
||||
import com.minelittlepony.unicopia.ability.data.Hit;
|
||||
import com.minelittlepony.unicopia.ability.data.Pos;
|
||||
import com.minelittlepony.unicopia.block.UBlocks;
|
||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
import com.minelittlepony.unicopia.particle.MagicParticleEffect;
|
||||
import com.minelittlepony.unicopia.particle.ParticleUtils;
|
||||
import com.minelittlepony.unicopia.recipe.TransformCropsRecipe;
|
||||
import com.minelittlepony.unicopia.recipe.URecipes;
|
||||
import com.minelittlepony.unicopia.server.world.BlockDestructionManager;
|
||||
import com.minelittlepony.unicopia.server.world.ModificationType;
|
||||
import com.minelittlepony.unicopia.util.TraceHelper;
|
||||
import com.minelittlepony.unicopia.util.VecHelper;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.block.CarrotsBlock;
|
||||
import net.minecraft.block.FarmlandBlock;
|
||||
import net.minecraft.item.BoneMealItem;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.particle.ParticleTypes;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.WorldEvents;
|
||||
|
||||
/**
|
||||
* Earth Pony ability to grow crops
|
||||
|
@ -33,11 +48,6 @@ public class EarthPonyGrowAbility implements Ability<Pos> {
|
|||
return 50;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canUse(Race race) {
|
||||
return race.canUseEarth();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Pos> prepare(Pony player) {
|
||||
return TraceHelper.findBlock(player.asEntity(), 3, 1).map(Pos::new);
|
||||
|
@ -57,10 +67,16 @@ public class EarthPonyGrowAbility implements Ability<Pos> {
|
|||
public boolean apply(Pony player, Pos data) {
|
||||
int count = 0;
|
||||
|
||||
for (BlockPos pos : BlockPos.iterate(
|
||||
data.pos().add(-2, -2, -2),
|
||||
data.pos().add( 2, 2, 2))) {
|
||||
count += applySingle(player.asWorld(), player.asWorld().getBlockState(pos), pos);
|
||||
if (!applyDirectly(player, data.pos())) {
|
||||
for (BlockPos pos : BlockPos.iterate(
|
||||
data.pos().add(-2, -2, -2),
|
||||
data.pos().add( 2, 2, 2))) {
|
||||
if (player.canModifyAt(pos, ModificationType.PHYSICAL)) {
|
||||
count += applySingle(player, player.asWorld(), player.asWorld().getBlockState(pos), pos);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
count = 1;
|
||||
}
|
||||
|
||||
if (count > 0) {
|
||||
|
@ -69,7 +85,7 @@ public class EarthPonyGrowAbility implements Ability<Pos> {
|
|||
return true;
|
||||
}
|
||||
|
||||
protected int applySingle(World w, BlockState state, BlockPos pos) {
|
||||
protected int applySingle(Pony player, World w, BlockState state, BlockPos pos) {
|
||||
|
||||
ItemStack stack = new ItemStack(Items.BONE_MEAL);
|
||||
|
||||
|
@ -77,12 +93,33 @@ public class EarthPonyGrowAbility implements Ability<Pos> {
|
|||
return growable.grow(w, state, pos) ? 1 : 0;
|
||||
}
|
||||
|
||||
if (state.isOf(Blocks.CARROTS)) {
|
||||
if (state.get(CarrotsBlock.AGE) == CarrotsBlock.MAX_AGE) {
|
||||
boolean transform = w.random.nextInt(3) == 0;
|
||||
spawnConversionParticles(w, pos, transform);
|
||||
if (transform) {
|
||||
w.setBlockState(pos, UBlocks.GOLD_ROOT.getDefaultState().with(CarrotsBlock.AGE, CarrotsBlock.MAX_AGE));
|
||||
}
|
||||
|
||||
return 5;
|
||||
}
|
||||
}
|
||||
|
||||
if (w.getBlockState(pos).isIn(UTags.Blocks.UNAFFECTED_BY_GROW_ABILITY)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (BoneMealItem.useOnFertilizable(stack, w, pos)) {
|
||||
if (w.random.nextInt(350) == 0) {
|
||||
if (w.getBlockState(pos.down()).isOf(Blocks.FARMLAND)) {
|
||||
w.setBlockState(pos.down(), Blocks.DIRT.getDefaultState());
|
||||
FarmlandBlock.setToDirt(null, state, w, pos.down());
|
||||
}
|
||||
w.setBlockState(pos, UBlocks.PLUNDER_VINE_BUD.getDefaultState());
|
||||
} else if (w.random.nextInt(5000) == 0) {
|
||||
if (w.getBlockState(pos.down()).isOf(Blocks.FARMLAND)) {
|
||||
FarmlandBlock.setToDirt(null, state, w, pos.down());
|
||||
}
|
||||
UBlocks.CURING_JOKE.grow(w, state, pos);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
@ -94,6 +131,56 @@ public class EarthPonyGrowAbility implements Ability<Pos> {
|
|||
return 0;
|
||||
}
|
||||
|
||||
private boolean applyDirectly(Pony player, BlockPos pos) {
|
||||
return player.asWorld().getRecipeManager()
|
||||
.getAllMatches(URecipes.GROWING, new TransformCropsRecipe.PlacementArea(player, pos), player.asWorld())
|
||||
.stream()
|
||||
.map(recipe -> recipe.value().checkPattern(player.asWorld(), pos))
|
||||
.filter(result -> result.matchedLocations().size() + 1 >= TransformCropsRecipe.MINIMUM_INPUT)
|
||||
.filter(result -> {
|
||||
boolean transform = result.shoudTransform(player.asWorld().random);
|
||||
|
||||
player.playSound(USounds.ENTITY_CRYSTAL_SHARDS_AMBIENT, 1);
|
||||
|
||||
result.matchedLocations().forEach(cell -> {
|
||||
spawnConversionParticles(player.asWorld(), cell.up(), false);
|
||||
BlockDestructionManager manager = BlockDestructionManager.of(player.asWorld());
|
||||
if (transform) {
|
||||
if (manager.damageBlock(cell, 8) >= BlockDestructionManager.MAX_DAMAGE || player.asWorld().random.nextInt(20) == 0) {
|
||||
player.asWorld().setBlockState(cell, Blocks.DIRT.getDefaultState());
|
||||
player.asWorld().syncWorldEvent(WorldEvents.BLOCK_BROKEN, cell, Block.getRawIdFromState(player.asWorld().getBlockState(cell)));
|
||||
}
|
||||
} else {
|
||||
if (manager.damageBlock(cell, 4) >= BlockDestructionManager.MAX_DAMAGE || player.asWorld().random.nextInt(20) == 0) {
|
||||
player.asWorld().setBlockState(cell, Blocks.DIRT.getDefaultState());
|
||||
player.asWorld().syncWorldEvent(WorldEvents.BLOCK_BROKEN, cell, Block.getRawIdFromState(player.asWorld().getBlockState(cell)));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
spawnConversionParticles(player.asWorld(), pos, transform);
|
||||
if (transform) {
|
||||
player.asWorld().setBlockState(pos, result.recipe().getResult(player.asWorld(), pos));
|
||||
}
|
||||
|
||||
return true;
|
||||
})
|
||||
.findFirst()
|
||||
.isPresent();
|
||||
}
|
||||
|
||||
private static void spawnConversionParticles(World w, BlockPos pos, boolean success) {
|
||||
DoubleSupplier vecComponentFactory = () -> w.random.nextTriangular(0, 0.5);
|
||||
Supplier<Vec3d> posSupplier = () -> pos.toCenterPos().add(VecHelper.supply(vecComponentFactory));
|
||||
|
||||
for (int i = 0; i < 25; i++) {
|
||||
ParticleUtils.spawnParticle(w, new MagicParticleEffect(0xFFFF00), posSupplier.get(), Vec3d.ZERO);
|
||||
if (success) {
|
||||
ParticleUtils.spawnParticle(w, ParticleTypes.CLOUD, posSupplier.get(), Vec3d.ZERO);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warmUp(Pony player, AbilitySlot slot) {
|
||||
player.getMagicalReserves().getExertion().addPercent(30);
|
||||
|
|
|
@ -17,6 +17,7 @@ import com.minelittlepony.unicopia.entity.player.Pony;
|
|||
import com.minelittlepony.unicopia.particle.ParticleUtils;
|
||||
import com.minelittlepony.unicopia.particle.UParticles;
|
||||
import com.minelittlepony.unicopia.server.world.BlockDestructionManager;
|
||||
import com.minelittlepony.unicopia.server.world.ModificationType;
|
||||
import com.minelittlepony.unicopia.util.*;
|
||||
|
||||
import net.minecraft.block.BeehiveBlock;
|
||||
|
@ -53,15 +54,10 @@ public class EarthPonyKickAbility implements Ability<Pos> {
|
|||
return 50;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canUse(Race race) {
|
||||
return race.canUseEarth();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier getIcon(Pony player) {
|
||||
return getId().withPath(p -> "textures/gui/ability/" + p
|
||||
+ "_" + player.getObservedSpecies().getId().getPath()
|
||||
+ "_" + (player.getObservedSpecies().isHuman() ? Race.EARTH : player.getObservedSpecies()).getId().getPath()
|
||||
+ "_" + (getKickDirection(player) > 0 ? "forward" : "backward")
|
||||
+ ".png");
|
||||
}
|
||||
|
@ -103,7 +99,7 @@ public class EarthPonyKickAbility implements Ability<Pos> {
|
|||
}
|
||||
|
||||
BlockPos pos = kickLocation.pos();
|
||||
EarthPonyStompAbility.stompBlock(w, pos, 10 * (1 + player.getLevel().getScaled(5)) * w.getBlockState(pos).calcBlockBreakingDelta(player.asEntity(), w, pos));
|
||||
EarthPonyStompAbility.stompBlock(player, w, pos, 10 * (1 + player.getLevel().getScaled(5)) * w.getBlockState(pos).calcBlockBreakingDelta(player.asEntity(), w, pos));
|
||||
player.setAnimation(Animation.KICK, Animation.Recipient.ANYONE);
|
||||
});
|
||||
}
|
||||
|
@ -121,6 +117,11 @@ public class EarthPonyKickAbility implements Ability<Pos> {
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptsQuickAction(Pony player, ActivationType type) {
|
||||
return type == ActivationType.NONE || type == ActivationType.TAP || type == ActivationType.DOUBLE_TAP;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Optional<Pos> prepare(Pony player) {
|
||||
|
@ -165,10 +166,16 @@ public class EarthPonyKickAbility implements Ability<Pos> {
|
|||
|
||||
if (BlockDestructionManager.of(player.getWorld()).getBlockDestruction(pos) + 4 >= BlockDestructionManager.MAX_DAMAGE) {
|
||||
if (player.getWorld().random.nextInt(30) == 0) {
|
||||
tree.logs().forEach(player.getWorld(), (w, state, p) -> w.breakBlock(p, true));
|
||||
tree.logs().forEach(player.getWorld(), (w, state, p) -> {
|
||||
if (iplayer.canModifyAt(p, ModificationType.PHYSICAL)) {
|
||||
w.breakBlock(p, true);
|
||||
}
|
||||
});
|
||||
tree.leaves().forEach(player.getWorld(), (w, state, p) -> {
|
||||
Block.dropStacks(w.getBlockState(p), w, p);
|
||||
w.setBlockState(p, Blocks.AIR.getDefaultState(), Block.NOTIFY_ALL);
|
||||
if (iplayer.canModifyAt(p, ModificationType.PHYSICAL)) {
|
||||
Block.dropStacks(w.getBlockState(p), w, p);
|
||||
w.setBlockState(p, Blocks.AIR.getDefaultState(), Block.NOTIFY_ALL);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -6,8 +6,11 @@ import org.jetbrains.annotations.Nullable;
|
|||
|
||||
import com.minelittlepony.unicopia.AwaitTickQueue;
|
||||
import com.minelittlepony.unicopia.Race;
|
||||
import com.minelittlepony.unicopia.USounds;
|
||||
import com.minelittlepony.unicopia.UTags;
|
||||
import com.minelittlepony.unicopia.ability.data.Hit;
|
||||
import com.minelittlepony.unicopia.client.render.PlayerPoser.Animation;
|
||||
import com.minelittlepony.unicopia.entity.LandingEventHandler;
|
||||
import com.minelittlepony.unicopia.entity.Living;
|
||||
import com.minelittlepony.unicopia.entity.damage.UDamageTypes;
|
||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
|
@ -16,7 +19,9 @@ import com.minelittlepony.unicopia.item.enchantment.UEnchantments;
|
|||
import com.minelittlepony.unicopia.particle.ParticleUtils;
|
||||
import com.minelittlepony.unicopia.particle.UParticles;
|
||||
import com.minelittlepony.unicopia.server.world.BlockDestructionManager;
|
||||
import com.minelittlepony.unicopia.server.world.ModificationType;
|
||||
import com.minelittlepony.unicopia.util.PosHelper;
|
||||
import com.minelittlepony.unicopia.util.VecHelper;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
|
@ -26,6 +31,7 @@ import net.minecraft.entity.LivingEntity;
|
|||
import net.minecraft.entity.attribute.EntityAttributes;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.particle.BlockStateParticleEffect;
|
||||
import net.minecraft.registry.tag.BlockTags;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
@ -33,6 +39,7 @@ import net.minecraft.util.math.BlockBox;
|
|||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Box;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.WorldEvents;
|
||||
|
||||
|
@ -58,16 +65,12 @@ public class EarthPonyStompAbility implements Ability<Hit> {
|
|||
return 50;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canUse(Race race) {
|
||||
return race.canUseEarth();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier getIcon(Pony player) {
|
||||
Identifier id = Abilities.REGISTRY.getId(this);
|
||||
Race race = player.getObservedSpecies();
|
||||
return new Identifier(id.getNamespace(), "textures/gui/ability/" + id.getPath()
|
||||
+ "_" + player.getObservedSpecies().getId().getPath()
|
||||
+ "_" + (race.isHuman() ? Race.EARTH : race).getId().getPath()
|
||||
+ ".png");
|
||||
}
|
||||
|
||||
|
@ -80,7 +83,9 @@ public class EarthPonyStompAbility implements Ability<Hit> {
|
|||
@Override
|
||||
public Optional<Hit> prepare(Pony player) {
|
||||
if (player.asEntity().getVelocity().y * player.getPhysics().getGravitySignum() < 0
|
||||
&& !player.asEntity().getAbilities().flying) {
|
||||
&& !player.asEntity().getAbilities().flying
|
||||
&& !player.asEntity().isFallFlying()
|
||||
&& !player.asEntity().isUsingRiptide()) {
|
||||
thrustDownwards(player);
|
||||
return Hit.INSTANCE;
|
||||
}
|
||||
|
@ -104,69 +109,88 @@ public class EarthPonyStompAbility implements Ability<Hit> {
|
|||
|
||||
@Override
|
||||
public boolean apply(Pony iplayer, Hit data) {
|
||||
PlayerEntity player = iplayer.asEntity();
|
||||
final PlayerEntity player = iplayer.asEntity();
|
||||
final double initialY = player.getY() + 5;
|
||||
|
||||
Runnable r = () -> {
|
||||
BlockPos center = PosHelper.findSolidGroundAt(player.getEntityWorld(), player.getBlockPos(), iplayer.getPhysics().getGravitySignum());
|
||||
|
||||
float heavyness = 1 + EnchantmentHelper.getEquipmentLevel(UEnchantments.HEAVY, player);
|
||||
|
||||
iplayer.asWorld().getOtherEntities(player, areaOfEffect.offset(iplayer.getOriginVector())).forEach(i -> {
|
||||
double dist = Math.sqrt(center.getSquaredDistance(i.getBlockPos()));
|
||||
|
||||
if (dist <= rad + 3) {
|
||||
double inertia = 2 / dist;
|
||||
|
||||
if (i instanceof LivingEntity) {
|
||||
inertia *= 1 + EnchantmentHelper.getEquipmentLevel(UEnchantments.HEAVY, (LivingEntity)i);
|
||||
}
|
||||
inertia /= heavyness;
|
||||
|
||||
double liftAmount = Math.sin(Math.PI * dist / rad) * 12 * iplayer.getPhysics().getGravitySignum();
|
||||
|
||||
i.addVelocity(
|
||||
-(player.getX() - i.getX()) / inertia,
|
||||
-(player.getY() - i.getY() - liftAmount) / inertia + (dist < 1 ? dist : 0),
|
||||
-(player.getZ() - i.getZ()) / inertia);
|
||||
|
||||
double amount = (1.5F * player.getAttributeInstance(EntityAttributes.GENERIC_ATTACK_DAMAGE).getValue() + heavyness * 0.4) / (float)(dist * 1.3F);
|
||||
|
||||
if (i instanceof PlayerEntity) {
|
||||
Race.Composite race = Pony.of((PlayerEntity)i).getCompositeRace();
|
||||
if (race.canUseEarth()) {
|
||||
amount /= 3;
|
||||
}
|
||||
|
||||
if (race.canFly()) {
|
||||
amount *= 4;
|
||||
}
|
||||
}
|
||||
|
||||
if (i instanceof LivingEntity) {
|
||||
amount /= 1 + (EnchantmentHelper.getEquipmentLevel(UEnchantments.PADDED, (LivingEntity)i) / 6F);
|
||||
}
|
||||
|
||||
i.damage(iplayer.damageOf(UDamageTypes.SMASH, iplayer), (float)amount);
|
||||
Living.updateVelocity(i);
|
||||
var r = new LandingEventHandler.Callback() {
|
||||
@Override
|
||||
public float dispatch(float fallDistance) {
|
||||
// fail if landing above the starting position
|
||||
if (player.getY() > initialY) {
|
||||
return fallDistance;
|
||||
}
|
||||
});
|
||||
|
||||
double radius = rad + heavyness * 0.3;
|
||||
player.fallDistance = 0;
|
||||
BlockPos center = PosHelper.findSolidGroundAt(player.getEntityWorld(), player.getBlockPos(), iplayer.getPhysics().getGravitySignum());
|
||||
|
||||
spawnEffectAround(player, center, radius, rad);
|
||||
float heavyness = 1 + EnchantmentHelper.getEquipmentLevel(UEnchantments.HEAVY, player);
|
||||
|
||||
ParticleUtils.spawnParticle(player.getWorld(), UParticles.GROUND_POUND, player.getX(), player.getY() - 1, player.getZ(), 0, 0, 0);
|
||||
ParticleUtils.spawnParticle(player.getWorld(), UParticles.SHOCKWAVE, player.getX(), player.getY() - 1, player.getZ(), 0, 0, 0);
|
||||
iplayer.asWorld().getOtherEntities(player, areaOfEffect.offset(iplayer.getOriginVector())).forEach(i -> {
|
||||
double dist = Math.sqrt(center.getSquaredDistance(i.getBlockPos()));
|
||||
|
||||
iplayer.subtractEnergyCost(rad);
|
||||
iplayer.asEntity().addExhaustion(3);
|
||||
if (dist <= rad + 3) {
|
||||
double inertia = 2 / dist;
|
||||
|
||||
if (i instanceof LivingEntity) {
|
||||
inertia *= 1 + EnchantmentHelper.getEquipmentLevel(UEnchantments.HEAVY, (LivingEntity)i);
|
||||
}
|
||||
inertia /= heavyness;
|
||||
|
||||
double liftAmount = Math.sin(Math.PI * dist / rad) * 12 * iplayer.getPhysics().getGravitySignum();
|
||||
|
||||
i.addVelocity(
|
||||
-(player.getX() - i.getX()) / inertia,
|
||||
-(player.getY() - i.getY() - liftAmount) / inertia + (dist < 1 ? dist : 0),
|
||||
-(player.getZ() - i.getZ()) / inertia);
|
||||
|
||||
double amount = (1.5F * player.getAttributeInstance(EntityAttributes.GENERIC_ATTACK_DAMAGE).getValue() + heavyness * 0.4) / (float)(dist * 1.3F);
|
||||
|
||||
if (i instanceof PlayerEntity) {
|
||||
Race.Composite race = Pony.of((PlayerEntity)i).getCompositeRace();
|
||||
if (race.canUseEarth()) {
|
||||
amount /= 3;
|
||||
}
|
||||
|
||||
if (race.canFly()) {
|
||||
amount *= 4;
|
||||
}
|
||||
}
|
||||
|
||||
if (i instanceof LivingEntity) {
|
||||
amount /= 1 + (EnchantmentHelper.getEquipmentLevel(UEnchantments.PADDED, (LivingEntity)i) / 6F);
|
||||
}
|
||||
|
||||
i.damage(iplayer.damageOf(UDamageTypes.SMASH, iplayer), (float)amount);
|
||||
Living.updateVelocity(i);
|
||||
}
|
||||
});
|
||||
|
||||
double radius = rad + heavyness * 0.3;
|
||||
|
||||
spawnEffectAround(iplayer, player, center, radius, rad);
|
||||
|
||||
ParticleUtils.spawnParticle(player.getWorld(), UParticles.GROUND_POUND, player.getX(), player.getY() - 1, player.getZ(), 0, 0, 0);
|
||||
BlockState steppingState = player.getSteppingBlockState();
|
||||
if (steppingState.isIn(UTags.Blocks.KICKS_UP_DUST)) {
|
||||
ParticleUtils.spawnParticle(player.getWorld(), new BlockStateParticleEffect(UParticles.DUST_CLOUD, steppingState), player.getBlockPos().down().toCenterPos(), Vec3d.ZERO);
|
||||
}
|
||||
|
||||
iplayer.subtractEnergyCost(rad);
|
||||
iplayer.asEntity().addExhaustion(3);
|
||||
return 0F;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancelled() {
|
||||
iplayer.playSound(USounds.GUI_ABILITY_FAIL, 1F);
|
||||
}
|
||||
};
|
||||
|
||||
if (iplayer.asEntity().isOnGround()) {
|
||||
iplayer.setAnimation(Animation.STOMP, Animation.Recipient.ANYONE, 10);
|
||||
iplayer.asEntity().jump();
|
||||
iplayer.updateVelocity();
|
||||
AwaitTickQueue.scheduleTask(iplayer.asWorld(), w -> r.run(), 5);
|
||||
AwaitTickQueue.scheduleTask(iplayer.asWorld(), w -> r.dispatch(0F), 5);
|
||||
} else {
|
||||
thrustDownwards(iplayer);
|
||||
iplayer.waitForFall(r);
|
||||
|
@ -175,17 +199,17 @@ public class EarthPonyStompAbility implements Ability<Hit> {
|
|||
return true;
|
||||
}
|
||||
|
||||
public static void spawnEffectAround(Entity source, BlockPos center, double radius, double range) {
|
||||
public static void spawnEffectAround(Pony pony, Entity source, BlockPos center, double radius, double range) {
|
||||
BlockPos.stream(new BlockBox(center).expand(MathHelper.ceil(radius))).forEach(i -> {
|
||||
double dist = Math.sqrt(i.getSquaredDistance(source.getX(), source.getY(), source.getZ()));
|
||||
|
||||
if (dist <= radius) {
|
||||
spawnEffect(source.getWorld(), i, dist, range);
|
||||
spawnEffect(pony, source.getWorld(), i, dist, range);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void spawnEffect(World w, BlockPos pos, double dist, double rad) {
|
||||
public static void spawnEffect(Pony pony, World w, BlockPos pos, double dist, double rad) {
|
||||
if (w.getBlockState(pos.up()).isAir()) {
|
||||
BlockState state = w.getBlockState(pos);
|
||||
|
||||
|
@ -193,18 +217,18 @@ public class EarthPonyStompAbility implements Ability<Hit> {
|
|||
float scaledHardness = (1 - hardness / 70);
|
||||
float damage = hardness < 0 ? 0 : MathHelper.clamp((int)((1 - dist / rad) * 9 * scaledHardness), 0, BlockDestructionManager.MAX_DAMAGE - 1);
|
||||
|
||||
stompBlock(w, pos, damage);
|
||||
stompBlock(pony, w, pos, damage);
|
||||
}
|
||||
}
|
||||
|
||||
public static void stompBlock(World w, BlockPos pos, float damage) {
|
||||
public static void stompBlock(Pony pony, World w, BlockPos pos, float damage) {
|
||||
BlockState state = w.getBlockState(pos);
|
||||
|
||||
if (state.isAir() || damage <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (BlockDestructionManager.of(w).damageBlock(pos, damage) >= BlockDestructionManager.MAX_DAMAGE) {
|
||||
if (BlockDestructionManager.of(w).damageBlock(pos, damage) >= BlockDestructionManager.MAX_DAMAGE && pony.canModifyAt(pos, ModificationType.PHYSICAL)) {
|
||||
w.breakBlock(pos, true);
|
||||
|
||||
if (w instanceof ServerWorld) {
|
||||
|
@ -218,6 +242,12 @@ public class EarthPonyStompAbility implements Ability<Hit> {
|
|||
} else {
|
||||
w.syncWorldEvent(WorldEvents.BLOCK_BROKEN, pos, Block.getRawIdFromState(state));
|
||||
}
|
||||
|
||||
if (state.isIn(UTags.Blocks.KICKS_UP_DUST)) {
|
||||
if (w.random.nextInt(4) == 0 && w.isAir(pos.up()) && w.getFluidState(pos.up()).isEmpty()) {
|
||||
ParticleUtils.spawnParticle(w, new BlockStateParticleEffect(UParticles.DUST_CLOUD, state), pos.up().toCenterPos(), VecHelper.supply(() -> w.random.nextTriangular(0, 0.1F)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -4,7 +4,6 @@ import java.util.Optional;
|
|||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.minelittlepony.unicopia.Race;
|
||||
import com.minelittlepony.unicopia.ability.data.Hit;
|
||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
|
||||
|
@ -23,11 +22,6 @@ public class FlyingDashAbility implements Ability<Hit> {
|
|||
return 30;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canUse(Race race) {
|
||||
return race == Race.HIPPOGRIFF;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Optional<Hit> prepare(Pony player) {
|
||||
|
@ -55,6 +49,11 @@ public class FlyingDashAbility implements Ability<Hit> {
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptsQuickAction(Pony player, ActivationType type) {
|
||||
return type == ActivationType.NONE || type == ActivationType.TAP;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Pony player, Hit data) {
|
||||
player.getPhysics().dashForward((float)player.asWorld().random.nextTriangular(2.5F, 0.3F));
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package com.minelittlepony.unicopia.ability;
|
||||
|
||||
import com.minelittlepony.unicopia.Race;
|
||||
import com.minelittlepony.unicopia.ability.data.Hit;
|
||||
import com.minelittlepony.unicopia.client.render.PlayerPoser.Animation;
|
||||
import com.minelittlepony.unicopia.entity.Living;
|
||||
|
@ -16,12 +15,6 @@ import net.minecraft.particle.ParticleTypes;
|
|||
* Ability to hug mobs. Not all of them are receptive to your advances though, so be careful!
|
||||
*/
|
||||
public class HugAbility extends CarryAbility {
|
||||
|
||||
@Override
|
||||
public boolean canUse(Race race) {
|
||||
return race.canUseEarth();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Pony pony, Hit data) {
|
||||
PlayerEntity player = pony.asEntity();
|
||||
|
|
|
@ -1,16 +1,10 @@
|
|||
package com.minelittlepony.unicopia.ability;
|
||||
|
||||
import com.minelittlepony.unicopia.Race;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType;
|
||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
import net.minecraft.particle.ParticleTypes;
|
||||
|
||||
public class KirinCastingAbility extends UnicornCastingAbility {
|
||||
@Override
|
||||
public boolean canUse(Race race) {
|
||||
return race == Race.KIRIN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void coolDown(Pony player, AbilitySlot slot) {
|
||||
player.spawnParticles(ParticleTypes.FLAME, 5);
|
||||
|
|
|
@ -4,7 +4,6 @@ import java.util.Optional;
|
|||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.minelittlepony.unicopia.Race;
|
||||
import com.minelittlepony.unicopia.USounds;
|
||||
import com.minelittlepony.unicopia.ability.data.Hit;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.CastingMethod;
|
||||
|
@ -30,11 +29,6 @@ public class KirinRageAbility implements Ability<Hit> {
|
|||
return 60;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canUse(Race race) {
|
||||
return race == Race.KIRIN;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Optional<Hit> prepare(Pony player) {
|
||||
|
|
|
@ -5,7 +5,6 @@ import java.util.Optional;
|
|||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.minelittlepony.unicopia.EquinePredicates;
|
||||
import com.minelittlepony.unicopia.Race;
|
||||
import com.minelittlepony.unicopia.ability.data.Hit;
|
||||
import com.minelittlepony.unicopia.client.render.PlayerPoser.Animation;
|
||||
import com.minelittlepony.unicopia.client.render.PlayerPoser.Animation.Recipient;
|
||||
|
@ -36,11 +35,6 @@ public class NirikBlastAbility implements Ability<Hit> {
|
|||
return 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canUse(Race race) {
|
||||
return race == Race.KIRIN;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Optional<Hit> prepare(Pony player) {
|
||||
|
|
|
@ -3,7 +3,6 @@ package com.minelittlepony.unicopia.ability;
|
|||
import java.util.Optional;
|
||||
|
||||
import com.minelittlepony.unicopia.EquinePredicates;
|
||||
import com.minelittlepony.unicopia.Race;
|
||||
import com.minelittlepony.unicopia.USounds;
|
||||
import com.minelittlepony.unicopia.ability.data.Hit;
|
||||
import com.minelittlepony.unicopia.ability.data.Numeric;
|
||||
|
@ -54,11 +53,6 @@ public class PeckAbility implements Ability<Hit> {
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canUse(Race race) {
|
||||
return race == Race.HIPPOGRIFF;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Hit> prepare(Pony player) {
|
||||
return Hit.INSTANCE;
|
||||
|
|
|
@ -4,7 +4,6 @@ import java.util.Optional;
|
|||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.minelittlepony.unicopia.Race;
|
||||
import com.minelittlepony.unicopia.ability.data.Hit;
|
||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
import com.minelittlepony.unicopia.item.UItems;
|
||||
|
@ -33,11 +32,6 @@ public class PegasusCaptureStormAbility implements Ability<Hit> {
|
|||
return 6;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canUse(Race race) {
|
||||
return race.canInteractWithClouds();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Optional<Hit> prepare(Pony player) {
|
||||
|
|
|
@ -4,16 +4,11 @@ import java.util.Optional;
|
|||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.minelittlepony.unicopia.Race;
|
||||
import com.minelittlepony.unicopia.ability.data.Hit;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.CastingMethod;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType;
|
||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
import com.minelittlepony.unicopia.particle.MagicParticleEffect;
|
||||
import com.minelittlepony.unicopia.particle.OrientedBillboardParticleEffect;
|
||||
import com.minelittlepony.unicopia.particle.UParticles;
|
||||
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
/**
|
||||
* Pegasus ability to perform rainbooms
|
||||
|
@ -30,11 +25,6 @@ public class PegasusRainboomAbility implements Ability<Hit> {
|
|||
return 60;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canUse(Race race) {
|
||||
return race.canInteractWithClouds();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Optional<Hit> prepare(Pony player) {
|
||||
|
@ -64,6 +54,11 @@ public class PegasusRainboomAbility implements Ability<Hit> {
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptsQuickAction(Pony player, ActivationType type) {
|
||||
return type == ActivationType.NONE || type == ActivationType.TAP;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Pony player, Hit data) {
|
||||
|
||||
|
@ -72,7 +67,6 @@ public class PegasusRainboomAbility implements Ability<Hit> {
|
|||
}
|
||||
|
||||
if (player.consumeSuperMove()) {
|
||||
player.addParticle(new OrientedBillboardParticleEffect(UParticles.RAINBOOM_RING, player.getPhysics().getMotionAngle()), player.getOriginVector(), Vec3d.ZERO);
|
||||
SpellType.RAINBOOM.withTraits().apply(player, CastingMethod.INNATE);
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -3,12 +3,12 @@ package com.minelittlepony.unicopia.ability;
|
|||
import java.util.Optional;
|
||||
|
||||
import com.minelittlepony.unicopia.EquinePredicates;
|
||||
import com.minelittlepony.unicopia.Race;
|
||||
import com.minelittlepony.unicopia.USounds;
|
||||
import com.minelittlepony.unicopia.UTags;
|
||||
import com.minelittlepony.unicopia.ability.data.Numeric;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType;
|
||||
import com.minelittlepony.unicopia.advancement.UCriteria;
|
||||
import com.minelittlepony.unicopia.client.minelittlepony.MineLPDelegate;
|
||||
import com.minelittlepony.unicopia.client.render.PlayerPoser.Animation;
|
||||
import com.minelittlepony.unicopia.entity.Living;
|
||||
import com.minelittlepony.unicopia.entity.damage.UDamageTypes;
|
||||
|
@ -49,11 +49,6 @@ public class ScreechAbility implements Ability<Numeric> {
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canUse(Race race) {
|
||||
return race == Race.HIPPOGRIFF;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Numeric> prepare(Pony player) {
|
||||
return player.getAbilities().getActiveStat()
|
||||
|
@ -98,7 +93,7 @@ public class ScreechAbility implements Ability<Numeric> {
|
|||
(1.2F + (rng.nextFloat() - 0.5F) / 2F) * strength,
|
||||
1.1F + (rng.nextFloat() - 0.5F)
|
||||
);
|
||||
player.asWorld().emitGameEvent(player.asEntity(), GameEvent.ENTITY_ROAR, player.asEntity().getEyePos());
|
||||
player.asWorld().emitGameEvent(player.asEntity(), GameEvent.ENTITY_ACTION, player.asEntity().getEyePos());
|
||||
}
|
||||
|
||||
protected void spookMob(Pony player, LivingEntity living, float strength) {
|
||||
|
@ -110,7 +105,7 @@ public class ScreechAbility implements Ability<Numeric> {
|
|||
|
||||
|
||||
if (living.getWorld().random.nextInt(MOB_SPOOK_PROBABILITY) == 0) {
|
||||
RegistryUtils.pickRandom(living.getWorld(), UTags.SPOOKED_MOB_DROPS).ifPresent(drop -> {
|
||||
RegistryUtils.pickRandom(living.getWorld(), UTags.Items.SPOOKED_MOB_DROPS).ifPresent(drop -> {
|
||||
living.dropStack(drop.getDefaultStack());
|
||||
living.playSound(USounds.Vanilla.ENTITY_ITEM_PICKUP, 1, 0.1F);
|
||||
UCriteria.SPOOK_MOB.trigger(player.asEntity());
|
||||
|
@ -132,8 +127,10 @@ public class ScreechAbility implements Ability<Numeric> {
|
|||
|
||||
@Override
|
||||
public void coolDown(Pony player, AbilitySlot slot) {
|
||||
Vec3d eyePos = player.asEntity().getPos().add(0, MineLPDelegate.getInstance().getPonyHeight(player.asEntity()) * 0.8, 0);
|
||||
|
||||
for (int i = 0; i < 20; i++) {
|
||||
player.addParticle(ParticleTypes.BUBBLE_POP, player.asEntity().getEyePos(),
|
||||
player.addParticle(ParticleTypes.BUBBLE_POP, eyePos,
|
||||
VecHelper.supply(() -> (player.asWorld().getRandom().nextGaussian() - 0.5) * 0.3)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ import java.util.Optional;
|
|||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.minelittlepony.unicopia.AwaitTickQueue;
|
||||
import com.minelittlepony.unicopia.Race;
|
||||
import com.minelittlepony.unicopia.UPOIs;
|
||||
import com.minelittlepony.unicopia.USounds;
|
||||
import com.minelittlepony.unicopia.ability.data.Hit;
|
||||
|
@ -13,6 +12,8 @@ import com.minelittlepony.unicopia.client.render.PlayerPoser.Animation;
|
|||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
import com.minelittlepony.unicopia.particle.ParticleUtils;
|
||||
import com.minelittlepony.unicopia.particle.UParticles;
|
||||
|
||||
import net.minecraft.block.ChestBlock;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityGroup;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
|
@ -36,11 +37,6 @@ public class SeaponySonarPulseAbility implements Ability<Hit> {
|
|||
return 100;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canUse(Race race) {
|
||||
return race == Race.SEAPONY;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Optional<Hit> prepare(Pony player) {
|
||||
|
@ -78,8 +74,8 @@ public class SeaponySonarPulseAbility implements Ability<Hit> {
|
|||
|
||||
if (player.asWorld() instanceof ServerWorld sw) {
|
||||
sw.getPointOfInterestStorage().getNearestPosition(
|
||||
type -> type.value() == UPOIs.CHESTS,
|
||||
pos -> player.asWorld().getFluidState(pos).isIn(FluidTags.WATER), player.getOrigin(), 64, OccupationStatus.ANY)
|
||||
UPOIs::isChest,
|
||||
pos -> player.asWorld().getFluidState(pos).isIn(FluidTags.WATER) && (player.asWorld().getBlockState(pos).getBlock() instanceof ChestBlock), player.getOrigin(), 64, OccupationStatus.ANY)
|
||||
.ifPresent(chestPos -> {
|
||||
emitPing(player, chestPos.toCenterPos(), 20, 0.5F, 2F);
|
||||
});
|
||||
|
|
|
@ -12,14 +12,9 @@ import com.minelittlepony.unicopia.server.world.UGameRules;
|
|||
|
||||
public class TimeChangeAbility implements Ability<Rot> {
|
||||
|
||||
@Override
|
||||
public boolean canUse(Race race) {
|
||||
return race == Race.ALICORN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canUse(Race.Composite race) {
|
||||
return race.pseudo() == Race.UNICORN;
|
||||
return canUse(race.physical()) || race.pseudo() == Race.UNICORN;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -62,9 +57,7 @@ public class TimeChangeAbility implements Ability<Rot> {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (player.getSpellSlot().contains(SpellType.TIME_CONTROL)) {
|
||||
player.getSpellSlot().removeWhere(SpellType.TIME_CONTROL, true);
|
||||
} else {
|
||||
if (!player.getSpellSlot().removeWhere(SpellType.TIME_CONTROL)) {
|
||||
SpellType.TIME_CONTROL.withTraits().apply(player, CastingMethod.INNATE).update(player, data.applyTo(player));
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import com.minelittlepony.unicopia.entity.Living;
|
|||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
public class ToggleFlightAbility implements Ability<Hit> {
|
||||
|
||||
|
@ -24,11 +25,6 @@ public class ToggleFlightAbility implements Ability<Hit> {
|
|||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canUse(Race race) {
|
||||
return race.canFly();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Optional<Hit> prepare(Pony player) {
|
||||
|
@ -43,9 +39,10 @@ public class ToggleFlightAbility implements Ability<Hit> {
|
|||
@Override
|
||||
public Identifier getIcon(Pony player) {
|
||||
Identifier id = Abilities.REGISTRY.getId(this);
|
||||
Race race = player.getObservedSpecies();
|
||||
return new Identifier(id.getNamespace(), "textures/gui/ability/" + id.getPath()
|
||||
+ (player.getPhysics().isFlying() ? "_land" : "_takeoff")
|
||||
+ "_" + player.getObservedSpecies().getId().getPath()
|
||||
+ "_" + (race.isHuman() ? Race.EARTH : race).getId().getPath()
|
||||
+ ".png");
|
||||
}
|
||||
|
||||
|
@ -63,13 +60,17 @@ public class ToggleFlightAbility implements Ability<Hit> {
|
|||
player.subtractEnergyCost(1);
|
||||
|
||||
if (!player.getPhysics().isFlying()) {
|
||||
if (player.asEntity().hasVehicle()) {
|
||||
Vec3d pos = player.asEntity().getPos();
|
||||
player.asEntity().stopRiding();
|
||||
player.asEntity().setPosition(pos.getX(), pos.getY() + 0.25, pos.getZ());
|
||||
}
|
||||
player.asEntity().addVelocity(0, player.getPhysics().getGravitySignum() * 0.7F, 0);
|
||||
Living.updateVelocity(player.asEntity());
|
||||
player.getPhysics().startFlying(true);
|
||||
} else {
|
||||
player.getPhysics().cancelFlight(true);
|
||||
}
|
||||
player.setDirty();
|
||||
player.setAnimation(Animation.SPREAD_WINGS, Animation.Recipient.ANYONE);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ public class UnicornCastingAbility extends AbstractSpellCastingAbility {
|
|||
|
||||
@Override
|
||||
public int getWarmupTime(Pony player) {
|
||||
return 20;
|
||||
return (int)(20 - Math.min(17F, player.getLevel().get() * 0.75F));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -100,12 +100,21 @@ public class UnicornCastingAbility extends AbstractSpellCastingAbility {
|
|||
|
||||
if (newSpell.getResult() != ActionResult.FAIL && canCast(newSpell.getValue().type())) {
|
||||
CustomisedSpellType<?> spell = newSpell.getValue();
|
||||
if (newSpell.getResult() == ActionResult.CONSUME) {
|
||||
CustomisedSpellType<?> equippedType = player.getCharms().getEquippedSpell(player.getCharms().getHand());
|
||||
if (equippedType.type() == spell.type()) {
|
||||
player.getCharms().equipSpell(player.getCharms().getHand(), spell);
|
||||
}
|
||||
}
|
||||
|
||||
boolean removed = player.getSpellSlot().removeWhere(s -> {
|
||||
return s.findMatches(spell).findAny().isPresent() && (spell.isEmpty() || !SpellType.PLACED_SPELL.test(s));
|
||||
}, true);
|
||||
if (spell.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean has = !spell.isStackable() && player.getSpellSlot().contains(spell);
|
||||
boolean removed = !spell.isStackable() && player.getSpellSlot().removeWhere(spell.type());
|
||||
player.subtractEnergyCost(removed ? 2 : 4);
|
||||
if (!removed) {
|
||||
if (!has) {
|
||||
Spell s = spell.apply(player, CastingMethod.DIRECT);
|
||||
if (s == null) {
|
||||
player.spawnParticles(ParticleTypes.LARGE_SMOKE, 6);
|
||||
|
@ -113,7 +122,7 @@ public class UnicornCastingAbility extends AbstractSpellCastingAbility {
|
|||
} else {
|
||||
player.setAnimation(Animation.ARMS_UP, Animation.Recipient.HUMAN);
|
||||
if (s instanceof HomingSpell homer) {
|
||||
TraceHelper.findEntity(player.asEntity(), homer.getRange(player), 1, EquinePredicates.VALID_LIVING_AND_NOT_MAGIC_IMMUNE).ifPresent(homer::setTarget);
|
||||
TraceHelper.findEntity(player.asEntity(), homer.getRange(player), 1, EquinePredicates.EXCEPT_MAGIC_IMMUNE).ifPresent(homer::setTarget);
|
||||
}
|
||||
player.playSound(USounds.SPELL_CAST_SUCCESS, 0.05F, 2.2F);
|
||||
}
|
||||
|
|
|
@ -32,11 +32,6 @@ public class UnicornDispellAbility implements Ability<Pos> {
|
|||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canUse(Race race) {
|
||||
return race.canCast() || race == Race.CHANGELING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getColor(Pony player) {
|
||||
return SpellType.PORTAL.getColor();
|
||||
|
@ -68,7 +63,7 @@ public class UnicornDispellAbility implements Ability<Pos> {
|
|||
}
|
||||
|
||||
if (type == ActivationType.TAP && player.isClient()) {
|
||||
InteractionManager.instance().openScreen(InteractionManager.SCREEN_DISPELL_ABILITY);
|
||||
InteractionManager.getInstance().openScreen(InteractionManager.SCREEN_DISPELL_ABILITY);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -76,6 +71,11 @@ public class UnicornDispellAbility implements Ability<Pos> {
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptsQuickAction(Pony player, ActivationType type) {
|
||||
return type == ActivationType.NONE || (player.getSpecies() != Race.CHANGELING && type == ActivationType.TAP);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getCostEstimate(Pony player) {
|
||||
return getTarget(player)
|
||||
|
@ -92,7 +92,7 @@ public class UnicornDispellAbility implements Ability<Pos> {
|
|||
public boolean apply(Pony player, Pos data) {
|
||||
player.setAnimation(Animation.WOLOLO, Animation.Recipient.ANYONE);
|
||||
Caster.stream(VecHelper.findInRange(player.asEntity(), player.asWorld(), data.vec(), 3, EquinePredicates.IS_PLACED_SPELL).stream()).forEach(target -> {
|
||||
target.getSpellSlot().clear();
|
||||
target.getSpellSlot().clear(false);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ import net.minecraft.util.TypedActionResult;
|
|||
public class UnicornProjectileAbility extends AbstractSpellCastingAbility {
|
||||
@Override
|
||||
public int getWarmupTime(Pony player) {
|
||||
return 8;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -56,6 +56,11 @@ public class UnicornProjectileAbility extends AbstractSpellCastingAbility {
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptsQuickAction(Pony player, ActivationType type) {
|
||||
return type == ActivationType.NONE || type == ActivationType.DOUBLE_TAP;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Pony player, Hit data) {
|
||||
TypedActionResult<CustomisedSpellType<?>> thrown = player.getCharms().getSpellInHand(true);
|
||||
|
|
|
@ -2,12 +2,12 @@ package com.minelittlepony.unicopia.ability;
|
|||
|
||||
import java.util.Optional;
|
||||
|
||||
import com.minelittlepony.unicopia.Race;
|
||||
import com.minelittlepony.unicopia.USounds;
|
||||
import com.minelittlepony.unicopia.ability.data.Hit;
|
||||
import com.minelittlepony.unicopia.ability.data.Pos;
|
||||
import com.minelittlepony.unicopia.ability.magic.Caster;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType;
|
||||
import com.minelittlepony.unicopia.advancement.UCriteria;
|
||||
import com.minelittlepony.unicopia.block.state.StatePredicate;
|
||||
import com.minelittlepony.unicopia.entity.Living;
|
||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
|
@ -15,6 +15,9 @@ import com.minelittlepony.unicopia.particle.MagicParticleEffect;
|
|||
import com.minelittlepony.unicopia.util.Trace;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.block.LeavesBlock;
|
||||
import net.minecraft.block.PowderSnowBlock;
|
||||
import net.minecraft.block.ShapeContext;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
|
@ -23,6 +26,7 @@ import net.minecraft.sound.SoundCategory;
|
|||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.util.shape.VoxelShape;
|
||||
import net.minecraft.world.World;
|
||||
|
@ -47,17 +51,12 @@ public class UnicornTeleportAbility implements Ability<Pos> {
|
|||
|
||||
@Override
|
||||
public int getWarmupTime(Pony player) {
|
||||
return 20;
|
||||
return (int)(20 - Math.min(17F, player.getLevel().get() * 0.75F));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCooldownTime(Pony player) {
|
||||
return 50;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canUse(Race race) {
|
||||
return race.canCast() && race != Race.KIRIN;
|
||||
return (int)(50 - Math.min(45F, player.getLevel().get() * 0.75F));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -77,8 +76,7 @@ public class UnicornTeleportAbility implements Ability<Pos> {
|
|||
return Optional.empty();
|
||||
}
|
||||
|
||||
int maxDistance = player.asEntity().isCreative() ? 1000 : 100;
|
||||
|
||||
int maxDistance = (int)((player.asEntity().isCreative() ? 1000 : 100) + (player.getLevel().get() * 0.25F));
|
||||
|
||||
World w = player.asWorld();
|
||||
|
||||
|
@ -86,10 +84,18 @@ public class UnicornTeleportAbility implements Ability<Pos> {
|
|||
return trace.getBlockOrEntityPos().map(pos -> {
|
||||
final BlockPos originalPos = pos;
|
||||
|
||||
boolean airAbove = enterable(w, pos.up()) && enterable(w, pos.up(2));
|
||||
Direction globalUp = player.getPhysics().isGravityNegative() ? Direction.DOWN : Direction.UP;
|
||||
|
||||
if (exception(w, pos, player.asEntity())) {
|
||||
boolean originalPosHasSupport = exception(w, pos, player.asEntity());
|
||||
boolean originalPosValid = enterable(w, pos.offset(globalUp)) && enterable(w, pos.offset(globalUp, 2));
|
||||
|
||||
if (w.getBlockState(pos).isOf(Blocks.POWDER_SNOW) && !PowderSnowBlock.canWalkOnPowderSnow(player.asEntity())) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (originalPosHasSupport) {
|
||||
final BlockPos p = pos;
|
||||
// offset to adjacent
|
||||
pos = trace.getSide().map(sideHit -> {
|
||||
if (player.asEntity().isSneaking()) {
|
||||
sideHit = sideHit.getOpposite();
|
||||
|
@ -99,20 +105,24 @@ public class UnicornTeleportAbility implements Ability<Pos> {
|
|||
}).orElse(pos);
|
||||
}
|
||||
|
||||
if (enterable(w, pos.down())) {
|
||||
pos = pos.down();
|
||||
|
||||
if (enterable(w, pos.down())) {
|
||||
if (!airAbove) {
|
||||
return null;
|
||||
if (pos.getX() != originalPos.getX() || pos.getZ() != originalPos.getZ()) {
|
||||
// check support
|
||||
int steps = 0;
|
||||
while (enterable(w, pos.offset(globalUp.getOpposite()))) {
|
||||
pos = pos.offset(globalUp.getOpposite());
|
||||
if (++steps > 2) {
|
||||
if (originalPosValid) {
|
||||
pos = originalPos.offset(globalUp);
|
||||
break;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
pos = originalPos.up(2);
|
||||
}
|
||||
}
|
||||
|
||||
if ((!enterable(w, pos) && exception(w, pos, player.asEntity()))
|
||||
|| (!enterable(w, pos.up()) && exception(w, pos.up(), player.asEntity()))) {
|
||||
|| (!enterable(w, pos.offset(globalUp)) && exception(w, pos.offset(globalUp), player.asEntity()))) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -161,25 +171,37 @@ public class UnicornTeleportAbility implements Ability<Pos> {
|
|||
participant.getZ() - Math.floor(participant.getZ())
|
||||
);
|
||||
|
||||
Vec3d dest = destination.vec().add(offset);
|
||||
|
||||
participant.teleport(
|
||||
dest.x,
|
||||
getTargetYPosition(participant.getEntityWorld(), BlockPos.ofFloored(dest), ShapeContext.of(participant)),
|
||||
dest.z
|
||||
double yPos = getTargetYPosition(participant.getEntityWorld(), destination.pos(), ShapeContext.of(participant));
|
||||
Vec3d dest = new Vec3d(
|
||||
destination.x() + offset.getX(),
|
||||
yPos,
|
||||
destination.z() + offset.getZ()
|
||||
);
|
||||
participant.teleport(dest.x, dest.y, dest.z);
|
||||
if (participant.getWorld().getBlockCollisions(participant, participant.getBoundingBox()).iterator().hasNext()) {
|
||||
dest = destination.vec();
|
||||
participant.teleport(dest.x, participant.getY(), dest.z);
|
||||
}
|
||||
teleporter.subtractEnergyCost(distance);
|
||||
|
||||
participant.fallDistance /= distance;
|
||||
|
||||
participant.getWorld().playSound(null, destination.pos(), USounds.ENTITY_PLAYER_UNICORN_TELEPORT, SoundCategory.PLAYERS, 1, 1);
|
||||
BlockPos blockPos = BlockPos.ofFloored(dest);
|
||||
|
||||
participant.getWorld().playSound(null, blockPos, USounds.ENTITY_PLAYER_UNICORN_TELEPORT, SoundCategory.PLAYERS, 1, 1);
|
||||
if (!participant.getEntityWorld().isInBuildLimit(blockPos)) {
|
||||
UCriteria.TELEPORT_ABOVE_WORLD.trigger(teleporter.asEntity());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean enterable(World w, BlockPos pos) {
|
||||
BlockState state = w.getBlockState(pos);
|
||||
return w.isAir(pos) || !state.isOpaque();
|
||||
if (StatePredicate.isFluid(state) || state.getBlock() instanceof LeavesBlock) {
|
||||
return false;
|
||||
}
|
||||
return w.isAir(pos) || !state.isOpaque() || !state.shouldSuffocate(w, pos);
|
||||
}
|
||||
|
||||
private boolean exception(World w, BlockPos pos, PlayerEntity player) {
|
||||
|
@ -189,12 +211,12 @@ public class UnicornTeleportAbility implements Ability<Pos> {
|
|||
return state.hasSolidTopSurface(w, pos, player)
|
||||
|| StatePredicate.isFluid(state)
|
||||
|| (shape = state.getCollisionShape(w, pos, ShapeContext.of(player))).isEmpty()
|
||||
|| shape.getBoundingBox().getYLength() > 1;
|
||||
|| shape.getBoundingBox().getLengthY() > 1;
|
||||
}
|
||||
|
||||
private double getTargetYPosition(World world, BlockPos pos, ShapeContext context) {
|
||||
VoxelShape shape = world.getBlockState(pos).getCollisionShape(world, pos, context);
|
||||
return pos.getY() + (shape.isEmpty() ? 0 : shape.getBoundingBox().getYLength());
|
||||
return pos.getY() + (shape.isEmpty() ? 0 : shape.getBoundingBox().getLengthY());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -19,4 +19,8 @@ public interface Affine {
|
|||
default boolean isFriendlyTogether(Affine other) {
|
||||
return getAffinity() != Affinity.BAD && other.getAffinity() != Affinity.BAD;
|
||||
}
|
||||
|
||||
default boolean applyInversion(Affine other, boolean friendly) {
|
||||
return isEnemy(other) ? !friendly : friendly;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,17 +7,22 @@ import java.util.stream.Stream;
|
|||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.minelittlepony.unicopia.*;
|
||||
import com.minelittlepony.unicopia.ability.Ability;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.effect.AreaProtectionSpell;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType;
|
||||
import com.minelittlepony.unicopia.entity.*;
|
||||
import com.minelittlepony.unicopia.entity.damage.UDamageSources;
|
||||
import com.minelittlepony.unicopia.particle.ParticleSource;
|
||||
import com.minelittlepony.unicopia.server.world.Ether;
|
||||
import com.minelittlepony.unicopia.server.world.ModificationType;
|
||||
import com.minelittlepony.unicopia.server.world.OfflinePlayerCache;
|
||||
import com.minelittlepony.unicopia.util.SoundEmitter;
|
||||
import com.minelittlepony.unicopia.util.VecHelper;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.GameRules;
|
||||
|
@ -36,7 +41,7 @@ public interface Caster<E extends Entity> extends
|
|||
|
||||
Physics getPhysics();
|
||||
|
||||
SpellContainer getSpellSlot();
|
||||
SpellSlots getSpellSlot();
|
||||
|
||||
/**
|
||||
* Removes the desired amount of mana or health from this caster in exchange for a spell's benefits.
|
||||
|
@ -65,10 +70,18 @@ public interface Caster<E extends Entity> extends
|
|||
}
|
||||
|
||||
if (getMaster() instanceof PlayerEntity player) {
|
||||
if (!asWorld().canPlayerModifyAt(player, pos)) {
|
||||
if (!player.canModifyBlocks() || !asWorld().canPlayerModifyAt(player, pos)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (asWorld() instanceof ServerWorld sw) {
|
||||
@Nullable
|
||||
PlayerEntity player = OfflinePlayerCache.getOfflinePlayer(sw, getMasterId().orElse(null));
|
||||
if (player != null && !player.canModifyBlocks() || !sw.canPlayerModifyAt(player, pos)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!asWorld().getGameRules().getBoolean(GameRules.DO_MOB_GRIEFING)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -99,11 +112,23 @@ public interface Caster<E extends Entity> extends
|
|||
}
|
||||
|
||||
default boolean canCastAt(Vec3d pos) {
|
||||
return findAllSpellsInRange(500, SpellType.ARCANE_PROTECTION::isOn).noneMatch(caster -> caster
|
||||
.getSpellSlot().get(SpellType.ARCANE_PROTECTION, false)
|
||||
.filter(spell -> spell.blocksMagicFor(caster, this, pos))
|
||||
.isPresent()
|
||||
);
|
||||
return !Ether.get(asWorld()).anyMatch(SpellType.ARCANE_PROTECTION, entry -> {
|
||||
var target = entry.entity.getTarget().orElse(null);
|
||||
if (target != null && target.pos().distanceTo(pos) <= entry.getRadius()) {
|
||||
Caster<?> caster = entry.getCaster();
|
||||
if (caster != null) {
|
||||
AreaProtectionSpell spell = entry.getSpell();
|
||||
if (spell != null) {
|
||||
return spell.blocksMagicFor(caster, this, pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
default boolean canUse(Ability<?> ability) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static Stream<Caster<?>> stream(Stream<Entity> entities) {
|
||||
|
|
|
@ -1,44 +0,0 @@
|
|||
package com.minelittlepony.unicopia.ability.magic;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.minelittlepony.unicopia.EquinePredicates;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.Spell;
|
||||
import com.minelittlepony.unicopia.util.VecHelper;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.*;
|
||||
|
||||
public interface CasterView {
|
||||
EntityView getWorld();
|
||||
|
||||
default <S extends Spell> Stream<Map.Entry<Caster<?>, S>> findAllSpellsInRange(BlockPos pos, double radius, SpellPredicate<S> type) {
|
||||
return findAllCastersInRange(pos, radius).flatMap(caster -> {
|
||||
return caster.getSpellSlot().stream(type, false).map(spell -> {
|
||||
return Map.entry(caster, spell);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
default Stream<Caster<?>> findAllCastersInRange(BlockPos pos, double radius) {
|
||||
return findAllCastersInRange(pos, radius, null);
|
||||
}
|
||||
|
||||
default Stream<Caster<?>> findAllCastersInRange(BlockPos pos, double radius, @Nullable Predicate<Entity> test) {
|
||||
return Caster.stream(findAllEntitiesInRange(pos, radius, test == null ? EquinePredicates.IS_CASTER : EquinePredicates.IS_CASTER.and(test)));
|
||||
}
|
||||
|
||||
default Stream<Entity> findAllEntitiesInRange(BlockPos pos, double radius, @Nullable Predicate<Entity> test) {
|
||||
return VecHelper.findInRange(null, getWorld(), Vec3d.ofCenter(pos), radius, test).stream();
|
||||
}
|
||||
|
||||
default Stream<Entity> findAllEntitiesInRange(BlockPos pos, double radius) {
|
||||
return findAllEntitiesInRange(pos, radius, null);
|
||||
}
|
||||
}
|
|
@ -1,33 +1,32 @@
|
|||
package com.minelittlepony.unicopia.ability.magic;
|
||||
|
||||
import java.util.function.IntConsumer;
|
||||
import java.util.function.IntSupplier;
|
||||
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
|
||||
/**
|
||||
* Object with levelling capabilities.
|
||||
*/
|
||||
public interface Levelled {
|
||||
LevelStore EMPTY = fixed(0);
|
||||
LevelStore ZERO = of(0, 1);
|
||||
|
||||
static LevelStore fixed(int level) {
|
||||
return of(() -> level);
|
||||
}
|
||||
|
||||
static LevelStore of(IntSupplier supplier) {
|
||||
static LevelStore of(IntSupplier getter, IntConsumer setter, IntSupplier max) {
|
||||
return new LevelStore() {
|
||||
@Override
|
||||
public int get() {
|
||||
return supplier.getAsInt();
|
||||
return getter.getAsInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(int level) {
|
||||
setter.accept(level);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMax() {
|
||||
return get();
|
||||
return max.getAsInt();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -37,7 +36,9 @@ public interface Levelled {
|
|||
}
|
||||
|
||||
static LevelStore fromNbt(NbtCompound compound) {
|
||||
return of(compound.getInt("value"), compound.getInt("max"));
|
||||
int max = Math.max(1, compound.getInt("max"));
|
||||
int value = MathHelper.clamp(compound.getInt("value"), 0, max);
|
||||
return of(value, max);
|
||||
}
|
||||
|
||||
static LevelStore of(int level, int max) {
|
||||
|
@ -70,6 +71,9 @@ public interface Levelled {
|
|||
void set(int level);
|
||||
|
||||
default float getScaled(float max) {
|
||||
if (getMax() == 0) {
|
||||
return max;
|
||||
}
|
||||
return ((float)get() / getMax()) * max;
|
||||
}
|
||||
|
||||
|
|