mirror of
https://gitlab.com/cable-mc/cobblemon.git
synced 2026-10-23 23:56:24 -04:00
Compare commits
657
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bf50570ade | ||
|
|
8951816ddd | ||
|
|
bc668d84c9 | ||
|
|
b1290cbc38 | ||
|
|
2261cf1077 | ||
|
|
0ae427fd14 | ||
|
|
37a25c6b5a | ||
|
|
597080aac2 | ||
|
|
2ae2d9f53b | ||
|
|
38df6f4833 | ||
|
|
bed2e3035b | ||
|
|
a784aa38cb | ||
|
|
c18d853a55 | ||
|
|
d6581e9931 | ||
|
|
d7962e7d48 | ||
|
|
f3f6a9744b | ||
|
|
715112f8d9 | ||
|
|
278d0d6f96 | ||
|
|
95c26448bc | ||
|
|
8d99ebbcde | ||
|
|
4c024ac947 | ||
|
|
b4946e13f2 | ||
|
|
bc4af40a34 | ||
|
|
64ecec1a9a | ||
|
|
7f8ef38b64 | ||
|
|
e4360ca9b5 | ||
|
|
bc27ec7288 | ||
|
|
875f2d99ab | ||
|
|
a4d18eba89 | ||
|
|
edffc248f4 | ||
|
|
600bbfc5f3 | ||
|
|
692f1de510 | ||
|
|
e230dd740d | ||
|
|
e24008c89e | ||
|
|
ed29801820 | ||
|
|
a5fe51b8fa | ||
|
|
600cc48073 | ||
|
|
a4aa8f3778 | ||
|
|
2f16490aa8 | ||
|
|
ed82a72919 | ||
|
|
953163b12e | ||
|
|
aa57cd7e3e | ||
|
|
863baa5ae6 | ||
|
|
913ca3d467 | ||
|
|
22b541af10 | ||
|
|
c1a706ca69 | ||
|
|
47f8647d48 | ||
|
|
a0e01b9652 | ||
|
|
9d88fb7ca2 | ||
|
|
ca0170f1ed | ||
|
|
050f7e6161 | ||
|
|
658ec95e6b | ||
|
|
883f8149da | ||
|
|
e5e4871c96 | ||
|
|
e074411596 | ||
|
|
adf0ba7c9f | ||
|
|
3d8c22fd68 | ||
|
|
a966f0f9a6 | ||
|
|
da74990909 | ||
|
|
0e3102f5e4 | ||
|
|
36e3816bf3 | ||
|
|
99e47e4cb7 | ||
|
|
aa875b06ab | ||
|
|
dfb08c8db0 | ||
|
|
eefff036b7 | ||
|
|
43050b4276 | ||
|
|
b1b8c6e9db | ||
|
|
583a973e53 | ||
|
|
c0b945e3da | ||
|
|
fa73fb8e46 | ||
|
|
1fd9128b33 | ||
|
|
f9799ef55e | ||
|
|
ab69c4f095 | ||
|
|
a9a0fff643 | ||
|
|
9bdb8102c1 | ||
|
|
febcb7092a | ||
|
|
4ec8b01efb | ||
|
|
95b15d50c3 | ||
|
|
88d7b38a90 | ||
|
|
471eef6c31 | ||
|
|
513910e448 | ||
|
|
528f1d68b9 | ||
|
|
1613250f5d | ||
|
|
f8a2802a8e | ||
|
|
fdcbca4410 | ||
|
|
85b96268be | ||
|
|
0a94c00859 | ||
|
|
b7a2091c3e | ||
|
|
2dcd9467ec | ||
|
|
4fc6d35aab | ||
|
|
89d62606d3 | ||
|
|
c424e3a8c5 | ||
|
|
792a8795ed | ||
|
|
05d3c6d928 | ||
|
|
3f56af4b86 | ||
|
|
fe0e32de76 | ||
|
|
7456afac58 | ||
|
|
ee07204bae | ||
|
|
252296bf71 | ||
|
|
3c4da18040 | ||
|
|
88ff54b97b | ||
|
|
1f1590a49f | ||
|
|
c9476efe6f | ||
|
|
ac77262c88 | ||
|
|
ba649652da | ||
|
|
c63dff32a0 | ||
|
|
c253683506 | ||
|
|
d7788e277f | ||
|
|
44cd81eb24 | ||
|
|
0987afe645 | ||
|
|
d407561978 | ||
|
|
dfe6c19e01 | ||
|
|
978e625ba2 | ||
|
|
d401009dbb | ||
|
|
0d16619eb8 | ||
|
|
fd8feca60b | ||
|
|
d13908a8e7 | ||
|
|
1aae6fcc57 | ||
|
|
6331742f93 | ||
|
|
a21d99c871 | ||
|
|
c8f230ee8f | ||
|
|
8cf6645cdd | ||
|
|
2b4b8fe13a | ||
|
|
3fcfac1cf6 | ||
|
|
c73bfe67bf | ||
|
|
25bdef0510 | ||
|
|
d0c9093f41 | ||
|
|
98e38836c5 | ||
|
|
b3a3064e1b | ||
|
|
a8caaf4654 | ||
|
|
232e0f478a | ||
|
|
c039bf7f20 | ||
|
|
88d6c17c90 | ||
|
|
4e76871046 | ||
|
|
598d016172 | ||
|
|
0c5baec179 | ||
|
|
4729d4204c | ||
|
|
1a07b21b8d | ||
|
|
b10bee6a3e | ||
|
|
44889a6c7d | ||
|
|
705eeae700 | ||
|
|
a2122c7b24 | ||
|
|
940ed1450d | ||
|
|
265ecd3749 | ||
|
|
561ded8747 | ||
|
|
4e695cf020 | ||
|
|
f9288efb31 | ||
|
|
f69ffe9d99 | ||
|
|
6ec81e6af2 | ||
|
|
c6baf6eafb | ||
|
|
31fc59236f | ||
|
|
c4fa18ef41 | ||
|
|
2d34b7446e | ||
|
|
eee994831c | ||
|
|
72768ed1ac | ||
|
|
635279c076 | ||
|
|
ad9f758b2f | ||
|
|
6a804792e3 | ||
|
|
2104bf28b1 | ||
|
|
2300581493 | ||
|
|
7ce6fb065a | ||
|
|
dcea385b66 | ||
|
|
d680e998ce | ||
|
|
23ea4c6474 | ||
|
|
abf106ce94 | ||
|
|
1b3343589f | ||
|
|
96c6af8d59 | ||
|
|
82bbcfad26 | ||
|
|
70e55626a0 | ||
|
|
107665c415 | ||
|
|
c8dd002e4a | ||
|
|
fd2d06458b | ||
|
|
29cb1276eb | ||
|
|
0e0f6cee27 | ||
|
|
9c3a0704b9 | ||
|
|
e9db3fc70c | ||
|
|
a41c3cb805 | ||
|
|
dd9fc85100 | ||
|
|
00483ef54c | ||
|
|
03210f0465 | ||
|
|
26dc76a4f3 | ||
|
|
ae5e63aac9 | ||
|
|
08c8dd0f99 | ||
|
|
2044862edd | ||
|
|
148b3c4271 | ||
|
|
870cd0ec52 | ||
|
|
ef58d38c12 | ||
|
|
7250b1a83c | ||
|
|
710b3f0303 | ||
|
|
57cf6f09fd | ||
|
|
ec6820fa9d | ||
|
|
bf4b211c4f | ||
|
|
3a2accb239 | ||
|
|
6508d39e22 | ||
|
|
d0c7862103 | ||
|
|
f12962fd24 | ||
|
|
9c7db81e22 | ||
|
|
6be1caf41a | ||
|
|
d582507a6e | ||
|
|
302c0e6fe7 | ||
|
|
97761ba1e3 | ||
|
|
a75b578954 | ||
|
|
44ade828fa | ||
|
|
4c1a5f12b7 | ||
|
|
bbe7f96332 | ||
|
|
a29a7ebbca | ||
|
|
f4a7cc92ee | ||
|
|
9768711c5e | ||
|
|
4b3a864b28 | ||
|
|
60f057d28e | ||
|
|
3c4219b069 | ||
|
|
0db6da951e | ||
|
|
3963537e40 | ||
|
|
dd5e578d3a | ||
|
|
4dab4b7ef6 | ||
|
|
c19444816a | ||
|
|
0610a997e2 | ||
|
|
10faab68f9 | ||
|
|
42c91c667b | ||
|
|
bde9ddd017 | ||
|
|
c19a92406e | ||
|
|
93389ae98b | ||
|
|
cb1dba64c0 | ||
|
|
2d01e7a482 | ||
|
|
88f285199c | ||
|
|
e17bd10660 | ||
|
|
c2ac903180 | ||
|
|
84feb449d9 | ||
|
|
c475e51a1c | ||
|
|
682abbdd43 | ||
|
|
f8e68d2217 | ||
|
|
e8ddabe3ac | ||
|
|
32dd49b669 | ||
|
|
b9d3966cfe | ||
|
|
682325af59 | ||
|
|
d145969631 | ||
|
|
432ccf17c0 | ||
|
|
c6452d1905 | ||
|
|
f72f422ef0 | ||
|
|
d10ba586c8 | ||
|
|
39fc384b67 | ||
|
|
477318b124 | ||
|
|
367d79a976 | ||
|
|
eb36320396 | ||
|
|
6409b75aef | ||
|
|
98e4f6facc | ||
|
|
5ea8bbd08e | ||
|
|
e7efb94ee9 | ||
|
|
c3230f0722 | ||
|
|
0fd6328ae4 | ||
|
|
43a05e5037 | ||
|
|
c2b5eca4c7 | ||
|
|
e9c88ae899 | ||
|
|
fece798b92 | ||
|
|
564b5ae413 | ||
|
|
a8c93146da | ||
|
|
a0c3e40cc4 | ||
|
|
1da011026e | ||
|
|
4ab4f27690 | ||
|
|
5aaf3aaa8a | ||
|
|
73ba27a148 | ||
|
|
7493ac80c4 | ||
|
|
5d4c4a2d9d | ||
|
|
dad87454cf | ||
|
|
fbcbdd0d1f | ||
|
|
37ac4837b2 | ||
|
|
8cae97b297 | ||
|
|
3981ccc332 | ||
|
|
e5c2daac2e | ||
|
|
cccd3aa310 | ||
|
|
b8dc811a4f | ||
|
|
2e8529cc62 | ||
|
|
5f8a49e008 | ||
|
|
a945c839f0 | ||
|
|
607413db61 | ||
|
|
d478eecf47 | ||
|
|
dd624d06f3 | ||
|
|
bc596a48ed | ||
|
|
25ad6e96f4 | ||
|
|
8efd658a93 | ||
|
|
c565a79697 | ||
|
|
81f82faa2d | ||
|
|
978e886b6e | ||
|
|
6d7784cb3a | ||
|
|
63de39b970 | ||
|
|
05a8154d2e | ||
|
|
134b071a1d | ||
|
|
5f4366735f | ||
|
|
7fd0f2710e | ||
|
|
7a4760e1bc | ||
|
|
6574976f2d | ||
|
|
6126653a2c | ||
|
|
f45bc68ee6 | ||
|
|
1c71e68323 | ||
|
|
2d9523b9a1 | ||
|
|
5ed9fba170 | ||
|
|
22583bd207 | ||
|
|
32d68ce554 | ||
|
|
72a897063c | ||
|
|
a471a0183f | ||
|
|
11cfb7184d | ||
|
|
e2645e02d1 | ||
|
|
33ff9e90b6 | ||
|
|
e75e2801ce | ||
|
|
7f77abd9a2 | ||
|
|
592e6ce5a8 | ||
|
|
f653d325bb | ||
|
|
859ca62dc8 | ||
|
|
148f4be444 | ||
|
|
4bf6ec80b4 | ||
|
|
d9a0998213 | ||
|
|
eeec0e853b | ||
|
|
925b18d809 | ||
|
|
9c817f77dc | ||
|
|
b044fe01bb | ||
|
|
d46c88dcf3 | ||
|
|
03231beab7 | ||
|
|
3d84063f9a | ||
|
|
73237073c2 | ||
|
|
05b04cfa67 | ||
|
|
4187c04374 | ||
|
|
d5fca78ba0 | ||
|
|
8411cd44f9 | ||
|
|
e1dc9b1b1b | ||
|
|
595a079625 | ||
|
|
cf5bd4dca6 | ||
|
|
a0d9322e55 | ||
|
|
304f6c83ee | ||
|
|
8d4a7de267 | ||
|
|
3b302d6777 | ||
|
|
59a92391cd | ||
|
|
d18a3e43e4 | ||
|
|
c9baf9332b | ||
|
|
ccf3d8eefe | ||
|
|
9ac8ca3a7b | ||
|
|
0698f8265b | ||
|
|
a10622151c | ||
|
|
f69ed78582 | ||
|
|
c52ad67435 | ||
|
|
a79428cfb6 | ||
|
|
a0672f6354 | ||
|
|
72000a1340 | ||
|
|
9d25da31dc | ||
|
|
96778d2de0 | ||
|
|
c646f7555e | ||
|
|
c5600ff881 | ||
|
|
a39b3092be | ||
|
|
8c5a24c431 | ||
|
|
fb84c48d4d | ||
|
|
efc59ab2be | ||
|
|
44560195fc | ||
|
|
9b2f0c9375 | ||
|
|
5cbcef5a88 | ||
|
|
7aa76587df | ||
|
|
ebbbec9d6c | ||
|
|
8bb2d1321d | ||
|
|
e5ffb6db96 | ||
|
|
7700a606d0 | ||
|
|
57dbb9fc02 | ||
|
|
938cd995d7 | ||
|
|
112649081f | ||
|
|
d27ee304cb | ||
|
|
1b5ad6e860 | ||
|
|
d283eb061a | ||
|
|
92111b1046 | ||
|
|
fbc976bfa0 | ||
|
|
5c6ecb1807 | ||
|
|
cb266499a3 | ||
|
|
094f860b80 | ||
|
|
79c1259cae | ||
|
|
01f922b653 | ||
|
|
71d1730697 | ||
|
|
84dfd56c12 | ||
|
|
770abc2b9b | ||
|
|
353069803f | ||
|
|
03227d07f2 | ||
|
|
3a759eccf7 | ||
|
|
d515091b30 | ||
|
|
1f3e408396 | ||
|
|
f800070f91 | ||
|
|
5f4c2d1d7e | ||
|
|
d8bae04239 | ||
|
|
4efd8a7fef | ||
|
|
e7911644d8 | ||
|
|
590c3cfcd2 | ||
|
|
2b1b393c92 | ||
|
|
0b3d78e509 | ||
|
|
b42b561e49 | ||
|
|
68639390f5 | ||
|
|
226fefc08a | ||
|
|
c8fb04e0ea | ||
|
|
f4aa67390a | ||
|
|
de3342226b | ||
|
|
ca890133ba | ||
|
|
c452aa77a9 | ||
|
|
1530f4d09a | ||
|
|
2a64c405f9 | ||
|
|
d5a22165c6 | ||
|
|
a16ae6665a | ||
|
|
12595dde53 | ||
|
|
68299d2b57 | ||
|
|
3d8935136e | ||
|
|
fba2217e6f | ||
|
|
462a8502bf | ||
|
|
d8645530de | ||
|
|
8026a7c0b7 | ||
|
|
1e27298f36 | ||
|
|
640c7b1086 | ||
|
|
35cc7cc956 | ||
|
|
a34bc3ef49 | ||
|
|
e7f1092264 | ||
|
|
077669d34f | ||
|
|
d3784e918e | ||
|
|
d0f2d816fe | ||
|
|
d54d91e60f | ||
|
|
301b210d5a | ||
|
|
b942c3a45e | ||
|
|
8b053f491b | ||
|
|
a65c82c2b4 | ||
|
|
813258064c | ||
|
|
c5124cf19d | ||
|
|
6ffa7b1be3 | ||
|
|
cd68665cf4 | ||
|
|
de9d9ec645 | ||
|
|
598748220f | ||
|
|
0fd4f68f69 | ||
|
|
313250347c | ||
|
|
cbdb63b102 | ||
|
|
d211fb2310 | ||
|
|
2f730be207 | ||
|
|
761eb07300 | ||
|
|
fec9ace152 | ||
|
|
63e5274fc9 | ||
|
|
ae28d186a0 | ||
|
|
e901d3d1e7 | ||
|
|
1e0c2005da | ||
|
|
33aa6d4591 | ||
|
|
14c3e4e9a0 | ||
|
|
b89cd88639 | ||
|
|
87a106bd1e | ||
|
|
1aacad2733 | ||
|
|
89dca86a21 | ||
|
|
cdcd7bdec6 | ||
|
|
35c3e8f245 | ||
|
|
678b0cc7fd | ||
|
|
f2dd1a5c62 | ||
|
|
7c26008ad4 | ||
|
|
b54d284fdb | ||
|
|
79d8425749 | ||
|
|
36c4e4e553 | ||
|
|
c28c17b514 | ||
|
|
75faa7b798 | ||
|
|
f76d0511b9 | ||
|
|
ebe47700b2 | ||
|
|
f1de8adc68 | ||
|
|
ee0e76a172 | ||
|
|
0b7c183eeb | ||
|
|
e790f03066 | ||
|
|
12da3a428f | ||
|
|
0ddd8a499a | ||
|
|
faa9e73d22 | ||
|
|
b2fe1c2fb4 | ||
|
|
3a3fe49c7c | ||
|
|
cf06bed1f3 | ||
|
|
0011cab21e | ||
|
|
d282631662 | ||
|
|
260767bed4 | ||
|
|
2895c0a2ef | ||
|
|
e7cbd74b05 | ||
|
|
bd9ebce842 | ||
|
|
94a1943398 | ||
|
|
acc87f9eae | ||
|
|
41cf571958 | ||
|
|
c09f534746 | ||
|
|
3f389bd351 | ||
|
|
26d431cd5e | ||
|
|
2f32886576 | ||
|
|
074b32ef9c | ||
|
|
e169009c6c | ||
|
|
3102189a66 | ||
|
|
1be9325a65 | ||
|
|
db048b68bb | ||
|
|
76c3cba300 | ||
|
|
653e048d2e | ||
|
|
36f87425c9 | ||
|
|
57603e60e6 | ||
|
|
487361208e | ||
|
|
20b2711703 | ||
|
|
43d4eacefc | ||
|
|
caa9ff5eba | ||
|
|
3f5286c0a9 | ||
|
|
fedf2eb950 | ||
|
|
56b2951d88 | ||
|
|
35d96d2eb7 | ||
|
|
b6e6d9a151 | ||
|
|
d01989343c | ||
|
|
fd40ec47ab | ||
|
|
eed218b994 | ||
|
|
2013f890a5 | ||
|
|
42efbe5a07 | ||
|
|
cf17f2f4ac | ||
|
|
301d1c377a | ||
|
|
df3d2f99d4 | ||
|
|
2c6229417f | ||
|
|
94d18593a0 | ||
|
|
b4b6606f39 | ||
|
|
a70c08f484 | ||
|
|
b19a5f637a | ||
|
|
331551a614 | ||
|
|
0897d3afb5 | ||
|
|
a2be8c9fdd | ||
|
|
9f71d45eeb | ||
|
|
910d42af16 | ||
|
|
8af83a2cb9 | ||
|
|
04c3a1cd0d | ||
|
|
6f5efa3d62 | ||
|
|
32c7f178b5 | ||
|
|
4129f29da0 | ||
|
|
a2145b6bf7 | ||
|
|
e14c8b5264 | ||
|
|
22385421ef | ||
|
|
dc103d286b | ||
|
|
766a7e5595 | ||
|
|
9f75d842d8 | ||
|
|
636e938789 | ||
|
|
26a4e9a7d8 | ||
|
|
6fd1e31c87 | ||
|
|
85a855be97 | ||
|
|
4d108e424e | ||
|
|
b1333e490f | ||
|
|
9a57fc5d40 | ||
|
|
78bce64df2 | ||
|
|
0e7b9bdd0c | ||
|
|
9c8ff24bf2 | ||
|
|
3738b035d1 | ||
|
|
7a97b7e92a | ||
|
|
2ac91b0731 | ||
|
|
c689f7c48e | ||
|
|
12592f437e | ||
|
|
22565a0ed5 | ||
|
|
e9085a3339 | ||
|
|
5d32d043a1 | ||
|
|
1028ba07af | ||
|
|
86bd2240c3 | ||
|
|
27b276fc36 | ||
|
|
8fdb551fe8 | ||
|
|
0f3104f9d4 | ||
|
|
21a32bd459 | ||
|
|
f9a37791b7 | ||
|
|
fb6e9f3493 | ||
|
|
b851fa0d5f | ||
|
|
ee73058f5b | ||
|
|
1d20051888 | ||
|
|
5ec1ef72be | ||
|
|
76560198b8 | ||
|
|
b546327af9 | ||
|
|
04d1f8c37e | ||
|
|
2363d76f85 | ||
|
|
eead2724e7 | ||
|
|
419cb48327 | ||
|
|
8a91a58caa | ||
|
|
2b68ccd0f9 | ||
|
|
5adefaac5e | ||
|
|
eee563f07a | ||
|
|
a231250372 | ||
|
|
14f486d086 | ||
|
|
c2f7f3d506 | ||
|
|
593f9cee03 | ||
|
|
ba6513942d | ||
|
|
84c7d36840 | ||
|
|
f0821bc1d2 | ||
|
|
084e5f744a | ||
|
|
90a1acb56e | ||
|
|
ef7ad797d1 | ||
|
|
56f86e15ae | ||
|
|
a285dbbe43 | ||
|
|
cc2783a553 | ||
|
|
2ca67c805f | ||
|
|
4b0f1e3d7d | ||
|
|
06a8c9e713 | ||
|
|
a447228de1 | ||
|
|
c6032fdaab | ||
|
|
103af083a3 | ||
|
|
e67c0ebbb8 | ||
|
|
a51d282007 | ||
|
|
afb93ba15c | ||
|
|
fef655065b | ||
|
|
1d2ce79fba | ||
|
|
0b13ad2fbc | ||
|
|
3004c2a44c | ||
|
|
a2a2d8860e | ||
|
|
af81763577 | ||
|
|
c3dafcc615 | ||
|
|
0340f54e2c | ||
|
|
e2917b044a | ||
|
|
34f00dbb05 | ||
|
|
93801ae6d5 | ||
|
|
b50bf547f8 | ||
|
|
01ac831c24 | ||
|
|
adcccfee02 | ||
|
|
365dd2c45c | ||
|
|
a97e8c819d | ||
|
|
4eeaf5102f | ||
|
|
e9d4524a4f | ||
|
|
78c32e5396 | ||
|
|
58cb6295fa | ||
|
|
4bc94f8deb | ||
|
|
25d3d9f7da | ||
|
|
e5235cb121 | ||
|
|
3534dc0722 | ||
|
|
ce5b94745e | ||
|
|
0868d71c59 | ||
|
|
801de096fd | ||
|
|
347c56c484 | ||
|
|
a184c8b960 | ||
|
|
d15307a809 | ||
|
|
950994d95c | ||
|
|
19535fc81e | ||
|
|
a80938badf | ||
|
|
a484ba6c68 | ||
|
|
8afe6d5b22 | ||
|
|
30ba386294 | ||
|
|
f2ae51df7d | ||
|
|
b5d354164c | ||
|
|
935fd53b70 | ||
|
|
fe69659191 | ||
|
|
536fac3904 | ||
|
|
77a416b699 | ||
|
|
1e05d35e06 | ||
|
|
a84c72d703 | ||
|
|
0b29bbf82c | ||
|
|
35085c462e | ||
|
|
db33633406 | ||
|
|
809f1aeca3 | ||
|
|
dfa76da95e | ||
|
|
776883c96d | ||
|
|
c5c58c0c60 | ||
|
|
9861877f45 | ||
|
|
338a312485 | ||
|
|
a3b2bed484 | ||
|
|
fa2ac5d984 | ||
|
|
951676e6bf | ||
|
|
49095f73d5 | ||
|
|
15940ff0a6 | ||
|
|
bec608be96 | ||
|
|
2ffe107789 | ||
|
|
f2f6c3d0ef | ||
|
|
3704865ddb | ||
|
|
8815e8f03e | ||
|
|
a2414f9ffc | ||
|
|
db8ee43fd3 | ||
|
|
7e755721a8 | ||
|
|
231b3d2eac | ||
|
|
ac4d36100a | ||
|
|
2bf1c39839 | ||
|
|
ad2c307b60 | ||
|
|
74ba080937 |
+2
-1
@@ -39,4 +39,5 @@ common/src/main/resources/assets/cobblemon/showdown
|
||||
common/.fabric
|
||||
|
||||
# MacOS
|
||||
.DS_Store
|
||||
.DS_Store
|
||||
.kotlin/sessions/kotlin-compiler-16609242564043830292.salive
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ publish:
|
||||
- neoforge/build/libs/*.jar
|
||||
- fabric/build/libs/*.jar
|
||||
rules:
|
||||
- if: '$CI_COMMIT_BRANCH == "sega_bass_pro_fishing_2"'
|
||||
- if: '$CI_COMMIT_BRANCH == "main"'
|
||||
script:
|
||||
- export GRADLE_OPTS="-Xmx4G -Xms4G"
|
||||
- chmod +x ./gradlew
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
### Additions
|
||||
- Added the Poké Dex as a craftable item.
|
||||
- Poké Dexes can be placed on lecterns.
|
||||
@@ -0,0 +1,6 @@
|
||||
### Additions
|
||||
- Added `moves` option to PokemonProperties, allowing you to set the moves of a Pokémon in commands and spawn files.
|
||||
- Added /spawnnpc and /spawnnpcat commands.
|
||||
|
||||
### Fixes
|
||||
- Fixed sync issues with recently learned moves where their PP would not go down until you logout and in.
|
||||
+197
-119
@@ -1,77 +1,36 @@
|
||||
# Changelog
|
||||
## [1.6.0 - The Bass Pro Fishing Update (Month Xth, 2024)](#1-6-0)
|
||||
#### "Now that there's a fishing mechanic, the mod is actually good!"
|
||||
### Fixes
|
||||
- Fixed trading Pokémon setting their friendsip to 0 instead of the base value.
|
||||
- Fixed a scenario where a Pokémon that rolled to spawn with a special Tera type sometimes has a Tera type that is already a part of their natural typing.
|
||||
- Fixed PokemonProperty argument suggestions for ``tera`` and ``tera_type`` not suggesting ``stellar``.
|
||||
- Fixed being able to stack Relic Coin Pouches on top of each other.
|
||||
- Fixed Model loader generating misleading crash-reports when client is crashing
|
||||
|
||||
### Additions
|
||||
- Added Pokémon (and item) fishing using modified fishing rods - Poké Rods! You'll need a Poké Rod smithing template, a fishing rod, and some type of Poké Ball. Each Poké Ball makes a differently themed rod. Why not?
|
||||
- Added Lure Ball functionality, increasing the catch rate of Pokémon that were caught on a fishing rod.
|
||||
- Added Repeat Ball functionality, increasing the catch rate of Pokémon that are already registered as caught in a player's Pokédex.
|
||||
- Added property chaining support for duplicate CustomPokemonPropertyType elements.
|
||||
- Added ``aspect`` and ``unaspect`` PokemonProperty arguments (which also includes commands such as /pokemonedit, /spawnpokemon, and /givepokemon) to allow forcing or un-forcing an aspect on a Pokémon.
|
||||
- Added ``type`` alternatively ``elemental_type`` PokemonProperty argument, this is only used for filtering and is not applied to Pokémon. Example ``type=fire`` would be true for Charmander but false for Squirtle.
|
||||
|
||||
### Developer
|
||||
- SpawnCause is now an implementation of SpawningInfluence.
|
||||
- Added "forcedAspects" to Pokemon to make it easier to easily add basic aspects to a Pokémon in a way that persists. We already know that everyone is going to overuse this.
|
||||
- Made the Pokemon.aspects setter private. This could technically break sidemods but if you are affected by this then you were using it wrong! Use Pokemon.forcedAspects to fix it.
|
||||
- Many types related to ``Pokemon`` including itself now have dedicated ``Codec``, please migrate to them from the NBT/JSON/PacketBuffer write/read methods.
|
||||
- ``TeraTypes`` now implements ``Iterable``.
|
||||
|
||||
## [1.5.3](#1-5-3)
|
||||
### Fixes
|
||||
- Scaled down Amaura's fetus model to avoid clipping through the tank while animating
|
||||
- Fixed Cubone's cry not having a sound.
|
||||
- Fixed the Seafloor spawning context not being a usable context.
|
||||
- Fixed Pokemon spawning in non-full blocks like slabs.
|
||||
- Fixed Gilded Chests not dropping the chest itself when broken, only the contents.
|
||||
- Fixed Pokémon losing their Hidden Ability through evolution if the middle stage did not have a Hidden Ability.
|
||||
- Hidden Power no longer plays the water type action effect. (It now plays the normal type action effect.)
|
||||
- Fixed Chimchar and Monferno T posing whenever they sleep.
|
||||
- Fixed the Magby line not having any placeholder walk animations.
|
||||
- Fixed Duskull and Dusclops using skylight levels for their nether spawn data. There is no sun in the Nether!
|
||||
- Fixed Hisuian Zoroark using base Zoroark stats.
|
||||
- Fixed Bellossom clipping into the player head when shoulder mounted.
|
||||
- Fixed Shroomish's look range to prevent it from looking higher than it should.
|
||||
- Fixed Crumbling Arch not blending in with the world.
|
||||
- Fixed Energy Root applying being usable on a fainted Pokemon.
|
||||
- Fixed Pokémon entity not spawning when starting a battle while recalling said Pokémon
|
||||
- Fixed species comparison not using namespace for both sides in PokemonProperties.isSubsetOf.
|
||||
- Fixed PokemonProperties#asString prefixing nicknames with a '$'
|
||||
- Fixed PC not saving when Pokemon was changed outside.
|
||||
- Fixed shearble Pokemon not dropping correct wool colors.
|
||||
- Fixed pasture spawning Pokemon inside solid blocks when closest spawning position is blocked off.
|
||||
- Fixed Tumbling Down advancement not being granted by tumblestone variants.
|
||||
- Improve error handling when loading spawn-sets to ensure invalid configurations don't crash the server
|
||||
- Fixed empty JsonPlayerData files resulting in players being unable to join server/world
|
||||
|
||||
### Additions
|
||||
- Added extra visuals to early berry growth stages
|
||||
- Added `aspect` and `unaspect` PokemonProperty arguments (which also includes commands such as `/pokemonedit`, `/spawnpokemon`, and `/givepokemon`) to allow forcing or un-forcing an aspect on a Pokémon.
|
||||
- Added `type` alternatively `elemental_type` PokemonProperty argument, this is only used for filtering and is not applied to Pokémon. Example `type=fire` would be true for Charmander but false for Squirtle.
|
||||
- Added support for Double Battles, Triple Battles, and Multi-battles.
|
||||
- CriticalCaptures and Pokédex progress capture multiplier now work with the Pokédex.
|
||||
- Added extra visuals to early berry growth stages.
|
||||
- Hidden Power now displays its effective typing.
|
||||
- Moves impacted by the abilities Pixelate, Refrigerate, Aerilate, Galvanize, and Normalize now display as their altered typing.
|
||||
- Added Polished Tumblestone and Tumblestone Brick block sets from Tumblestone, Black Tumblestone, and Sky Tumblestone.
|
||||
- Added Metronome, Protective Pads, Punching Glove, Room Service, Scope Lens, Shed Shell, Terrain Extender, Throat Spray, Utility Umbrella, Wide Lens, and Zoom Lens held items
|
||||
|
||||
### Added cries to the following Pokémon
|
||||
- Timburr, Gurdurr, Conkeldurr
|
||||
- Golett, Golurk
|
||||
|
||||
### Changes
|
||||
- Altered the item model for Medicinal Leeks and Roasted Leeks to be held like sticks and other rod items.
|
||||
- Adjusted some berry balance values like yield and growth times
|
||||
- Changes to mulch buffs/durations
|
||||
- Dreepy is now shoulder mountable
|
||||
- Link Cable recipe has been redesigned
|
||||
- Updated potion sprites
|
||||
- Weedle, Caterpie, Spearow, Smoochum, Mew, Murkrow, Larvitar, Taillow, Plusle, Minun, Beldum, Starly, Buneary, Combee, Pachirisu, Pidove, Petilil, Hisui Bias Petilil, Zorua, Hisuian Zorua, Elgyem, Fletchling, Skrelp, Klefki, Fomantis, Morelull, Dreepy, Shroodle, Tatsugiri, Glimmet, and Roaming Gimmighoul are now shoulder mountable
|
||||
- Chikorita's ability to look around removed due to the awkwardness of it.
|
||||
- Link Cable recipe has been redesigned
|
||||
- Updated potion sprites
|
||||
- Removed the interchangeable evolution results for the first stage Hisuian starters to prevent confusion. The method still exists for stage 2 to 3, but stage 1 to 2 was not distinguishable enough for many users.
|
||||
- Added Fire, Water, Thunder, Leaf, Ice, Sun, Moon, Shiny, Dawn, and Dusk Stone storage blocks.
|
||||
- Added Eject Pack, Metronome, Protective Pads, Punching Glove, Room Service, Scope Lens, Shed Shell, Terrain Extender, Throat Spray, Utility Umbrella, Wide Lens, and Zoom Lens held items
|
||||
- Moves can now be benched without specifying a replacement move, allowing for empty move slots.
|
||||
- Moves learned via Sketch now persist after battle.
|
||||
- Added `stonjourner_henge_ruins`, `luna_henge_ruins`, and `sol_henge_ruins` structures.
|
||||
- Added a `battleInvulnerability` gamerule to make players invulnerable to any damage during a battle.
|
||||
- Added a `mobTargetInBattle` gamerule to exclude players from being targeted by mobs during a battle.
|
||||
- Added battle log messages for switching out Pokémon.
|
||||
- Added Evolution particles and sounds for Pokémon that are sent out when evolution is started.
|
||||
- Added a Nurse profession that can be unlocked by having villagers claim a healing machine block.
|
||||
- Added pokecenters to all 5 village types.
|
||||
- Added a `natural` block state property for the healing machine block; when property is set to true, the block will have a different texture and drop an iron ingot instead of itself.
|
||||
- New config setting `displayEntityNameLabel` and `displayEntityLabelsWhenCrouchingOnly` to control what and when is displayed for the pokemon label
|
||||
- `/freezepokemon` command to pause a Pokémon's animation at a specific point in time.
|
||||
- Added `no_ai` and `freeze_frame` options to the `/spawnpokemon` command.
|
||||
- Added shiny Pokémon particles with sound effects.
|
||||
|
||||
### Pokémon Added
|
||||
#### Gen 2
|
||||
@@ -85,17 +44,136 @@
|
||||
#### Gen 3
|
||||
- Wynaut
|
||||
|
||||
#### Gen 8
|
||||
- Cramorant
|
||||
|
||||
#### Gen 9
|
||||
- Farigiraf
|
||||
|
||||
### Added cries to the following Pokémon
|
||||
- Timburr, Gurdurr, Conkeldurr
|
||||
- Golett, Golurk
|
||||
|
||||
### Changes
|
||||
- Kakuna, Beedrill, Snorlax, Munchlax, and Lurantis received model updates
|
||||
- Buffed Dusk Ball catch multipliers: Increased multiplier to 3.5 (from 3.0) in light level 0. Increased multiplier to 3.0 (from 1.5) in light levels 1-7.
|
||||
- Altered the item model for Medicinal Leeks and Roasted Leeks to be held like sticks and other rod items.
|
||||
- Adjusted some berry balance values like yield and growth times.
|
||||
- Adjusted volumes of sounds made by Display Cases, Berry Bushes, Energy Root, Medicinal Leek, Vivichoke, Mints, Revival Herbs and Gilded Chests.
|
||||
- Changes to mulch buffs/durations.
|
||||
- Dreepy is now shoulder mountable.
|
||||
- Updated potion sprites.
|
||||
- Weedle, Caterpie, Spearow, Smoochum, Mew, Murkrow, Larvitar, Taillow, Plusle, Minun, Beldum, Starly, Buneary, Combee, Pachirisu, Pidove, Petilil, Hisui Bias Petilil, Zorua, Hisuian Zorua, Elgyem, Fletchling, Skrelp, Klefki, Fomantis, Morelull, Dreepy, Shroodle, Tatsugiri, Glimmet, and Roaming Gimmighoul are now shoulder mountable.
|
||||
- Link Cable recipe has been redesigned.
|
||||
- Updated sounds for Medicinal Leeks, Big Roots, Energy Roots and Revival Herbs.
|
||||
- Updated UI sounds for clicking and evolving Pokémon.
|
||||
- Removed the interchangeable evolution results for the first stage Hisuian starters to prevent confusion. The method still exists for stage 2 to 3, but stage 1 to 2 was not distinguishable enough for many users.
|
||||
- Kakuna, Beedrill, Snorlax, Munchlax, Krabby, Kingler, and Lurantis received model updates.
|
||||
- Vivillon wings will stop being clear when you remove any Vivillon related resourcepacks. The default pattern will be the meadow wings.
|
||||
- Adjusted Pokémon sendout positions for single battles.
|
||||
- Wild Pokémon interaction range increased to 12 blocks (from 10 blocks).
|
||||
- Player trade range increased to 12 blocks (from 10 blocks).
|
||||
- PvP battle range increased to 32 blocks (from 10 blocks).
|
||||
- Spectate range increased to 64 blocks (from 10 blocks).
|
||||
- The inventory key now closes our GUIs if they are open, mirroring how Minecraft screens usually work.
|
||||
- The noise from the pasture and PC blocks being interacted with now activates Sculk sensors.
|
||||
- Updated dialogue GUI assets with proper assets.
|
||||
- Updated party switching interface when in battle.
|
||||
- Relic coin pouches can now be waterlogged.
|
||||
- Pokemon Name (and level) labels are now only visible when crouching by default, set the `displayEntityLabelsWhenCrouchingOnly` to `false` to always them even when not crouching
|
||||
- The "Press R to start battle prompt" will now disappear after a player's first battle has been won
|
||||
- The default number of digits for the Pokédex number in the summary has been increased, from 3 to 4.
|
||||
|
||||
### Fixes
|
||||
- Scaled down Amaura's fetus model to avoid clipping through the tank while animating.
|
||||
- Fixed Cubone's cry not having a sound.
|
||||
- Fixed the Seafloor spawning context not being a usable context.
|
||||
- Fixed Pokemon spawning in non-full blocks like slabs.
|
||||
- Fixed Gilded Chests not dropping the chest itself when broken, only the contents.
|
||||
- Fixed Pokémon losing their Hidden Ability through evolution if the middle stage did not have a Hidden Ability.
|
||||
- Hidden Power no longer plays the water type action effect (It now plays the normal type action effect).
|
||||
- Fixed Chimchar and Monferno T-posing whenever they sleep.
|
||||
- Fixed the Magby line not having any placeholder walk animations.
|
||||
- Fixed Duskull and Dusclops using skylight levels for their nether spawn data. There is no sun in the Nether!
|
||||
- Fixed Hisuian Zoroark using base Zoroark stats.
|
||||
- Fixed Bellossom clipping into the player head when shoulder mounted.
|
||||
- Fixed Shroomish's look range to prevent it from looking higher than it should.
|
||||
- Fixed Crumbling Arch not blending in with the world.
|
||||
- Fixed Energy Root applying being usable on a fainted Pokémon.
|
||||
- Fixed Pokémon entity not spawning when starting a battle while recalling said Pokémon.
|
||||
- Fixed species comparison not using namespace for both sides in `PokemonProperties.isSubsetOf`.
|
||||
- Fixed `PokemonProperties#asString` prefixing nicknames with a '$'.
|
||||
- Fixed PC not saving when Pokémon was changed outside.
|
||||
- Fixed shearable Pokémon not dropping correct wool colors.
|
||||
- Fixed pasture spawning Pokémon inside solid blocks when closest spawning position is blocked off.
|
||||
- Fixed Tumbling Down advancement not being granted by tumblestone variants.
|
||||
- Improve error handling when loading spawn sets to ensure invalid configurations don't crash the server.
|
||||
- Fixed empty `JsonPlayerData` files resulting in players being unable to join server/world.
|
||||
- Evolution notification and UI sound is now correctly playing (again).
|
||||
- Fix Starter prompt not showing up.
|
||||
- Fix evolution now granting Pokédex entries.
|
||||
- Fix Pokédex crash when a form is looked up without ever seeing the "normal" form.
|
||||
- Fixed owned poké balls floating upwards if pausing mid-transition.
|
||||
- Fixed all mouse buttons working for Battle UI navigation (now it's only primary/left click).
|
||||
- Fixed trading Pokémon setting their friendship to 0 instead of the base value.
|
||||
- Fixed a scenario where a Pokémon that rolled to spawn with a special Tera type sometimes has a Tera type that is already a part of their natural typing.
|
||||
- Fixed PokemonProperty argument suggestions for `tera` and `tera_type` not suggesting `stellar`.
|
||||
- Fixed being able to stack Relic Coin Pouches on top of each other.
|
||||
- Fixed Model loader generating misleading crash-reports when client is crashing.
|
||||
- Big Roots and Energy Roots now share the same sounds as intended.
|
||||
- Fixed sounds made by blocks playing at a lower pitch than intended.
|
||||
- Fixed Chimchar and Monferno T posing whenever they sleep.
|
||||
- Fixed the Magby line not having any placeholder walk animations.
|
||||
- Fixed Duskull and Dusclops using skylight levels for their nether spawn data. There is no sun in the Nether!
|
||||
- Fixed Hisuian Zoroark using base Zoroark stats.
|
||||
- Fixed Bellossom clipping into the player head when shoulder mounted.
|
||||
- Fixed Shroomish's look range to prevent it from looking higher than it should.
|
||||
- Fixed Maushold's faint animations not playing. It's sadder than Tandemaus!
|
||||
- Fixed Slowking's battle idle.
|
||||
- Fixed Grafaiai's walk speed to prevent model sliding.
|
||||
- Fixed reviving items throwing an exception when used in battle.
|
||||
- Fixed messages for Focus Sash, Confusion, Mummy, Ice Face, Own Tempo, and Revive.
|
||||
- Improve error handling when loading spawn-sets to ensure invalid configurations don't crash the server.
|
||||
- Fixed `crumbling_arch_ruins` from generating a giant cube of air and removed the chest.
|
||||
- Fixed possible crash on large population servers due to concurrent access of data.
|
||||
- Quickly sending out and recalling Pokémon now looks smoother and can no longer be spammed to cause desync issues.
|
||||
- Pokémon are now invulnerable during sendout animation and intangible during recall animation.
|
||||
- Pokémon are now invincible during sendout animation and intangible during recall animation.
|
||||
- Scrolling with party keybinding now behaves properly when using high scroll speed or scroll sensitivity.
|
||||
- Fixed battle log GUI flashing when Battle GUI is opened.
|
||||
- Bag Items used during a turn will now be refunded if the battle ends before the next turn begins.
|
||||
- Pokémon whose current owner is not its Original Trainer now gains extra experience.
|
||||
- Fixed Fossil Resurrection advancement not being granted.
|
||||
- Fixed village generation caps not applying for berry farms. You were not meant to see more than two berry farms per village!
|
||||
- Fixed the Ice Face ability activation being displayed incorrectly in a battle
|
||||
|
||||
### Developer
|
||||
- `SpawnCause` is now an implementation of `SpawningInfluence`.
|
||||
- Many types related to `Pokemon` including itself now have dedicated `Codec`, please migrate to them from the NBT/JSON/PacketBuffer write/read methods.
|
||||
- `TeraTypes` now implements `Iterable`.
|
||||
- `PokemonBattle` now starts on turn 0.
|
||||
- SpawnCause is now an implementation of SpawningInfluence.
|
||||
- Renamed Pokemon.hp to Pokemon.maxHealth to make it clearer. Backwards compatibility is provided but it is an active deprecation, please migrate away from it.
|
||||
- Many types related to ``Pokemon`` including itself now have dedicated ``Codec``, please migrate to them from the NBT/JSON/PacketBuffer write/read methods.
|
||||
- Serialization of PokemonStores and Pokemon themselves now require registry access, which will break some sidemods. This sucked for us more than it will suck for you! If you have a world or player instance, you can get it from there.
|
||||
- ``TeraTypes`` now implements ``Iterable``.
|
||||
- PokemonBattle now starts on turn 0.
|
||||
- All sounds related to evolving Pokémon have been moved to the "sounds/evolution" folder.
|
||||
- Added `forcedAspects` to Pokémon to make it easier to easily add basic aspects to a Pokémon in a way that persists. We already know that everyone is going to overuse this.
|
||||
- Made the `Pokemon.aspects` setter private. This could technically break side-mods but if you are affected by this then you were using it wrong! Use `Pokemon.forcedAspects` to fix it.
|
||||
- Cobblemon's main logger is properly static now.
|
||||
- PokemonEntity.enablePoseTypeRecalculation can be used to disable automatic pose type recalculation.
|
||||
|
||||
### Data Pack & Resource Pack Creators
|
||||
- Added support for "shedders" similar to Shedinja's evolution logic.
|
||||
- Fixed the placeholder WingFlapIdle animation so the wings are not rotating opposite to each other.
|
||||
- Fixed the placeholder `WingFlapIdle` animation so the wings are not rotating opposite to each other.
|
||||
- 'player' type dialogue faces can now be explicitly stated so that NPC mods that use fake players can show in dialogue portraits.
|
||||
- Added `isLeftSide` field for dialogue faces. This determines what side of dialogue box the portrait is on.
|
||||
|
||||
### Localization
|
||||
- Updated translations for:
|
||||
- Czech, German, Greek, Spanish, Mexican Spanish, French, Canadian French, Hungarian, Italian, Japanese, Korean, Dutch, Polish, Portuguese, Brazilian Portuguese, Russian, Ukrainian, Simplified Chinese, and Traditional Chinese
|
||||
- Migrated translation project to Weblate at https://lang.cobblemon.com/projects/cobblemon/mod/
|
||||
|
||||
|
||||
## [1.5.2 (May 27th, 2024)](#1-5-2)
|
||||
### Fixes
|
||||
@@ -194,13 +272,13 @@
|
||||
- Added parametric motion and rotation support to particle effects.
|
||||
- Added entity_scale as a molang var for particles (likely only applicable to Pokemon)
|
||||
- Added support for primary quirk animations using the following format:
|
||||
```JSON
|
||||
`JSON
|
||||
{
|
||||
"quirks": [
|
||||
"q.bedrock_primary_quirk('<pokemon>', '<animation>', <minSeconds>, <maxSeconds>, <loopTimes>, '<excludedLabels>', q.curve('<waveFunction>'))"
|
||||
]
|
||||
}
|
||||
```
|
||||
`
|
||||
- Added support for custom stashes, similar to Gimmighoul's coin and scrap stashes.
|
||||
|
||||
### Localization
|
||||
@@ -506,7 +584,7 @@ These are our compromise for having both regular and Hisuian forms of these Pok
|
||||
- Fixed mod incompatibility with [Just Enough Resources](https://modrinth.com/mod/just-enough-resources-jer).
|
||||
- Fixed mod incompatibility with [Visual Overhaul](https://modrinth.com/mod/visual-overhaul).
|
||||
- Fixed an issue that allowed Pokémon to spawn on rails.
|
||||
- Fixed the data set on Pokémon when abilities are given via properties such as in ``/spawnpokemon``.
|
||||
- Fixed the data set on Pokémon when abilities are given via properties such as in `/spawnpokemon`.
|
||||
- Fixed Pokémon sometimes losing hidden abilities when evolving. This fix will only take effect for newly created Pokémon because of technical reasons that were explained to me but which I then forgot.
|
||||
- Fixed capture messages not displaying in battle.
|
||||
- Fixed the Illusion ability causing the wrong Pokémon to be targeted in battle.
|
||||
@@ -519,17 +597,17 @@ These are our compromise for having both regular and Hisuian forms of these Pok
|
||||
### Developer
|
||||
- Significantly changed the way the properties in PokemonEntity work. This could break some plugins (not in a big way, but changes will be needed for some things).
|
||||
- Rebuilt the scheduling API to more clearly force side choices and temporal frames of reference for tasks. The developers say that how it works is cool but I stopped listening.
|
||||
- Added dialogue API and data registry. This is powerful, and there is a full example in the Cobblemon mod you can trigger using /opendialogue \<username\> cobblemon:example. The example JSON is inside the data folder of the mod.
|
||||
- Added dialogue API and data registry. This is powerful, and there is a full example in the Cobblemon mod you can trigger using `/opendialogue <username> cobblemon:example`. The example JSON is inside the data folder of the mod.
|
||||
- Opened up the ItemDropEntry class to allow for it to be extended.
|
||||
- Added a new "advancement" evolution variant that takes an advancement identifier and succeeds if the player has the advancement.
|
||||
- Made the spawning API capable of non-entity spawning. You can make it 'spawn' commands if you want. Go nuts.
|
||||
- Made PokemonProperties.parse more interoperable with Java. Save yourself and stop using Java.
|
||||
- Added the ``HeldItemEvent``, this comes with 2 implementation ``HeldItemEvent.Pre`` and ``HeldItemEvent.Post``.
|
||||
- Corrections to the ability implementation have been made that make ``Ability.forced`` function as intended and never reroll an ability for a Pokémon, please check your implementations to ensure the corrected behavior is intended for your use case.
|
||||
- ``Pokemon.ability`` no longer has a public setter. Please migrate to using ``Pokemon#updateAbility``, this handles the ability coordinate storage for you when necessary.
|
||||
- ``Ability.forced``, ``Ability.index`` and ``Ability.priority`` have all had their setters internalized, there is no longer any need to manually adjust these migrate to the method mentioned above to handle that process for you.
|
||||
- ``AbilityChanger`` has been added to API alongside some implementations, this is subject to change as the ability capsule and patch currently only expect the traditional behaviour in the Pokémon games of 1 or 2 regular abilities and 1 hidden ability.
|
||||
- ``Pokemon#rollAbility`` has been added which rerolls for a legal ability for the Pokémon.
|
||||
- Made `PokemonProperties.parse` more interoperable with Java. Save yourself and stop using Java.
|
||||
- Added the `HeldItemEvent`, this comes with 2 implementation `HeldItemEvent.Pre` and `HeldItemEvent.Post`.
|
||||
- Corrections to the ability implementation have been made that make `Ability.forced` function as intended and never reroll an ability for a Pokémon, please check your implementations to ensure the corrected behavior is intended for your use case.
|
||||
- `Pokemon.ability` no longer has a public setter. Please migrate to using `Pokemon#updateAbility`, this handles the ability coordinate storage for you when necessary.
|
||||
- `Ability.forced`, `Ability.index` and `Ability.priority` have all had their setters internalized, there is no longer any need to manually adjust these migrate to the method mentioned above to handle that process for you.
|
||||
- `AbilityChanger` has been added to API alongside some implementations, this is subject to change as the ability capsule and patch currently only expect the traditional behaviour in the Pokémon games of 1 or 2 regular abilities and 1 hidden ability.
|
||||
- `Pokemon#rollAbility` has been added which re9rolls for a legal ability for the Pokémon.
|
||||
- `docs/cobblemon-tags` tags and spawn-presets can now be auto-generated from the current tags in the Cobblemon mod with the `generateSpawnPresetList.py` and `generateTagList.py` scripts.
|
||||
- `public_spawns_to_json.py` script has been added to give the powerful spawn.json generator a simplistic UI.
|
||||
- Updated Showdown with Gen 9 DLC.
|
||||
@@ -538,14 +616,14 @@ These are our compromise for having both regular and Hisuian forms of these Pok
|
||||
### Datapack & Resourcepack Creators
|
||||
- The maximum amount of fossils that can fit in the Fossil Analyzer can be adjusted in the config.
|
||||
- Custom fossils can be defined using a list of items and the resulting Pokémon. An example of `aerodactyl.json`:
|
||||
```JSON
|
||||
`JSON
|
||||
{
|
||||
"result": "aerodactyl",
|
||||
"fossils": [
|
||||
"cobblemon:old_amber_fossil"
|
||||
]
|
||||
}
|
||||
```
|
||||
`
|
||||
- Fetus models can be defined in `bedrock/fossils`.
|
||||
- Fetus textures can be defined in `textures/fossils`.
|
||||
- Fuel for the Restoration Machine is registered inside the `natural_materials` folder. To register more fuels, create a JSON file containing an array of objects. Each object supports the following fields:
|
||||
@@ -554,10 +632,10 @@ These are our compromise for having both regular and Hisuian forms of these Pok
|
||||
- `returnItem`: Identifier of an item to return to the player after consumption.
|
||||
- Added 3 new item tags: `ancient_poke_balls`, `fossils`, and `tumblestones`.
|
||||
- Added a spawn rules system to modify general spawning behaviour, see the [wiki](https://wiki.cobblemon.com/index.php/Spawn_Rules) for more information.
|
||||
- Added dialogue datapack folder and /opendialogue command.
|
||||
- Added the item tag ``cobblemon:held/leaves_leftovers`` this can be used to flag apple-like items that can create leftovers when eaten.
|
||||
- Added dialogue datapack folder and `/opendialogue` command.
|
||||
- Added the item tag `cobblemon:held/leaves_leftovers` this can be used to flag apple-like items that can create leftovers when eaten.
|
||||
- You can now add support for dynamic lighting implementations, Cobblemon ships with a default implementation for [LambDynamicLights](https://modrinth.com/mod/lambdynamiclights) and the [Dynamic Lights Reforged](https://www.curseforge.com/minecraft/mc-mods/dynamiclights-reforged), add the following to any species or form:
|
||||
```JSON
|
||||
`JSON
|
||||
{
|
||||
"lightingData": {
|
||||
"lightLevel": 14,
|
||||
@@ -566,10 +644,10 @@ These are our compromise for having both regular and Hisuian forms of these Pok
|
||||
"_liquidGlowModeCommentRemoveMe": "Above supports LAND, UNDERWATER or BOTH"
|
||||
}
|
||||
}
|
||||
```
|
||||
- Following up on this change ``light_source`` was removed as a possible shoulder effect due to becoming unnecessary and never having had a default implementation.
|
||||
- Added the item tag ``cobblemon:ability_changers``, contains the ``cobblemon:ability_capsule`` & ``cobblemon:ability_patch`` by default.
|
||||
- Added the item tag ``cobblemon:held/is_friendship_booster``, allows items to give the Soothe Bell effect of a boost of 1.5x Friendship gained, contains ``cobblemon:soothe_bell`` by default.
|
||||
`
|
||||
- Following up on this change `light_source` was removed as a possible shoulder effect due to becoming unnecessary and never having had a default implementation.
|
||||
- Added the item tag `cobblemon:ability_changers`, contains the `cobblemon:ability_capsule` & `cobblemon:ability_patch` by default.
|
||||
- Added the item tag `cobblemon:held/is_friendship_booster`, allows items to give the Soothe Bell effect of a boost of 1.5x Friendship gained, contains `cobblemon:soothe_bell` by default.
|
||||
|
||||
## [1.4.1 (December 23rd, 2023)](#1-4-1)
|
||||
|
||||
@@ -585,7 +663,7 @@ These are our compromise for having both regular and Hisuian forms of these Pok
|
||||
- Mooshtank can now be milked with a bowl for Mushroom Stew.
|
||||
- Updated Showdown version to use generation 9 battle data.
|
||||
- Added cries to Beldum, Metang and Metagross.
|
||||
- Added a /bedrockparticle command to run Snowstorm-format particle effects.
|
||||
- Added a `/bedrockparticle` command to run Snowstorm-format particle effects.
|
||||
- Added data for Dipplin, Fezandipiti, Munkidori, Ogerpon, Okidogi, Poltchageist and Sinistcha.
|
||||
- Added additional nickname trigger "Grumm" for Inkay's evolution.
|
||||
|
||||
@@ -1078,7 +1156,7 @@ Thank you so much to all of our community translators that bring the mod to the
|
||||
- Fixed apricorn tree leaves looking gross on the Fast graphics mode.
|
||||
- Fixed hoes not breaking apricorn tree leaves any faster.
|
||||
- Fixed Shiftry's PC model position.
|
||||
- Fixed the /pc command not playing the opening sound.
|
||||
- Fixed the `/pc` command not playing the opening sound.
|
||||
- Fixed different forms of Pokémon not being able to appear as different sizes.
|
||||
- Fixed the Healing Machine soft locking you from using others when removed by non-players.
|
||||
- Fixed animations being sped up when using the Replay Mod.
|
||||
@@ -1095,11 +1173,11 @@ Thank you so much to all of our community translators that bring the mod to the
|
||||
- Fixed battles soft-locking when consecutive Pokémon faint on switch-in.
|
||||
- Fixed timing and color of battle window messages.
|
||||
- Fixed players being able to trade, battle and let out their Pokémon while in spectator mode.
|
||||
- Fixed Galarian Yamask not being able to evolve and by proxy the ``damage_taken`` evolution requirement.
|
||||
- Fixed Bisharp not being able to evolve and by proxy the ``defeat`` evolution requirement.
|
||||
- Fixed White-Striped Basculin not being able to evolve because of a broken ``recoil`` evolution requirement.
|
||||
- Fixed Primeape, Qwilfish and Stantler not being able to evolve because of a broken ``use_move`` evolution requirement.
|
||||
- Fixed Bramblin, Pawmo, and Rellor not being able to evolve because of a broken ``blocks_traveled`` evolution requirement.
|
||||
- Fixed Galarian Yamask not being able to evolve and by proxy the `damage_taken` evolution requirement.
|
||||
- Fixed Bisharp not being able to evolve and by proxy the `defeat` evolution requirement.
|
||||
- Fixed White-Striped Basculin not being able to evolve because of a broken `recoil` evolution requirement.
|
||||
- Fixed Primeape, Qwilfish and Stantler not being able to evolve because of a broken `use_move` evolution requirement.
|
||||
- Fixed Bramblin, Pawmo, and Rellor not being able to evolve because of a broken `blocks_traveled` evolution requirement.
|
||||
- Fixed displayName property in spawn files not doing what it's meant to do.
|
||||
- Fixed Pokémon not sleeping in the wild like we wanted them to.
|
||||
|
||||
@@ -1114,11 +1192,11 @@ Thank you so much to all of our community translators that bring the mod to the
|
||||
- Added MongoDB support for storing Pokémon and Player data. Must be enabled in config, requires MongoDB core and sync drivers (4.10.0+).
|
||||
- CobblemonShowdown updated to version 10.
|
||||
- Generation of a battle can be set in BattleFormat.
|
||||
- Pokémon now have ``teraType``, ``dmaxLevel``, and ``gmaxFactor`` properties. Gimmicks can be used during battle by adding the respective identifiers to ``keyItems`` in PlayerData: ``key_stone``, ``z_ring``, ``dynamax_band``, and ``tera_orb``. Dynamax is only supported in Gen 8 battles. Mega Evolution and Z-Power require custom held items to be added (e.g. an item with the path ``gengarite`` will allow Gengar to Mega Evolve). Currently custom Z-Crystals and Mega Stones are not supported.
|
||||
- Pokémon now have `teraType`, `dmaxLevel`, and `gmaxFactor` properties. Gimmicks can be used during battle by adding the respective identifiers to `keyItems` in PlayerData: `key_stone`, `z_ring`, `dynamax_band`, and `tera_orb`. Dynamax is only supported in Gen 8 battles. Mega Evolution and Z-Power require custom held items to be added (e.g. an item with the path `gengarite` will allow Gengar to Mega Evolve). Currently custom Z-Crystals and Mega Stones are not supported.
|
||||
|
||||
### Datapack & Resourcepack Creators
|
||||
- All potion related shoulder effects have had their IDs changed. They now all share the same type being `potion_effect` and use the vanilla Potion data [parameters](https://minecraft.fandom.com/wiki/Potion#Item_data). For example, here is the converted Pidgey asset:
|
||||
- ```json
|
||||
- `json
|
||||
{
|
||||
"type": "potion_effect",
|
||||
"effect": "minecraft:slow_falling",
|
||||
@@ -1127,18 +1205,18 @@ Thank you so much to all of our community translators that bring the mod to the
|
||||
"showParticles": false,
|
||||
"showIcon": false
|
||||
}
|
||||
```
|
||||
- Renamed the ``walked_steps`` evolution requirement to ``blocks_traveled``.
|
||||
`
|
||||
- Renamed the `walked_steps` evolution requirement to `blocks_traveled`.
|
||||
- Added support for scale in animations.
|
||||
- Added support for jump keyframes (i.e. pre and post keyframes)
|
||||
- Added structure spawning conditions
|
||||
- Added Advancement trigger for defeating Pokémon and collecting varieties of Pokémon.
|
||||
- Added support for "isBattle" and "isTouchingWater" properties on resource pack Pokémon poses. This allows your custom Pokémon to be posed differently when in battle.
|
||||
- Added support for "isVisible" on a transformed part on resource pack Pokémon poses. This allows your custom Pokémon to have bones disappear in specific poses, such as hiding Greninja's throwing star when not in a battle pose.
|
||||
- Added support for battle music. Sounds can be added to the ``battle.pvp.default`` and ``battle.pvw.default`` sound events.
|
||||
- Added support for battle music. Sounds can be added to the `battle.pvp.default` and `battle.pvw.default` sound events.
|
||||
- Added 'enabled' optional property on model layers, allowing later variations to disable previously-defined layers. See [this issue](https://gitlab.com/cable-mc/cobblemon/-/issues/335) for how this looks.
|
||||
- Cobblemon items can now all have their own tooltips via resourcepacks. To add a tooltip, add a lang entry like "item.cobblemon.{item_id}.tooltip". If you want to add multiple tooltip lines you can do so with "item.cobblemon.{item_id}.tooltip_1" and upwards.
|
||||
- Item interaction evolutions and held item requirements now support NBT by creating an object JSON containing the key ``item`` for what used to be the existing condition support and a ``nbt`` key for the NBT format, this is the string [format](https://minecraft.fandom.com/wiki/NBT_format) expected in commands. Existing data does not need to be updated.
|
||||
- Item interaction evolutions and held item requirements now support NBT by creating an object JSON containing the key `item` for what used to be the existing condition support and a `nbt` key for the NBT format, this is the string [format](https://minecraft.fandom.com/wiki/NBT_format) expected in commands. Existing data does not need to be updated.
|
||||
- Fixed faint animations not working properly in add-ons.
|
||||
- Fixed non-existent species in spawn pool files causing random species to spawn.
|
||||
|
||||
@@ -1156,7 +1234,7 @@ Thank you so much to all of our community translators that bring the mod to the
|
||||
- Added animations to Staryu line and Porygon line.
|
||||
- Added faint animations to Klink line.
|
||||
- Add lava surface spawn preset.
|
||||
- Added an ``any`` evolution requirement allowing you to define ``possibilities`` of other evolution requirements, for example, this allows you to create an evolution that requires the Pokémon to be shiny or a female.
|
||||
- Added an `any` evolution requirement allowing you to define `possibilities` of other evolution requirements, for example, this allows you to create an evolution that requires the Pokémon to be shiny or a female.
|
||||
- Added the `/spawnpokemonfrompool [amount]` or `/forcespawn [amount]` command to spawn Pokémon(s) in the surrounding area using the natural spawn rates/pool of that area, this will be a cheat command in the Minecraft permission system or use the permission `cobblemon.command.spawnpokemon` if a permission mod is present. On a successful execution of the command, the amount of Pokémon spawned will be the output.
|
||||
- Added the `/pokebox` and `/pokeboxall` commands to move Pokémon(s) to the PC from a Player's party, this will be a cheat command in the Minecraft permission system or use the permission `cobblemon.command.pokebox` if a permission mod is present. On a successful execution of the command the output will be the number of pokemon moved to the Player's PC.
|
||||
- Added the `/pc` command which opens up the PC UI the same way interacting with the block would, this will be a cheat command in the Minecraft permission system or use the permission `cobblemon.command.pc` if a permission mod is present.
|
||||
@@ -1281,7 +1359,7 @@ Thank you so much to all of our community translators that bring the mod to the
|
||||
- Added support for custom Pokémon to implement 'quirks' such as blinks.
|
||||
- Added sound effect for harvesting Apricorns.
|
||||
- Added icon to summary and PC interfaces to indicated if a Pokémon is shiny.
|
||||
- Added the ``/spawnpokemonat <pos> <properties>`` command, the ``pos`` argument uses the same syntax as the Minecraft [summon](https://minecraft.fandom.com/wiki/Commands/summon) command.
|
||||
- Added the `/spawnpokemonat <pos> <properties>` command, the `pos` argument uses the same syntax as the Minecraft [summon](https://minecraft.fandom.com/wiki/Commands/summon) command.
|
||||
- Added the `/giveallpokemon` command which is definitely safe and not insane.
|
||||
- Added compatibility with Carry On by preventing the mod being able to interact with Cobblemon entities, the mod caused too many gameplay detrimental features to stay enabled.
|
||||
- Added healing to your party when you sleep in a bed.
|
||||
@@ -1290,18 +1368,18 @@ Thank you so much to all of our community translators that bring the mod to the
|
||||
- Added a config option for disallowing players from damaging Pokémon by hand.
|
||||
- Apricorn seeds can now be used with the [Composter](https://minecraft.fandom.com/wiki/Composter), these have the layer increase chance of 65% like Apricorns and various Minecraft crops.
|
||||
- Added support for Pokémon species data appending making it so datapack developers no longer need to overwrite files.
|
||||
- Added an implementation of every [catch rate](https://bulbapedia.bulbagarden.net/wiki/Catch_rate) from generation 1 to 9, these can be used by changing the ``captureCalculator`` config value:
|
||||
- ``generation_1`` Sets the calculator to the generation 1 implementation.
|
||||
- ``generation_2`` Sets the calculator to the generation 2 implementation.
|
||||
- ``generation_2_fixed`` Sets the calculator to the generation 2 implementation with the status multiplier bug fixed.
|
||||
- ``generation_3_4`` Sets the calculator to the generation 3 and 4 implementation.
|
||||
- ``generation_5`` Sets the calculator to the generation 5 implementation.
|
||||
- ``generation_6`` Sets the calculator to the generation 6 implementation.
|
||||
- ``generation_7`` Sets the calculator to the generation 7 implementation.
|
||||
- ``generation_8`` Sets the calculator to the generation 8 implementation.
|
||||
- ``generation_9`` Sets the calculator to the generation 9 implementation.
|
||||
- ``cobblemon`` Sets the calculator to the custom Cobblemon implementation. This is the default value.
|
||||
- ``debug`` Sets the calculator to the debug/cheat implementation, every attempt will be a successful critical capture.
|
||||
- Added an implementation of every [catch rate](https://bulbapedia.bulbagarden.net/wiki/Catch_rate) from generation 1 to 9, these can be used by changing the `captureCalculator` config value:
|
||||
- `generation_1` Sets the calculator to the generation 1 implementation.
|
||||
- `generation_2` Sets the calculator to the generation 2 implementation.
|
||||
- `generation_2_fixed` Sets the calculator to the generation 2 implementation with the status multiplier bug fixed.
|
||||
- `generation_3_4` Sets the calculator to the generation 3 and 4 implementation.
|
||||
- `generation_5` Sets the calculator to the generation 5 implementation.
|
||||
- `generation_6` Sets the calculator to the generation 6 implementation.
|
||||
- `generation_7` Sets the calculator to the generation 7 implementation.
|
||||
- `generation_8` Sets the calculator to the generation 8 implementation.
|
||||
- `generation_9` Sets the calculator to the generation 9 implementation.
|
||||
- `cobblemon` Sets the calculator to the custom Cobblemon implementation. This is the default value.
|
||||
- `debug` Sets the calculator to the debug/cheat implementation, every attempt will be a successful critical capture.
|
||||
|
||||
### Changes
|
||||
- Pokémon now save to the world by default, meaning the same Pokémon will remain in the world and not disappear after you log out and log back in. They still despawn over time though.
|
||||
@@ -1314,9 +1392,9 @@ Thank you so much to all of our community translators that bring the mod to the
|
||||
- Made it so that particles are not shown whenever you have a shoulder Pokémon that gives potion effects.
|
||||
- Changed hitbox and size definitions for Decidueye, Blastoise, and Magmortar
|
||||
- Apricorns can now be harvested with Axes, the speed will scale with enchantments and tool material, only dropping the Apricorn if fully grown, these will still destroy the Apricorn so the manual harvest still is recommended unless you're just keen on destroying trees.
|
||||
- Apricorns are now a part of the vanilla tag ``minecraft:blocks/mineable/axe``.
|
||||
- Apricorns are now a part of the vanilla tag `minecraft:blocks/mineable/axe`.
|
||||
- Apricorns are now compatible with any mod that breaks a whole tree at once.
|
||||
- Apricorns no longer have a config value for the seed drop chance these are now a part of their loot table which can be found in ``cobblemon/loot_tables/blocks/<color>_apricorn.json``.
|
||||
- Apricorns no longer have a config value for the seed drop chance these are now a part of their loot table which can be found in `cobblemon/loot_tables/blocks/<color>_apricorn.json`.
|
||||
- Advancements were redone to be slightly more interesting, with improved names, descriptions, and sorting.
|
||||
- Updated models and textures for Tentacool line, Gengar, Slowpoke line, Tyrogue line, Doduo line, Dratini, Dragonair, Quagsire, and Piplup line. There were probably others, the team lost track.
|
||||
- Improved sending out Pokémon at the start of battle so that they are positioned in a less annoying way.
|
||||
@@ -1354,17 +1432,17 @@ Thank you so much to all of our community translators that bring the mod to the
|
||||
- Fixed positioning of Poké Balls when rendered in Healing Machines.
|
||||
- Fixed a desync issue on servers where all Pokémon seemed like they were special forms when they weren't.
|
||||
- Fixed an incompatibility with [Exordium](https://www.curseforge.com/minecraft/mc-mods/exordium).
|
||||
- Fixed datapack Pokémon language key generation. A Pokémon under the namespace ``example`` named ``Pogemon`` will now correctly look for the lang key ``example.species.pogemon.name``.
|
||||
- Fixed datapack Pokémon language key generation. A Pokémon under the namespace `example` named `Pogemon` will now correctly look for the lang key `example.species.pogemon.name`.
|
||||
- Fixed client not receiving messages for the different "stages" for the move Bide.
|
||||
- Fixed the Medium Slow and Medium Fast experience group IDs, they're now ```medium_slow``` and ``medium_fast``. Any custom datapack Pokémon will require an update.
|
||||
- Fixed the Medium Slow and Medium Fast experience group IDs, they're now `medium_slow` and `medium_fast`. Any custom datapack Pokémon will require an update.
|
||||
- Fixed Pokémon friendship being capped to the maximum level config value instead of the friendship one when loading Pokémon data.
|
||||
- Fixed Poké Balls taking forever to capture Pokémon if you are underwater or up in the air where it takes a long time to hit the ground.
|
||||
- Fixed Pokémon being unable to spawn on blocks such as snow layers.
|
||||
- Fixed Pokémon spawning inside of trees.
|
||||
- Fixed Pokémon experience not loading after a restart and instead going back to the minimal amount for the current level.
|
||||
- Fixed being able to use ``/healpokemon`` in battle.
|
||||
- Fixed being able to use `/healpokemon` in battle.
|
||||
- Fixed being able to select fainted party members in the switch menu causing the battle to lock.
|
||||
- Fixed ``/spawnpokemon`` command not supporting any command source other than players.
|
||||
- Fixed `/spawnpokemon` command not supporting any command source other than players.
|
||||
- Fixed issues with Charizard's sleep pose.
|
||||
- Fixed players being able to use multiple healer machines at once.
|
||||
- Fixed Pokémon layers not rendering when a Pokémon is on your shoulder.
|
||||
@@ -1399,7 +1477,7 @@ Thank you so much to all of our community translators that bring the mod to the
|
||||
- Added models for Natu and Xatu, Murkrow and Honchkrow, Wailmer and Wailord.
|
||||
- Added new PC interface and it is beautiful.
|
||||
- Reworked the battle system so that battles load faster, cause fewer bugs, and can run on shared server hosts. This is a very big change that also reduced the size of the mod by 50mb!
|
||||
- Added full resource pack / data pack customization of models, textures, animations, spawning, and spawn file presets to make custom Pokémon species and variations very easy to create. You can find the guide for creating custom Pokémon on [our website](https://cobblemon.com/guides/custompokemon.html)!
|
||||
- Added full resource pack and data pack customization of models, textures, animations, spawning, and spawn file presets to make custom Pokémon species and variations very easy to create. You can find the guide for creating custom Pokémon on [our website](https://cobblemon.com/guides/custompokemon.html)!
|
||||
- Added water surface spawning for Pokémon like Lapras.
|
||||
- Added emissive texture support to Pokémon render layers.
|
||||
- Added compatibility for Mod Menu ([CurseForge](https://www.curseforge.com/minecraft/mc-mods/modmenu), [Modrinth](https://modrinth.com/mod/modmenu)).
|
||||
|
||||
@@ -40,7 +40,7 @@ dependencies {
|
||||
modApi(libs.molang)
|
||||
|
||||
// Integrations
|
||||
// compileOnlyApi(libs.jei.api)
|
||||
compileOnlyApi(libs.jei.api)
|
||||
modCompileOnly(libs.bundles.fabric.integrations.compileOnly) {
|
||||
isTransitive = false
|
||||
}
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common;
|
||||
|
||||
import com.cobblemon.mod.common.entity.npc.NPCEntity;
|
||||
import java.util.Collection;
|
||||
import net.minecraft.world.entity.ai.Brain;
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType;
|
||||
import net.minecraft.world.entity.ai.sensing.Sensor;
|
||||
import net.minecraft.world.entity.ai.sensing.SensorType;
|
||||
|
||||
public class GenericsCheatClass {
|
||||
// For some reason, doing this in the NPCEntity class in Kotlin gives confusing generic errors I could not resolve.
|
||||
public static Brain.Provider<NPCEntity> createNPCBrain(Collection<MemoryModuleType<?>> memories, Collection<SensorType<? extends Sensor<? super NPCEntity>>> sensors) {
|
||||
return Brain.provider(memories, sensors);
|
||||
}
|
||||
}
|
||||
+1
-7
@@ -10,18 +10,12 @@ package com.cobblemon.mod.common.duck;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import net.minecraft.client.resources.sounds.SoundInstance;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
|
||||
public interface SoundSystemDuck {
|
||||
public interface SoundEngineDuck {
|
||||
|
||||
void pauseSounds(@Nullable ResourceLocation id, @Nullable SoundSource category);
|
||||
|
||||
void resumeSounds(@Nullable ResourceLocation id, @Nullable SoundSource category);
|
||||
|
||||
void stopSounds(@Nullable ResourceLocation id, @Nullable SoundSource category);
|
||||
|
||||
Collection<SoundInstance> getSounds(@Nullable SoundSource category);
|
||||
}
|
||||
@@ -17,6 +17,4 @@ public interface SoundManagerDuck {
|
||||
void pauseSounds(@Nullable ResourceLocation id, @Nullable SoundSource category);
|
||||
|
||||
void resumeSounds(@Nullable ResourceLocation id, @Nullable SoundSource category);
|
||||
|
||||
void stopSounds(@Nullable ResourceLocation id, @Nullable SoundSource category);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import static com.cobblemon.mod.common.datafixer.CobblemonSchemas.VERSION_KEY;
|
||||
|
||||
import com.cobblemon.mod.common.datafixer.CobblemonSchemas;
|
||||
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
|
||||
import com.mojang.serialization.MapCodec;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Supplier;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.IntTag;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.util.datafix.DataFixTypes;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.chunk.ChunkGenerator;
|
||||
import net.minecraft.world.level.chunk.storage.ChunkStorage;
|
||||
import net.minecraft.world.level.storage.DimensionDataStorage;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.ModifyVariable;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
@Mixin(ChunkStorage.class)
|
||||
public class ChunkStorageMixin {
|
||||
//Modifies the NBT returned by the vanilla upgradeChunkTag to also incorporate cobblemon fixup stuff
|
||||
@ModifyExpressionValue(
|
||||
method = "upgradeChunkTag(Lnet/minecraft/resources/ResourceKey;Ljava/util/function/Supplier;Lnet/minecraft/nbt/CompoundTag;Ljava/util/Optional;)Lnet/minecraft/nbt/CompoundTag;",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/util/datafix/DataFixTypes;updateToCurrentVersion(Lcom/mojang/datafixers/DataFixer;Lnet/minecraft/nbt/CompoundTag;I)Lnet/minecraft/nbt/CompoundTag;"
|
||||
)
|
||||
)
|
||||
public CompoundTag cobblemon$doChunkFix(
|
||||
CompoundTag vanillaFixed
|
||||
) {
|
||||
int curVersion = vanillaFixed.contains(VERSION_KEY) ? vanillaFixed.getInt(VERSION_KEY) : 0;
|
||||
return DataFixTypes.CHUNK.update(CobblemonSchemas.getDATA_FIXER(), vanillaFixed, curVersion, CobblemonSchemas.DATA_VERSION);
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "upgradeChunkTag(Lnet/minecraft/resources/ResourceKey;Ljava/util/function/Supplier;Lnet/minecraft/nbt/CompoundTag;Ljava/util/Optional;)Lnet/minecraft/nbt/CompoundTag;",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/nbt/NbtUtils;addCurrentDataVersion(Lnet/minecraft/nbt/CompoundTag;)Lnet/minecraft/nbt/CompoundTag;"
|
||||
)
|
||||
)
|
||||
public void cobblemon$addChunkVersion(
|
||||
ResourceKey<Level> resourceKey,
|
||||
Supplier<DimensionDataStorage> supplier,
|
||||
CompoundTag compoundTag,
|
||||
Optional<ResourceKey<MapCodec<? extends ChunkGenerator>>> optional,
|
||||
CallbackInfoReturnable<CompoundTag> cir
|
||||
) {
|
||||
compoundTag.put(VERSION_KEY, IntTag.valueOf(CobblemonSchemas.DATA_VERSION));
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
@Mixin(CrashReport.class)
|
||||
public final class CrashReportMixin {
|
||||
|
||||
@Inject(method = "getDetails", at = @At(value = "INVOKE", target = "Lnet/minecraft/SystemReport;appendToCrashReportString(Ljava/lang/StringBuilder;)V"))
|
||||
@Inject(method = "getDetails(Ljava/lang/StringBuilder;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/SystemReport;appendToCrashReportString(Ljava/lang/StringBuilder;)V"))
|
||||
public void cobblemon$printCobblemonDetails(StringBuilder builder, CallbackInfo callback) {
|
||||
CrashReportCategory cobblemon = new CrashReportCategory("Cobblemon");
|
||||
cobblemon.setDetail("Version", CobblemonBuildDetails.VERSION);
|
||||
|
||||
@@ -21,11 +21,13 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
@Mixin(DecoratedPotPatterns.class)
|
||||
public abstract class DecoratedPotPatternsMixin {
|
||||
@Inject(method = "getPatternFromItem", at=@At("HEAD"), cancellable = true)
|
||||
private static void cobblemon$getCobblemonSherdTexture(Item sherd,
|
||||
CallbackInfoReturnable<ResourceKey<DecoratedPotPattern>> cir) {
|
||||
private static void cobblemon$getCobblemonSherdTexture(
|
||||
Item sherd,
|
||||
CallbackInfoReturnable<ResourceKey<DecoratedPotPattern>> cir
|
||||
) {
|
||||
if (CobblemonSherds.INSTANCE.getSherdToPattern().containsKey(sherd)) {
|
||||
cir.setReturnValue(CobblemonSherds.INSTANCE.getSherdToPattern().get(sherd));
|
||||
return;
|
||||
cir.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import static com.cobblemon.mod.common.datafixer.CobblemonSchemas.VERSION_KEY;
|
||||
|
||||
import com.cobblemon.mod.common.datafixer.CobblemonSchemas;
|
||||
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.IntTag;
|
||||
import net.minecraft.util.datafix.DataFixTypes;
|
||||
import net.minecraft.world.level.chunk.storage.EntityStorage;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
|
||||
@Mixin(EntityStorage.class)
|
||||
public class EntityStorageMixin {
|
||||
//Modifies the NBT returned by the vanilla upgradeChunkTag to also incorporate cobblemon fixup stuff
|
||||
@ModifyExpressionValue(
|
||||
method = "method_31731(Lnet/minecraft/world/level/ChunkPos;Ljava/util/Optional;)Lnet/minecraft/world/level/entity/ChunkEntities;",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/world/level/chunk/storage/SimpleRegionStorage;upgradeChunkTag(Lnet/minecraft/nbt/CompoundTag;I)Lnet/minecraft/nbt/CompoundTag;"
|
||||
)
|
||||
)
|
||||
public CompoundTag cobblemon$doEntityFix(
|
||||
CompoundTag vanillaFixed
|
||||
) {
|
||||
int curVersion = vanillaFixed.contains(VERSION_KEY) ? vanillaFixed.getInt(VERSION_KEY) : 0;
|
||||
CompoundTag newTag = DataFixTypes.ENTITY_CHUNK.update(CobblemonSchemas.getDATA_FIXER(), vanillaFixed, curVersion, CobblemonSchemas.DATA_VERSION);
|
||||
newTag.put(VERSION_KEY, IntTag.valueOf(CobblemonSchemas.DATA_VERSION));
|
||||
return newTag;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.item.PokedexItem;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.client.player.AbstractClientPlayer;
|
||||
import net.minecraft.client.renderer.ItemInHandRenderer;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(ItemInHandRenderer.class)
|
||||
public class ItemInHandRendererMixin {
|
||||
@Inject(method = "renderArmWithItem", at = @At(value = "HEAD"), cancellable = true)
|
||||
private void cobblemon$renderArmWithItem(AbstractClientPlayer abstractClientPlayer, float f, float g, InteractionHand interactionHand, float h, ItemStack itemStack, float i, PoseStack poseStack, MultiBufferSource multiBufferSource, int j, CallbackInfo ci) {
|
||||
if (abstractClientPlayer.isUsingItem() && abstractClientPlayer.getUseItem().getItem() instanceof PokedexItem) {
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
+38
-17
@@ -6,11 +6,13 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.pokeball;
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon;
|
||||
import com.cobblemon.mod.common.ModAPI;
|
||||
import com.cobblemon.mod.common.client.CobblemonBakingOverrides;
|
||||
import com.cobblemon.mod.common.item.PokeBallItem;
|
||||
import com.cobblemon.mod.common.item.PokedexItem;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.client.renderer.ItemModelShaper;
|
||||
@@ -31,15 +33,40 @@ import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
/*
|
||||
I think it would be nice to maybe use the existing mixin we have for custom item rendering [BuiltinModelItemRendererMixin]
|
||||
Obviously that would require changes. Potentially each item renderer defines what modes it overrides for?
|
||||
*/
|
||||
@Mixin(ItemRenderer.class)
|
||||
public abstract class ItemRendererMixin {
|
||||
|
||||
@Unique private static final String MODEL_PATH = Cobblemon.implementation.getModAPI() == ModAPI.FABRIC ? "fabric_resource" : "standalone";
|
||||
@Unique private final String MODEL_PATH = Cobblemon.implementation.getModAPI() == ModAPI.FABRIC ? "fabric_resource" : "standalone";
|
||||
|
||||
@Shadow @Final private ItemModelShaper itemModelShaper;
|
||||
|
||||
@Shadow public abstract void render(ItemStack stack, ItemDisplayContext renderMode, boolean leftHanded, PoseStack matrices, MultiBufferSource vertexConsumers, int light, int overlay, BakedModel model);
|
||||
|
||||
@Inject(
|
||||
method = "render(Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/item/ItemDisplayContext;ZLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;IILnet/minecraft/client/resources/model/BakedModel;)V",
|
||||
at = @At("HEAD"),
|
||||
cancellable = true
|
||||
)
|
||||
private void cobblemon$overrideItemModel(ItemStack stack, ItemDisplayContext renderMode, boolean leftHanded, PoseStack matrices, MultiBufferSource multiBufferSource, int light, int overlay, BakedModel model, CallbackInfo ci) {
|
||||
boolean shouldBe2d = renderMode == ItemDisplayContext.GUI || renderMode == ItemDisplayContext.FIXED;
|
||||
if (!shouldBe2d && stack.getItem() instanceof PokedexItem) {
|
||||
BakedModel replacementModel = CobblemonBakingOverrides.INSTANCE.getPokedexOverride(((PokedexItem) stack.getItem()).getType()).getModel();
|
||||
if (!cobblemon$isSameModel(model, replacementModel)) {
|
||||
ci.cancel();
|
||||
render(stack, renderMode, leftHanded, matrices, multiBufferSource, light, overlay, replacementModel);
|
||||
}
|
||||
} else if (shouldBe2d && stack.getItem() instanceof PokeBallItem pokeBallItem) {
|
||||
BakedModel replacementModel = this.itemModelShaper.getModelManager().getModel(new ModelResourceLocation(pokeBallItem.getPokeBall().getModel2d(), "inventory"));
|
||||
if (!cobblemon$isSameModel(model, replacementModel)) {
|
||||
ci.cancel();
|
||||
render(stack, renderMode, leftHanded, matrices, multiBufferSource, light, overlay, replacementModel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "getModel", at = @At("HEAD"), cancellable = true)
|
||||
private void cobblemon$bakePokeballModel(ItemStack stack, Level world, LivingEntity entity, int seed, CallbackInfoReturnable<BakedModel> cir) {
|
||||
if (stack.getItem() instanceof PokeBallItem pokeBallItem) {
|
||||
@@ -50,20 +77,14 @@ public abstract class ItemRendererMixin {
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "render(Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/item/ItemDisplayContext;ZLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;IILnet/minecraft/client/resources/model/BakedModel;)V",
|
||||
at = @At("HEAD"),
|
||||
cancellable = true
|
||||
)
|
||||
private void cobblemon$determinePokeballModel(ItemStack stack, ItemDisplayContext renderMode, boolean leftHanded, PoseStack matrices, MultiBufferSource vertexConsumers, int light, int overlay, BakedModel model, CallbackInfo ci) {
|
||||
boolean shouldBe2d = renderMode == ItemDisplayContext.GUI || renderMode == ItemDisplayContext.FIXED;
|
||||
if (shouldBe2d && stack.getItem() instanceof PokeBallItem pokeBallItem) {
|
||||
BakedModel replacementModel = this.itemModelShaper.getModelManager().getModel(new ModelResourceLocation(pokeBallItem.getPokeBall().getModel2d(), "inventory"));
|
||||
if (!model.equals(replacementModel)) {
|
||||
ci.cancel();
|
||||
render(stack, renderMode, leftHanded, matrices, vertexConsumers, light, overlay, replacementModel);
|
||||
}
|
||||
}
|
||||
// this method aims to cover an issue with modernfixes and it's "dynamic resource" causing the usual .equals check to always fail, resulting in a StackOverflow
|
||||
// this falls back to comparing the model contents (e.g. location of the texture, width and height)
|
||||
@Unique
|
||||
private static boolean cobblemon$isSameModel(BakedModel original, BakedModel replacement) {
|
||||
return original.equals(replacement) ||
|
||||
(original.getParticleIcon().contents().name().equals(replacement.getParticleIcon().contents().name()) &&
|
||||
original.getParticleIcon().contents().width() == replacement.getParticleIcon().contents().width() &&
|
||||
original.getParticleIcon().contents().height() == replacement.getParticleIcon().contents().height());
|
||||
}
|
||||
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.util.DataKeys;
|
||||
import com.mojang.serialization.Dynamic;
|
||||
import net.minecraft.util.datafix.fixes.ItemStackComponentizationFix;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@Mixin(ItemStackComponentizationFix.class)
|
||||
public class ItemStackComponentizationFixMixin
|
||||
{
|
||||
@Inject(method = "fixItemStack", at = @At("TAIL"))
|
||||
private static void fixItemStack(ItemStackComponentizationFix.ItemStackData itemStackData, Dynamic<?> dynamic, CallbackInfo ci) {
|
||||
cobblemon$attemptPokemonModelDataFix(itemStackData, dynamic);
|
||||
}
|
||||
|
||||
@Unique
|
||||
private static void cobblemon$attemptPokemonModelDataFix(ItemStackComponentizationFix.ItemStackData itemStackData, Dynamic<?> dynamic)
|
||||
{
|
||||
var species = itemStackData.removeTag(DataKeys.POKEMON_ITEM_SPECIES).asString();
|
||||
var aspects = itemStackData.removeTag(DataKeys.POKEMON_ITEM_ASPECTS).asList(dynamic1 -> dynamic1);
|
||||
var redTint = itemStackData.removeTag(DataKeys.POKEMON_ITEM_TINT_RED).asNumber();
|
||||
var greenTint = itemStackData.removeTag(DataKeys.POKEMON_ITEM_TINT_GREEN).asNumber();
|
||||
var blueTint = itemStackData.removeTag(DataKeys.POKEMON_ITEM_TINT_BLUE).asNumber();
|
||||
var alphaTint = itemStackData.removeTag(DataKeys.POKEMON_ITEM_TINT_ALPHA).asNumber();
|
||||
if(species.hasResultOrPartial() && aspects != null) {
|
||||
var pokeComponent = dynamic.emptyMap().set("species", dynamic.createString(species.getOrThrow()));
|
||||
pokeComponent = pokeComponent.set("aspects", dynamic.createList(aspects.stream()));
|
||||
if(redTint.hasResultOrPartial() || blueTint.hasResultOrPartial() || greenTint.hasResultOrPartial() || alphaTint.hasResultOrPartial()) {
|
||||
pokeComponent = pokeComponent.set("tint", dynamic.createList(Stream.of(redTint, greenTint, blueTint, alphaTint)
|
||||
.map(x -> x.mapOrElse(Number::floatValue, error -> 0F))
|
||||
.map(dynamic::createFloat)));
|
||||
}
|
||||
itemStackData.setComponent("cobblemon:pokemon_item", pokeComponent);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.block.entity.LecternBlockEntity;
|
||||
import com.cobblemon.mod.common.CobblemonBlocks;
|
||||
import com.cobblemon.mod.common.CobblemonSounds;
|
||||
import com.cobblemon.mod.common.item.PokedexItem;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.ItemInteractionResult;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.HorizontalDirectionalBlock;
|
||||
import net.minecraft.world.level.block.LecternBlock;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import static net.minecraft.world.level.block.LecternBlock.HAS_BOOK;
|
||||
|
||||
@Mixin(LecternBlock.class)
|
||||
public abstract class LecternBlockMixin {
|
||||
@Inject(method = "useItemOn", at = @At(value = "HEAD"), cancellable = true)
|
||||
private void cobblemon$useItemOn(ItemStack itemStack, BlockState blockState, Level world, BlockPos blockPos, Player player, InteractionHand interactionHand, BlockHitResult blockHitResult, CallbackInfoReturnable<ItemInteractionResult> cir) {
|
||||
if (!world.isClientSide && itemStack.getItem() instanceof PokedexItem) {
|
||||
BlockEntity blockEntity = world.getBlockEntity(blockPos);
|
||||
if (!blockState.getValue(HAS_BOOK)
|
||||
&& blockEntity instanceof net.minecraft.world.level.block.entity.LecternBlockEntity
|
||||
&& blockState.getBlock() instanceof LecternBlock
|
||||
) {
|
||||
ItemStack pokedexItemStack = itemStack.copy();
|
||||
Direction facing = blockState.getValue(HorizontalDirectionalBlock.FACING);
|
||||
itemStack.consumeAndReturn(1, player);
|
||||
blockEntity.setRemoved();
|
||||
BlockState newBlockState = CobblemonBlocks.LECTERN.defaultBlockState().setValue(HorizontalDirectionalBlock.FACING, facing);
|
||||
world.setBlockAndUpdate(blockPos, newBlockState);
|
||||
BlockEntity lecternEntity = world.getBlockEntity(blockPos);
|
||||
|
||||
if (lecternEntity instanceof LecternBlockEntity) {
|
||||
((LecternBlockEntity) lecternEntity).setItemStack((pokedexItemStack));
|
||||
}
|
||||
|
||||
world.playSound(null, blockPos, CobblemonSounds.POKEDEX_CLOSE, SoundSource.BLOCKS, 0.5F, 1.25F);
|
||||
cir.setReturnValue(itemStack.isEmpty() && interactionHand == InteractionHand.MAIN_HAND ? ItemInteractionResult.SKIP_DEFAULT_BLOCK_INTERACTION : ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -8,7 +8,7 @@
|
||||
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.client.sound.battle.BattleMusicController;
|
||||
import com.cobblemon.mod.common.client.sound.BattleMusicController;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.resources.sounds.SoundInstance;
|
||||
import net.minecraft.client.sounds.MusicManager;
|
||||
@@ -21,7 +21,7 @@ import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(MusicManager.class)
|
||||
public class MusicTrackerMixin {
|
||||
public class MusicManagerMixin {
|
||||
|
||||
@Shadow @Final
|
||||
private Minecraft minecraft;
|
||||
@@ -10,8 +10,13 @@ package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.client.CobblemonClient;
|
||||
import com.cobblemon.mod.common.client.keybind.keybinds.PartySendBinding;
|
||||
import com.cobblemon.mod.common.item.PokedexItem;
|
||||
import com.cobblemon.mod.common.pokedex.scanner.PokedexUsageContext;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.MouseHandler;
|
||||
import net.minecraft.util.Mth;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
@@ -23,6 +28,8 @@ public class PartyScrollMixin {
|
||||
@Shadow
|
||||
private double accumulatedScrollY;
|
||||
|
||||
@Shadow @Final private Minecraft minecraft;
|
||||
|
||||
@Inject(
|
||||
method = "onScroll",
|
||||
at = @At(
|
||||
@@ -34,20 +41,37 @@ public class PartyScrollMixin {
|
||||
),
|
||||
cancellable = true
|
||||
)
|
||||
public void onMouseScroll(long window, double horizontal, double vertical, CallbackInfo ci) {
|
||||
public void cobblemon$scrollParty(long window, double horizontal, double vertical, CallbackInfo ci) {
|
||||
if (PartySendBinding.INSTANCE.getWasDown()) {
|
||||
int i = (int)accumulatedScrollY;
|
||||
int i = (int) accumulatedScrollY;
|
||||
if (i > 0) {
|
||||
while (i-- > 0) CobblemonClient.INSTANCE.getStorage().shiftSelected(false);
|
||||
accumulatedScrollY -= i;
|
||||
CobblemonClient.INSTANCE.getStorage().shiftSelected(false);
|
||||
ci.cancel();
|
||||
accumulatedScrollY = 0;
|
||||
PartySendBinding.INSTANCE.actioned();
|
||||
} else if (i < 0) {
|
||||
while (i++ < 0) CobblemonClient.INSTANCE.getStorage().shiftSelected(true);
|
||||
accumulatedScrollY -= i;
|
||||
CobblemonClient.INSTANCE.getStorage().shiftSelected(true);
|
||||
ci.cancel();
|
||||
accumulatedScrollY = 0;
|
||||
PartySendBinding.INSTANCE.actioned();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "onScroll",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/world/entity/player/Inventory;swapPaint(D)V"
|
||||
),
|
||||
cancellable = true
|
||||
)
|
||||
public void cobblemon$doPokedexZoom(long window, double horizontal, double vertical, CallbackInfo ci) {
|
||||
PokedexUsageContext usageContext = CobblemonClient.INSTANCE.getPokedexUsageContext();
|
||||
if (usageContext.getScanningGuiOpen()) {
|
||||
usageContext.adjustZoom(vertical);
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -18,7 +18,18 @@ import com.cobblemon.mod.common.api.tags.CobblemonItemTags;
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon;
|
||||
import com.cobblemon.mod.common.util.CompoundTagExtensionsKt;
|
||||
import com.cobblemon.mod.common.util.DataKeys;
|
||||
import com.cobblemon.mod.common.world.gamerules.CobblemonGameRules;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.damagesource.DamageSource;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.item.ItemEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.food.FoodProperties;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.Level;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
@@ -29,15 +40,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.food.FoodProperties;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.Level;
|
||||
|
||||
@Mixin(Player.class)
|
||||
public abstract class PlayerMixin extends LivingEntity {
|
||||
@@ -63,7 +65,7 @@ public abstract class PlayerMixin extends LivingEntity {
|
||||
super(p_20966_, p_20967_);
|
||||
}
|
||||
|
||||
@Inject(method = "respawnEntityOnShoulder", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/EntityType;create(Lnet/minecraft/nbt/CompoundTag;Lnet/minecraft/world/Level;)Ljava/util/Optional;"), cancellable = true)
|
||||
@Inject(method = "respawnEntityOnShoulder", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/EntityType;create(Lnet/minecraft/nbt/CompoundTag;Lnet/minecraft/world/level/Level;)Ljava/util/Optional;"), cancellable = true)
|
||||
private void cobblemon$removePokemon(CompoundTag nbt, CallbackInfo ci) {
|
||||
if (CompoundTagExtensionsKt.isPokemonEntity(nbt)) {
|
||||
final UUID uuid = this.getPokemonID(nbt);
|
||||
@@ -117,14 +119,12 @@ public abstract class PlayerMixin extends LivingEntity {
|
||||
|
||||
private void recallPokemon(UUID uuid) {
|
||||
// We need to do this cause the Entity doesn't store a reference to its storage
|
||||
try {
|
||||
final PartyStore party = Cobblemon.INSTANCE.getStorage().getParty(this.uuid);
|
||||
for (Pokemon pokemon : party) {
|
||||
if (pokemon.getUuid().equals(uuid)) {
|
||||
pokemon.recall();
|
||||
}
|
||||
final PartyStore party = Cobblemon.INSTANCE.getStorage().getParty(this.getUUID(), this.registryAccess());
|
||||
for (Pokemon pokemon : party) {
|
||||
if (pokemon.getUuid().equals(uuid)) {
|
||||
pokemon.recall();
|
||||
}
|
||||
} catch (NoPokemonStoreException ignored) {}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isShoulderPokemon(CompoundTag nbt) {
|
||||
@@ -159,4 +159,16 @@ public abstract class PlayerMixin extends LivingEntity {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "isInvulnerableTo", at = @At("HEAD"), cancellable = true)
|
||||
public void isInvulnerableTo(DamageSource source, CallbackInfoReturnable<Boolean> ci) {
|
||||
if (!level().isClientSide) {
|
||||
ServerPlayer player = (ServerPlayer)(Object)this;
|
||||
boolean invulnerableInBattle = this.level().getGameRules().getBoolean(CobblemonGameRules.BATTLE_INVULNERABILITY);
|
||||
boolean inBattle = Cobblemon.INSTANCE.getBattleRegistry().getBattleByParticipatingPlayer(player) != null;
|
||||
if (invulnerableInBattle && inBattle) {
|
||||
ci.setReturnValue(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.client.CobblemonClient;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.client.player.AbstractClientPlayer;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.entity.player.PlayerRenderer;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(PlayerRenderer.class)
|
||||
public class PlayerRendererMixin {
|
||||
@Inject(
|
||||
method = "render(Lnet/minecraft/client/player/AbstractClientPlayer;FFLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V",
|
||||
at = @At(value = "TAIL")
|
||||
)
|
||||
public void renderPlayer(AbstractClientPlayer player, float f, float g, PoseStack poseStack, MultiBufferSource multiBufferSource, int i, CallbackInfo ci) {
|
||||
CobblemonClient.INSTANCE.getRequests().onRenderPlayer(player, g);
|
||||
}
|
||||
}
|
||||
+4
-4
@@ -8,8 +8,8 @@
|
||||
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.client.sound.battle.BattleMusicController;
|
||||
import com.cobblemon.mod.common.duck.SoundSystemDuck;
|
||||
import com.cobblemon.mod.common.client.sound.BattleMusicController;
|
||||
import com.cobblemon.mod.common.duck.SoundEngineDuck;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.mojang.blaze3d.audio.Channel;
|
||||
import net.minecraft.client.resources.sounds.SoundInstance;
|
||||
@@ -28,7 +28,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import java.util.Map;
|
||||
|
||||
@Mixin(SoundEngine.class)
|
||||
public abstract class SoundSystemMixin implements SoundSystemDuck {
|
||||
public abstract class SoundEngineMixin implements SoundEngineDuck {
|
||||
|
||||
@Shadow
|
||||
private boolean loaded;
|
||||
@@ -91,7 +91,7 @@ public abstract class SoundSystemMixin implements SoundSystemDuck {
|
||||
|
||||
/** Allows stopping all SoundInstances that belong to a queried category. */
|
||||
@Inject(method = "stop(Lnet/minecraft/resources/ResourceLocation;Lnet/minecraft/sounds/SoundSource;)V", at = @At("HEAD"), cancellable = true)
|
||||
public void stopSoustopnds(@Nullable ResourceLocation id, @Nullable SoundSource category, CallbackInfo cb) {
|
||||
public void stopSounds(@Nullable ResourceLocation id, @Nullable SoundSource category, CallbackInfo cb) {
|
||||
if (id == null && category != null) {
|
||||
this.instanceBySource.get(category).forEach(this::stop);
|
||||
cb.cancel();
|
||||
@@ -8,9 +8,12 @@
|
||||
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.client.sound.battle.BattleMusicController;
|
||||
import com.cobblemon.mod.common.client.sound.BlockEntitySoundTracker;
|
||||
import com.cobblemon.mod.common.client.sound.EntitySoundTracker;
|
||||
import com.cobblemon.mod.common.client.sound.BattleMusicController;
|
||||
import com.cobblemon.mod.common.client.sound.SoundTracker;
|
||||
import com.cobblemon.mod.common.duck.SoundManagerDuck;
|
||||
import com.cobblemon.mod.common.duck.SoundSystemDuck;
|
||||
import com.cobblemon.mod.common.duck.SoundEngineDuck;
|
||||
import net.minecraft.client.resources.sounds.BiomeAmbientSoundsHandler;
|
||||
import net.minecraft.client.resources.sounds.SoundInstance;
|
||||
import net.minecraft.client.resources.sounds.UnderwaterAmbientSoundInstances;
|
||||
@@ -55,19 +58,13 @@ public abstract class SoundManagerMixin implements SoundManagerDuck {
|
||||
/** Pauses the queried SoundInstance(s). If id is null, will pause all sounds belonging to the SoundCategory. */
|
||||
@Override
|
||||
public void pauseSounds(@Nullable ResourceLocation id, @Nullable SoundSource category) {
|
||||
((SoundSystemDuck)soundEngine).pauseSounds(id, category);
|
||||
((SoundEngineDuck)soundEngine).pauseSounds(id, category);
|
||||
}
|
||||
|
||||
/** Resumes the queried SoundInstance(s). If id is null, will resume all sounds belonging to the SoundCategory. */
|
||||
@Override
|
||||
public void resumeSounds(@Nullable ResourceLocation id, @Nullable SoundSource category) {
|
||||
((SoundSystemDuck)soundEngine).resumeSounds(id, category);
|
||||
}
|
||||
|
||||
/** Stops the queried SoundInstance(s). If id is null, will stop all sounds belonging to the SoundCategory. */
|
||||
@Override
|
||||
public void stopSounds(@Nullable ResourceLocation id, @Nullable SoundSource category) {
|
||||
((SoundSystemDuck)soundEngine).stopSounds(id, category);
|
||||
((SoundEngineDuck)soundEngine).resumeSounds(id, category);
|
||||
}
|
||||
|
||||
/** Blocks filtered sounds from being played while a BattleMusicInstance is in progress. */
|
||||
@@ -91,4 +88,10 @@ public abstract class SoundManagerMixin implements SoundManagerDuck {
|
||||
public void playEnd(SoundInstance sound, int delay, CallbackInfo cb) {
|
||||
if (ambientLoopCondition(sound)) this.pauseSounds(sound.getLocation(), SoundSource.AMBIENT);
|
||||
}
|
||||
|
||||
/** Clears tracked sounds on the client when disconnected. */
|
||||
@Inject(method = "stop()V", at = @At("TAIL"))
|
||||
public void stop(CallbackInfo cb) {
|
||||
SoundTracker.Companion.clear();
|
||||
}
|
||||
}
|
||||
|
||||
+28
-74
@@ -9,22 +9,26 @@
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.world.CobblemonStructureIDs;
|
||||
import com.llamalad7.mixinextras.sugar.Local;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.LevelHeightAccessor;
|
||||
import net.minecraft.world.level.chunk.ChunkGenerator;
|
||||
import net.minecraft.world.level.levelgen.RandomState;
|
||||
import net.minecraft.world.level.levelgen.structure.PoolElementStructurePiece;
|
||||
import net.minecraft.world.level.levelgen.structure.pools.JigsawPlacement;
|
||||
import net.minecraft.world.level.levelgen.structure.pools.LegacySinglePoolElement;
|
||||
import net.minecraft.world.level.levelgen.structure.pools.SinglePoolElement;
|
||||
import net.minecraft.world.level.levelgen.structure.pools.StructurePoolElement;
|
||||
import net.minecraft.world.level.levelgen.structure.pools.StructureTemplatePool;
|
||||
import net.minecraft.world.level.levelgen.structure.pools.*;
|
||||
import net.minecraft.world.level.levelgen.structure.pools.alias.PoolAliasLookup;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.LiquidSettings;
|
||||
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager;
|
||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
import org.apache.commons.lang3.mutable.MutableObject;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.ModifyVariable;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@@ -39,11 +43,11 @@ public abstract class StructurePoolGeneratorMixin {
|
||||
String pokecenter = "pokecenter";
|
||||
String berry = "berry_farm";
|
||||
|
||||
structureGroups.put(CobblemonStructureIDs.PLAINS_POKECENTER, Set.of(pokecenter));
|
||||
structureGroups.put(CobblemonStructureIDs.DESERT_POKECENTER, Set.of(pokecenter));
|
||||
structureGroups.put(CobblemonStructureIDs.SAVANNA_POKECENTER, Set.of(pokecenter));
|
||||
structureGroups.put(CobblemonStructureIDs.SNOWY_POKECENTER, Set.of(pokecenter));
|
||||
structureGroups.put(CobblemonStructureIDs.TAIGA_POKECENTER, Set.of(pokecenter));
|
||||
structureGroups.put(CobblemonStructureIDs.VILLAGE_PLAINS_POKECENTER, Set.of(pokecenter));
|
||||
structureGroups.put(CobblemonStructureIDs.VILLAGE_DESERT_POKECENTER, Set.of(pokecenter));
|
||||
structureGroups.put(CobblemonStructureIDs.VILLAGE_SAVANNA_POKECENTER, Set.of(pokecenter));
|
||||
structureGroups.put(CobblemonStructureIDs.VILLAGE_SNOWY_POKECENTER, Set.of(pokecenter));
|
||||
structureGroups.put(CobblemonStructureIDs.VILLAGE_TAIGA_POKECENTER, Set.of(pokecenter));
|
||||
|
||||
structureGroups.put(CobblemonStructureIDs.SAVANNA_BERRY_SMALL, Set.of(berry));
|
||||
structureGroups.put(CobblemonStructureIDs.SAVANNA_BERRY_LARGE, Set.of(berry));
|
||||
@@ -117,53 +121,25 @@ public abstract class StructurePoolGeneratorMixin {
|
||||
return reducedList.iterator();
|
||||
}
|
||||
|
||||
@ModifyVariable(method = "tryPlacingChildren", at = @At("HEAD"), ordinal = 0, argsOnly = true)
|
||||
private PoolElementStructurePiece injected(PoolElementStructurePiece poolStructurePiece) {
|
||||
ResourceLocation structureLocationKey = getCobblemonOnlyLocation(poolStructurePiece.getElement());
|
||||
@Inject(method = "tryPlacingChildren", at = @At(value = "NEW", target = "net/minecraft/world/level/levelgen/structure/PoolElementStructurePiece", ordinal = 0), locals = LocalCapture.CAPTURE_FAILHARD)
|
||||
private void afterTryPlacingChildren(
|
||||
PoolElementStructurePiece poolElementStructurePiece,
|
||||
MutableObject<VoxelShape> mutableObject,
|
||||
int i,
|
||||
boolean bl,
|
||||
LevelHeightAccessor levelHeightAccessor,
|
||||
RandomState randomState,
|
||||
PoolAliasLookup poolAliasLookup,
|
||||
LiquidSettings liquidSettings,
|
||||
CallbackInfo ci,
|
||||
@Local(ordinal = 1) StructurePoolElement structurePoolElement
|
||||
) {
|
||||
ResourceLocation structureLocationKey = getCobblemonOnlyLocation(structurePoolElement);
|
||||
if (structureLocationKey != null) {
|
||||
incrementStructureCount(structureLocationKey);
|
||||
}
|
||||
return poolStructurePiece;
|
||||
}
|
||||
|
||||
// This doesn't SEEM necessary? It appears to work without.
|
||||
// @Inject(method = "generatePiece", at = @At("HEAD"))
|
||||
// private void beforeGeneratePiece(PoolStructurePiece piece, MutableObject<VoxelShape> pieceShape, int minY, boolean modifyBoundingBox, HeightLimitView world, NoiseConfig noiseConfig, CallbackInfo ci) {
|
||||
//// Identifier structureLocationKey = getCobblemonOnlyLocation(piece.getPoolElement());
|
||||
////
|
||||
//// if (structureLocationKey != null) {
|
||||
//// Integer currentlyGenerated = generatedStructureCounts.get(structureLocationKey);
|
||||
//// if (currentlyGenerated == null) currentlyGenerated = 0;
|
||||
//// generatedStructureCounts.put(structureLocationKey, currentlyGenerated + 1);
|
||||
//// }
|
||||
////
|
||||
//// List<StructurePoolBasedGenerator.ShapedPoolStructurePiece> reducedStructurePiecesList = structurePieces.stream().toList();
|
||||
////
|
||||
//// for (Identifier maxStructureLocationKey : structureMaxes.keySet()) {
|
||||
//// Integer maxAllowed = structureMaxes.get(maxStructureLocationKey);
|
||||
////
|
||||
//// Integer currentlyGenerated = generatedStructureCounts.get(maxStructureLocationKey);
|
||||
//// if (currentlyGenerated == null) currentlyGenerated = 0;
|
||||
//// if (currentlyGenerated < maxAllowed) {
|
||||
//// continue;
|
||||
//// }
|
||||
////
|
||||
//// //Already have max so need to remove
|
||||
//// reducedStructurePiecesList = reducedStructurePiecesList.stream()
|
||||
//// .filter(shapedStructurePiece -> {
|
||||
//// Identifier locationKey = getCobblemonOnlyLocation(shapedStructurePiece.piece.getPoolElement());
|
||||
//// if (locationKey == null) {
|
||||
//// return true;
|
||||
//// }
|
||||
////
|
||||
//// return !locationKey.equals(maxStructureLocationKey);
|
||||
//// })
|
||||
//// .collect(Collectors.toList());
|
||||
//// }
|
||||
////
|
||||
//// structurePieces = new ArrayDeque<>(reducedStructurePiecesList);
|
||||
// }
|
||||
|
||||
private static ResourceLocation getCobblemonOnlyLocation(StructurePoolElement structurePoolElement) {
|
||||
ResourceLocation location = getLocationIfAvailable(structurePoolElement);
|
||||
if (location == null) return null;
|
||||
@@ -186,26 +162,4 @@ public abstract class StructurePoolGeneratorMixin {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// private List<StructurePoolElement> removeInstanceOfLocationKeyFrom(List<StructurePoolElement> structureList, Integer allowedNumberOfInstances, Identifier locationKey) {
|
||||
// List<StructurePoolElement> reducedList = new ArrayList<>();
|
||||
// int instancesFound = 0;
|
||||
//
|
||||
// for (StructurePoolElement structurePoolElement: structureList) {
|
||||
// Identifier structureKey = getCobblemonOnlyLocation(structurePoolElement);
|
||||
// if (structureKey == null || !structureKey.equals(locationKey)) {
|
||||
// reducedList.add(structurePoolElement);
|
||||
// continue;
|
||||
// }
|
||||
//
|
||||
// if (instancesFound >= allowedNumberOfInstances) {
|
||||
// continue;
|
||||
// }
|
||||
//
|
||||
// reducedList.add(structurePoolElement);
|
||||
// instancesFound++;
|
||||
// }
|
||||
//
|
||||
// return reducedList;
|
||||
// }
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon;
|
||||
import com.cobblemon.mod.common.world.gamerules.CobblemonGameRules;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.ai.targeting.TargetingConditions;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
@Mixin(TargetingConditions.class)
|
||||
public class TargetingConditionsMixin {
|
||||
|
||||
@Inject(method = "test", at = @At("HEAD"), cancellable = true)
|
||||
public void test(@Nullable LivingEntity baseEntity, LivingEntity targetEntity, CallbackInfoReturnable<Boolean> ci) {
|
||||
if (targetEntity instanceof ServerPlayer player) {
|
||||
boolean canTargetInBattle = player.level().getGameRules().getBoolean(CobblemonGameRules.MOB_TARGET_IN_BATTLE);
|
||||
boolean targetInBattle = Cobblemon.INSTANCE.getBattleRegistry().getBattleByParticipatingPlayer(player) != null;
|
||||
if (!canTargetInBattle && targetInBattle) ci.setReturnValue(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon;
|
||||
import com.cobblemon.mod.common.CobblemonVillagerProfessions;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import kotlin.Pair;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.client.model.EntityModel;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.entity.LivingEntityRenderer;
|
||||
import net.minecraft.client.renderer.entity.layers.RenderLayer;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.monster.ZombieVillager;
|
||||
import net.minecraft.world.entity.npc.Villager;
|
||||
import net.minecraft.world.entity.npc.VillagerProfession;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(RenderLayer.class)
|
||||
public abstract class VillagerProfessionLayerMixin {
|
||||
@Inject(method = "renderColoredCutoutModel", at = @At(value = "HEAD"), cancellable = true)
|
||||
private static <T extends LivingEntity> void cobblemon$renderVillagerProfessionLayer(EntityModel<T> entityModel, ResourceLocation resourceLocation, PoseStack poseStack, MultiBufferSource multiBufferSource, int i, T livingEntity, int j, CallbackInfo ci) {
|
||||
if (resourceLocation.getNamespace().equals(Cobblemon.MODID)) {
|
||||
VillagerProfession profession = null;
|
||||
boolean isZombie = false;
|
||||
|
||||
if (livingEntity instanceof Villager) profession = ((Villager) livingEntity).getVillagerData().getProfession();
|
||||
if (livingEntity instanceof ZombieVillager) {
|
||||
profession = ((ZombieVillager) livingEntity).getVillagerData().getProfession();
|
||||
isZombie = true;
|
||||
}
|
||||
|
||||
Pair<String, String[]> override = CobblemonVillagerProfessions.INSTANCE.getNameTagOverride(profession);
|
||||
if (profession != null && override != null) {
|
||||
String entityName = ChatFormatting.stripFormatting(livingEntity.getName().getString());
|
||||
boolean nameMatches = false;
|
||||
for (String name: override.getSecond())
|
||||
if (entityName.endsWith(name)) {
|
||||
nameMatches = true;
|
||||
break;
|
||||
}
|
||||
if (nameMatches && resourceLocation.equals(getProfessionResourceLocation(resourceLocation.getNamespace(), ResourceLocation.parse(profession.name()).getPath(), isZombie))) {
|
||||
ResourceLocation textureLocation = getProfessionResourceLocation(resourceLocation.getNamespace(), override.getFirst(), isZombie);
|
||||
VertexConsumer vertexConsumer = multiBufferSource.getBuffer(RenderType.entityCutoutNoCull(textureLocation));
|
||||
entityModel.renderToBuffer(poseStack, vertexConsumer, i, LivingEntityRenderer.getOverlayCoords(livingEntity, 0.0F), j);
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static ResourceLocation getProfessionResourceLocation(String namespace, String profession, Boolean isZombie) {
|
||||
return ResourceLocation.fromNamespaceAndPath(namespace, "textures/entity/" + (isZombie ? "zombie_villager" : "villager") + "/profession/" + profession + ".png");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.accessor;
|
||||
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
@Mixin(Biome.class)
|
||||
public interface BiomeAccessor {
|
||||
@Accessor("climateSettings")
|
||||
Biome.ClimateSettings getClimateSettings();
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.accessor;
|
||||
|
||||
import net.minecraft.client.gui.components.AbstractSelectionList;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
@Mixin(AbstractSelectionList.class)
|
||||
public interface EntryListWidgetAccessor {
|
||||
@Accessor("renderHeader")
|
||||
boolean getRenderHeader();
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.client;
|
||||
|
||||
import com.cobblemon.mod.common.client.CobblemonClient;
|
||||
import com.cobblemon.mod.common.pokedex.scanner.PokedexUsageContext;
|
||||
import net.minecraft.client.player.AbstractClientPlayer;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
@Mixin(AbstractClientPlayer.class)
|
||||
public class AbstractClientPlayerMixin {
|
||||
@Inject(
|
||||
method = "getFieldOfViewModifier()F",
|
||||
at = @At(
|
||||
value = "HEAD"
|
||||
),
|
||||
cancellable = true
|
||||
)
|
||||
public void cobblemon$getPokedexFovMultiplier(CallbackInfoReturnable<Float> cir) {
|
||||
PokedexUsageContext usageContext = CobblemonClient.INSTANCE.getPokedexUsageContext();
|
||||
if (usageContext.getScanningGuiOpen()) {
|
||||
cir.setReturnValue(usageContext.getFovMultiplier());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.client;
|
||||
|
||||
import com.cobblemon.mod.common.client.gui.ScrollingWidget;
|
||||
import net.minecraft.client.gui.components.AbstractSelectionList;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.Constant;
|
||||
import org.spongepowered.asm.mixin.injection.ModifyConstant;
|
||||
|
||||
@Mixin(AbstractSelectionList.class)
|
||||
public abstract class EntryListWidgetMixin {
|
||||
|
||||
@SuppressWarnings("ConstantValue")
|
||||
@ModifyConstant(method = "getEntryAtPosition", constant = @Constant(intValue = 4))
|
||||
public int cobblemon$adjustOnlyIfNecessary(int input) {
|
||||
if(ScrollingWidget.class.isInstance(this)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.client;
|
||||
|
||||
import com.cobblemon.mod.common.client.CobblemonClient;
|
||||
import net.minecraft.client.DeltaTracker;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.Gui;
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
/**
|
||||
* Mixin to give us a hook to render the PartyOverlay below the Chat
|
||||
*
|
||||
* @author Qu
|
||||
* @since 2022-02-22
|
||||
*/
|
||||
@Mixin(Gui.class)
|
||||
public class GuiMixin {
|
||||
//This injects into the actual BooleanSupplier lambda for the "this.layers.add(layeredDraw, () -> !minecraft.options.hideGui)" call
|
||||
// sus af. You have to get the method name by looking at the bytecode of the class. Can do in intellij By clicking View -> Show Bytecode (top left)
|
||||
@Inject(method = "method_55797", at = @At("HEAD"), cancellable = true)
|
||||
private static void cobblemon$dontRenderUiInPokedex(Minecraft minecraft, CallbackInfoReturnable<Boolean> cir) {
|
||||
if (CobblemonClient.INSTANCE.getPokedexUsageContext().getScanningGuiOpen() && minecraft.options.getCameraType().isFirstPerson()) {
|
||||
cir.setReturnValue(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,12 +16,7 @@ import com.cobblemon.mod.common.api.drop.CommandDropEntry
|
||||
import com.cobblemon.mod.common.api.drop.DropEntry
|
||||
import com.cobblemon.mod.common.api.drop.ItemDropEntry
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents.BATTLE_VICTORY
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents.DATA_SYNCHRONIZED
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents.EVOLUTION_COMPLETE
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents.LEVEL_UP_EVENT
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents.POKEMON_CAPTURED
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents.TRADE_COMPLETED
|
||||
import com.cobblemon.mod.common.api.permission.PermissionValidator
|
||||
import com.cobblemon.mod.common.api.pokeball.catching.calculators.CaptureCalculator
|
||||
import com.cobblemon.mod.common.api.pokeball.catching.calculators.CaptureCalculators
|
||||
@@ -48,7 +43,6 @@ import com.cobblemon.mod.common.api.spawning.prospecting.SpawningProspector
|
||||
import com.cobblemon.mod.common.api.starter.StarterHandler
|
||||
import com.cobblemon.mod.common.api.storage.PokemonStoreManager
|
||||
import com.cobblemon.mod.common.api.storage.adapter.conversions.ReforgedConversion
|
||||
import com.cobblemon.mod.common.api.storage.adapter.database.MongoDBStoreAdapter
|
||||
import com.cobblemon.mod.common.api.storage.adapter.flatfile.FileStoreAdapter
|
||||
import com.cobblemon.mod.common.api.storage.adapter.flatfile.JSONStoreAdapter
|
||||
import com.cobblemon.mod.common.api.storage.adapter.flatfile.NBTStoreAdapter
|
||||
@@ -56,9 +50,11 @@ import com.cobblemon.mod.common.api.storage.factory.FileBackedPokemonStoreFactor
|
||||
import com.cobblemon.mod.common.api.storage.molang.NbtMoLangDataStoreFactory
|
||||
import com.cobblemon.mod.common.api.storage.pc.PCStore
|
||||
import com.cobblemon.mod.common.api.storage.pc.link.PCLinkManager
|
||||
import com.cobblemon.mod.common.api.storage.player.PlayerDataStoreManager
|
||||
import com.cobblemon.mod.common.api.storage.player.factory.JsonPlayerDataStoreFactory
|
||||
import com.cobblemon.mod.common.api.storage.player.factory.MongoPlayerDataStoreFactory
|
||||
import com.cobblemon.mod.common.api.storage.player.PlayerInstancedDataStoreManager
|
||||
import com.cobblemon.mod.common.api.storage.player.PlayerInstancedDataStoreTypes
|
||||
import com.cobblemon.mod.common.api.storage.player.adapter.DexDataNbtBackend
|
||||
import com.cobblemon.mod.common.api.storage.player.adapter.PlayerDataJsonBackend
|
||||
import com.cobblemon.mod.common.api.storage.player.factory.CachedPlayerDataStoreFactory
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonEntityTypeTags
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonItemTags
|
||||
import com.cobblemon.mod.common.battles.BagItems
|
||||
@@ -68,19 +64,23 @@ import com.cobblemon.mod.common.battles.BattleSide
|
||||
import com.cobblemon.mod.common.battles.ShowdownThread
|
||||
import com.cobblemon.mod.common.battles.actor.PokemonBattleActor
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
import com.cobblemon.mod.common.command.argument.DexArgumentType
|
||||
import com.cobblemon.mod.common.command.argument.DialogueArgumentType
|
||||
import com.cobblemon.mod.common.command.argument.FormArgumentType
|
||||
import com.cobblemon.mod.common.command.argument.MoveArgumentType
|
||||
import com.cobblemon.mod.common.command.argument.NPCClassArgumentType
|
||||
import com.cobblemon.mod.common.command.argument.PartySlotArgumentType
|
||||
import com.cobblemon.mod.common.command.argument.PokemonArgumentType
|
||||
import com.cobblemon.mod.common.command.argument.PokemonPropertiesArgumentType
|
||||
import com.cobblemon.mod.common.command.argument.PokemonStoreArgumentType
|
||||
import com.cobblemon.mod.common.command.argument.SpawnBucketArgumentType
|
||||
import com.cobblemon.mod.common.command.argument.SpeciesArgumentType
|
||||
import com.cobblemon.mod.common.config.CobblemonConfig
|
||||
import com.cobblemon.mod.common.config.LastChangedVersion
|
||||
import com.cobblemon.mod.common.config.constraint.IntConstraint
|
||||
import com.cobblemon.mod.common.config.starter.StarterConfig
|
||||
import com.cobblemon.mod.common.data.CobblemonDataProvider
|
||||
import com.cobblemon.mod.common.events.AdvancementHandler
|
||||
import com.cobblemon.mod.common.events.PokedexHandler
|
||||
import com.cobblemon.mod.common.events.ServerTickHandler
|
||||
import com.cobblemon.mod.common.net.messages.client.settings.ServerSettingsPacket
|
||||
import com.cobblemon.mod.common.permission.LaxPermissionValidator
|
||||
@@ -92,7 +92,9 @@ import com.cobblemon.mod.common.pokemon.evolution.variants.BlockClickEvolution
|
||||
import com.cobblemon.mod.common.pokemon.feature.TagSeasonResolver
|
||||
import com.cobblemon.mod.common.pokemon.helditem.CobblemonHeldItemManager
|
||||
import com.cobblemon.mod.common.pokemon.properties.AspectPropertyType
|
||||
import com.cobblemon.mod.common.pokemon.properties.FreezeFrameProperty
|
||||
import com.cobblemon.mod.common.pokemon.properties.HiddenAbilityPropertyType
|
||||
import com.cobblemon.mod.common.pokemon.properties.NoAIProperty
|
||||
import com.cobblemon.mod.common.pokemon.properties.UnaspectPropertyType
|
||||
import com.cobblemon.mod.common.pokemon.properties.UncatchableProperty
|
||||
import com.cobblemon.mod.common.pokemon.properties.tags.PokemonFlagProperty
|
||||
@@ -103,10 +105,7 @@ import com.cobblemon.mod.common.util.*
|
||||
import com.cobblemon.mod.common.world.feature.CobblemonPlacedFeatures
|
||||
import com.cobblemon.mod.common.world.feature.ore.CobblemonOrePlacedFeatures
|
||||
import com.cobblemon.mod.common.world.gamerules.CobblemonGameRules
|
||||
import com.mongodb.ConnectionString
|
||||
import com.mongodb.MongoClientSettings
|
||||
import com.mongodb.client.MongoClient
|
||||
import com.mongodb.client.MongoClients
|
||||
import java.io.File
|
||||
import java.io.FileReader
|
||||
import java.io.FileWriter
|
||||
@@ -130,6 +129,7 @@ object Cobblemon {
|
||||
const val MODID = CobblemonBuildDetails.MOD_ID
|
||||
const val VERSION = CobblemonBuildDetails.VERSION
|
||||
const val CONFIG_PATH = "config/$MODID/main.json"
|
||||
@JvmField
|
||||
val LOGGER: Logger = LogManager.getLogger()
|
||||
|
||||
lateinit var implementation: CobblemonImplementation
|
||||
@@ -151,7 +151,7 @@ object Cobblemon {
|
||||
val battleRegistry = BattleRegistry
|
||||
var storage = PokemonStoreManager()
|
||||
var molangData = NbtMoLangDataStoreFactory
|
||||
lateinit var playerData: PlayerDataStoreManager
|
||||
lateinit var playerDataManager: PlayerInstancedDataStoreManager
|
||||
lateinit var starterConfig: StarterConfig
|
||||
val dataProvider: DataProvider = CobblemonDataProvider
|
||||
var permissionValidator: PermissionValidator by Delegates.observable(LaxPermissionValidator().also { it.initialize() }) { _, _, newValue -> newValue.initialize() }
|
||||
@@ -162,7 +162,7 @@ object Cobblemon {
|
||||
this.implementation = implementation
|
||||
|
||||
this.LOGGER.info("Launching Cobblemon ${CobblemonBuildDetails.VERSION}${if(CobblemonBuildDetails.SNAPSHOT) "-SNAPSHOT" else ""} ")
|
||||
if(CobblemonBuildDetails.SNAPSHOT) {
|
||||
if (CobblemonBuildDetails.SNAPSHOT) {
|
||||
this.LOGGER.info(" - Git Commit: ${smallCommitHash()} (https://gitlab.com/cable-mc/cobblemon/-/commit/${CobblemonBuildDetails.GIT_COMMIT})")
|
||||
this.LOGGER.info(" - Branch: ${CobblemonBuildDetails.BRANCH}")
|
||||
}
|
||||
@@ -175,6 +175,7 @@ object Cobblemon {
|
||||
implementation.registerEntityTypes()
|
||||
implementation.registerEntityAttributes()
|
||||
implementation.registerBlockEntityTypes()
|
||||
implementation.registerVillagers()
|
||||
implementation.registerWorldGenFeatures()
|
||||
implementation.registerParticles()
|
||||
implementation.registerEntityDataSerializers()
|
||||
@@ -199,15 +200,15 @@ object Cobblemon {
|
||||
|
||||
DATA_SYNCHRONIZED.subscribe {
|
||||
storage.onPlayerDataSync(it)
|
||||
playerData.get(it).sendToPlayer(it)
|
||||
playerDataManager.syncAllToPlayer(it)
|
||||
starterHandler.handleJoin(it)
|
||||
ServerSettingsPacket(this.config.preventCompletePartyDeposit, this.config.displayEntityLevelLabel).sendToPlayer(it)
|
||||
ServerSettingsPacket(this.config.preventCompletePartyDeposit, this.config.displayEntityLevelLabel, this.config.displayEntityNameLabel).sendToPlayer(it)
|
||||
}
|
||||
PlatformEvents.SERVER_PLAYER_LOGOUT.subscribe {
|
||||
PCLinkManager.removeLink(it.player.uuid)
|
||||
BattleRegistry.getBattleByParticipatingPlayer(it.player)?.stop()
|
||||
BattleRegistry.onPlayerDisconnect(it.player)
|
||||
storage.onPlayerDisconnect(it.player)
|
||||
playerData.onPlayerDisconnect(it.player)
|
||||
playerDataManager.onPlayerDisconnect(it.player)
|
||||
TradeManager.onLogoff(it.player)
|
||||
}
|
||||
PlatformEvents.PLAYER_DEATH.subscribe {
|
||||
@@ -232,9 +233,6 @@ object Cobblemon {
|
||||
}
|
||||
}
|
||||
|
||||
// Register the grow_tumblestone advancement
|
||||
PlatformEvents.RIGHT_CLICK_BLOCK.subscribe { AdvancementHandler.onTumbleStonePlaced(it) }
|
||||
|
||||
PlatformEvents.CHANGE_DIMENSION.subscribe {
|
||||
it.player.party().forEach { pokemon -> pokemon.entity?.recallWithAnimation() }
|
||||
}
|
||||
@@ -250,6 +248,8 @@ object Cobblemon {
|
||||
}
|
||||
|
||||
HeldItemProvider.register(CobblemonHeldItemManager, Priority.LOWEST)
|
||||
|
||||
|
||||
}
|
||||
|
||||
fun initialize() {
|
||||
@@ -277,6 +277,8 @@ object Cobblemon {
|
||||
CustomPokemonProperty.register(HiddenAbilityPropertyType)
|
||||
CustomPokemonProperty.register(AspectPropertyType)
|
||||
CustomPokemonProperty.register(UnaspectPropertyType)
|
||||
CustomPokemonProperty.register(FreezeFrameProperty)
|
||||
CustomPokemonProperty.register(NoAIProperty)
|
||||
|
||||
ifDedicatedServer {
|
||||
isDedicatedServer = true
|
||||
@@ -291,16 +293,21 @@ object Cobblemon {
|
||||
}
|
||||
PlatformEvents.SERVER_STARTING.subscribe { event ->
|
||||
val server = event.server
|
||||
playerData = PlayerDataStoreManager().also { it.setup(server) }
|
||||
playerDataManager = PlayerInstancedDataStoreManager().also { it.setup(server) }
|
||||
|
||||
val mongoClient: MongoClient?
|
||||
|
||||
val pokemonStoreRoot = server.getWorldPath(LevelResource.ROOT).resolve("pokemon").toFile()
|
||||
val storeAdapter = when (config.storageFormat) {
|
||||
"nbt", "json" -> {
|
||||
val jsonFactory = JsonPlayerDataStoreFactory()
|
||||
jsonFactory.setup(server)
|
||||
playerData.setFactory(jsonFactory)
|
||||
val generalJsonFactory = CachedPlayerDataStoreFactory(PlayerDataJsonBackend())
|
||||
generalJsonFactory.setup(server)
|
||||
|
||||
val pokedexNbtFactory = CachedPlayerDataStoreFactory(DexDataNbtBackend())
|
||||
pokedexNbtFactory.setup(server)
|
||||
|
||||
playerDataManager.setFactory(generalJsonFactory, PlayerInstancedDataStoreTypes.GENERAL)
|
||||
playerDataManager.setFactory(pokedexNbtFactory, PlayerInstancedDataStoreTypes.POKEDEX)
|
||||
|
||||
if (config.storageFormat == "nbt") {
|
||||
NBTStoreAdapter(pokemonStoreRoot.absolutePath, useNestedFolders = true, folderPerClass = true)
|
||||
@@ -313,7 +320,9 @@ object Cobblemon {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
"mongodb" -> {
|
||||
/*
|
||||
try {
|
||||
Class.forName("com.mongodb.client.MongoClient")
|
||||
|
||||
@@ -322,14 +331,18 @@ object Cobblemon {
|
||||
.build()
|
||||
mongoClient = MongoClients.create(mongoClientSettings)
|
||||
val mongoFactory = MongoPlayerDataStoreFactory(mongoClient, config.mongoDBDatabaseName)
|
||||
playerData.setFactory(mongoFactory)
|
||||
playerData.setFactory(mongoFactory, PlayerInstancedDataStoreType.GENERAL)
|
||||
MongoDBStoreAdapter(mongoClient, config.mongoDBDatabaseName)
|
||||
} catch (e: ClassNotFoundException) {
|
||||
LOGGER.error("MongoDB driver not found.")
|
||||
throw e
|
||||
}
|
||||
|
||||
*/
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
else -> throw IllegalArgumentException("Unsupported storageFormat: ${config.storageFormat}")
|
||||
}
|
||||
.with(ReforgedConversion(server.getWorldPath(LevelResource.ROOT))) as FileStoreAdapter<*>
|
||||
@@ -345,22 +358,14 @@ object Cobblemon {
|
||||
}
|
||||
|
||||
PlatformEvents.SERVER_STOPPED.subscribe {
|
||||
storage.unregisterAll()
|
||||
playerData.saveAll()
|
||||
storage.unregisterAll(it.server.registryAccess())
|
||||
playerDataManager.saveAllStores()
|
||||
}
|
||||
PlatformEvents.SERVER_STARTED.subscribe {
|
||||
bestSpawner.onServerStarted()
|
||||
battleRegistry.onServerStarted()
|
||||
}
|
||||
PlatformEvents.SERVER_TICK_POST.subscribe { ServerTickHandler.onTick(it.server) }
|
||||
POKEMON_CAPTURED.subscribe { AdvancementHandler.onCapture(it) }
|
||||
// EGG_HATCH.subscribe { AdvancementHandler.onHatch(it) }
|
||||
BATTLE_VICTORY.subscribe { AdvancementHandler.onWinBattle(it) }
|
||||
EVOLUTION_COMPLETE.subscribe(Priority.LOWEST) { event ->
|
||||
AdvancementHandler.onEvolve(event)
|
||||
}
|
||||
LEVEL_UP_EVENT.subscribe { AdvancementHandler.onLevelUp(it) }
|
||||
TRADE_COMPLETED.subscribe { AdvancementHandler.onTradeCompleted(it) }
|
||||
|
||||
BagItems.observable.subscribe {
|
||||
LOGGER.info("Starting dummy Showdown battle to force it to pre-load data.")
|
||||
@@ -372,8 +377,12 @@ object Cobblemon {
|
||||
).ifSuccessful { it.mute = true }
|
||||
}
|
||||
|
||||
//To whomever is merging, this is moved out of Cobblemon and into the CobblemonImplementations
|
||||
//CobblemonSherds.registerSherds()
|
||||
registerEventHandlers()
|
||||
}
|
||||
|
||||
fun registerEventHandlers() {
|
||||
AdvancementHandler.registerListeners()
|
||||
PokedexHandler.registerListeners()
|
||||
}
|
||||
|
||||
fun getLevel(dimension: ResourceKey<Level>): Level? {
|
||||
@@ -471,13 +480,16 @@ object Cobblemon {
|
||||
}
|
||||
|
||||
private fun registerArgumentTypes() {
|
||||
this.implementation.registerCommandArgument(cobblemonResource("pokemon"), PokemonArgumentType::class, SingletonArgumentInfo.contextFree(PokemonArgumentType::pokemon))
|
||||
this.implementation.registerCommandArgument(cobblemonResource("pokemon"), SpeciesArgumentType::class, SingletonArgumentInfo.contextFree(SpeciesArgumentType::species))
|
||||
this.implementation.registerCommandArgument(cobblemonResource("pokemon_properties"), PokemonPropertiesArgumentType::class, SingletonArgumentInfo.contextFree(PokemonPropertiesArgumentType::properties))
|
||||
this.implementation.registerCommandArgument(cobblemonResource("spawn_bucket"), SpawnBucketArgumentType::class, SingletonArgumentInfo.contextFree(SpawnBucketArgumentType::spawnBucket))
|
||||
this.implementation.registerCommandArgument(cobblemonResource("move"), MoveArgumentType::class, SingletonArgumentInfo.contextFree(MoveArgumentType::move))
|
||||
this.implementation.registerCommandArgument(cobblemonResource("party_slot"), PartySlotArgumentType::class, SingletonArgumentInfo.contextFree(PartySlotArgumentType::partySlot))
|
||||
this.implementation.registerCommandArgument(cobblemonResource("pokemon_store"), PokemonStoreArgumentType::class, SingletonArgumentInfo.contextFree(PokemonStoreArgumentType::pokemonStore))
|
||||
this.implementation.registerCommandArgument(cobblemonResource("dialogue"), DialogueArgumentType::class, SingletonArgumentInfo.contextFree(DialogueArgumentType::dialogue))
|
||||
this.implementation.registerCommandArgument(cobblemonResource("form"), FormArgumentType::class, SingletonArgumentInfo.contextFree(FormArgumentType::form))
|
||||
this.implementation.registerCommandArgument(cobblemonResource("dex"), DexArgumentType::class, SingletonArgumentInfo.contextFree (DexArgumentType::dex))
|
||||
this.implementation.registerCommandArgument(cobblemonResource("npc_class"), NPCClassArgumentType::class, SingletonArgumentInfo.contextFree(NPCClassArgumentType::npcClass))
|
||||
}
|
||||
|
||||
}
|
||||
@@ -14,6 +14,8 @@ object CobblemonActivities {
|
||||
val activities = mutableListOf<Activity>()
|
||||
val BATTLING_ACTIVITY = Activity("pokemon_battling")
|
||||
val NPC_BATTLING = Activity("npc_battling")
|
||||
val NPC_ACTION_EFFECT = Activity("npc_action_effect")
|
||||
val NPC_CHATTING = Activity("npc_chatting")
|
||||
|
||||
fun register(activity: Activity): Activity {
|
||||
activities.add(activity)
|
||||
|
||||
@@ -36,6 +36,9 @@ object CobblemonBlockEntities : PlatformRegistry<Registry<BlockEntityType<*>>, R
|
||||
@JvmField
|
||||
val PC: BlockEntityType<PCBlockEntity> = this.create("pc", BlockEntityType.Builder.of(::PCBlockEntity, CobblemonBlocks.PC).build(null))
|
||||
|
||||
@JvmField
|
||||
val LECTERN: BlockEntityType<LecternBlockEntity> = this.create("lectern", BlockEntityType.Builder.of(::LecternBlockEntity, CobblemonBlocks.LECTERN).build(null))
|
||||
|
||||
@JvmField
|
||||
val BERRY = this.create("berry", BlockEntityType.Builder.of(::BerryBlockEntity, *CobblemonBlocks.berries().values.toTypedArray()).build(null))
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ package com.cobblemon.mod.common
|
||||
|
||||
import com.cobblemon.mod.common.api.apricorn.Apricorn
|
||||
import com.cobblemon.mod.common.block.*
|
||||
import com.cobblemon.mod.common.block.LecternBlock
|
||||
import com.cobblemon.mod.common.block.MintBlock.MintType
|
||||
import com.cobblemon.mod.common.block.chest.GildedChestBlock
|
||||
import com.cobblemon.mod.common.block.sign.CobblemonHangingSignBlock
|
||||
@@ -263,6 +264,27 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
)
|
||||
)
|
||||
@JvmField
|
||||
val SMOOTH_TUMBLESTONE = this.create("smooth_tumblestone",
|
||||
Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.TERRACOTTA_ORANGE)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BASEDRUM)
|
||||
)
|
||||
)
|
||||
@JvmField
|
||||
val SMOOTH_TUMBLESTONE_STAIRS = this.create("smooth_tumblestone_stairs", StairsBlockInvoker.`cobblemon$create`(SMOOTH_TUMBLESTONE.defaultBlockState(), BlockBehaviour.Properties.ofFullCopy(SMOOTH_TUMBLESTONE)))
|
||||
@JvmField
|
||||
val SMOOTH_TUMBLESTONE_SLAB = this.create("smooth_tumblestone_slab", SlabBlock(BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.TERRACOTTA_ORANGE)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BASEDRUM)
|
||||
))
|
||||
@JvmField
|
||||
val TUMBLESTONE_BRICKS = this.create("tumblestone_bricks", Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.TERRACOTTA_ORANGE)
|
||||
@@ -270,8 +292,7 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
.sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BASEDRUM)
|
||||
)
|
||||
)
|
||||
))
|
||||
@JvmField
|
||||
val TUMBLESTONE_BRICK_STAIRS = this.create("tumblestone_brick_stairs", StairsBlockInvoker.`cobblemon$create`(TUMBLESTONE_BRICKS.defaultBlockState(), BlockBehaviour.Properties.ofFullCopy(TUMBLESTONE_BRICKS)))
|
||||
@JvmField
|
||||
@@ -342,6 +363,27 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
)
|
||||
)
|
||||
@JvmField
|
||||
val SMOOTH_SKY_TUMBLESTONE = this.create("smooth_sky_tumblestone",
|
||||
Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.COLOR_LIGHT_BLUE)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BASEDRUM)
|
||||
)
|
||||
)
|
||||
@JvmField
|
||||
val SMOOTH_SKY_TUMBLESTONE_STAIRS = this.create("smooth_sky_tumblestone_stairs", StairsBlockInvoker.`cobblemon$create`(SMOOTH_SKY_TUMBLESTONE.defaultBlockState(), BlockBehaviour.Properties.ofFullCopy(SMOOTH_SKY_TUMBLESTONE)))
|
||||
@JvmField
|
||||
val SMOOTH_SKY_TUMBLESTONE_SLAB = this.create("smooth_sky_tumblestone_slab", SlabBlock(BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.COLOR_LIGHT_BLUE)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BASEDRUM)
|
||||
))
|
||||
@JvmField
|
||||
val SKY_TUMBLESTONE_BRICKS = this.create("sky_tumblestone_bricks",
|
||||
Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
@@ -422,6 +464,28 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
.instrument(NoteBlockInstrument.BASEDRUM)
|
||||
)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val SMOOTH_BLACK_TUMBLESTONE = this.create("smooth_black_tumblestone",
|
||||
Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.TERRACOTTA_BLACK)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BASEDRUM)
|
||||
)
|
||||
)
|
||||
@JvmField
|
||||
val SMOOTH_BLACK_TUMBLESTONE_STAIRS = this.create("smooth_black_tumblestone_stairs", StairsBlockInvoker.`cobblemon$create`(SMOOTH_BLACK_TUMBLESTONE.defaultBlockState(), BlockBehaviour.Properties.ofFullCopy(SMOOTH_BLACK_TUMBLESTONE)))
|
||||
@JvmField
|
||||
val SMOOTH_BLACK_TUMBLESTONE_SLAB = this.create("smooth_black_tumblestone_slab", SlabBlock(BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.TERRACOTTA_BLACK)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.TUMBLESTONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BASEDRUM)
|
||||
))
|
||||
@JvmField
|
||||
val BLACK_TUMBLESTONE_BRICKS = this.create("black_tumblestone_bricks",
|
||||
Block(
|
||||
@@ -464,6 +528,117 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val FIRE_STONE_BLOCK = this.create("fire_stone_block",
|
||||
Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.FIRE)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.EVOLUTION_STONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BIT)
|
||||
)
|
||||
)
|
||||
@JvmField
|
||||
val WATER_STONE_BLOCK = this.create("water_stone_block",
|
||||
Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.WATER)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.EVOLUTION_STONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BIT)
|
||||
)
|
||||
)
|
||||
@JvmField
|
||||
val THUNDER_STONE_BLOCK = this.create("thunder_stone_block",
|
||||
Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.GLOW_LICHEN)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.EVOLUTION_STONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BIT)
|
||||
)
|
||||
)
|
||||
@JvmField
|
||||
val LEAF_STONE_BLOCK = this.create("leaf_stone_block",
|
||||
Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.COLOR_GREEN)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.EVOLUTION_STONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BIT)
|
||||
)
|
||||
)
|
||||
@JvmField
|
||||
val ICE_STONE_BLOCK = this.create("ice_stone_block",
|
||||
Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.ICE)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.EVOLUTION_STONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BIT)
|
||||
)
|
||||
)
|
||||
@JvmField
|
||||
val SUN_STONE_BLOCK = this.create("sun_stone_block",
|
||||
Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.TERRACOTTA_ORANGE)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.EVOLUTION_STONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BIT)
|
||||
)
|
||||
)
|
||||
@JvmField
|
||||
val MOON_STONE_BLOCK = this.create("moon_stone_block",
|
||||
Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.DEEPSLATE)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.EVOLUTION_STONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BIT)
|
||||
)
|
||||
)
|
||||
@JvmField
|
||||
val SHINY_STONE_BLOCK = this.create("shiny_stone_block",
|
||||
Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.QUARTZ)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.EVOLUTION_STONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BIT)
|
||||
)
|
||||
)
|
||||
@JvmField
|
||||
val DAWN_STONE_BLOCK = this.create("dawn_stone_block",
|
||||
Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.DIAMOND)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.EVOLUTION_STONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BIT)
|
||||
)
|
||||
)
|
||||
@JvmField
|
||||
val DUSK_STONE_BLOCK = this.create("dusk_stone_block",
|
||||
Block(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.WARPED_HYPHAE)
|
||||
.strength(1.0F)
|
||||
.sound(CobblemonSounds.EVOLUTION_STONE_BLOCK_SOUNDS)
|
||||
.requiresCorrectToolForDrops()
|
||||
.instrument(NoteBlockInstrument.BIT)
|
||||
)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val BLACK_APRICORN = apricornBlock("black_apricorn", Apricorn.BLACK)
|
||||
@JvmField
|
||||
@@ -486,7 +661,6 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
BlockBehaviour.Properties.of()
|
||||
.sound(CobblemonSounds.RELIC_COIN_POUCH_SOUNDS)
|
||||
.pushReaction(PushReaction.DESTROY)
|
||||
.strength(0.4f)
|
||||
.noOcclusion(), true
|
||||
)
|
||||
)
|
||||
@@ -638,6 +812,19 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val LECTERN = create(
|
||||
"lectern",
|
||||
LecternBlock(
|
||||
BlockBehaviour.Properties.of()
|
||||
.mapColor(MapColor.WOOD)
|
||||
.instrument(NoteBlockInstrument.BASS)
|
||||
.sound(SoundType.WOOD)
|
||||
.strength(2.5F)
|
||||
.ignitedByLava()
|
||||
)
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val DISPLAY_CASE = create(
|
||||
"display_case",
|
||||
@@ -647,7 +834,7 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
.noOcclusion()
|
||||
.pushReaction(PushReaction.BLOCK)
|
||||
.mapColor(MapColor.STONE)
|
||||
.strength(0.3f)
|
||||
.strength(0.3F)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ import net.minecraft.commands.Commands
|
||||
object CobblemonCommands {
|
||||
fun register(dispatcher: CommandDispatcher<CommandSourceStack>, registry: CommandBuildContext, selection: Commands.CommandSelection) {
|
||||
SpawnPokemon.register(dispatcher)
|
||||
SpawnNPCCommand.register(dispatcher)
|
||||
GivePokemon.register(dispatcher)
|
||||
TakePokemon.register(dispatcher)
|
||||
ChangeScaleAndSize.register(dispatcher)
|
||||
@@ -39,6 +40,7 @@ object CobblemonCommands {
|
||||
PcCommand.register(dispatcher)
|
||||
SpawnPokemonFromPool.register(dispatcher)
|
||||
PokeboxCommand.register(dispatcher)
|
||||
PokedexCommand.register(dispatcher)
|
||||
TestStoreCommand.register(dispatcher)
|
||||
QueryLearnsetCommand.register(dispatcher)
|
||||
TestPcSlotCommand.register(dispatcher)
|
||||
@@ -49,6 +51,9 @@ object CobblemonCommands {
|
||||
BedrockParticleCommand.register(dispatcher)
|
||||
OpenDialogueCommand.register(dispatcher)
|
||||
NPCEditCommand.register(dispatcher)
|
||||
AbandonMultiTeam.register(dispatcher)
|
||||
FreezePokemonCommand.register(dispatcher)
|
||||
ApplyPlayerTextureCommand.register(dispatcher)
|
||||
|
||||
// Possibly lock down registration if and only if under dev environment or running in an environment
|
||||
// with a certain system environment variable set
|
||||
|
||||
@@ -97,6 +97,12 @@ interface CobblemonImplementation {
|
||||
*/
|
||||
fun registerBlockEntityTypes()
|
||||
|
||||
/**
|
||||
* TODO
|
||||
*
|
||||
*/
|
||||
fun registerVillagers()
|
||||
|
||||
/**
|
||||
* TODO
|
||||
*
|
||||
|
||||
@@ -19,6 +19,7 @@ import com.cobblemon.mod.common.api.text.gray
|
||||
import com.cobblemon.mod.common.block.BerryBlock
|
||||
import com.cobblemon.mod.common.block.MintBlock
|
||||
import com.cobblemon.mod.common.block.MintBlock.MintType
|
||||
import com.cobblemon.mod.common.client.pokedex.PokedexTypes
|
||||
import com.cobblemon.mod.common.entity.boat.CobblemonBoatType
|
||||
import com.cobblemon.mod.common.item.*
|
||||
import com.cobblemon.mod.common.item.armor.CobblemonArmorTrims
|
||||
@@ -152,6 +153,21 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val ANCIENT_ORIGIN_BALL = pokeBallItem(PokeBalls.ANCIENT_ORIGIN_BALL)
|
||||
|
||||
@JvmField
|
||||
val POKEDEX_BLACK = create("pokedex_black", PokedexItem(PokedexTypes.BLACK))
|
||||
@JvmField
|
||||
val POKEDEX_BLUE = create("pokedex_blue", PokedexItem(PokedexTypes.BLUE))
|
||||
@JvmField
|
||||
val POKEDEX_GREEN = create("pokedex_green", PokedexItem(PokedexTypes.GREEN))
|
||||
@JvmField
|
||||
val POKEDEX_PINK = create("pokedex_pink", PokedexItem(PokedexTypes.PINK))
|
||||
@JvmField
|
||||
val POKEDEX_RED = create("pokedex_red", PokedexItem(PokedexTypes.RED))
|
||||
@JvmField
|
||||
val POKEDEX_WHITE = create("pokedex_white", PokedexItem(PokedexTypes.WHITE))
|
||||
@JvmField
|
||||
val POKEDEX_YELLOW = create("pokedex_yellow", PokedexItem(PokedexTypes.YELLOW))
|
||||
|
||||
@JvmField
|
||||
val VIVICHOKE = compostableItem("vivichoke")
|
||||
|
||||
@@ -256,6 +272,8 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
val PASTURE = blockItem("pasture", CobblemonBlocks.PASTURE)
|
||||
@JvmField
|
||||
val DISPLAY_CASE = blockItem("display_case", CobblemonBlocks.DISPLAY_CASE)
|
||||
@JvmField
|
||||
val LECTERN = blockItem("lectern", CobblemonBlocks.LECTERN)
|
||||
|
||||
// Evolution items
|
||||
@JvmField val LINK_CABLE = create("link_cable", LinkCableItem())
|
||||
@@ -962,6 +980,12 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val CHISELED_POLISHED_TUMBLESTONE = blockItem("chiseled_polished_tumblestone", CobblemonBlocks.CHISELED_POLISHED_TUMBLESTONE)
|
||||
@JvmField
|
||||
val SMOOTH_TUMBLESTONE = blockItem("smooth_tumblestone", CobblemonBlocks.SMOOTH_TUMBLESTONE)
|
||||
@JvmField
|
||||
val SMOOTH_TUMBLESTONE_STAIRS = blockItem("smooth_tumblestone_stairs", CobblemonBlocks.SMOOTH_TUMBLESTONE_STAIRS)
|
||||
@JvmField
|
||||
val SMOOTH_TUMBLESTONE_SLAB = blockItem("smooth_tumblestone_slab", CobblemonBlocks.SMOOTH_TUMBLESTONE_SLAB)
|
||||
@JvmField
|
||||
val TUMBLESTONE_BRICKS = blockItem("tumblestone_bricks", CobblemonBlocks.TUMBLESTONE_BRICKS)
|
||||
@JvmField
|
||||
val TUMBLESTONE_BRICK_STAIRS = blockItem("tumblestone_brick_stairs", CobblemonBlocks.TUMBLESTONE_BRICK_STAIRS)
|
||||
@@ -982,6 +1006,12 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val CHISELED_POLISHED_SKY_TUMBLESTONE = blockItem("chiseled_polished_sky_tumblestone", CobblemonBlocks.CHISELED_POLISHED_SKY_TUMBLESTONE)
|
||||
@JvmField
|
||||
val SMOOTH_SKY_TUMBLESTONE = blockItem("smooth_sky_tumblestone", CobblemonBlocks.SMOOTH_SKY_TUMBLESTONE)
|
||||
@JvmField
|
||||
val SMOOTH_SKY_TUMBLESTONE_STAIRS = blockItem("smooth_sky_tumblestone_stairs", CobblemonBlocks.SMOOTH_SKY_TUMBLESTONE_STAIRS)
|
||||
@JvmField
|
||||
val SMOOTH_SKY_TUMBLESTONE_SLAB = blockItem("smooth_sky_tumblestone_slab", CobblemonBlocks.SMOOTH_SKY_TUMBLESTONE_SLAB)
|
||||
@JvmField
|
||||
val SKY_TUMBLESTONE_BRICKS = blockItem("sky_tumblestone_bricks", CobblemonBlocks.SKY_TUMBLESTONE_BRICKS)
|
||||
@JvmField
|
||||
val SKY_TUMBLESTONE_BRICK_STAIRS = blockItem("sky_tumblestone_brick_stairs", CobblemonBlocks.SKY_TUMBLESTONE_BRICK_STAIRS)
|
||||
@@ -1002,6 +1032,12 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val CHISELED_POLISHED_BLACK_TUMBLESTONE = blockItem("chiseled_polished_black_tumblestone", CobblemonBlocks.CHISELED_POLISHED_BLACK_TUMBLESTONE)
|
||||
@JvmField
|
||||
val SMOOTH_BLACK_TUMBLESTONE = blockItem("smooth_black_tumblestone", CobblemonBlocks.SMOOTH_BLACK_TUMBLESTONE)
|
||||
@JvmField
|
||||
val SMOOTH_BLACK_TUMBLESTONE_STAIRS = blockItem("smooth_black_tumblestone_stairs", CobblemonBlocks.SMOOTH_BLACK_TUMBLESTONE_STAIRS)
|
||||
@JvmField
|
||||
val SMOOTH_BLACK_TUMBLESTONE_SLAB = blockItem("smooth_black_tumblestone_slab", CobblemonBlocks.SMOOTH_BLACK_TUMBLESTONE_SLAB)
|
||||
@JvmField
|
||||
val BLACK_TUMBLESTONE_BRICKS = blockItem("black_tumblestone_bricks", CobblemonBlocks.BLACK_TUMBLESTONE_BRICKS)
|
||||
@JvmField
|
||||
val BLACK_TUMBLESTONE_BRICK_STAIRS = blockItem("black_tumblestone_brick_stairs", CobblemonBlocks.BLACK_TUMBLESTONE_BRICK_STAIRS)
|
||||
@@ -1012,6 +1048,27 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val CHISELED_BLACK_TUMBLESTONE_BRICKS = blockItem("chiseled_black_tumblestone_bricks", CobblemonBlocks.CHISELED_BLACK_TUMBLESTONE_BRICKS)
|
||||
|
||||
@JvmField
|
||||
val FIRE_STONE_BLOCK = blockItem("fire_stone_block", CobblemonBlocks.FIRE_STONE_BLOCK)
|
||||
@JvmField
|
||||
val WATER_STONE_BLOCK = blockItem("water_stone_block", CobblemonBlocks.WATER_STONE_BLOCK)
|
||||
@JvmField
|
||||
val THUNDER_STONE_BLOCK = blockItem("thunder_stone_block", CobblemonBlocks.THUNDER_STONE_BLOCK)
|
||||
@JvmField
|
||||
val LEAF_STONE_BLOCK = blockItem("leaf_stone_block", CobblemonBlocks.LEAF_STONE_BLOCK)
|
||||
@JvmField
|
||||
val ICE_STONE_BLOCK = blockItem("ice_stone_block", CobblemonBlocks.ICE_STONE_BLOCK)
|
||||
@JvmField
|
||||
val SUN_STONE_BLOCK = blockItem("sun_stone_block", CobblemonBlocks.SUN_STONE_BLOCK)
|
||||
@JvmField
|
||||
val MOON_STONE_BLOCK = blockItem("moon_stone_block", CobblemonBlocks.MOON_STONE_BLOCK)
|
||||
@JvmField
|
||||
val SHINY_STONE_BLOCK = blockItem("shiny_stone_block", CobblemonBlocks.SHINY_STONE_BLOCK)
|
||||
@JvmField
|
||||
val DAWN_STONE_BLOCK = blockItem("dawn_stone_block", CobblemonBlocks.DAWN_STONE_BLOCK)
|
||||
@JvmField
|
||||
val DUSK_STONE_BLOCK = blockItem("dusk_stone_block", CobblemonBlocks.DUSK_STONE_BLOCK)
|
||||
|
||||
@JvmField
|
||||
val AUTOMATON_ARMOR_TRIM_SMITHING_TEMPLATE: SmithingTemplateItem = this.create(
|
||||
"automaton_armor_trim_smithing_template",
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
|
||||
package com.cobblemon.mod.common
|
||||
|
||||
import com.cobblemon.mod.common.api.dialogue.ActiveDialogue
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffectContext
|
||||
import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.codecs.ListCodec
|
||||
import com.mojang.serialization.codecs.PrimitiveCodec
|
||||
@@ -20,6 +22,8 @@ object CobblemonMemories {
|
||||
|
||||
val BATTLING_POKEMON = register("battling_pokemon", ListCodec(UUIDUtil.CODEC, 0, 31))
|
||||
val NPC_BATTLING = register("npc_battling", PrimitiveCodec.BOOL)
|
||||
val DIALOGUES = register<List<ActiveDialogue>>("npc_dialogues")
|
||||
val ACTIVE_ACTION_EFFECT = register<ActionEffectContext>("active_action_effect")
|
||||
|
||||
fun <U> register(id: String, codec: Codec<U>): MemoryModuleType<U> {
|
||||
val memoryModule = MemoryModuleType(Optional.of(codec))
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.cobblemon.mod.common.client.net.effect.RunPosableMoLangHandler
|
||||
import com.cobblemon.mod.common.client.net.effect.SpawnSnowstormEntityParticleHandler
|
||||
import com.cobblemon.mod.common.client.net.effect.SpawnSnowstormParticleHandler
|
||||
import com.cobblemon.mod.common.client.net.gui.InteractPokemonUIPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.gui.PokedexUIPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.gui.SummaryUIPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.npc.CloseNPCEditorHandler
|
||||
import com.cobblemon.mod.common.client.net.npc.OpenNPCEditorHandler
|
||||
@@ -31,6 +32,7 @@ import com.cobblemon.mod.common.client.net.pasture.ClosePastureHandler
|
||||
import com.cobblemon.mod.common.client.net.pasture.OpenPastureHandler
|
||||
import com.cobblemon.mod.common.client.net.pasture.PokemonPasturedHandler
|
||||
import com.cobblemon.mod.common.client.net.pasture.PokemonUnpasturedHandler
|
||||
import com.cobblemon.mod.common.client.net.pokedex.ServerConfirmedRegisterHandler
|
||||
import com.cobblemon.mod.common.client.net.pokemon.update.PokemonUpdatePacketHandler
|
||||
import com.cobblemon.mod.common.client.net.settings.ServerSettingsPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.sound.UnvalidatedPlaySoundS2CPacketHandler
|
||||
@@ -85,22 +87,18 @@ import com.cobblemon.mod.common.net.messages.client.pokemon.update.evolution.Rem
|
||||
import com.cobblemon.mod.common.net.messages.client.settings.ServerSettingsPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.sound.UnvalidatedPlaySoundS2CPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.spawn.SpawnGenericBedrockPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.spawn.SpawnNPCPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.spawn.SpawnPokeballPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.spawn.SpawnPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.starter.OpenStarterUIPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.starter.SetClientPlayerDataPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.SetClientPlayerDataPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.RemoveClientPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.SwapClientPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.party.InitializePartyPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.party.MoveClientPartyPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.party.SetPartyPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.party.SetPartyReferencePacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.ClosePCPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.InitializePCPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.MoveClientPCPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.OpenPCPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.SetPCBoxPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.SetPCPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.*
|
||||
import com.cobblemon.mod.common.net.messages.client.toast.ToastPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeAcceptanceChangedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeCancelledPacket
|
||||
@@ -110,13 +108,9 @@ import com.cobblemon.mod.common.net.messages.client.trade.TradeOfferNotification
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeStartedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeUpdatedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.ui.InteractPokemonUIPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.ui.PokedexUIPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.ui.SummaryUIPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.BattleChallengePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.BenchMovePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.RequestMoveSwapPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.RequestPlayerInteractionsPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.SelectStarterPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.SendOutPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.*
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.BattleSelectActionsPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.RemoveSpectatorPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.SpectateBattlePacket
|
||||
@@ -132,6 +126,7 @@ import com.cobblemon.mod.common.net.messages.server.npc.SaveNPCPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pasture.PasturePokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pasture.UnpastureAllPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pasture.UnpasturePokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokedex.scanner.StartScanningPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokemon.interact.InteractPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokemon.update.SetNicknamePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokemon.update.evolution.AcceptEvolutionPacket
|
||||
@@ -151,8 +146,7 @@ import com.cobblemon.mod.common.net.messages.server.trade.CancelTradePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.ChangeTradeAcceptancePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.OfferTradePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.UpdateTradeOfferPacket
|
||||
import com.cobblemon.mod.common.net.serverhandling.ChallengeHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.RequestInteractionsHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.*
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.BattleSelectActionsHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.RemoveSpectatorHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.SpectateBattleHandler
|
||||
@@ -191,6 +185,10 @@ import com.cobblemon.mod.common.net.serverhandling.trade.CancelTradeHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.trade.ChangeTradeAcceptanceHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.trade.OfferTradeHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.trade.UpdateTradeOfferHandler
|
||||
import com.cobblemon.mod.common.net.messages.client.pokedex.ServerConfirmedRegisterPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokedex.scanner.FinishScanningPacket
|
||||
import com.cobblemon.mod.common.net.serverhandling.pokedex.scanner.FinishScanningHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pokedex.scanner.StartScanningHandler
|
||||
import com.cobblemon.mod.common.util.server
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
|
||||
@@ -270,6 +268,7 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(SummaryUIPacket.ID, SummaryUIPacket::decode, SummaryUIPacketHandler))
|
||||
list.add(PacketRegisterInfo(InteractPokemonUIPacket.ID, InteractPokemonUIPacket::decode, InteractPokemonUIPacketHandler))
|
||||
list.add(PacketRegisterInfo(PlayerInteractOptionsPacket.ID, PlayerInteractOptionsPacket::decode, PlayerInteractOptionsHandler))
|
||||
list.add(PacketRegisterInfo(PokedexUIPacket.ID, PokedexUIPacket::decode, PokedexUIPacketHandler))
|
||||
|
||||
// Starter packets
|
||||
list.add(PacketRegisterInfo(OpenStarterUIPacket.ID, OpenStarterUIPacket::decode, StarterUIPacketHandler))
|
||||
@@ -284,6 +283,7 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(BattleHealthChangePacket.ID, BattleHealthChangePacket::decode, BattleHealthChangeHandler))
|
||||
list.add(PacketRegisterInfo(BattleSetTeamPokemonPacket.ID, BattleSetTeamPokemonPacket::decode, BattleSetTeamPokemonHandler))
|
||||
list.add(PacketRegisterInfo(BattleSwitchPokemonPacket.ID, BattleSwitchPokemonPacket::decode, BattleSwitchPokemonHandler))
|
||||
list.add(PacketRegisterInfo(BattleSwapPokemonPacket.ID, BattleSwapPokemonPacket::decode, BattleSwapPokemonHandler))
|
||||
list.add(PacketRegisterInfo(BattleMessagePacket.ID, BattleMessagePacket::decode, BattleMessageHandler))
|
||||
list.add(PacketRegisterInfo(BattleCaptureStartPacket.ID, BattleCaptureStartPacket::decode, BattleCaptureStartHandler))
|
||||
list.add(PacketRegisterInfo(BattleCaptureEndPacket.ID, BattleCaptureEndPacket::decode, BattleCaptureEndHandler))
|
||||
@@ -298,6 +298,12 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(BattleReplacePokemonPacket.ID, BattleReplacePokemonPacket::decode, BattleReplacePokemonHandler))
|
||||
list.add(PacketRegisterInfo(BattleTransformPokemonPacket.ID, BattleTransformPokemonPacket::decode, BattleTransformPokemonHandler))
|
||||
|
||||
// MultiBattleTeam Packets
|
||||
list.add(PacketRegisterInfo(TeamRequestNotificationPacket.ID, TeamRequestNotificationPacket::decode, TeamRequestNotificationHandler))
|
||||
list.add(PacketRegisterInfo(TeamRequestExpiredPacket.ID, TeamRequestExpiredPacket::decode, TeamRequestExpiredHandler))
|
||||
list.add(PacketRegisterInfo(TeamMemberRemoveNotificationPacket.ID, TeamMemberRemoveNotificationPacket::decode, TeamMemberRemoveNotificationHandler))
|
||||
list.add(PacketRegisterInfo(TeamJoinNotificationPacket.ID, TeamJoinNotificationPacket::decode, TeamJoinNotificationHandler))
|
||||
|
||||
// Settings packets
|
||||
list.add(PacketRegisterInfo(ServerSettingsPacket.ID, ServerSettingsPacket::decode, ServerSettingsPacketHandler))
|
||||
|
||||
@@ -316,6 +322,8 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(NPCRegistrySyncPacket.ID, NPCRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(PokeRodRegistrySyncPacket.ID, PokeRodRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(ScriptRegistrySyncPacket.ID, ScriptRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(PokedexDexSyncPacket.ID, PokedexDexSyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(DexEntrySyncPacket.ID, DexEntrySyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(FishingBaitRegistrySyncPacket.ID, FishingBaitRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
|
||||
// Effects
|
||||
@@ -327,8 +335,9 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(UnvalidatedPlaySoundS2CPacket.ID, UnvalidatedPlaySoundS2CPacket::decode, UnvalidatedPlaySoundS2CPacketHandler))
|
||||
list.add(PacketRegisterInfo(SpawnPokemonPacket.ID, SpawnPokemonPacket::decode, SpawnExtraDataEntityHandler()))
|
||||
list.add(PacketRegisterInfo(SpawnPokeballPacket.ID, SpawnPokeballPacket::decode, SpawnExtraDataEntityHandler()))
|
||||
list.add(PacketRegisterInfo(ToastPacket.ID, ToastPacket::decode, ToastPacketHandler))
|
||||
list.add(PacketRegisterInfo(SpawnGenericBedrockPacket.ID, SpawnGenericBedrockPacket::decode, SpawnExtraDataEntityHandler()))
|
||||
list.add(PacketRegisterInfo(SpawnNPCPacket.ID, SpawnNPCPacket::decode, SpawnExtraDataEntityHandler()))
|
||||
list.add(PacketRegisterInfo(ToastPacket.ID, ToastPacket::decode, ToastPacketHandler))
|
||||
|
||||
// Trade packets
|
||||
list.add(PacketRegisterInfo(TradeAcceptanceChangedPacket.ID, TradeAcceptanceChangedPacket::decode, TradeAcceptanceChangedHandler))
|
||||
@@ -365,6 +374,8 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(CloseNPCEditorPacket.ID, CloseNPCEditorPacket::decode, CloseNPCEditorHandler))
|
||||
list.add(PacketRegisterInfo(OpenNPCEditorPacket.ID, OpenNPCEditorPacket::decode, OpenNPCEditorHandler))
|
||||
|
||||
//Pokedex scanning
|
||||
list.add(PacketRegisterInfo(ServerConfirmedRegisterPacket.ID, ServerConfirmedRegisterPacket::decode, ServerConfirmedRegisterHandler))
|
||||
return list
|
||||
}
|
||||
|
||||
@@ -385,6 +396,10 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(RequestMoveSwapPacket.ID, RequestMoveSwapPacket::decode, RequestMoveSwapHandler))
|
||||
list.add(PacketRegisterInfo(BenchMovePacket.ID, BenchMovePacket::decode, BenchMoveHandler))
|
||||
list.add(PacketRegisterInfo(BattleChallengePacket.ID, BattleChallengePacket::decode, ChallengeHandler))
|
||||
list.add(PacketRegisterInfo(BattleChallengeResponsePacket.ID, BattleChallengeResponsePacket::decode, ChallengeResponseHandler))
|
||||
list.add(PacketRegisterInfo(BattleTeamRequestPacket.ID, BattleTeamRequestPacket::decode, TeamRequestHandler))
|
||||
list.add(PacketRegisterInfo(BattleTeamResponsePacket.ID, BattleTeamResponsePacket::decode, TeamRequestResponseHandler))
|
||||
list.add(PacketRegisterInfo(BattleTeamLeavePacket.ID, BattleTeamLeavePacket::decode, TeamLeaveHandler))
|
||||
|
||||
list.add(PacketRegisterInfo(MovePCPokemonToPartyPacket.ID, MovePCPokemonToPartyPacket::decode, MovePCPokemonToPartyHandler))
|
||||
list.add(PacketRegisterInfo(MovePartyPokemonToPCPacket.ID, MovePartyPokemonToPCPacket::decode, MovePartyPokemonToPCHandler))
|
||||
@@ -416,6 +431,10 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(OfferTradePacket.ID, OfferTradePacket::decode, OfferTradeHandler))
|
||||
list.add(PacketRegisterInfo(UpdateTradeOfferPacket.ID, UpdateTradeOfferPacket::decode, UpdateTradeOfferHandler))
|
||||
|
||||
// Pokedex scanning
|
||||
list.add(PacketRegisterInfo(StartScanningPacket.ID, StartScanningPacket::decode, StartScanningHandler))
|
||||
list.add(PacketRegisterInfo(FinishScanningPacket.ID, FinishScanningPacket::decode, FinishScanningHandler))
|
||||
|
||||
// Pasture
|
||||
list.add(PacketRegisterInfo(PasturePokemonPacket.ID, PasturePokemonPacket::decode, PasturePokemonHandler))
|
||||
list.add(PacketRegisterInfo(UnpasturePokemonPacket.ID, UnpasturePokemonPacket::decode, UnpasturePokemonHandler))
|
||||
|
||||
@@ -39,6 +39,8 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, ResourceKey<Regi
|
||||
@JvmField
|
||||
val PC_CLICK = this.create("pc.click")
|
||||
|
||||
@JvmField
|
||||
val VILLAGER_WORK_NURSE = this.create("entity.villager.work_nurse")
|
||||
@JvmField
|
||||
val HEALING_MACHINE_ACTIVE = this.create("healing_machine.active")
|
||||
|
||||
@@ -51,24 +53,51 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, ResourceKey<Regi
|
||||
@JvmField
|
||||
val POKE_BALL_OPEN = this.create("poke_ball.open")
|
||||
@JvmField
|
||||
val POKE_BALL_SHINY_OPEN = this.create("poke_ball.shiny_open")
|
||||
@JvmField
|
||||
val POKE_BALL_HIT = this.create("poke_ball.hit")
|
||||
@JvmField
|
||||
val POKE_BALL_SEND_OUT = this.create("poke_ball.send_out")
|
||||
@JvmField
|
||||
val POKE_BALL_SHINY_SEND_OUT = this.create("poke_ball.shiny_send_out")
|
||||
@JvmField
|
||||
val POKE_BALL_RECALL = this.create("poke_ball.recall")
|
||||
@JvmField
|
||||
val POKE_BALL_THROW = this.create("poke_ball.throw")
|
||||
@JvmField
|
||||
val POKE_BALL_TRAIL = this.create("poke_ball.trail")
|
||||
|
||||
@JvmField
|
||||
val POKEDEX_OPEN = this.create("item.pokedex.open")
|
||||
@JvmField
|
||||
val POKEDEX_CLOSE = this.create("item.pokedex.close")
|
||||
@JvmField
|
||||
val POKEDEX_CLICK = this.create("item.pokedex.click")
|
||||
@JvmField
|
||||
val POKEDEX_CLICK_SHORT = this.create("item.pokedex.click_short")
|
||||
@JvmField
|
||||
val POKEDEX_SCAN_OPEN = this.create("item.pokedex.scan_open")
|
||||
@JvmField
|
||||
val POKEDEX_SCAN_CLOSE = this.create("item.pokedex.scan_close")
|
||||
@JvmField
|
||||
val POKEDEX_SCAN_LOOP = this.create("item.pokedex.scan_loop")
|
||||
@JvmField
|
||||
val POKEDEX_SCAN_DETAIL = this.create("item.pokedex.scan_detail")
|
||||
@JvmField
|
||||
val POKEDEX_SCAN_REGISTER_POKEMON = this.create("item.pokedex.scan_register_pokemon")
|
||||
@JvmField
|
||||
val POKEDEX_SCAN_REGISTER_ASPECT = this.create("item.pokedex.scan_register_aspect")
|
||||
@JvmField
|
||||
val POKEDEX_SCAN_ZOOM_INCREMENT = this.create("item.pokedex.scan_zoom_increment")
|
||||
|
||||
@JvmField
|
||||
val ITEM_USE = this.create("item.use")
|
||||
@JvmField
|
||||
val CAN_EVOLVE = this.create("pokemon.can_evolve")
|
||||
val EVOLUTION_NOTIFICATION = this.create("evolution.notification")
|
||||
@JvmField
|
||||
val EVOLVING = this.create("pokemon.evolving")
|
||||
val EVOLUTION_UI = this.create("evolution.ui")
|
||||
@JvmField
|
||||
val EVOLVE = this.create("evolution.evolve")
|
||||
val EVOLUTION = this.create("evolution.full")
|
||||
|
||||
@JvmField
|
||||
val PVN_BATTLE = this.create("battle.pvn.default")
|
||||
@@ -161,6 +190,15 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, ResourceKey<Regi
|
||||
@JvmField
|
||||
val TUMBLESTONE_STEP = this.create("tumblestone.step")
|
||||
|
||||
@JvmField
|
||||
val EVOLUTION_STONE_BLOCK_BREAK = this.create("evolution_stone_block.break")
|
||||
@JvmField
|
||||
val EVOLUTION_STONE_BLOCK_HIT = this.create("evolution_stone_block.hit")
|
||||
@JvmField
|
||||
val EVOLUTION_STONE_BLOCK_PLACE = this.create("evolution_stone_block.place")
|
||||
@JvmField
|
||||
val EVOLUTION_STONE_BLOCK_STEP = this.create("evolution_stone_block.step")
|
||||
|
||||
@JvmField
|
||||
val GIMMIGHOUL_GIVE_ITEM_SMALL = this.create("gimmighoul.give_item_small")
|
||||
@JvmField
|
||||
@@ -210,7 +248,7 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, ResourceKey<Regi
|
||||
val GILDED_CHEST_PLACE = this.create("gilded_chest.place")
|
||||
|
||||
@JvmField
|
||||
val RELIC_COIN_SACK_SOUNDS = SoundType(1f, 1f,
|
||||
val RELIC_COIN_SACK_SOUNDS = SoundType(1f, 1.1f,
|
||||
RELIC_COIN_SACK_BREAK,
|
||||
RELIC_COIN_SACK_STEP,
|
||||
RELIC_COIN_SACK_PLACE,
|
||||
@@ -218,7 +256,7 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, ResourceKey<Regi
|
||||
RELIC_COIN_SACK_STEP
|
||||
)
|
||||
@JvmField
|
||||
val RELIC_COIN_POUCH_SOUNDS = SoundType(1f, 1f,
|
||||
val RELIC_COIN_POUCH_SOUNDS = SoundType(1f, 1.1f,
|
||||
RELIC_COIN_POUCH_BREAK,
|
||||
RELIC_COIN_SACK_STEP,
|
||||
RELIC_COIN_POUCH_PLACE,
|
||||
@@ -264,7 +302,7 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, ResourceKey<Regi
|
||||
val IMPACT_WATER = this.create("impact.water")
|
||||
|
||||
@JvmField
|
||||
val TUMBLESTONE_SOUNDS = SoundType(1f, 1f,
|
||||
val TUMBLESTONE_SOUNDS = SoundType(1f, 1.1f,
|
||||
TUMBLESTONE_BREAK,
|
||||
TUMBLESTONE_STEP,
|
||||
TUMBLESTONE_PLACE,
|
||||
@@ -273,16 +311,25 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, ResourceKey<Regi
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val TUMBLESTONE_BLOCK_SOUNDS = SoundType(1f, 1f,
|
||||
val TUMBLESTONE_BLOCK_SOUNDS = SoundType(1f, 1.1f,
|
||||
TUMBLESTONE_BLOCK_BREAK,
|
||||
TUMBLESTONE_STEP,
|
||||
TUMBLESTONE_PLACE,
|
||||
TUMBLESTONE_HIT,
|
||||
TUMBLESTONE_STEP
|
||||
)
|
||||
@JvmField
|
||||
val EVOLUTION_STONE_BLOCK_SOUNDS = SoundType(1f, 1.1f,
|
||||
EVOLUTION_STONE_BLOCK_BREAK,
|
||||
EVOLUTION_STONE_BLOCK_STEP,
|
||||
EVOLUTION_STONE_BLOCK_PLACE,
|
||||
EVOLUTION_STONE_BLOCK_HIT,
|
||||
EVOLUTION_STONE_BLOCK_STEP
|
||||
)
|
||||
|
||||
|
||||
@JvmField
|
||||
val BERRY_BUSH_SOUNDS = SoundType(1f, 1f,
|
||||
val BERRY_BUSH_SOUNDS = SoundType(0.8f, 1.1f,
|
||||
BERRY_BUSH_BREAK,
|
||||
SoundEvents.GRASS_STEP,
|
||||
BERRY_BUSH_PLACE,
|
||||
@@ -291,25 +338,25 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, ResourceKey<Regi
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val BIG_ROOT_SOUNDS = SoundType(1f, 1f,
|
||||
val BIG_ROOT_SOUNDS = SoundType(0.8f, 1.1f,
|
||||
BIG_ROOT_BREAK,
|
||||
SoundEvents.ROOTS_STEP,
|
||||
SoundEvents.ROOTS_PLACE,
|
||||
SoundEvents.ROOTS_HIT,
|
||||
SoundEvents.ROOTS_FALL
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val ENERGY_ROOT_SOUNDS = SoundType(1f, 1f,
|
||||
SoundEvents.ROOTS_BREAK,
|
||||
SoundEvents.ROOTS_STEP,
|
||||
ENERGY_ROOT_PLACE,
|
||||
SoundEvents.ROOTS_HIT,
|
||||
SoundEvents.ROOTS_FALL
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val MEDICINAL_LEEK_SOUNDS = SoundType(1f, 1f,
|
||||
val ENERGY_ROOT_SOUNDS = SoundType(0.8f, 1.1f,
|
||||
BIG_ROOT_BREAK,
|
||||
SoundEvents.ROOTS_STEP,
|
||||
ENERGY_ROOT_PLACE,
|
||||
SoundEvents.ROOTS_HIT,
|
||||
SoundEvents.ROOTS_FALL
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val MEDICINAL_LEEK_SOUNDS = SoundType(1f, 1.1f,
|
||||
MEDICINAL_LEEK_BREAK,
|
||||
SoundEvents.GRASS_STEP,
|
||||
MEDICINAL_LEEK_PLACE,
|
||||
@@ -318,7 +365,7 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, ResourceKey<Regi
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val VIVICHOKE_SOUNDS = SoundType(1f, 1f,
|
||||
val VIVICHOKE_SOUNDS = SoundType(0.6f, 1.1f,
|
||||
VIVICHOKE_BREAK,
|
||||
SoundEvents.GRASS_STEP,
|
||||
VIVICHOKE_PLACE,
|
||||
@@ -327,7 +374,7 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, ResourceKey<Regi
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val MINT_SOUNDS = SoundType(1f, 1f,
|
||||
val MINT_SOUNDS = SoundType(0.6f, 1.1f,
|
||||
MINT_BREAK,
|
||||
SoundEvents.GRASS_STEP,
|
||||
MINT_PLACE,
|
||||
@@ -336,7 +383,7 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, ResourceKey<Regi
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val REVIVAL_HERB_SOUNDS = SoundType(1f, 1f,
|
||||
val REVIVAL_HERB_SOUNDS = SoundType(0.6f, 1.1f,
|
||||
REVIVAL_HERB_BREAK,
|
||||
SoundEvents.GRASS_STEP,
|
||||
REVIVAL_HERB_PLACE,
|
||||
@@ -345,7 +392,7 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, ResourceKey<Regi
|
||||
)
|
||||
|
||||
@JvmField
|
||||
val GILDED_CHEST_SOUNDS = SoundType(1f, 1f,
|
||||
val GILDED_CHEST_SOUNDS = SoundType(1f, 1.1f,
|
||||
GILDED_CHEST_BREAK,
|
||||
GILDED_CHEST_STEP,
|
||||
GILDED_CHEST_PLACE,
|
||||
|
||||
@@ -9,9 +9,16 @@
|
||||
package com.cobblemon.mod.common
|
||||
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
import net.minecraft.util.RandomSource
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.entity.npc.VillagerData
|
||||
import net.minecraft.world.entity.npc.VillagerProfession
|
||||
import net.minecraft.world.entity.npc.VillagerTrades
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.Items
|
||||
import net.minecraft.world.item.trading.ItemCost
|
||||
import net.minecraft.world.item.trading.MerchantOffer
|
||||
import java.util.Optional
|
||||
|
||||
/**
|
||||
* A generator for various trade offers in the mod.
|
||||
@@ -32,8 +39,41 @@ object CobblemonTradeOffers {
|
||||
* @return The resulting list.
|
||||
*/
|
||||
fun tradeOffersFor(profession: VillagerProfession): List<VillagerTradeOffer> = when (profession) {
|
||||
VillagerProfession.FARMER -> listOf(
|
||||
VillagerTradeOffer(VillagerProfession.FARMER, 3, listOf(VillagerTrades.ItemsForEmeralds(CobblemonItems.VIVICHOKE_SEEDS, 24, 1, 1, 6)))
|
||||
CobblemonVillagerProfessions.NURSE -> listOf(
|
||||
// requiredLevel = the level of the villager for the trade to appear for
|
||||
// Novice = 1, Apprentice = 2, Journeyman = 3, Expert = 4, Master = 5
|
||||
VillagerTradeOffer(CobblemonVillagerProfessions.NURSE, 1, listOf(
|
||||
// i = emeraldCost, j = numberOfItems, k = maxUses, l = villagerXp, f = priceMultiplier
|
||||
VillagerTrades.ItemsForEmeralds(CobblemonItems.ORAN_BERRY, 4, 1, 16, 1),
|
||||
VillagerTrades.ItemsForEmeralds(CobblemonItems.PERSIM_BERRY, 4, 1, 16, 1),
|
||||
VillagerTrades.ItemsForEmeralds(CobblemonItems.ENERGY_ROOT, 4, 1, 12, 1),
|
||||
TradeOffer(ItemCost(CobblemonItems.MEDICINAL_LEEK, 24), ItemStack(Items.EMERALD, 1), 12, 2)
|
||||
)),
|
||||
VillagerTradeOffer(CobblemonVillagerProfessions.NURSE, 2, listOf(
|
||||
TradeOffer(ItemCost(Items.EMERALD, 8), ItemStack(CobblemonItems.MEDICINAL_BREW), 8, 5, Optional.of<ItemCost>(ItemCost(Items.GLASS_BOTTLE))),
|
||||
VillagerTrades.ItemsForEmeralds(CobblemonItems.BLUE_MINT_LEAF, 2, 1, 8, 5),
|
||||
VillagerTrades.ItemsForEmeralds(CobblemonItems.CYAN_MINT_LEAF, 2, 1, 8, 5),
|
||||
VillagerTrades.ItemsForEmeralds(CobblemonItems.GREEN_MINT_LEAF, 2, 1, 8, 5),
|
||||
VillagerTrades.ItemsForEmeralds(CobblemonItems.PINK_MINT_LEAF, 2, 1, 8, 5),
|
||||
VillagerTrades.ItemsForEmeralds(CobblemonItems.RED_MINT_LEAF, 2, 1, 8, 5),
|
||||
VillagerTrades.ItemsForEmeralds(CobblemonItems.WHITE_MINT_LEAF, 2, 1, 8, 5)
|
||||
)),
|
||||
VillagerTradeOffer(CobblemonVillagerProfessions.NURSE, 3, listOf(
|
||||
TradeOffer(ItemCost(CobblemonItems.MULCH_BASE, 4), ItemStack(Items.EMERALD, 2), 16, 20),
|
||||
VillagerTrades.ItemsForEmeralds(Items.GLASS_BOTTLE, 1, 1, 16, 10)
|
||||
)),
|
||||
VillagerTradeOffer(CobblemonVillagerProfessions.NURSE, 4, listOf(
|
||||
VillagerTrades.ItemsForEmeralds(CobblemonItems.REVIVAL_HERB, 8, 1, 16, 15),
|
||||
VillagerTrades.ItemsForEmeralds(CobblemonItems.VIVICHOKE_SEEDS, 24, 1, 4, 15)
|
||||
)),
|
||||
VillagerTradeOffer(CobblemonVillagerProfessions.NURSE, 5, listOf(
|
||||
TradeOffer(ItemCost(Items.EMERALD, 10), ItemStack(CobblemonItems.ANTIDOTE, 1), 12, 30, Optional.of<ItemCost>(ItemCost(Items.GLASS_BOTTLE))),
|
||||
TradeOffer(ItemCost(Items.EMERALD, 10), ItemStack(CobblemonItems.AWAKENING, 1), 12, 30, Optional.of<ItemCost>(ItemCost(Items.GLASS_BOTTLE))),
|
||||
TradeOffer(ItemCost(Items.EMERALD, 10), ItemStack(CobblemonItems.BURN_HEAL, 1), 12, 30, Optional.of<ItemCost>(ItemCost(Items.GLASS_BOTTLE))),
|
||||
TradeOffer(ItemCost(Items.EMERALD, 10), ItemStack(CobblemonItems.ICE_HEAL, 1), 12, 30, Optional.of<ItemCost>(ItemCost(Items.GLASS_BOTTLE))),
|
||||
TradeOffer(ItemCost(Items.EMERALD, 10), ItemStack(CobblemonItems.PARALYZE_HEAL, 1), 12, 30, Optional.of<ItemCost>(ItemCost(Items.GLASS_BOTTLE))),
|
||||
TradeOffer(ItemCost(Items.EMERALD, 22), ItemStack(CobblemonItems.VIVICHOKE_DIP, 1), 4, 30, Optional.of<ItemCost>(ItemCost(Items.BOWL)))
|
||||
))
|
||||
)
|
||||
VillagerProfession.FISHERMAN -> listOf(
|
||||
VillagerTradeOffer(VillagerProfession.FISHERMAN, 5, listOf(
|
||||
@@ -53,7 +93,7 @@ object CobblemonTradeOffers {
|
||||
)
|
||||
|
||||
/**
|
||||
* Represents a trade offer that can be attached to a villager or a wandering trader.
|
||||
* Represents trade offers that can be attached to a villager or a wandering trader.
|
||||
*/
|
||||
interface TradeOfferHolder {
|
||||
/**
|
||||
@@ -63,7 +103,7 @@ object CobblemonTradeOffers {
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a trade offer from a villager.
|
||||
* Represents trade offers from a villager.
|
||||
*
|
||||
* @property profession The target profession for this trade.
|
||||
* @property requiredLevel The level required must be a possible level.
|
||||
@@ -75,7 +115,7 @@ object CobblemonTradeOffers {
|
||||
val profession: VillagerProfession,
|
||||
val requiredLevel: Int,
|
||||
override val tradeOffers: List<VillagerTrades.ItemListing>
|
||||
) : TradeOfferHolder {
|
||||
): TradeOfferHolder {
|
||||
|
||||
init {
|
||||
if (this.requiredLevel < VillagerData.MIN_VILLAGER_LEVEL || this.requiredLevel > VillagerData.MAX_VILLAGER_LEVEL) {
|
||||
@@ -86,7 +126,7 @@ object CobblemonTradeOffers {
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a trade offer from a wandering trader.
|
||||
* Represents trade offers from a wandering trader.
|
||||
*
|
||||
* @property isRareTrade If this is rare or common trade.
|
||||
* @property tradeOffers The list of the possible [TradeOffers.Factory].
|
||||
@@ -94,6 +134,26 @@ object CobblemonTradeOffers {
|
||||
data class WandererTradeOffer(
|
||||
val isRareTrade: Boolean,
|
||||
override val tradeOffers: List<VillagerTrades.ItemListing>
|
||||
) : TradeOfferHolder
|
||||
|
||||
): TradeOfferHolder
|
||||
|
||||
/**
|
||||
* Represents a trade offer from a villager.
|
||||
*
|
||||
* @property offeredItem The item cost offered to the villager.
|
||||
* @property receivedItem The item received from the villager.
|
||||
* @property maxUses How many times the trade can be used before the villager resupplies.
|
||||
* @property villagerXp The experience the villager gains from the trade.
|
||||
* @property optionalOfferedItem The optional, secondary item cost offered to the villager.
|
||||
* @property priceMultiplier The amount multiplier of how much the item cost can rise and fall by depending on discounts and penalties
|
||||
*/
|
||||
class TradeOffer(
|
||||
private val offeredItem: ItemCost,
|
||||
private val receivedItem: ItemStack,
|
||||
private val maxUses: Int,
|
||||
private val villagerXp: Int = 1,
|
||||
private val optionalOfferedItem: Optional<ItemCost> = Optional.empty(),
|
||||
private val priceMultiplier: Float = 0.05F
|
||||
): VillagerTrades.ItemListing {
|
||||
override fun getOffer(entity: Entity?, randomSource: RandomSource?): MerchantOffer = MerchantOffer(offeredItem, optionalOfferedItem, receivedItem, maxUses, villagerXp, priceMultiplier)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common
|
||||
|
||||
import com.cobblemon.mod.common.platform.PlatformRegistry
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.google.common.collect.ImmutableSet
|
||||
import net.minecraft.core.Registry
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
import net.minecraft.core.registries.Registries
|
||||
import net.minecraft.resources.ResourceKey
|
||||
import net.minecraft.world.entity.ai.village.poi.PoiType
|
||||
import net.minecraft.world.level.block.Block
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
|
||||
object CobblemonVillagerPoiTypes: PlatformRegistry<Registry<PoiType>, ResourceKey<Registry<PoiType>>, PoiType>() {
|
||||
override val registry: Registry<PoiType> = BuiltInRegistries.POINT_OF_INTEREST_TYPE
|
||||
override val resourceKey: ResourceKey<Registry<PoiType>> = Registries.POINT_OF_INTEREST_TYPE
|
||||
|
||||
@JvmField
|
||||
val NURSE_KEY: ResourceKey<PoiType> = createKey("nurse")
|
||||
@JvmField
|
||||
val NURSE = create(NURSE_KEY.location().path, PoiType(getBlockStates(CobblemonBlocks.HEALING_MACHINE), 1, 1))
|
||||
|
||||
private fun createKey(string: String): ResourceKey<PoiType> = ResourceKey.create(Registries.POINT_OF_INTEREST_TYPE, cobblemonResource(string))
|
||||
|
||||
private fun getBlockStates(block: Block): Set<BlockState> = ImmutableSet.copyOf(block.stateDefinition.possibleStates)
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common
|
||||
|
||||
import com.cobblemon.mod.common.platform.PlatformRegistry
|
||||
import com.google.common.collect.ImmutableSet
|
||||
import net.minecraft.core.Holder
|
||||
import net.minecraft.core.Registry
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
import net.minecraft.core.registries.Registries
|
||||
import net.minecraft.resources.ResourceKey
|
||||
import net.minecraft.sounds.SoundEvent
|
||||
import net.minecraft.world.entity.ai.village.poi.PoiType
|
||||
import net.minecraft.world.entity.npc.VillagerProfession
|
||||
|
||||
object CobblemonVillagerProfessions: PlatformRegistry<Registry<VillagerProfession>, ResourceKey<Registry<VillagerProfession>>, VillagerProfession>() {
|
||||
override val registry: Registry<VillagerProfession> = BuiltInRegistries.VILLAGER_PROFESSION
|
||||
override val resourceKey: ResourceKey<Registry<VillagerProfession>> = Registries.VILLAGER_PROFESSION
|
||||
|
||||
@JvmField
|
||||
val NURSE = profession(CobblemonVillagerPoiTypes.NURSE_KEY, CobblemonSounds.VILLAGER_WORK_NURSE)
|
||||
|
||||
/**
|
||||
* Register a villager profession texture override for Cobblemon villagers of the given [VillagerProfession] for specified names.
|
||||
*
|
||||
* @param profession The Cobblemon [VillagerProfession] being overridden.
|
||||
* @return The profession override texture file name and a list of names that will trigger the override, as a pair.
|
||||
*/
|
||||
fun getNameTagOverride(profession: VillagerProfession?): Pair<String, Array<String>>? = when (profession) {
|
||||
NURSE -> Pair("nurse_joy", arrayOf("ジョーイ", "간호순", "祖兒", "喬伊", "乔伊", "האחות ג'וי", "الممرضة جوي", "Joy", "Joelle", "Joëlle", "Джой", "จอย"))
|
||||
else -> null
|
||||
}
|
||||
|
||||
private fun profession(resourceKey: ResourceKey<PoiType>, soundEvent: SoundEvent?): VillagerProfession =
|
||||
create(resourceKey.location().path, VillagerProfession(
|
||||
resourceKey.location().toString(),
|
||||
{ holder: Holder<PoiType> -> holder.`is`(resourceKey) },
|
||||
{ holder: Holder<PoiType> -> holder.`is`(resourceKey) },
|
||||
ImmutableSet.of(), ImmutableSet.of(), soundEvent
|
||||
))
|
||||
}
|
||||
+1
-1
@@ -59,7 +59,7 @@ class AspectCriterion(
|
||||
// pokemon = json.get("pokemon").asString.asIdentifierDefaultingNamespace()
|
||||
// }
|
||||
//
|
||||
// override fun matches(player: ServerPlayerEntity, context: MutableMap<Identifier, MutableSet<String>>): Boolean {
|
||||
// override fun matches(player: ServerPlayer, context: MutableMap<Identifier, MutableSet<String>>): Boolean {
|
||||
// val caughtAspects = context.getOrDefault(pokemon, mutableSetOf())
|
||||
// return this.aspects.all { it in caughtAspects }
|
||||
// }
|
||||
|
||||
+2
-3
@@ -34,8 +34,7 @@ class BattleCountableCriterion(
|
||||
|
||||
override fun matches(player: ServerPlayer, context: BattleCountableContext): Boolean {
|
||||
var typeCheck = false
|
||||
val advancementData = Cobblemon.playerData.get(player).advancementData
|
||||
|
||||
val advancementData = Cobblemon.playerDataManager.getGenericData(player).advancementData
|
||||
if (battleTypes.isEmpty() || battleTypes.contains("any")) {
|
||||
typeCheck = true
|
||||
}
|
||||
@@ -87,7 +86,7 @@ class BattleCountableCriterion(
|
||||
// json.add("battle_types", battleTypes.toJsonArray())
|
||||
// }
|
||||
//
|
||||
// override fun matches(player: ServerPlayerEntity, context: BattleCountableContext): Boolean {
|
||||
// override fun matches(player: ServerPlayer, context: BattleCountableContext): Boolean {
|
||||
// var typeCheck = false
|
||||
// val advancementData = Cobblemon.playerData.get(player).advancementData
|
||||
// if (battleTypes.isEmpty() || battleTypes.contains("any")) {
|
||||
|
||||
+1
-1
@@ -54,7 +54,7 @@ class CaughtPokemonCriterion(
|
||||
// type = json.get("type")?.asString ?: "any"
|
||||
// }
|
||||
//
|
||||
// override fun matches(player: ServerPlayerEntity, context: CountablePokemonTypeContext): Boolean {
|
||||
// override fun matches(player: ServerPlayer, context: CountablePokemonTypeContext): Boolean {
|
||||
// return super.matches(player, context) && (context.type == type || type == "any")
|
||||
// }
|
||||
//}
|
||||
+2
-2
@@ -50,7 +50,7 @@ open class CountableCriterion<T : CountableContext>(
|
||||
// json.addProperty("count", count)
|
||||
// }
|
||||
//
|
||||
// override fun matches(player: ServerPlayerEntity, context: T) = context.times >= count
|
||||
// override fun matches(player: ServerPlayer, context: T) = context.times >= count
|
||||
//}
|
||||
//
|
||||
///**
|
||||
@@ -64,7 +64,7 @@ open class CountableCriterion<T : CountableContext>(
|
||||
// * @since November 4th, 2022
|
||||
// */
|
||||
//class SimpleCountableCriterionCondition(id: Identifier, predicate: LootContextPredicate) : CountableCriterionCondition<CountableContext>(id, predicate)
|
||||
//fun SimpleCriterionTrigger<CountableContext, SimpleCountableCriterionCondition>.trigger(player: ServerPlayerEntity, times: Int) = trigger(player, CountableContext(times))
|
||||
//fun SimpleCriterionTrigger<CountableContext, SimpleCountableCriterionCondition>.trigger(player: ServerPlayer, times: Int) = trigger(player, CountableContext(times))
|
||||
//
|
||||
///**
|
||||
// * Some type of context that has a count associated with it, representing how many times the trigger has occurred.
|
||||
|
||||
+1
-1
@@ -55,7 +55,7 @@ class EvolvePokemonCriterion(
|
||||
// evolution = json.get("evolution")?.asString ?: "any"
|
||||
// }
|
||||
//
|
||||
// override fun matches(player: ServerPlayerEntity, context: EvolvePokemonContext): Boolean {
|
||||
// override fun matches(player: ServerPlayer, context: EvolvePokemonContext): Boolean {
|
||||
// return context.times >= count && (context.species == species.asIdentifierDefaultingNamespace() || species == "any") &&
|
||||
// (context.evolution == evolution.asIdentifierDefaultingNamespace() || evolution == "any")
|
||||
// }
|
||||
|
||||
+1
-1
@@ -57,7 +57,7 @@ class LevelUpCriterion(
|
||||
evolved = json.get("has_evolved")?.asBoolean ?: true
|
||||
}
|
||||
|
||||
override fun matches(player: ServerPlayerEntity, context: LevelUpContext): Boolean {
|
||||
override fun matches(player: ServerPlayer, context: LevelUpContext): Boolean {
|
||||
val preEvo = context.pokemon.preEvolution == null
|
||||
val hasEvolution = !context.pokemon.evolutions.none()
|
||||
var evolutionCheck = true
|
||||
|
||||
+1
-1
@@ -79,7 +79,7 @@ class PartyCheckCriterion(
|
||||
}
|
||||
}
|
||||
|
||||
override fun matches(player: ServerPlayerEntity, context: PartyCheckContext): Boolean {
|
||||
override fun matches(player: ServerPlayer, context: PartyCheckContext): Boolean {
|
||||
val playerParty = player.party()
|
||||
val matches = mutableListOf<Identifier>()
|
||||
party.forEach {
|
||||
|
||||
+1
-1
@@ -57,7 +57,7 @@ class PlantTumblestoneCriterion(
|
||||
// * @param context The context of the criterion
|
||||
// * @return True if the tumblestone block can grow at the given position, false otherwise
|
||||
// */
|
||||
// override fun matches(player: ServerPlayerEntity, context: PlantTumblestoneContext): Boolean {
|
||||
// override fun matches(player: ServerPlayer, context: PlantTumblestoneContext): Boolean {
|
||||
// return context.tumbleStoneBlock.canGrow(context.pos, player.level())
|
||||
// }
|
||||
//}
|
||||
|
||||
+5
-7
@@ -21,20 +21,18 @@ class PokemonInteractContext(val type: ResourceLocation, val item: ResourceLocat
|
||||
|
||||
class PokemonInteractCriterion(
|
||||
playerCtx: Optional<ContextAwarePredicate>,
|
||||
val type: Optional<String>,
|
||||
val item: Optional<String>
|
||||
val type: String,
|
||||
val item: String
|
||||
): SimpleCriterionCondition<PokemonInteractContext>(playerCtx) {
|
||||
companion object {
|
||||
val CODEC: Codec<PokemonInteractCriterion> = RecordCodecBuilder.create { it.group(
|
||||
EntityPredicate.ADVANCEMENT_CODEC.optionalFieldOf("player").forGetter(PokemonInteractCriterion::playerCtx),
|
||||
Codec.STRING.optionalFieldOf("type").forGetter(PokemonInteractCriterion::type),
|
||||
Codec.STRING.optionalFieldOf("item").forGetter(PokemonInteractCriterion::item)
|
||||
Codec.STRING.optionalFieldOf("type", "any").forGetter(PokemonInteractCriterion::type),
|
||||
Codec.STRING.optionalFieldOf("item", "any").forGetter(PokemonInteractCriterion::item)
|
||||
).apply(it, ::PokemonInteractCriterion) }
|
||||
}
|
||||
|
||||
override fun matches(player: ServerPlayer, context: PokemonInteractContext): Boolean {
|
||||
val otherType = this.type.orElse("any")
|
||||
val otherItem = this.item.orElse("any")
|
||||
return (context.type == otherType.asIdentifierDefaultingNamespace() || otherType == "any") && (context.type == otherItem.asIdentifierDefaultingNamespace() || otherItem == "any")
|
||||
return (context.type == this.type.asIdentifierDefaultingNamespace() || this.type == "any") && (context.item == this.item.asIdentifierDefaultingNamespace() || this.item == "any")
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -80,7 +80,7 @@ class TradePokemonCriterion(
|
||||
receivedHeldItem = json.get("received_held_item")?.asString ?: "minecraft:air"
|
||||
}
|
||||
|
||||
override fun matches(player: ServerPlayerEntity, context: TradePokemonContext): Boolean {
|
||||
override fun matches(player: ServerPlayer, context: TradePokemonContext): Boolean {
|
||||
val heldItem1 = context.traded.heldItem().item.registryEntry.ResourceKey().value
|
||||
val heldItem2 = context.received.heldItem().item.registryEntry.ResourceKey().value
|
||||
return (context.traded.species.resourceIdentifier == traded.asIdentifierDefaultingNamespace() || traded == "any") &&
|
||||
|
||||
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.api.battles.model
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.bedrockk.molang.runtime.value.MoValue
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.Cobblemon.LOGGER
|
||||
import com.cobblemon.mod.common.CobblemonNetwork
|
||||
@@ -21,6 +22,7 @@ import com.cobblemon.mod.common.api.battles.model.actor.EntityBackedBattleActor
|
||||
import com.cobblemon.mod.common.api.battles.model.actor.FleeableBattleActor
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents
|
||||
import com.cobblemon.mod.common.api.events.battles.BattleFledEvent
|
||||
import com.cobblemon.mod.common.api.moves.Moves
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
|
||||
import com.cobblemon.mod.common.api.net.NetworkPacket
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonItemTags
|
||||
@@ -40,20 +42,27 @@ import com.cobblemon.mod.common.battles.dispatch.WaitDispatch
|
||||
import com.cobblemon.mod.common.battles.interpreter.ContextManager
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
import com.cobblemon.mod.common.battles.runner.ShowdownService
|
||||
import com.cobblemon.mod.common.entity.npc.NPCBattleActor
|
||||
import com.cobblemon.mod.common.entity.npc.NPCEntity
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.net.messages.client.battle.BattleEndPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.battle.BattleMessagePacket
|
||||
import com.cobblemon.mod.common.pokemon.evolution.progress.DefeatEvolutionProgress
|
||||
import com.cobblemon.mod.common.pokemon.evolution.progress.LastBattleCriticalHitsEvolutionProgress
|
||||
import com.cobblemon.mod.common.pokemon.evolution.requirements.DefeatRequirement
|
||||
import com.cobblemon.mod.common.pokemon.helditem.CobblemonHeldItemManager
|
||||
import com.cobblemon.mod.common.util.battleLang
|
||||
import com.cobblemon.mod.common.util.getPlayer
|
||||
import net.minecraft.network.chat.Component
|
||||
import com.cobblemon.mod.common.util.giveOrDropItemStack
|
||||
import com.cobblemon.mod.common.util.itemRegistry
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import java.io.File
|
||||
import java.util.UUID
|
||||
import java.util.concurrent.CompletableFuture
|
||||
import java.util.concurrent.ConcurrentLinkedDeque
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.item.ItemStack
|
||||
|
||||
/**
|
||||
* Individual battle instance
|
||||
@@ -84,6 +93,7 @@ open class PokemonBattle(
|
||||
.filterIsInstance<LastBattleCriticalHitsEvolutionProgress>()
|
||||
.forEach { it.reset() }
|
||||
}
|
||||
actor.setupStruct()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,7 +119,7 @@ open class PokemonBattle(
|
||||
var ended = false
|
||||
// TEMP battle showcase stuff
|
||||
var announcingRules = false
|
||||
var turn: Int = 1
|
||||
var turn: Int = 0
|
||||
private set
|
||||
|
||||
private var ticks: Int = 0
|
||||
@@ -175,6 +185,11 @@ open class PokemonBattle(
|
||||
*/
|
||||
fun getActor(player: ServerPlayer) = actors.firstOrNull { it.isForPlayer(player) }
|
||||
|
||||
/**
|
||||
* Gets the first battle actor whom the given NPC controls, or null if there is no such actor.
|
||||
*/
|
||||
fun getActor(npc: NPCEntity) = actors.firstOrNull { it is NPCBattleActor && it.npc == npc }
|
||||
|
||||
/**
|
||||
* Gets a [BattleActor] and an [ActiveBattlePokemon] from a pnx key, e.g. p2a
|
||||
*
|
||||
@@ -214,11 +229,12 @@ open class PokemonBattle(
|
||||
|
||||
fun turn(newTurnNumber: Int) {
|
||||
actors.forEach { it.turn() }
|
||||
// TODO: If a pokemon switches in the same turn another pokemon is KO'd it will not receive exp for the KO
|
||||
for (side in sides) {
|
||||
val opposite = side.getOppositeSide()
|
||||
side.activePokemon.forEach {
|
||||
val battlePokemon = it.battlePokemon ?: return@forEach
|
||||
battlePokemon.facedOpponents.addAll(opposite.activePokemon.mapNotNull { it.battlePokemon })
|
||||
side.activePokemon.filter { it.isAlive() }.forEach { activePokemon ->
|
||||
val battlePokemon = activePokemon.battlePokemon ?: return@forEach
|
||||
battlePokemon.facedOpponents.addAll(opposite.activePokemon.filter { opposingActivePokemon -> opposingActivePokemon.isAlive() }.mapNotNull { it.battlePokemon })
|
||||
}
|
||||
}
|
||||
this.turn = newTurnNumber
|
||||
@@ -261,6 +277,13 @@ open class PokemonBattle(
|
||||
}
|
||||
}
|
||||
}
|
||||
if(actor.itemsUsed.isNotEmpty() && actor.getPlayerUUIDs().count() > 0) {
|
||||
val player = actor.getPlayerUUIDs().first().getPlayer()
|
||||
player?.level()?.itemRegistry.let { registry ->
|
||||
actor.itemsUsed.mapNotNull { registry?.get(ResourceLocation.tryBySeparator(it.itemName.substringAfter('.'), '.')) }
|
||||
.forEach { player?.giveOrDropItemStack(ItemStack(it))}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Heal Mon if wild
|
||||
actors.filter { it.type == ActorType.WILD }
|
||||
|
||||
+17
-4
@@ -8,6 +8,8 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.battles.model.actor
|
||||
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
|
||||
import com.cobblemon.mod.common.api.net.NetworkPacket
|
||||
import com.cobblemon.mod.common.battles.ActiveBattlePokemon
|
||||
@@ -17,6 +19,7 @@ import com.cobblemon.mod.common.battles.ShowdownActionResponse
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.exception.IllegalActionChoiceException
|
||||
import com.cobblemon.mod.common.item.battle.BagItem
|
||||
import com.cobblemon.mod.common.net.messages.client.battle.BattleApplyPassResponsePacket
|
||||
import com.cobblemon.mod.common.net.messages.client.battle.BattleMakeChoicePacket
|
||||
import com.cobblemon.mod.common.net.messages.client.battle.BattleMessagePacket
|
||||
@@ -33,6 +36,8 @@ abstract class BattleActor(
|
||||
pokemonList.forEach { it.actor = this }
|
||||
}
|
||||
|
||||
val struct = QueryStruct(hashMapOf())
|
||||
|
||||
lateinit var showdownId: String
|
||||
lateinit var battle: PokemonBattle
|
||||
|
||||
@@ -44,6 +49,7 @@ abstract class BattleActor(
|
||||
val expectingPassActions = mutableListOf<ShowdownActionResponse>()
|
||||
var mustChoose = false
|
||||
|
||||
var itemsUsed = mutableListOf<BagItem>()
|
||||
/** For when battles start, it's the number of Pokémon that are still in the process of being sent out (animation wise) */
|
||||
var stillSendingOutCount = 0
|
||||
|
||||
@@ -65,11 +71,14 @@ abstract class BattleActor(
|
||||
open fun isForPlayer(serverPlayerEntity: ServerPlayer) = serverPlayerEntity.uuid in getPlayerUUIDs()
|
||||
open fun isForPokemon(pokemonEntity: PokemonEntity) = activePokemon.any { it.battlePokemon?.effectedPokemon?.entity == pokemonEntity }
|
||||
|
||||
fun turn() {
|
||||
fun turn() {
|
||||
val request = request ?: return
|
||||
responses.clear()
|
||||
mustChoose = true
|
||||
sendUpdate(BattleMakeChoicePacket())
|
||||
if(activePokemon.any { it.isAlive() }) {
|
||||
mustChoose = true
|
||||
sendUpdate(BattleMakeChoicePacket())
|
||||
}
|
||||
|
||||
|
||||
val requestActive = request.active
|
||||
if (requestActive == null || requestActive.isEmpty() || request.wait) {
|
||||
@@ -129,6 +138,10 @@ abstract class BattleActor(
|
||||
battle.writeShowdownAction(">$showdownId ${showdownMessages.joinToString()}")
|
||||
}
|
||||
|
||||
open fun setupStruct() {
|
||||
struct.addFunction("uuid") { StringValue(uuid.toString()) }
|
||||
}
|
||||
|
||||
abstract fun getName(): MutableComponent
|
||||
|
||||
/**
|
||||
@@ -136,7 +149,7 @@ abstract class BattleActor(
|
||||
* NPC and player actors expect to append their [getName] while wild Pokémon append nothing.
|
||||
*
|
||||
* @param name The name of an object being appended, typically a Pokémon nickname received from showdown.
|
||||
* @return A [MutableText] of the [name] append with owner prefix.
|
||||
* @return A [MutableComponent] of the [name] append with owner prefix.
|
||||
*/
|
||||
abstract fun nameOwned(name: String): MutableComponent
|
||||
|
||||
|
||||
+2
@@ -9,6 +9,7 @@
|
||||
package com.cobblemon.mod.common.api.battles.model.actor
|
||||
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
/**
|
||||
* Allows a [BattleActor] to attach a [LivingEntity] to itself.
|
||||
@@ -21,5 +22,6 @@ interface EntityBackedBattleActor<T : LivingEntity> {
|
||||
* The [LivingEntity] attached to the [BattleActor].
|
||||
*/
|
||||
val entity: T?
|
||||
val initialPos: Vec3?
|
||||
|
||||
}
|
||||
@@ -139,7 +139,7 @@ open class PartySelectPokemonDTO(
|
||||
aspects = pokemon.aspects,
|
||||
heldItem = pokemon.heldItemNoCopy(),
|
||||
currentHealth = pokemon.currentHealth,
|
||||
maxHealth = pokemon.hp,
|
||||
maxHealth = pokemon.maxHealth,
|
||||
enabled = enabled
|
||||
)
|
||||
|
||||
|
||||
@@ -22,8 +22,10 @@ import com.cobblemon.mod.common.api.molang.MoLangFunctions.addStandardFunctions
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
|
||||
import com.cobblemon.mod.common.api.scheduling.ServerRealTimeTaskTracker
|
||||
import com.cobblemon.mod.common.entity.npc.NPCEntity
|
||||
import com.cobblemon.mod.common.net.messages.client.dialogue.DialogueOpenedPacket
|
||||
import java.util.UUID
|
||||
import java.util.concurrent.CompletableFuture
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
|
||||
/**
|
||||
@@ -34,19 +36,31 @@ import net.minecraft.server.level.ServerPlayer
|
||||
* @since December 27th, 2023
|
||||
*/
|
||||
class ActiveDialogue(var playerEntity: ServerPlayer, var dialogueReference: Dialogue) {
|
||||
var initialized = false
|
||||
val dialogueId = UUID.randomUUID()
|
||||
val runtime = MoLangRuntime().setup()
|
||||
var npc: NPCEntity? = null
|
||||
var currentPage = dialogueReference.pages[0]
|
||||
val playerStruct = playerEntity.asMoLangValue()
|
||||
var activeInput = ActiveInput(this, currentPage.input)
|
||||
|
||||
init {
|
||||
val completion = CompletableFuture<Unit>()
|
||||
|
||||
fun initialize() {
|
||||
runtime.environment.query.addFunctions(
|
||||
mapOf(
|
||||
"dialogue" to java.util.function.Function { _ -> toMoLangStruct() },
|
||||
"player" to java.util.function.Function { _ -> playerStruct }
|
||||
)
|
||||
)
|
||||
|
||||
dialogueReference.initializationAction.invoke(this)
|
||||
|
||||
if (!completion.isDone) {
|
||||
val packet = DialogueOpenedPacket(this, true)
|
||||
playerEntity.sendPacket(packet)
|
||||
}
|
||||
initialized = true
|
||||
}
|
||||
|
||||
val currentPageIndex
|
||||
@@ -85,7 +99,9 @@ class ActiveDialogue(var playerEntity: ServerPlayer, var dialogueReference: Dial
|
||||
}
|
||||
}
|
||||
}
|
||||
playerEntity.sendPacket(DialogueOpenedPacket(this, false))
|
||||
if (initialized) {
|
||||
playerEntity.sendPacket(DialogueOpenedPacket(this, false))
|
||||
}
|
||||
}
|
||||
|
||||
fun setPage(index: Int) {
|
||||
@@ -114,7 +130,10 @@ class ActiveDialogue(var playerEntity: ServerPlayer, var dialogueReference: Dial
|
||||
}
|
||||
|
||||
fun close() {
|
||||
DialogueManager.stopDialogue(playerEntity)
|
||||
if (initialized) {
|
||||
DialogueManager.stopDialogue(playerEntity)
|
||||
}
|
||||
completion.complete(Unit)
|
||||
}
|
||||
|
||||
fun escape() {
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
package com.cobblemon.mod.common.api.dialogue
|
||||
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
|
||||
/**
|
||||
* A dialogue that could be sent to players.
|
||||
@@ -18,29 +20,39 @@ import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
*/
|
||||
class Dialogue(
|
||||
val pages: List<DialoguePage> = mutableListOf(),
|
||||
val background: ResourceLocation = DEFAULT_BACKGROUND,
|
||||
val escapeAction: DialogueAction = FunctionDialogueAction { dialogue, _ -> dialogue.close() },
|
||||
val speakers: Map<String, DialogueSpeaker> = emptyMap()
|
||||
val speakers: Map<String, DialogueSpeaker> = emptyMap(),
|
||||
val initializationAction: DialogueAction = FunctionDialogueAction { _, _ -> }
|
||||
) {
|
||||
companion object {
|
||||
val DEFAULT_BACKGROUND = cobblemonResource("textures/gui/dialogue/dialogue_box.png")
|
||||
|
||||
@JvmOverloads
|
||||
fun of(
|
||||
pages: Iterable<DialoguePage>,
|
||||
background: ResourceLocation = DEFAULT_BACKGROUND,
|
||||
escapeAction: ExpressionLike,
|
||||
speakers: Map<String, DialogueSpeaker>
|
||||
): Dialogue {
|
||||
return Dialogue(
|
||||
pages = pages.toList(),
|
||||
escapeAction = ExpressionLikeDialogueAction(escapeAction),
|
||||
background = background,
|
||||
speakers = speakers
|
||||
)
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
fun of(
|
||||
pages: Iterable<DialoguePage>,
|
||||
background: ResourceLocation = DEFAULT_BACKGROUND,
|
||||
escapeAction: (ActiveDialogue) -> Unit,
|
||||
speakers: Map<String, DialogueSpeaker>
|
||||
): Dialogue {
|
||||
val dialogue = Dialogue(
|
||||
pages = pages.toList(),
|
||||
background = background,
|
||||
escapeAction = FunctionDialogueAction { activeDialogue, _ -> escapeAction(activeDialogue) },
|
||||
speakers = speakers
|
||||
)
|
||||
|
||||
@@ -8,8 +8,10 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.dialogue
|
||||
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
|
||||
import com.cobblemon.mod.common.util.resolve
|
||||
|
||||
/**
|
||||
@@ -39,6 +41,9 @@ class ExpressionLikeDialogueAction(val expression: ExpressionLike) : DialogueAct
|
||||
if (input != null) {
|
||||
dialogue.runtime.environment.setSimpleVariable("selected_option", StringValue(input))
|
||||
}
|
||||
dialogue.runtime.resolve(expression)
|
||||
dialogue.runtime.resolve(
|
||||
expression,
|
||||
mapOf("player" to dialogue.playerStruct, "npc" to (dialogue.npc?.struct ?: QueryStruct(hashMapOf())))
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,8 @@ import net.minecraft.resources.ResourceLocation
|
||||
* @since January 1st, 2024
|
||||
*/
|
||||
sealed interface DialogueFaceProvider {
|
||||
val isLeftSide: Boolean
|
||||
|
||||
companion object {
|
||||
val types = mutableMapOf(
|
||||
"player" to PlayerDialogueFaceProvider::class.java,
|
||||
@@ -32,15 +34,24 @@ sealed interface DialogueFaceProvider {
|
||||
class ArtificialDialogueFaceProvider(
|
||||
val modelType: String = "",
|
||||
val identifier: ResourceLocation = cobblemonResource("bulbasaur"),
|
||||
val aspects: Set<String> = setOf()
|
||||
val aspects: Set<String> = setOf(),
|
||||
override val isLeftSide: Boolean = true
|
||||
) : DialogueFaceProvider
|
||||
|
||||
class ReferenceDialogueFaceProvider(
|
||||
val entityId: Int
|
||||
val entityId: Int,
|
||||
override val isLeftSide: Boolean = true
|
||||
): DialogueFaceProvider
|
||||
|
||||
class PlayerDialogueFaceProvider(val playerId: UUID) : DialogueFaceProvider
|
||||
/**
|
||||
* A face provider that uses the player's skin as the face, as long as there is a player with this UUID online.
|
||||
*
|
||||
* What's interesting is that this works for fake players, which is what Taterzens' NPCs use.
|
||||
*/
|
||||
class PlayerDialogueFaceProvider(val playerId: UUID = UUID.randomUUID(), override val isLeftSide: Boolean = true) : DialogueFaceProvider
|
||||
|
||||
class ExpressionLikeDialogueFaceProvider(
|
||||
val providerExpression: ExpressionLike
|
||||
): DialogueFaceProvider
|
||||
): DialogueFaceProvider {
|
||||
override val isLeftSide: Boolean = false // Doesn't get used
|
||||
}
|
||||
@@ -13,7 +13,7 @@ import com.cobblemon.mod.common.entity.npc.NPCEntity
|
||||
import com.cobblemon.mod.common.net.messages.client.dialogue.DialogueClosedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.dialogue.DialogueOpenedPacket
|
||||
import com.cobblemon.mod.common.util.activeDialogue
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import com.cobblemon.mod.common.util.withNPCValue
|
||||
import java.util.UUID
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
|
||||
@@ -28,20 +28,25 @@ import net.minecraft.server.level.ServerPlayer
|
||||
object DialogueManager {
|
||||
val activeDialogues = mutableMapOf<UUID, ActiveDialogue>()
|
||||
|
||||
fun startDialogue(playerEntity: ServerPlayer, dialogue: Dialogue) {
|
||||
startDialogue(ActiveDialogue(playerEntity, dialogue))
|
||||
fun startDialogue(playerEntity: ServerPlayer, dialogue: Dialogue): ActiveDialogue {
|
||||
val activeDialogue = ActiveDialogue(playerEntity, dialogue)
|
||||
startDialogue(activeDialogue)
|
||||
return activeDialogue
|
||||
}
|
||||
|
||||
fun startDialogue(playerEntity: ServerPlayer, npcEntity: NPCEntity, dialogue: Dialogue) {
|
||||
fun startDialogue(playerEntity: ServerPlayer, npcEntity: NPCEntity, dialogue: Dialogue): ActiveDialogue {
|
||||
val activeDialogue = ActiveDialogue(playerEntity, dialogue)
|
||||
activeDialogue.runtime.withQueryValue("npc") { npcEntity.struct }
|
||||
activeDialogue.runtime.withNPCValue("npc", npcEntity)
|
||||
activeDialogue.npc = npcEntity
|
||||
startDialogue(activeDialogue)
|
||||
return activeDialogue
|
||||
}
|
||||
|
||||
fun startDialogue(activeDialogue: ActiveDialogue) {
|
||||
activeDialogues[activeDialogue.playerEntity.uuid] = activeDialogue
|
||||
val packet = DialogueOpenedPacket(activeDialogue, true)
|
||||
activeDialogue.playerEntity.sendPacket(packet)
|
||||
activeDialogue.initialize()
|
||||
if (!activeDialogue.completion.isDone) {
|
||||
activeDialogues[activeDialogue.playerEntity.uuid] = activeDialogue
|
||||
}
|
||||
}
|
||||
|
||||
fun stopDialogue(playerEntity: ServerPlayer) {
|
||||
|
||||
@@ -17,6 +17,7 @@ import com.cobblemon.mod.common.api.dialogue.input.DialogueInput
|
||||
import com.cobblemon.mod.common.api.dialogue.input.DialogueNoInput
|
||||
import com.google.gson.JsonArray
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
|
||||
/**
|
||||
* A page of a dialogue. This has lines of text and also some kind of input expected from the player.
|
||||
@@ -29,6 +30,7 @@ class DialoguePage(
|
||||
var speaker: String? = null,
|
||||
var lines: MutableList<DialogueText> = mutableListOf(),
|
||||
var input: DialogueInput = DialogueNoInput(),
|
||||
var background: ResourceLocation? = null,
|
||||
var clientActions: MutableList<Expression> = mutableListOf(),
|
||||
var escapeAction: DialogueAction? = null,
|
||||
) {
|
||||
@@ -40,6 +42,7 @@ class DialoguePage(
|
||||
speaker: String? = null,
|
||||
lines: Iterable<MutableComponent>,
|
||||
input: DialogueInput = DialogueNoInput(),
|
||||
background: ResourceLocation? = null,
|
||||
clientActions: Iterable<Expression> = emptyList(),
|
||||
/** The thing to do when the player presses ESC while on this page. If null, falls back to the same property on [Dialogue]. */
|
||||
escapeAction: ((ActiveDialogue) -> Unit)? = null,
|
||||
@@ -49,6 +52,7 @@ class DialoguePage(
|
||||
speaker = speaker,
|
||||
lines = lines.map { WrappedDialogueText(it) }.toMutableList(),
|
||||
input = input,
|
||||
background = background,
|
||||
clientActions = clientActions.toMutableList(),
|
||||
escapeAction = escapeAction?.let { func -> FunctionDialogueAction { activeDialogue, _ -> func(activeDialogue) } }
|
||||
)
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
package com.cobblemon.mod.common.api.entity
|
||||
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import java.util.concurrent.CompletableFuture
|
||||
|
||||
/**
|
||||
@@ -20,6 +21,6 @@ import java.util.concurrent.CompletableFuture
|
||||
*
|
||||
*/
|
||||
interface PokemonSender {
|
||||
fun sendingOut(): CompletableFuture<Unit>
|
||||
fun sendingOut(pokemon: Pokemon): CompletableFuture<Unit>
|
||||
fun recalling(pokemonEntity: PokemonEntity): CompletableFuture<Unit>
|
||||
}
|
||||
@@ -11,10 +11,12 @@ package com.cobblemon.mod.common.api.entity
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import net.minecraft.world.damagesource.DamageSource
|
||||
import net.minecraft.world.entity.player.Player
|
||||
|
||||
interface PokemonSideDelegate : EntitySideDelegate<PokemonEntity> {
|
||||
fun changePokemon(pokemon: Pokemon)
|
||||
fun drop(source: DamageSource?) {}
|
||||
fun updatePostDeath() {}
|
||||
fun handleStatus(status: Byte) {}
|
||||
fun spawnShinyParticle(player: Player) {}
|
||||
}
|
||||
@@ -27,6 +27,7 @@ import com.cobblemon.mod.common.api.events.item.LeftoversCreatedEvent
|
||||
import com.cobblemon.mod.common.api.events.pokeball.PokeBallCaptureCalculatedEvent
|
||||
import com.cobblemon.mod.common.api.events.pokeball.PokemonCatchRateEvent
|
||||
import com.cobblemon.mod.common.api.events.pokeball.ThrownPokeballHitEvent
|
||||
import com.cobblemon.mod.common.api.events.pokedex.scanning.PokemonScannedEvent
|
||||
import com.cobblemon.mod.common.api.events.pokemon.*
|
||||
import com.cobblemon.mod.common.api.events.pokemon.evolution.EvolutionAcceptedEvent
|
||||
import com.cobblemon.mod.common.api.events.pokemon.evolution.EvolutionCompleteEvent
|
||||
@@ -40,6 +41,7 @@ import com.cobblemon.mod.common.api.events.storage.ReleasePokemonEvent
|
||||
import com.cobblemon.mod.common.api.events.world.BigRootPropagatedEvent
|
||||
import com.cobblemon.mod.common.api.reactive.CancelableObservable
|
||||
import com.cobblemon.mod.common.api.reactive.EventObservable
|
||||
import com.cobblemon.mod.common.api.reactive.Observable
|
||||
import com.cobblemon.mod.common.api.reactive.Observable.Companion.filter
|
||||
import com.cobblemon.mod.common.api.reactive.Observable.Companion.map
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
@@ -67,8 +69,6 @@ object CobblemonEvents {
|
||||
val EVOLUTION_COMPLETE = EventObservable<EvolutionCompleteEvent>()
|
||||
@JvmField
|
||||
val POKEMON_NICKNAMED = CancelableObservable<PokemonNicknamedEvent>()
|
||||
@JvmField
|
||||
val HELD_ITEM_UPDATED = CancelableObservable<HeldItemUpdatedEvent>()
|
||||
|
||||
@JvmField
|
||||
val THROWN_POKEBALL_HIT = CancelableObservable<ThrownPokeballHitEvent>()
|
||||
@@ -147,6 +147,9 @@ object CobblemonEvents {
|
||||
@JvmField
|
||||
val STARTER_CHOSEN = CancelableObservable<StarterChosenEvent>()
|
||||
|
||||
@JvmField
|
||||
val POKEMON_SCANNED = EventObservable<PokemonScannedEvent>()
|
||||
|
||||
@JvmField
|
||||
val APRICORN_HARVESTED = EventObservable<ApricornHarvestEvent>()
|
||||
// Berries
|
||||
@@ -166,4 +169,9 @@ object CobblemonEvents {
|
||||
val HELD_ITEM_PRE = CancelableObservable<HeldItemEvent.Pre>()
|
||||
@JvmField
|
||||
val HELD_ITEM_POST = EventObservable<HeldItemEvent.Post>()
|
||||
}
|
||||
|
||||
@JvmField
|
||||
val POKEMON_GAINED = EventObservable<PokemonGainedEvent>()
|
||||
@JvmField
|
||||
val POKEMON_SEEN = EventObservable<PokemonSeenEvent>()
|
||||
}
|
||||
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.events.pokedex.scanning
|
||||
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
|
||||
data class PokemonScannedEvent(val player: ServerPlayer, val scannedEntity: PokemonEntity) {
|
||||
val pokemon: Pokemon
|
||||
get() = scannedEntity.pokemon
|
||||
|
||||
val isOwned: Boolean
|
||||
get() = pokemon.getOwnerPlayer() == player
|
||||
}
|
||||
@@ -10,5 +10,5 @@ package com.cobblemon.mod.common.api.events.pokemon
|
||||
|
||||
//data class HatchEggEvent (
|
||||
// val pokemon: Pokemon,
|
||||
// val player: ServerPlayerEntity
|
||||
// val player: ServerPlayer
|
||||
//)
|
||||
+7
-6
@@ -6,12 +6,13 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.storage.player.adapter
|
||||
package com.cobblemon.mod.common.api.events.pokemon
|
||||
|
||||
import com.cobblemon.mod.common.api.storage.player.PlayerData
|
||||
import java.util.*
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import java.util.UUID
|
||||
|
||||
interface PlayerDataStoreAdapter {
|
||||
fun load(uuid: UUID): PlayerData
|
||||
fun save(playerData: PlayerData)
|
||||
data class PokemonGainedEvent(
|
||||
val playerId: UUID,
|
||||
val pokemon: Pokemon
|
||||
) {
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.events.pokemon
|
||||
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import java.util.UUID
|
||||
|
||||
data class PokemonSeenEvent(
|
||||
val playerId: UUID,
|
||||
val pokemon: Pokemon
|
||||
) {
|
||||
}
|
||||
@@ -29,7 +29,7 @@ data class PokeRod(
|
||||
val pokeBallId: ResourceLocation,
|
||||
//Hex string of color
|
||||
val lineColor: String,
|
||||
var name: ResourceLocation// ?// TODO (techdaan) Why was this nullable?
|
||||
var name: ResourceLocation
|
||||
) {
|
||||
internal fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeIdentifier(name)
|
||||
|
||||
@@ -17,4 +17,6 @@ object ColourLibrary {
|
||||
const val SIDE_1_ALLY_BATTLE_COLOUR = 0x34C2AC
|
||||
const val SIDE_2_BATTLE_COLOUR = 0xE43838
|
||||
const val SIDE_2_ALLY_BATTLE_COLOUR = 0xD55ABA
|
||||
|
||||
const val BATTLE_COMMAND_COLOUR = 0xEBBA15
|
||||
}
|
||||
@@ -16,6 +16,8 @@ import com.cobblemon.mod.common.client.render.models.blockbench.repository.Pokem
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.RenderContext
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.util.toHex
|
||||
import com.mojang.authlib.minecraft.client.MinecraftClient
|
||||
import com.mojang.blaze3d.platform.GlStateManager
|
||||
import com.mojang.blaze3d.platform.Lighting
|
||||
import com.mojang.blaze3d.systems.RenderSystem
|
||||
@@ -96,8 +98,6 @@ fun drawRectangle(
|
||||
bufferbuilder.addVertex(matrix, endX, endY, blitOffset).setUv(maxU, maxV)
|
||||
bufferbuilder.addVertex(matrix, endX, y, blitOffset).setUv(maxU, minV)
|
||||
bufferbuilder.addVertex(matrix, x, y, blitOffset).setUv(minU, minV)
|
||||
// TODO: Figure out if this is correct replacement.
|
||||
// OLD: BufferRenderer.draw(bufferbuilder)
|
||||
BufferUploader.drawWithShader(bufferbuilder.buildOrThrow())
|
||||
}
|
||||
|
||||
@@ -148,6 +148,21 @@ fun drawText(
|
||||
return isHovered
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
fun drawTextJustifiedRight(
|
||||
context: GuiGraphics,
|
||||
font: ResourceLocation? = null,
|
||||
text: MutableComponent,
|
||||
x: Number,
|
||||
y: Number,
|
||||
colour: Int,
|
||||
shadow: Boolean = true
|
||||
) {
|
||||
val comp = text.let { if (font != null) it.font(font) else it }
|
||||
val font = Minecraft.getInstance().font
|
||||
context.drawString(font, comp, x.toInt() - font.width(comp), y.toInt(), colour, shadow)
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
fun drawText(
|
||||
context: GuiGraphics,
|
||||
@@ -189,7 +204,6 @@ fun drawString(
|
||||
@JvmOverloads
|
||||
fun drawPosablePortrait(
|
||||
identifier: ResourceLocation,
|
||||
aspects: Set<String>,
|
||||
matrixStack: PoseStack,
|
||||
scale: Float = 13F,
|
||||
contextScale: Float = 1F,
|
||||
@@ -201,7 +215,11 @@ fun drawPosablePortrait(
|
||||
limbSwingAmount: Float = 0F,
|
||||
ageInTicks: Float = 0F,
|
||||
headYaw: Float = 0F,
|
||||
headPitch: Float = 0F
|
||||
headPitch: Float = 0F,
|
||||
r: Float = 1F,
|
||||
g: Float = 1F,
|
||||
b: Float = 1F,
|
||||
a: Float = 1F
|
||||
) {
|
||||
RenderSystem.applyModelViewMatrix()
|
||||
matrixStack.pushPose()
|
||||
@@ -209,21 +227,19 @@ fun drawPosablePortrait(
|
||||
matrixStack.scale(scale, scale, -scale)
|
||||
matrixStack.translate(0.0, -PORTRAIT_DIAMETER / 18.0, 0.0)
|
||||
|
||||
val sprite = repository.getSprite(identifier, aspects, SpriteType.PORTRAIT);
|
||||
val sprite = repository.getSprite(identifier, state, SpriteType.PORTRAIT);
|
||||
|
||||
if(sprite == null) {
|
||||
|
||||
val model = repository.getPoser(identifier, aspects)
|
||||
state.currentAspects = aspects
|
||||
if (sprite == null) {
|
||||
val model = repository.getPoser(identifier, state)
|
||||
state.currentModel = model
|
||||
val texture = repository.getTexture(identifier, aspects, state.animationSeconds)
|
||||
val texture = repository.getTexture(identifier, state)
|
||||
|
||||
val context = RenderContext()
|
||||
model.context = context
|
||||
repository.getTextureNoSubstitute(identifier, aspects, 0f).let { context.put(RenderContext.TEXTURE, it) }
|
||||
repository.getTextureNoSubstitute(identifier, state).let { context.put(RenderContext.TEXTURE, it) }
|
||||
context.put(RenderContext.SCALE, contextScale)
|
||||
context.put(RenderContext.SPECIES, identifier)
|
||||
context.put(RenderContext.ASPECTS, aspects)
|
||||
context.put(RenderContext.ASPECTS, state.currentAspects)
|
||||
context.put(RenderContext.POSABLE_STATE, state)
|
||||
|
||||
val renderType = RenderType.entityCutout(texture)
|
||||
@@ -243,7 +259,7 @@ fun drawPosablePortrait(
|
||||
model.portraitTranslation.z - 4
|
||||
)
|
||||
matrixStack.scale(model.portraitScale, model.portraitScale, 1 / model.portraitScale)
|
||||
matrixStack.mulPose(quaternion1) // TODO (techdaan): correct?
|
||||
matrixStack.mulPose(quaternion1)
|
||||
matrixStack.mulPose(quaternion2)
|
||||
|
||||
val light1 = Vector3f(0.2F, 1.0F, -1.0F)
|
||||
@@ -255,8 +271,9 @@ fun drawPosablePortrait(
|
||||
val buffer = immediate.getBuffer(renderType)
|
||||
val packedLight = LightTexture.pack(11, 7)
|
||||
|
||||
model.withLayerContext(immediate, state, repository.getLayers(identifier, aspects)) {
|
||||
model.render(context, matrixStack, buffer, packedLight, OverlayTexture.NO_OVERLAY, -0x1)
|
||||
val colour = toHex(r, g, b, a)
|
||||
model.withLayerContext(immediate, state, repository.getLayers(identifier, state)) {
|
||||
model.render(context, matrixStack, buffer, packedLight, OverlayTexture.NO_OVERLAY, colour)
|
||||
immediate.endBatch()
|
||||
}
|
||||
|
||||
@@ -273,7 +290,6 @@ fun drawPosablePortrait(
|
||||
fun drawProfile(
|
||||
repository: VaryingModelRepository<*>,
|
||||
resourceIdentifier: ResourceLocation,
|
||||
aspects: Set<String>,
|
||||
matrixStack: PoseStack,
|
||||
state: PosableState,
|
||||
partialTicks: Float,
|
||||
@@ -282,22 +298,20 @@ fun drawProfile(
|
||||
RenderSystem.applyModelViewMatrix()
|
||||
matrixStack.scale(scale, scale, -scale)
|
||||
|
||||
val sprite = repository.getSprite(resourceIdentifier, aspects, SpriteType.PROFILE);
|
||||
val sprite = repository.getSprite(resourceIdentifier, state, SpriteType.PROFILE)
|
||||
|
||||
if(sprite == null) {
|
||||
if (sprite == null) {
|
||||
|
||||
val model = repository.getPoser(resourceIdentifier, aspects)
|
||||
val texture = repository.getTexture(resourceIdentifier, aspects, state.animationSeconds)
|
||||
val model = repository.getPoser(resourceIdentifier, state)
|
||||
val texture = repository.getTexture(resourceIdentifier, state)
|
||||
|
||||
val context = RenderContext()
|
||||
model.context = context
|
||||
repository.getTextureNoSubstitute(resourceIdentifier, aspects, 0f)
|
||||
.let { context.put(RenderContext.TEXTURE, it) }
|
||||
repository.getTextureNoSubstitute(resourceIdentifier, state).let { context.put(RenderContext.TEXTURE, it) }
|
||||
context.put(RenderContext.SCALE, 1F)
|
||||
context.put(RenderContext.SPECIES, resourceIdentifier)
|
||||
context.put(RenderContext.ASPECTS, aspects)
|
||||
context.put(RenderContext.ASPECTS, state.currentAspects)
|
||||
context.put(RenderContext.POSABLE_STATE, state)
|
||||
state.currentAspects = aspects
|
||||
state.currentModel = model
|
||||
|
||||
val renderType = RenderType.entityCutout(texture)//model.getLayer(texture)
|
||||
@@ -312,7 +326,7 @@ fun drawProfile(
|
||||
val quaternion2 = Axis.XP.rotationDegrees(5F)
|
||||
matrixStack.mulPose(quaternion1)
|
||||
matrixStack.mulPose(quaternion2)
|
||||
Lighting.setupForEntityInInventory() // TODO (techdaan): Does this map correctly?
|
||||
Lighting.setupForEntityInInventory()
|
||||
val entityRenderDispatcher = Minecraft.getInstance().entityRenderDispatcher
|
||||
entityRenderDispatcher.setRenderShadow(true)
|
||||
|
||||
@@ -323,7 +337,7 @@ fun drawProfile(
|
||||
RenderSystem.setShaderLights(light1, light2)
|
||||
val packedLight = LightTexture.pack(11, 7)
|
||||
|
||||
model.withLayerContext(bufferSource, state, repository.getLayers(resourceIdentifier, aspects)) {
|
||||
model.withLayerContext(bufferSource, state, repository.getLayers(resourceIdentifier, state)) {
|
||||
model.render(context, matrixStack, buffer, packedLight, OverlayTexture.NO_OVERLAY, -0x1)
|
||||
bufferSource.endBatch()
|
||||
}
|
||||
|
||||
@@ -41,20 +41,27 @@ class MultiLineLabelK(
|
||||
fun renderLeftAligned(
|
||||
context: GuiGraphics,
|
||||
x: Number, y: Number,
|
||||
YStartOffset: Number = 0,
|
||||
ySpacing: Number,
|
||||
colour: Int,
|
||||
scale: Float = 1F,
|
||||
shadow: Boolean = true
|
||||
) {
|
||||
context.pose().pushPose()
|
||||
context.pose().scale(scale, scale, 1F)
|
||||
comps.forEachIndexed { index, textWithWidth ->
|
||||
val yOffset = if (index == 0) YStartOffset else 0
|
||||
drawString(
|
||||
context = context,
|
||||
x = x, y = y.toFloat() + ySpacing.toFloat() * index,
|
||||
x = x.toFloat() / scale,
|
||||
y = (y.toFloat() + yOffset.toFloat() + ySpacing.toFloat() * index) / scale,
|
||||
colour = colour,
|
||||
shadow = shadow,
|
||||
text = textWithWidth.text.string,
|
||||
font = font
|
||||
)
|
||||
}
|
||||
context.pose().popPose()
|
||||
}
|
||||
|
||||
class TextWithWidth internal constructor(val text: FormattedText, val width: Int)
|
||||
|
||||
@@ -97,8 +97,9 @@ interface PokemonSelectingItem {
|
||||
battlePokemon.actor.forceChoose(BagItemActionResponse(bagItem, battlePokemon))
|
||||
if (!player.isCreative) {
|
||||
stack.shrink(1)
|
||||
battlePokemon.actor.itemsUsed.add(bagItem)
|
||||
}
|
||||
CobblemonCriteria.POKEMON_INTERACT.trigger(player, PokemonInteractContext(battlePokemon.entity!!.pokemon.species.resourceIdentifier, BuiltInRegistries.ITEM.getKey(stack.item)))
|
||||
CobblemonCriteria.POKEMON_INTERACT.trigger(player, PokemonInteractContext(battlePokemon.effectedPokemon.species.resourceIdentifier, BuiltInRegistries.ITEM.getKey(stack.item)))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,8 @@ package com.cobblemon.mod.common.api.molang
|
||||
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.bedrockk.molang.runtime.value.MoValue
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.mojang.serialization.Codec
|
||||
|
||||
/**
|
||||
* An object that can be given a [MoLangRuntime] to produce a single [MoValue]. This abstracts
|
||||
@@ -21,7 +23,7 @@ import com.bedrockk.molang.runtime.value.MoValue
|
||||
interface ExpressionLike {
|
||||
override fun toString(): String
|
||||
/** Produces a [MoValue] for a [MoLangRuntime] to supply an environment. */
|
||||
fun resolve(runtime: MoLangRuntime, context: Map<String, MoValue> = emptyMap()): MoValue
|
||||
fun resolve(runtime: MoLangRuntime, context: Map<String, MoValue> = runtime.environment.context?.map ?: hashMapOf()): MoValue
|
||||
fun getString(): String = toString()
|
||||
|
||||
fun resolveDouble(runtime: MoLangRuntime) = resolve(runtime).asDouble()
|
||||
@@ -31,4 +33,11 @@ interface ExpressionLike {
|
||||
fun resolveBoolean(runtime: MoLangRuntime) = resolveDouble(runtime) == 1.0
|
||||
fun resolveObject(runtime: MoLangRuntime) = resolve(runtime) as ObjectValue<*>
|
||||
|
||||
companion object {
|
||||
val CODEC: Codec<ExpressionLike> = Codec.STRING.xmap({
|
||||
it.asExpressionLike()
|
||||
}) {
|
||||
it.getString()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,23 +18,25 @@ import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.bedrockk.molang.runtime.value.MoValue
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonActivities
|
||||
import com.cobblemon.mod.common.CobblemonBlockEntities
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
|
||||
import com.cobblemon.mod.common.api.dialogue.PlayerDialogueFaceProvider
|
||||
import com.cobblemon.mod.common.api.dialogue.ReferenceDialogueFaceProvider
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffectContext
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffects
|
||||
import com.cobblemon.mod.common.api.moves.animations.NPCProvider
|
||||
import com.cobblemon.mod.common.api.scripting.CobblemonScripts
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.wavefunction.WaveFunctions
|
||||
import com.cobblemon.mod.common.entity.npc.NPCEntity
|
||||
import com.cobblemon.mod.common.net.messages.client.effect.RunPosableMoLangPacket
|
||||
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
|
||||
import com.cobblemon.mod.common.util.effectiveName
|
||||
import com.cobblemon.mod.common.util.getBooleanOrNull
|
||||
import com.cobblemon.mod.common.util.getDoubleOrNull
|
||||
import com.cobblemon.mod.common.util.isInt
|
||||
import com.cobblemon.mod.common.util.itemRegistry
|
||||
import com.cobblemon.mod.common.util.worldRegistry
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.util.*
|
||||
import com.mojang.datafixers.util.Either
|
||||
import net.minecraft.client.gui.components.tabs.Tab
|
||||
import java.util.UUID
|
||||
import net.minecraft.commands.arguments.EntityAnchorArgument
|
||||
import net.minecraft.core.Holder
|
||||
import net.minecraft.core.Registry
|
||||
import net.minecraft.core.registries.Registries
|
||||
@@ -44,10 +46,9 @@ import net.minecraft.nbt.ListTag
|
||||
import net.minecraft.nbt.StringTag
|
||||
import net.minecraft.nbt.Tag
|
||||
import net.minecraft.resources.ResourceKey
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.commands.TagCommand
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.tags.TagKey
|
||||
import net.minecraft.world.damagesource.DamageSource
|
||||
import net.minecraft.world.damagesource.DamageTypes
|
||||
@@ -57,6 +58,8 @@ import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.biome.Biome
|
||||
import net.minecraft.world.level.block.Block
|
||||
import net.minecraft.world.level.dimension.DimensionType
|
||||
import net.minecraft.world.phys.AABB
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
/**
|
||||
* Holds a bunch of useful MoLang trickery that can be used or extended in API
|
||||
@@ -101,6 +104,12 @@ object MoLangFunctions {
|
||||
runtime.environment.context = params.environment.context
|
||||
val script = params.getString(0).asIdentifierDefaultingNamespace()
|
||||
CobblemonScripts.run(script, runtime) ?: DoubleValue(0)
|
||||
},
|
||||
"run_command" to java.util.function.Function { params ->
|
||||
val command = params.getString(0)
|
||||
server()?.let {
|
||||
return@Function DoubleValue(it.commands.dispatcher.execute(command, it.createCommandSourceStack()))
|
||||
} ?: return@Function DoubleValue.ZERO
|
||||
}
|
||||
)
|
||||
val biomeFunctions = hashMapOf<String, java.util.function.Function<MoParams, Any>>()
|
||||
@@ -116,10 +125,11 @@ object MoLangFunctions {
|
||||
map.put("save_data") { _ -> if (player is ServerPlayer) Cobblemon.molangData.save(player.uuid) else DoubleValue(0) }
|
||||
map.put("main_held_item") { _ -> player.level().itemRegistry.wrapAsHolder(player.mainHandItem.item).asMoLangValue(Registries.ITEM) }
|
||||
map.put("off_held_item") { _ -> player.level().itemRegistry.wrapAsHolder(player.offhandItem.item).asMoLangValue(Registries.ITEM) }
|
||||
map.put("face") { _ -> ObjectValue(PlayerDialogueFaceProvider(player.uuid)) }
|
||||
map.put("face") { params -> ObjectValue(PlayerDialogueFaceProvider(player.uuid, params.getBooleanOrNull(0) != false)) }
|
||||
map.put("swing_hand") { _ -> player.swing(player.usedItemHand) }
|
||||
map.put("food_level") { _ -> DoubleValue(player.foodData.foodLevel) }
|
||||
map.put("saturation_level") { _ -> DoubleValue(player.foodData.saturationLevel) }
|
||||
// map.put("has_permission") { params -> DoubleValue(Cobblemon.permissionValidator.hasPermission(player, Permission)) }
|
||||
map.put("tell") { params ->
|
||||
val message = params.getString(0).text()
|
||||
val overlay = params.getBooleanOrNull(1) ?: false
|
||||
@@ -141,12 +151,35 @@ object MoLangFunctions {
|
||||
environment.query = player.asMoLangValue()
|
||||
environment
|
||||
}
|
||||
if (player is ServerPlayer) {
|
||||
map.put("is_party_at_full_health") { _ ->
|
||||
DoubleValue(player.party().none(Pokemon::canBeHealed)) }
|
||||
map.put("can_heal_at_healer") { params ->
|
||||
val pos = params.get<ArrayStruct>(0).asBlockPos()
|
||||
val healer = player.level().getBlockEntity(pos, CobblemonBlockEntities.HEALING_MACHINE).orElse(null) ?: return@put DoubleValue.ZERO
|
||||
val party = player.party()
|
||||
return@put DoubleValue(healer.canHeal(party))
|
||||
}
|
||||
map.put("put_pokemon_in_healer") { params ->
|
||||
val healer = player.level()
|
||||
.getBlockEntity(params.get<ArrayStruct>(0).asBlockPos(), CobblemonBlockEntities.HEALING_MACHINE)
|
||||
.orElse(null) ?: return@put DoubleValue.ZERO
|
||||
val party = player.party()
|
||||
if (healer.canHeal(party)) {
|
||||
healer.activate(player.uuid, party)
|
||||
return@put DoubleValue.ONE
|
||||
} else {
|
||||
return@put DoubleValue.ZERO
|
||||
}
|
||||
}
|
||||
}
|
||||
map
|
||||
}
|
||||
)
|
||||
val entityFunctions = mutableListOf<(LivingEntity) -> HashMap<String, java.util.function.Function<MoParams, Any>>>(
|
||||
{ entity ->
|
||||
val map = hashMapOf<String, java.util.function.Function<MoParams, Any>>()
|
||||
map.put("uuid") { _ -> StringValue(entity.uuid.toString()) }
|
||||
map.put("damage") { params ->
|
||||
val amount = params.getDouble(0)
|
||||
val source = DamageSource(entity.level().registryAccess().registryOrThrow(Registries.DAMAGE_TYPE).getHolder(DamageTypes.GENERIC).get())
|
||||
@@ -178,15 +211,34 @@ object MoLangFunctions {
|
||||
map.put("is_on_ground") { _ -> DoubleValue(entity.onGround()) }
|
||||
map.put("world") { _ -> entity.level().worldRegistry.wrapAsHolder(entity.level()).asWorldMoLangValue() }
|
||||
map.put("biome") { _ -> entity.level().getBiome(entity.blockPosition()).asBiomeMoLangValue() }
|
||||
map.put("is_healer_in_use") { params ->
|
||||
val pos = params.get<ArrayStruct>(0).asBlockPos()
|
||||
val healer = entity.level().getBlockEntity(pos, CobblemonBlockEntities.HEALING_MACHINE).orElse(null) ?: return@put DoubleValue.ONE
|
||||
return@put DoubleValue(healer.isInUse)
|
||||
}
|
||||
map.put("find_nearby_block") { params ->
|
||||
val type = params.getString(0).asIdentifierDefaultingNamespace(namespace = "minecraft")
|
||||
val isTag = type.path.startsWith("#")
|
||||
val range = params.getDoubleOrNull(1) ?: 10
|
||||
val blockPos = entity.level().getBlockStatesWithPos(AABB.ofSize(entity.position(), range.toDouble(), range.toDouble(), range.toDouble()))
|
||||
.filter { it.first.blockHolder.let { if (isTag) it.`is`(TagKey.create(Registries.BLOCK, type)) else it.`is`(type) } }
|
||||
.minByOrNull { it.second.distSqr(entity.blockPosition()) }
|
||||
?.second
|
||||
if (blockPos != null) {
|
||||
return@put ArrayStruct(mapOf("0" to DoubleValue(blockPos.x), "1" to DoubleValue(blockPos.y), "2" to DoubleValue(blockPos.z)))
|
||||
} else {
|
||||
return@put DoubleValue.ZERO
|
||||
}
|
||||
}
|
||||
map
|
||||
}
|
||||
)
|
||||
val npcFunctions = mutableListOf<(NPCEntity) -> HashMap<String, java.util.function.Function<MoParams, Any>>>(
|
||||
{ npc ->
|
||||
val map = hashMapOf<String, java.util.function.Function<MoParams, Any>>()
|
||||
map.put("class") { StringValue(npc.npc.resourceIdentifier.toString()) }
|
||||
map.put("class") { StringValue(npc.npc.id.toString()) }
|
||||
map.put("name") { StringValue(npc.name.string) }
|
||||
map.put("face") { ObjectValue(ReferenceDialogueFaceProvider(npc.id)) }
|
||||
map.put("face") { params -> ObjectValue(ReferenceDialogueFaceProvider(npc.id, params.getBooleanOrNull(0) != false)) }
|
||||
map.put("in_battle") { DoubleValue(npc.isInBattle()) }
|
||||
map.put("run_script_on_client") { params ->
|
||||
val world = npc.level()
|
||||
@@ -199,13 +251,50 @@ object MoLangFunctions {
|
||||
}
|
||||
map.put("run_script") { params ->
|
||||
val script = params.getString(0).asIdentifierDefaultingNamespace()
|
||||
val environment = params.environment
|
||||
val runtime = MoLangRuntime()
|
||||
runtime.environment.query = environment.query
|
||||
runtime.environment.variable = environment.variable
|
||||
runtime.environment.context = environment.context
|
||||
runtime.environment.cloneFrom(params.environment)
|
||||
CobblemonScripts.run(script, runtime) ?: DoubleValue(0)
|
||||
}
|
||||
map.put("run_action_effect") { params ->
|
||||
val runtime = MoLangRuntime().setup()
|
||||
runtime.environment.cloneFrom(params.environment)
|
||||
runtime.withNPCValue(value = npc)
|
||||
val actionEffect = ActionEffects.actionEffects[params.getString(0).asIdentifierDefaultingNamespace()]
|
||||
if (actionEffect != null) {
|
||||
val context = ActionEffectContext(
|
||||
actionEffect = actionEffect,
|
||||
providers = mutableListOf(NPCProvider(npc)),
|
||||
runtime = runtime
|
||||
)
|
||||
npc.actionEffect = context
|
||||
npc.brain.setMemory(CobblemonMemories.ACTIVE_ACTION_EFFECT, context)
|
||||
npc.brain.setActiveActivityIfPossible(CobblemonActivities.NPC_ACTION_EFFECT)
|
||||
actionEffect.run(context).thenRun {
|
||||
val npcActionEffect = npc.brain.getMemory(CobblemonMemories.ACTIVE_ACTION_EFFECT).orElse(null)
|
||||
if (npcActionEffect == context && npc.brain.isActive(CobblemonActivities.NPC_ACTION_EFFECT)) {
|
||||
npc.brain.eraseMemory(CobblemonMemories.ACTIVE_ACTION_EFFECT)
|
||||
npc.actionEffect = null
|
||||
}
|
||||
}
|
||||
|
||||
return@put DoubleValue(1)
|
||||
}
|
||||
return@put DoubleValue(0)
|
||||
}
|
||||
map.put("put_pokemon_in_healer") { params ->
|
||||
val healer = npc.level().getBlockEntity(params.get<ArrayStruct>(0).asBlockPos(), CobblemonBlockEntities.HEALING_MACHINE).orElse(null) ?: return@put DoubleValue.ZERO
|
||||
val party = npc.staticParty ?: return@put DoubleValue.ZERO
|
||||
if (healer.canHeal(party)) {
|
||||
healer.activate(npc.uuid, party)
|
||||
return@put DoubleValue.ONE
|
||||
} else {
|
||||
return@put DoubleValue.ZERO
|
||||
}
|
||||
}
|
||||
map.put("look_at_position") { params ->
|
||||
val pos = Vec3(params.getDouble(0), params.getDouble(1), params.getDouble(2))
|
||||
npc.lookAt(EntityAnchorArgument.Anchor.EYES, pos)
|
||||
}
|
||||
map.put("environment") { _ -> npc.runtime.environment }
|
||||
map
|
||||
}
|
||||
@@ -220,6 +309,11 @@ object MoLangFunctions {
|
||||
map.put("is_pvw") { DoubleValue(battle.isPvW) }
|
||||
map.put("battle_type") { StringValue(battle.format.toString()) }
|
||||
map.put("environment") { battle.runtime.environment }
|
||||
map.put("get_actor") { params ->
|
||||
val uuid = UUID.fromString(params.getString(0))
|
||||
val actor = battle.actors.find { it.uuid == uuid } ?: return@put DoubleValue.ZERO
|
||||
return@put actor.struct
|
||||
}
|
||||
map
|
||||
}
|
||||
)
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
package com.cobblemon.mod.common.api.molang
|
||||
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.bedrockk.molang.runtime.value.MoValue
|
||||
|
||||
/**
|
||||
@@ -20,7 +21,7 @@ import com.bedrockk.molang.runtime.value.MoValue
|
||||
class ObjectValue<T>(
|
||||
var obj: T,
|
||||
val stringify: (T) -> String = { it.toString() },
|
||||
val doublify: (T) -> Double = { throw NotImplementedError("Doublify not implemented for this object value, are you doing weird molang") }
|
||||
val doublify: (T) -> Double = { DoubleValue.ONE.value }
|
||||
) : QueryStruct(hashMapOf()) {
|
||||
override fun value() = this
|
||||
override fun asDouble() = doublify(obj)
|
||||
|
||||
@@ -118,6 +118,8 @@ open class Move(
|
||||
return json
|
||||
}
|
||||
|
||||
fun copy() = loadFromJSON(saveToJSON(JsonObject()))
|
||||
|
||||
fun saveToBuffer(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeString(name)
|
||||
buffer.writeSizedInt(IntSize.U_BYTE, currentPp)
|
||||
|
||||
@@ -35,10 +35,8 @@ class MoveSet : Iterable<Move> {
|
||||
/**
|
||||
* Gets all Moves from the Pokémon but skips null Moves
|
||||
*/
|
||||
fun getMoves(): List<Move> {
|
||||
return moves.filterNotNull()
|
||||
}
|
||||
|
||||
fun getMoves() = moves.filterNotNull()
|
||||
fun getMovesWithNulls() = moves.toList()
|
||||
fun hasSpace() = moves.any { it == null }
|
||||
|
||||
/**
|
||||
@@ -56,7 +54,7 @@ class MoveSet : Iterable<Move> {
|
||||
fun copyFrom(other: MoveSet) {
|
||||
doWithoutEmitting {
|
||||
clear()
|
||||
other.getMoves().forEach { add(it) }
|
||||
other.getMoves().forEach { add(it.copy()) }
|
||||
}
|
||||
update()
|
||||
}
|
||||
@@ -125,6 +123,7 @@ class MoveSet : Iterable<Move> {
|
||||
for (i in 0 until MOVE_COUNT) {
|
||||
if (moves[i] == null) {
|
||||
moves[i] = move
|
||||
move.observable.subscribe { this.update() }
|
||||
update()
|
||||
return
|
||||
}
|
||||
|
||||
+7
-4
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.api.moves.animations
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.api.moves.animations.keyframes.ActionEffectKeyframe
|
||||
import com.cobblemon.mod.common.entity.npc.NPCEntity
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
import net.minecraft.world.entity.Entity
|
||||
@@ -38,7 +39,7 @@ class ActionEffectTimeline(
|
||||
CompletableFuture.completedFuture(Unit)
|
||||
} else {
|
||||
val finalFuture = CompletableFuture<Unit>()
|
||||
// .toList copy because I'm paranoid about iterators being trying to share between identical effects playing
|
||||
// .toList copy because I'm paranoid about iterators trying to share between identical effects playing
|
||||
chainKeyframes(context, timeline.toList().iterator(), finalFuture)
|
||||
finalFuture
|
||||
}.exceptionallyCompose {
|
||||
@@ -71,8 +72,6 @@ class ActionEffectContext(
|
||||
var currentKeyframes: MutableList<ActionEffectKeyframe> = mutableListOf()
|
||||
) {
|
||||
inline fun <reified T> findOneProvider() = providers.filterIsInstance<T>().firstOrNull()
|
||||
|
||||
|
||||
}
|
||||
|
||||
class UsersProvider(users: List<Entity>): EntityProvider {
|
||||
@@ -85,12 +84,16 @@ class TargetsProvider(targets: List<Entity>): EntityProvider {
|
||||
constructor(vararg targets: Entity): this(targets.toList())
|
||||
}
|
||||
|
||||
class NPCProvider(npc: NPCEntity): EntityProvider {
|
||||
override val entities = listOf(npc)
|
||||
}
|
||||
|
||||
interface EntityProvider {
|
||||
val entities: List<Entity>
|
||||
}
|
||||
|
||||
//class MoveAnimationKeyframe(
|
||||
// val sound: Identifier? = null,
|
||||
// val sound: ResourceLocation? = null,
|
||||
// val animation: List<AnimationWithMoments> = listOf(),
|
||||
// val effects: List<ActionEffect> = listOf()
|
||||
//)
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ class AnimationActionEffectKeyframe : ConditionalActionEffectKeyframe(), EntityC
|
||||
.filterIsInstance<EntityProvider>()
|
||||
.flatMap { prov -> prov.entities.filter { test(context, it, isUser = prov is UsersProvider) } }
|
||||
|
||||
val expressions = variables.map { it.originalString }.toSet()
|
||||
val expressions = variables.map { it.originalString }
|
||||
|
||||
// Treat them as expressions if possible but otherwise yeah just send them as strings
|
||||
val animation = animation.map {
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ import java.util.concurrent.CompletableFuture
|
||||
|
||||
class CannotInterruptActionEffectKeyframe : ConditionalActionEffectKeyframe() {
|
||||
override fun playWhenTrue(context: ActionEffectContext): CompletableFuture<Unit> {
|
||||
context.canBeInterrupted = true
|
||||
context.canBeInterrupted = false
|
||||
return CompletableFuture.completedFuture(Unit)
|
||||
}
|
||||
}
|
||||
+11
-6
@@ -13,6 +13,7 @@ import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffectContext
|
||||
import com.cobblemon.mod.common.entity.PosableEntity
|
||||
import net.minecraft.world.entity.Entity
|
||||
|
||||
/**
|
||||
@@ -24,12 +25,16 @@ import net.minecraft.world.entity.Entity
|
||||
interface EntityConditionalActionEffectKeyframe {
|
||||
val entityCondition: ExpressionLike
|
||||
fun test(context: ActionEffectContext, entity: Entity, isUser: Boolean): Boolean {
|
||||
// TODO this should use the entity's own query struct
|
||||
context.runtime.environment.query.addFunction("entity") {
|
||||
QueryStruct(hashMapOf())
|
||||
.addFunction("uuid") { StringValue(entity.stringUUID) }
|
||||
.addFunction("is_user") { DoubleValue(isUser) }
|
||||
}
|
||||
context.runtime.environment.query
|
||||
.addFunction("entity") {
|
||||
if (entity is PosableEntity) {
|
||||
entity.struct
|
||||
} else {
|
||||
QueryStruct(hashMapOf())
|
||||
}.addFunction("is_user") { DoubleValue(isUser) } // Deprecated tbh
|
||||
}
|
||||
.addFunction("is_user") { DoubleValue(isUser) }
|
||||
|
||||
return entityCondition.resolveBoolean(context.runtime)
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -45,7 +45,7 @@ class EntityParticlesActionEffectKeyframe : ConditionalActionEffectKeyframe(), E
|
||||
}?.asIdentifierDefaultingNamespace() ?: return skip()
|
||||
|
||||
entities.filter { it is PosableEntity }.forEach { entity ->
|
||||
val packet = SpawnSnowstormEntityParticlePacket(effectIdentifier, entity.id, locator)
|
||||
val packet = SpawnSnowstormEntityParticlePacket(effectIdentifier, entity.id, listOf(locator))
|
||||
val players = (entity.level() as ServerLevel).getPlayers { it.distanceTo(entity) <= visibilityRange }
|
||||
packet.sendToPlayers(players)
|
||||
}
|
||||
|
||||
+2
@@ -8,6 +8,8 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.moves.animations.keyframes
|
||||
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffectContext
|
||||
import com.cobblemon.mod.common.api.scheduling.delayedFuture
|
||||
|
||||
@@ -59,6 +59,8 @@ abstract class MultiblockEntity(
|
||||
}
|
||||
}
|
||||
|
||||
override fun isValidBlockState(blockState: BlockState) = blockState.block is MultiblockBlock
|
||||
|
||||
abstract override fun loadAdditional(nbt: CompoundTag, registryLookup: HolderLookup.Provider)
|
||||
|
||||
}
|
||||
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.net.serializers
|
||||
|
||||
import com.cobblemon.mod.common.entity.npc.NPCPlayerModelType
|
||||
import com.cobblemon.mod.common.entity.npc.NPCPlayerTexture
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.readEnumConstant
|
||||
import com.cobblemon.mod.common.util.writeEnumConstant
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.network.codec.StreamCodec
|
||||
import net.minecraft.network.syncher.EntityDataSerializer
|
||||
|
||||
object NPCPlayerTextureSerializer : EntityDataSerializer<NPCPlayerTexture> {
|
||||
val ID = cobblemonResource("npcplayertexture")
|
||||
|
||||
fun write(buffer: RegistryFriendlyByteBuf, texture: NPCPlayerTexture) {
|
||||
buffer.writeEnumConstant(texture.model)
|
||||
if (texture.model == NPCPlayerModelType.NONE) {
|
||||
return
|
||||
}
|
||||
buffer.writeByteArray(texture.texture)
|
||||
}
|
||||
|
||||
fun read(buffer: RegistryFriendlyByteBuf): NPCPlayerTexture {
|
||||
val model = buffer.readEnumConstant(NPCPlayerModelType::class.java)
|
||||
val texture = if (model == NPCPlayerModelType.NONE) ByteArray(1) else buffer.readByteArray()
|
||||
return NPCPlayerTexture(texture, model)
|
||||
}
|
||||
|
||||
override fun codec() = StreamCodec.of(::write, ::read)
|
||||
override fun copy(texture: NPCPlayerTexture) = NPCPlayerTexture(texture.texture, texture.model)
|
||||
}
|
||||
@@ -11,13 +11,15 @@ package com.cobblemon.mod.common.api.npc
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.bedrockk.molang.runtime.value.MoValue
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.api.npc.configuration.NPCBattleConfiguration
|
||||
import com.cobblemon.mod.common.api.npc.configuration.NPCConfigVariable
|
||||
import com.cobblemon.mod.common.api.npc.configuration.NPCInteractConfiguration
|
||||
import com.cobblemon.mod.common.api.npc.variation.NPCVariationProvider
|
||||
import com.cobblemon.mod.common.api.npc.variation.RandomNPCVariationProvider
|
||||
import com.cobblemon.mod.common.net.IntSize
|
||||
import com.cobblemon.mod.common.util.*
|
||||
import com.mojang.datafixers.util.Either
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.entity.EntityDimensions
|
||||
|
||||
@@ -30,24 +32,49 @@ import net.minecraft.world.entity.EntityDimensions
|
||||
*/
|
||||
class NPCClass {
|
||||
@Transient
|
||||
lateinit var resourceIdentifier: ResourceLocation
|
||||
lateinit var id: ResourceLocation
|
||||
|
||||
var names = mutableListOf(lang("npc.name.default"))
|
||||
var resourceIdentifier: ResourceLocation = cobblemonResource("dummy")
|
||||
var names: MutableList<Component> = mutableListOf()
|
||||
var aspects: MutableSet<String> = mutableSetOf() // These only make sense when applied via presets
|
||||
var hitbox = EntityDimensions.scalable(0.6F, 1.8F)
|
||||
var battleConfiguration = NPCBattleConfiguration()
|
||||
var aiScripts: MutableList<ResourceLocation> = mutableListOf()
|
||||
var interaction: NPCInteractConfiguration? = null
|
||||
var variables = mutableMapOf<String, MoValue>()
|
||||
var variations: MutableMap<String, NPCVariationProvider> = mutableMapOf()
|
||||
var config: MutableList<NPCConfigVariable> = mutableListOf()
|
||||
var variables = mutableMapOf<String, MoValue>() // Questionable whether this should be here.
|
||||
var party: NPCPartyProvider? = null
|
||||
var skill: Int = 0
|
||||
|
||||
// If you're adding stuff here, add it to NPCPreset and NPCClassAdapter too
|
||||
|
||||
fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeString(resourceIdentifier.toString())
|
||||
buffer.writeCollection(names) { _, v -> buffer.writeText(v) }
|
||||
buffer.writeFloat(this.hitbox.width)
|
||||
buffer.writeFloat(this.hitbox.height)
|
||||
buffer.writeBoolean(this.hitbox.fixed)
|
||||
battleConfiguration.encode(buffer)
|
||||
buffer.writeCollection(aiScripts) { _, v -> buffer.writeString(v.toString()) }
|
||||
buffer.writeNullable(interaction) { _, value ->
|
||||
buffer.writeString(value.type)
|
||||
value.encode(buffer)
|
||||
}
|
||||
buffer.writeSizedInt(IntSize.U_BYTE, variations.size)
|
||||
for ((key, value) in variations) {
|
||||
buffer.writeString(key)
|
||||
val aspects = value.aspects
|
||||
buffer.writeCollection(aspects) { _, v -> buffer.writeString(v) }
|
||||
}
|
||||
buffer.writeCollection(config) { _, v ->
|
||||
buffer.writeString(v.variableName)
|
||||
buffer.writeText(v.displayName)
|
||||
buffer.writeText(v.description)
|
||||
buffer.writeEnumConstant(v.type)
|
||||
buffer.writeString(v.defaultValue)
|
||||
}
|
||||
buffer.writeInt(skill)
|
||||
buffer.writeMapK(size = IntSize.U_BYTE, map = variables) { (key, value) ->
|
||||
buffer.writeString(key)
|
||||
buffer.writeString(value.asString())
|
||||
@@ -55,6 +82,7 @@ class NPCClass {
|
||||
}
|
||||
|
||||
fun decode(buffer: RegistryFriendlyByteBuf) {
|
||||
resourceIdentifier = ResourceLocation.parse(buffer.readString().toString())
|
||||
names = buffer.readList { buffer.readText().copy() }.toMutableList()
|
||||
val length = buffer.readFloat()
|
||||
val width = buffer.readFloat()
|
||||
@@ -62,6 +90,7 @@ class NPCClass {
|
||||
hitbox = if (fixed) EntityDimensions.fixed(length, width) else EntityDimensions.scalable(length, width)
|
||||
battleConfiguration = NPCBattleConfiguration()
|
||||
battleConfiguration.decode(buffer)
|
||||
aiScripts = buffer.readList { ResourceLocation.parse(buffer.readString()) }.toMutableList()
|
||||
interaction = buffer.readNullable {
|
||||
val type = buffer.readString()
|
||||
val configType = NPCInteractConfiguration.types[type] ?: return@readNullable null
|
||||
@@ -69,6 +98,22 @@ class NPCClass {
|
||||
instance.decode(buffer)
|
||||
instance
|
||||
}
|
||||
val variationSize = buffer.readSizedInt(IntSize.U_BYTE)
|
||||
for (i in 0 until variationSize) {
|
||||
val key = buffer.readString()
|
||||
val aspects = buffer.readList { buffer.readString() }.toSet()
|
||||
val provider = RandomNPCVariationProvider(aspects)
|
||||
variations[key] = provider
|
||||
}
|
||||
config = buffer.readList {
|
||||
val variableName = buffer.readString()
|
||||
val displayName = buffer.readText()
|
||||
val description = buffer.readText()
|
||||
val type = buffer.readEnumConstant(NPCConfigVariable.NPCVariableType::class.java)
|
||||
val defaultValue = buffer.readString()
|
||||
NPCConfigVariable(variableName, displayName, description, type, defaultValue)
|
||||
}.toMutableList()
|
||||
skill = buffer.readInt()
|
||||
buffer.readMapK(size = IntSize.U_BYTE, map = variables) {
|
||||
val key = buffer.readString()
|
||||
val value = buffer.readString()
|
||||
|
||||
@@ -18,6 +18,8 @@ import com.cobblemon.mod.common.api.drop.ItemDropMethod
|
||||
import com.cobblemon.mod.common.api.entity.EntityDimensionsAdapter
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.api.npc.configuration.NPCInteractConfiguration
|
||||
import com.cobblemon.mod.common.api.npc.variation.NPCVariationProvider
|
||||
import com.cobblemon.mod.common.api.npc.variation.WeightedAspect
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.api.spawning.TimeRange
|
||||
@@ -30,6 +32,7 @@ import com.google.gson.GsonBuilder
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import com.mojang.datafixers.util.Either
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.server.packs.PackType
|
||||
@@ -57,7 +60,12 @@ object NPCClasses : JsonDataRegistry<NPCClass> {
|
||||
.registerTypeAdapter(CompoundTag::class.java, NbtCompoundAdapter)
|
||||
.registerTypeAdapter(NPCPartyProvider::class.java, NPCPartyProviderAdapter)
|
||||
.registerTypeAdapter(NPCInteractConfiguration::class.java, NPCInteractConfigurationAdapter)
|
||||
.registerTypeAdapter(ExpressionLike::class.java, ExpressionLikeAdapter)
|
||||
.registerTypeAdapter(MoValue::class.java, MoValueAdapter)
|
||||
.registerTypeAdapter(NPCClass::class.java, NPCClassAdapter)
|
||||
.registerTypeAdapter(Component::class.java, TextAdapter)
|
||||
.registerTypeAdapter(NPCVariationProvider::class.java, NPCVariationProviderAdapter)
|
||||
.registerTypeAdapter(WeightedAspect::class.java, WeightedAspectAdapter)
|
||||
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Biome::class.java).type, BiomeLikeConditionAdapter)
|
||||
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Block::class.java).type, BlockLikeConditionAdapter)
|
||||
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Item::class.java).type, ItemLikeConditionAdapter)
|
||||
@@ -95,7 +103,7 @@ object NPCClasses : JsonDataRegistry<NPCClass> {
|
||||
/**
|
||||
* Finds an [NPCClass] by its unique [ResourceLocation].
|
||||
*
|
||||
* @param identifier The unique [NPCClass.resourceIdentifier] of the [NPCClass].
|
||||
* @param identifier The unique [NPCClass.id] of the [NPCClass].
|
||||
* @return The [NPCClass] if existing.
|
||||
*/
|
||||
fun getByIdentifier(identifier: ResourceLocation) = this.npcClassesByIdentifier[identifier]
|
||||
@@ -116,10 +124,20 @@ object NPCClasses : JsonDataRegistry<NPCClass> {
|
||||
*/
|
||||
fun random(): NPCClass = this.npcClassesByIdentifier.values.random()
|
||||
|
||||
fun dummy(): NPCClass {
|
||||
val dummy = NPCClass()
|
||||
dummy.id = cobblemonResource("dummy")
|
||||
return dummy
|
||||
}
|
||||
|
||||
override fun reload(data: Map<ResourceLocation, NPCClass>) {
|
||||
this.npcClassesByIdentifier.clear()
|
||||
data.forEach { (identifier, species) ->
|
||||
species.resourceIdentifier = identifier
|
||||
species.id = identifier
|
||||
// shortcut so they don't have to state the resource identifier if they don't wanna
|
||||
if (species.resourceIdentifier.path == "dummy") {
|
||||
species.resourceIdentifier = identifier
|
||||
}
|
||||
this.npcClassesByIdentifier[identifier] = species
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.npc
|
||||
|
||||
import com.cobblemon.mod.common.api.npc.partyproviders.DynamicPartyProvider
|
||||
import com.cobblemon.mod.common.api.npc.partyproviders.NPCParty
|
||||
import com.cobblemon.mod.common.api.npc.partyproviders.SimplePartyProvider
|
||||
import com.cobblemon.mod.common.api.storage.party.PartyStore
|
||||
import com.cobblemon.mod.common.entity.npc.NPCEntity
|
||||
@@ -26,16 +28,12 @@ import net.minecraft.server.level.ServerPlayer
|
||||
interface NPCPartyProvider {
|
||||
companion object {
|
||||
val types = mutableMapOf<String, (String) -> NPCPartyProvider>(
|
||||
SimplePartyProvider.TYPE to { SimplePartyProvider() }
|
||||
SimplePartyProvider.TYPE to { SimplePartyProvider() },
|
||||
DynamicPartyProvider.TYPE to { DynamicPartyProvider() }
|
||||
)
|
||||
}
|
||||
|
||||
val type: String
|
||||
fun provide(npc: NPCEntity, challengers: List<ServerPlayer>): PartyStore
|
||||
fun encode(buffer: RegistryFriendlyByteBuf)
|
||||
fun decode(buffer: RegistryFriendlyByteBuf)
|
||||
fun saveToNBT(nbt: CompoundTag)
|
||||
fun loadFromNBT(nbt: CompoundTag)
|
||||
|
||||
fun provide(npc: NPCEntity, level: Int): NPCParty
|
||||
fun loadFromJSON(json: JsonElement)
|
||||
}
|
||||
@@ -8,11 +8,40 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.npc
|
||||
|
||||
import com.cobblemon.mod.common.api.npc.configuration.NPCConfigVariable
|
||||
import com.cobblemon.mod.common.api.npc.configuration.NPCInteractConfiguration
|
||||
import com.cobblemon.mod.common.api.npc.variation.NPCVariationProvider
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.entity.EntityDimensions
|
||||
|
||||
class NPCPreset {
|
||||
lateinit var id: ResourceLocation
|
||||
var resourceIdentifier: ResourceLocation? = null
|
||||
var aspects: Set<String>? = null
|
||||
var variations: Map<String, NPCVariationProvider>? = null
|
||||
var config: List<NPCConfigVariable>? = null
|
||||
var party: NPCPartyProvider? = null
|
||||
// var mergeMode = MergeMode.KEEP
|
||||
var aiScripts: List<ResourceLocation>? = null
|
||||
var interaction: NPCInteractConfiguration? = null
|
||||
var names: MutableSet<Component>? = null
|
||||
var hitbox: EntityDimensions? = null
|
||||
var skill: Int? = null
|
||||
|
||||
fun applyTo(npcClass: NPCClass) {
|
||||
resourceIdentifier?.let { npcClass.resourceIdentifier = it }
|
||||
aspects?.let { npcClass.aspects.addAll(it) }
|
||||
config?.forEach {
|
||||
val variableName = it.variableName
|
||||
npcClass.config.removeIf { it.variableName == variableName }
|
||||
npcClass.config.add(it)
|
||||
}
|
||||
variations?.entries?.forEach { (key, value) -> npcClass.variations[key] = value }
|
||||
party?.let { npcClass.party = it }
|
||||
aiScripts?.let { npcClass.aiScripts.addAll(it) }
|
||||
interaction?.let { npcClass.interaction = it }
|
||||
names?.let { npcClass.names.addAll(it) }
|
||||
hitbox?.let { npcClass.hitbox = it }
|
||||
skill?.let { npcClass.skill = it }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.npc
|
||||
|
||||
import com.bedrockk.molang.runtime.value.MoValue
|
||||
import com.cobblemon.mod.common.api.ai.SleepDepth
|
||||
import com.cobblemon.mod.common.api.conditional.RegistryLikeCondition
|
||||
import com.cobblemon.mod.common.api.data.JsonDataRegistry
|
||||
import com.cobblemon.mod.common.api.drop.DropEntry
|
||||
import com.cobblemon.mod.common.api.drop.ItemDropMethod
|
||||
import com.cobblemon.mod.common.api.entity.EntityDimensionsAdapter
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.api.npc.configuration.NPCInteractConfiguration
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.api.spawning.TimeRange
|
||||
import com.cobblemon.mod.common.util.adapters.*
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import com.mojang.datafixers.util.Either
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.server.packs.PackType
|
||||
import net.minecraft.world.entity.EntityDimensions
|
||||
import net.minecraft.world.item.Item
|
||||
import net.minecraft.world.level.biome.Biome
|
||||
import net.minecraft.world.level.block.Block
|
||||
import net.minecraft.world.phys.AABB
|
||||
|
||||
object NPCPresets : JsonDataRegistry<NPCPreset> {
|
||||
|
||||
override val id = cobblemonResource("npc_preset")
|
||||
override val type = PackType.SERVER_DATA
|
||||
|
||||
override val gson: Gson = GsonBuilder()
|
||||
.registerTypeAdapter(EntityDimensions::class.java, EntityDimensionsAdapter)
|
||||
.registerTypeAdapter(AABB::class.java, BoxAdapter)
|
||||
.registerTypeAdapter(IntRange::class.java, IntRangeAdapter)
|
||||
.registerTypeAdapter(PokemonProperties::class.java, pokemonPropertiesShortAdapter)
|
||||
.registerTypeAdapter(ResourceLocation::class.java, IdentifierAdapter)
|
||||
.registerTypeAdapter(TimeRange::class.java, IntRangesAdapter(TimeRange.timeRanges) { TimeRange(*it) })
|
||||
.registerTypeAdapter(ItemDropMethod::class.java, ItemDropMethod.adapter)
|
||||
.registerTypeAdapter(SleepDepth::class.java, SleepDepth.adapter)
|
||||
.registerTypeAdapter(DropEntry::class.java, DropEntryAdapter)
|
||||
.registerTypeAdapter(CompoundTag::class.java, NbtCompoundAdapter)
|
||||
.registerTypeAdapter(NPCPartyProvider::class.java, NPCPartyProviderAdapter)
|
||||
.registerTypeAdapter(ExpressionLike::class.java, ExpressionLikeAdapter)
|
||||
.registerTypeAdapter(NPCInteractConfiguration::class.java, NPCInteractConfigurationAdapter)
|
||||
.registerTypeAdapter(MoValue::class.java, MoValueAdapter)
|
||||
.registerTypeAdapter(Component::class.java, TextAdapter)
|
||||
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Biome::class.java).type, BiomeLikeConditionAdapter)
|
||||
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Block::class.java).type, BlockLikeConditionAdapter)
|
||||
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Item::class.java).type, ItemLikeConditionAdapter)
|
||||
.registerTypeAdapter(TypeToken.getParameterized(Either::class.java, ResourceLocation::class.java, ExpressionLike::class.java).type, NPCScriptAdapter)
|
||||
.disableHtmlEscaping()
|
||||
.enableComplexMapKeySerialization()
|
||||
.create()
|
||||
|
||||
override val typeToken: TypeToken<NPCPreset> = TypeToken.get(NPCPreset::class.java)
|
||||
override val resourcePath = "npcs"
|
||||
override val observable = SimpleObservable<NPCPresets>()
|
||||
private val npcPresetsByIdentifier = mutableMapOf<ResourceLocation, NPCPreset>()
|
||||
|
||||
override fun sync(player: ServerPlayer) {
|
||||
// TODO probably do want to sync the presets
|
||||
}
|
||||
|
||||
override fun reload(data: Map<ResourceLocation, NPCPreset>) {
|
||||
npcPresetsByIdentifier.clear()
|
||||
npcPresetsByIdentifier.putAll(data)
|
||||
observable.emit(this)
|
||||
}
|
||||
|
||||
fun getPreset(identifier: ResourceLocation): NPCPreset? {
|
||||
return npcPresetsByIdentifier[identifier]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,273 @@
|
||||
# Cobbled NPCs
|
||||
|
||||
NPC's are AI-driven entities that are built on the same identifier-aspects rendering platform
|
||||
as Cobblemon's Pokémon entities. Every NPC in the world is based on an [NPC class](#npc-classes).
|
||||
|
||||
## NPC Classes
|
||||
|
||||
An NPC class is a datapacked JSON (inside the <code>npcs</code> folder) that defines many properties of an NPC in a way that's reusable
|
||||
across any number of individual NPC entities. The possible properties are explained in [NPC Properties](#npc-properties)
|
||||
|
||||
## NPC Class Presets
|
||||
|
||||
For many properties or sets of properties of an NPC class, there may be logical grouping of settings.
|
||||
As an example, many types of trainer NPC classes could share the logic of challenging nearby players
|
||||
that they are able to see. This could become tedious if the same AI script and range config needed to
|
||||
be defined on every NPC class. Not only is it tedious, but if there was some tweak that was made in the
|
||||
underlying logic of that AI, it would need to be updated in every single NPC class JSON that uses it.
|
||||
|
||||
The solution to this is NPC Class Presets, a datapack folder (<code>npc_presets</code>) with JSON files that have an almost identical
|
||||
format to [NPC Classes](#npc-classes), but with every property being nullable. An NPC class can reference
|
||||
any number of presets and the properties of those presets will be merged into the NPC class as it loads.
|
||||
|
||||
## NPC Properties
|
||||
{
|
||||
"hitbox": "player",
|
||||
"resourceIdentifier": "cobblemon:bug_catcher",
|
||||
"presets": [
|
||||
"cobblemon:npc-standard"
|
||||
],
|
||||
"variations": {
|
||||
"dirt": [
|
||||
"clean",
|
||||
"slightly_dirty",
|
||||
"dirty",
|
||||
"filthy"
|
||||
],
|
||||
"net": {
|
||||
"type": "weighted",
|
||||
"options": [
|
||||
{
|
||||
"aspect": "green-net",
|
||||
"weight": 10
|
||||
},
|
||||
{
|
||||
"aspect": "blue-net",
|
||||
"weight": 5
|
||||
},
|
||||
{
|
||||
"aspect": "red-net",
|
||||
"weight": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"config": [
|
||||
{
|
||||
"variableName": "challenge_distance",
|
||||
"displayName": "cobblemon.npc.challenge_distance",
|
||||
"description": "cobblemon.npc.challenge_distance.description",
|
||||
"type": "number",
|
||||
"default": "5"
|
||||
}
|
||||
],
|
||||
"names": [
|
||||
"Vera",
|
||||
"Hiro",
|
||||
"John Cobblemon"
|
||||
],
|
||||
"interaction": {
|
||||
"type": "dialogue",
|
||||
"dialogue": "cobblemon:npc-example"
|
||||
},
|
||||
"battleConfiguration": {
|
||||
"canChallenge": true
|
||||
},
|
||||
"skill": 5,
|
||||
"party": {
|
||||
"type": "simple",
|
||||
"pokemon": [
|
||||
"spiritomb level=1 moves=splash,firepunch,flamethrower,swift",
|
||||
"porygonz level=1 speed_ev=252",
|
||||
"togekiss level=1 nature=timid",
|
||||
"lucario level=1 held_item=cobblemon:focus_sash",
|
||||
"milotic level=1 ability=marvelscale ",
|
||||
"garchomp level=1 hp_iv=31 attack_iv=31"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
### hitbox
|
||||
The hitbox of the NPC, relevant to combat and pathing. This can be defined as an object
|
||||
or as a shortcut string that is predefined in the code. The only currently hardcoded
|
||||
hitbox name is "player", which is the standard Steve Minecraft hitbox and is the same as
|
||||
this fully defined hitbox:
|
||||
|
||||
"hitbox": {
|
||||
"width": 0.6,
|
||||
"height": 1.8
|
||||
}
|
||||
|
||||
### resourceIdentifier
|
||||
An optional property representing the 'identifier' that will be used for rendering the NPC.
|
||||
In a way, this is the same as the "species" of a Pokémon. It is this value combined with
|
||||
whatever aspects have been defined for the NPC that completely handles the appearance of the
|
||||
NPC. This identifier is referenced in the variation JSONs on the client.
|
||||
|
||||
If left blank, it will fallback to the identifier used for the NPC class itself. The reason why
|
||||
this is useful is that it allows several NPC classes to appear the same despite having differences
|
||||
in AI, parties, interactions, etc.
|
||||
|
||||
### presets
|
||||
A list of strings representing the identifiers of [NPC Class Presets](#npc-class-presets) that form the foundation of
|
||||
this NPC class. Any property defined in this class will override the same property in the presets.
|
||||
|
||||
### variations
|
||||
A map of variations that generate the aspects that control the appearance of the NPC. The keys of this
|
||||
map should represent the kind of variation that is being defined, and the values are some kind of [NPC Variation](#npc-variation).
|
||||
|
||||
Variations can be defined in presets and flow through to the NPC class, but they can also be defined
|
||||
in the NPC class. If the same name is used in both a preset and an NPC class, that which is on the NPC
|
||||
class will override that from the preset. If the variation names are different, they will be merged together.
|
||||
|
||||
#### NPC Variation
|
||||
An NPC variation is some way in which aspects can be generated for the NPC. The types of variation can
|
||||
be added using the API, but the type most anticipated is the weighted choice aspects.
|
||||
|
||||
This can be defined as a list of strings, in which case the aspect will be chosen randomly from the list
|
||||
with uniform distribution.
|
||||
|
||||
"dirt": [
|
||||
"clean",
|
||||
"slightly_dirty",
|
||||
"dirty",
|
||||
"filthy"
|
||||
]
|
||||
|
||||
The weighted variation can also be defined more fully, which is necessary if you want some options to be
|
||||
more likely than others.
|
||||
|
||||
"net": {
|
||||
"type": "weighted",
|
||||
"options": [
|
||||
{
|
||||
"aspect": "green-net",
|
||||
"weight": 10
|
||||
},
|
||||
{
|
||||
"aspect": "blue-net",
|
||||
"weight": 5
|
||||
},
|
||||
{
|
||||
"aspect": "red-net",
|
||||
"weight": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
In this example, the "net" value will be "green-net" most of the time, 10 times out of 16. The "blue-net"
|
||||
aspect will be chosen 5 times out of 16, and the "red-net" aspect will be chosen 1 time out of 16.
|
||||
|
||||
When using a type of NPC variation that is not "weighted", the value of "type" must specify it and the
|
||||
other values (instead of "options") will be in whatever format is dictated by that type.
|
||||
|
||||
### config
|
||||
A list of NPC config values that are predefined as being necessary for this class. An NPC config
|
||||
variable's value is used in the MoLang environment of the NPC and can be accessed in any MoLang
|
||||
environment that has the NPC.
|
||||
|
||||
This class property is a way to present clear options to the user if configuring an NPC in-game using
|
||||
the NPC Edit command. This does not mean that NPC variables can only be created when they were defined
|
||||
in the class, but it makes it easier for the user to know what variables should be set and will set
|
||||
the initial values when an NPC is initialized.
|
||||
|
||||
An example situation of using this is if there is an NPC class preset that defines an AI script for
|
||||
challenging a player when they come within a certain range. Inside that class preset, the AI script may
|
||||
need to know at what distance the player will be engaged. This can be defined in the NPC class preset as
|
||||
a config variable, and therefore any NPC class that relies on this preset will have that config variable
|
||||
and present it to users when they setup an NPC of that class.
|
||||
|
||||
"config": [
|
||||
{
|
||||
"variableName": "challenge_distance",
|
||||
"displayName": "cobblemon.npc.challenge_distance",
|
||||
"description": "cobblemon.npc.challenge_distance.description",
|
||||
"type": "number",
|
||||
"default": "5"
|
||||
}
|
||||
]
|
||||
|
||||
The "type" of variable is one of: `string`, `number`, or `boolean`. The type is used to preset a more
|
||||
appropriate input field for the user when they are setting up the NPC.
|
||||
|
||||
### names
|
||||
A list of strings that represent the names that the NPC can have. The name of the NPC is chosen randomly
|
||||
when initialized. These can either be simple names or translation keys so provide localization support.
|
||||
|
||||
### interaction
|
||||
An object that defines how the NPC will handle being interacted with by players. The type of interaction
|
||||
is defined by the "type" property, and different types of interaction have different properties.
|
||||
|
||||
#### dialogue
|
||||
The "dialogue" interaction type is a simple way to have an NPC say something when interacted with. The
|
||||
"dialogue" property should be the identifier of a datapacked dialogue JSON file. The dialogue that is
|
||||
created will have `c.npc` as a contextual property in any script that occurs as part of that dialogue,
|
||||
allowing the dialogue to work with the NPC (including the NPC config values, such as
|
||||
`c.npc.config.challenge_distance`).
|
||||
|
||||
"interaction": {
|
||||
"type": "dialogue",
|
||||
"dialogue": "cobblemon:npc-example"
|
||||
}
|
||||
|
||||
#### script
|
||||
The "script" interaction type is a way to have an NPC run a predefined script when interacted with. The
|
||||
script field is an identifier of a datapacked MoLang script file (in the `scripts` folder).
|
||||
|
||||
"interaction": {
|
||||
"type": "script",
|
||||
"script": "cobblemon:npc-example"
|
||||
}
|
||||
|
||||
#### custom_script
|
||||
The "custom_script" interaction type is a way to have an NPC run the MoLang script defined specifically
|
||||
in this file. The script property can be a single string or an array of strings to do multiline MoLang scripts.
|
||||
|
||||
"interaction": {
|
||||
"type": "custom_script",
|
||||
"script": "c.player.tell('My name is ' + c.npc.name);"
|
||||
}
|
||||
|
||||
### battleConfiguration
|
||||
I don't really know whether this is going to stay tbh
|
||||
|
||||
### skill
|
||||
The skill level when this NPC is used in battle. This is a number from 1 to 5, with 5 being most difficult
|
||||
to beat. This does not control their Pokémon's levels or moves, but it does control how well they use them.
|
||||
|
||||
### party
|
||||
A party provider which generates the party of Pokémon that this NPC will have when in battle. The type of
|
||||
party is defined by the "type", and different types of party have different properties. An NPC party is
|
||||
intended to be initialized when an NPC is spawned and uses a 'seed level'. When spawned using the world
|
||||
spawning system, it will use a seed level that is based on the player's party's average level. When
|
||||
spawned using the NPC command, the seed level can be defined in the command and is otherwise set to 1.
|
||||
|
||||
A party provider produces either 'static' or 'dynamic' parties. A static party is one that is generated
|
||||
when the NPC is initialized and will not change. A dynamic party is one that may be configured using the
|
||||
seed level but can be different any time the NPC is challenged.
|
||||
|
||||
A dynamic party prevents the NPC from doing several actions, such as using healing machines, having
|
||||
persistent health of their party that changes between battles, and keeping their Pokémon out of their
|
||||
balls. This is because the NPC's party is not stored in the world.
|
||||
|
||||
#### simple
|
||||
The "simple" party type is a way to define a party of Pokémon in a simple list format. Each string in the
|
||||
list should be a set of Pokémon properties, as used in commands and spawn files.
|
||||
|
||||
This party provider type is considered 'static'. Any level that is not mentioned in the Pokémon properties
|
||||
will be set to the seed level.
|
||||
|
||||
"party": {
|
||||
"type": "simple",
|
||||
"pokemon": [
|
||||
"spiritomb moves=splash,firepunch,flamethrower,swift",
|
||||
"porygonz speed_ev=252",
|
||||
"togekiss nature=timid",
|
||||
"lucario held_item=cobblemon:focus_sash",
|
||||
"milotic ability=marvelscale ",
|
||||
"garchomp level=100 hp_iv=31 attack_iv=31"
|
||||
]
|
||||
}
|
||||
|
||||
#### dynamic
|
||||
To be implemented
|
||||
+27
-29
@@ -10,8 +10,6 @@ package com.cobblemon.mod.common.api.npc.configuration
|
||||
|
||||
import com.cobblemon.mod.common.api.npc.NPCPartyProvider
|
||||
import com.cobblemon.mod.common.util.DataKeys
|
||||
import com.cobblemon.mod.common.util.readString
|
||||
import com.cobblemon.mod.common.util.writeString
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
|
||||
@@ -25,50 +23,50 @@ class NPCBattleConfiguration {
|
||||
buffer.writeBoolean(canChallenge)
|
||||
buffer.writeBoolean(simultaneousBattles)
|
||||
buffer.writeBoolean(healAfterwards)
|
||||
buffer.writeNullable(party) { _, provider ->
|
||||
buffer.writeString(provider.type)
|
||||
provider.encode(buffer)
|
||||
}
|
||||
// buffer.writeNullable(party) { _, provider ->
|
||||
// buffer.writeString(provider.type)
|
||||
// provider.encode(buffer)
|
||||
// }
|
||||
}
|
||||
|
||||
fun decode(buffer: RegistryFriendlyByteBuf) {
|
||||
canChallenge = buffer.readBoolean()
|
||||
simultaneousBattles = buffer.readBoolean()
|
||||
healAfterwards = buffer.readBoolean()
|
||||
party = buffer.readNullable {
|
||||
val type = buffer.readString()
|
||||
val providerBuilder = NPCPartyProvider.types[type]
|
||||
?: throw IllegalArgumentException("Failed to load NPC party provider of type: $type")
|
||||
|
||||
val decodedParty = providerBuilder(type)
|
||||
decodedParty.decode(buffer)
|
||||
decodedParty
|
||||
}
|
||||
// party = buffer.readNullable {
|
||||
// val type = buffer.readString()
|
||||
// val providerBuilder = NPCPartyProvider.types[type]
|
||||
// ?: throw IllegalArgumentException("Failed to load NPC party provider of type: $type")
|
||||
//
|
||||
// val decodedParty = providerBuilder(type)
|
||||
// decodedParty.decode(buffer)
|
||||
// decodedParty
|
||||
// }
|
||||
}
|
||||
|
||||
fun saveToNBT(nbt: CompoundTag) {
|
||||
nbt.putBoolean(DataKeys.NPC_CAN_CHALLENGE, canChallenge)
|
||||
nbt.putBoolean(DataKeys.NPC_SIMULTANEOUS_BATTLES, simultaneousBattles)
|
||||
nbt.putBoolean(DataKeys.NPC_HEAL_AFTERWARDS, healAfterwards)
|
||||
val party = party
|
||||
if (party != null) {
|
||||
val partyNBT = CompoundTag()
|
||||
partyNBT.putString(DataKeys.NPC_PARTY_TYPE, party.type)
|
||||
party.saveToNBT(partyNBT)
|
||||
nbt.put(DataKeys.NPC_PARTY, partyNBT)
|
||||
}
|
||||
// val party = party
|
||||
// if (party != null) {
|
||||
// val partyNBT = CompoundTag()
|
||||
// partyNBT.putString(DataKeys.NPC_PARTY_TYPE, party.type)
|
||||
// party.saveToNBT(partyNBT)
|
||||
// nbt.put(DataKeys.NPC_PARTY, partyNBT)
|
||||
// }
|
||||
}
|
||||
|
||||
fun loadFromNBT(nbt: CompoundTag) {
|
||||
canChallenge = nbt.getBoolean(DataKeys.NPC_CAN_CHALLENGE)
|
||||
simultaneousBattles = nbt.getBoolean(DataKeys.NPC_SIMULTANEOUS_BATTLES)
|
||||
healAfterwards = nbt.getBoolean(DataKeys.NPC_HEAL_AFTERWARDS)
|
||||
val partyNBT = nbt.getCompound(DataKeys.NPC_PARTY)
|
||||
if (!partyNBT.isEmpty) {
|
||||
val type = partyNBT.getString(DataKeys.NPC_PARTY_TYPE)
|
||||
val providerBuilder = NPCPartyProvider.types[type]
|
||||
?: throw IllegalArgumentException("Failed to load NPC party provider of type: $type")
|
||||
party = providerBuilder(type).also { it.loadFromNBT(partyNBT) }
|
||||
}
|
||||
// val partyNBT = nbt.getCompound(DataKeys.NPC_PARTY)
|
||||
// if (!partyNBT.isEmpty) {
|
||||
// val type = partyNBT.getString(DataKeys.NPC_PARTY_TYPE)
|
||||
// val providerBuilder = NPCPartyProvider.types[type]
|
||||
// ?: throw IllegalArgumentException("Failed to load NPC party provider of type: $type")
|
||||
// party = providerBuilder(type).also { it.loadFromNBT(partyNBT) }
|
||||
// }
|
||||
}
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.npc.configuration
|
||||
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.bedrockk.molang.runtime.value.MoValue
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.entity.npc.NPCEntity
|
||||
import com.cobblemon.mod.common.util.asTranslated
|
||||
import net.minecraft.network.chat.Component
|
||||
|
||||
/**
|
||||
* A predefined variable that will be declared and filled in on any NPC that extends from the class or preset
|
||||
* that specifies this variable. This gives the client a cleaner way to represent a variable that should exist
|
||||
* on the NPC.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since August 14th, 2023
|
||||
*/
|
||||
class NPCConfigVariable(
|
||||
val variableName: String = "variable",
|
||||
val displayName: Component = "Variable".asTranslated(),
|
||||
val description: Component = "A variable that can be used in the NPC's configuration.".asTranslated(),
|
||||
val type: NPCVariableType = NPCVariableType.NUMBER,
|
||||
val defaultValue: String = "0",
|
||||
) {
|
||||
enum class NPCVariableType {
|
||||
NUMBER,
|
||||
STRING,
|
||||
BOOLEAN
|
||||
}
|
||||
|
||||
fun apply(npc: NPCEntity, value: MoValue) {
|
||||
npc.config.setDirectly(variableName, value)
|
||||
}
|
||||
|
||||
fun applyDefault(npc: NPCEntity) {
|
||||
val value = when (type) {
|
||||
NPCVariableType.STRING -> StringValue(defaultValue)
|
||||
NPCVariableType.BOOLEAN -> DoubleValue(defaultValue.toBoolean())
|
||||
else -> DoubleValue(defaultValue.toDouble())
|
||||
}
|
||||
npc.config.set(variableName.split(".").iterator(), value)
|
||||
}
|
||||
}
|
||||
+16
-1
@@ -8,6 +8,7 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.npc.configuration.interaction
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.dialogue.ActiveDialogue
|
||||
import com.cobblemon.mod.common.api.dialogue.DialogueManager
|
||||
import com.cobblemon.mod.common.api.dialogue.Dialogues
|
||||
@@ -31,10 +32,24 @@ class DialogueNPCInteractionConfiguration : NPCInteractConfiguration {
|
||||
|
||||
override fun interact(npc: NPCEntity, player: ServerPlayer): Boolean {
|
||||
val dialogue = Dialogues.dialogues[this.dialogue] ?: return false
|
||||
DialogueManager.startDialogue(ActiveDialogue(player, dialogue))
|
||||
val currentDialogues = npc.brain.getMemory(CobblemonMemories.DIALOGUES).orElse(mutableListOf())
|
||||
val activeDialogue = DialogueManager.startDialogue(player, npc, dialogue)
|
||||
val newDialogues = currentDialogues + activeDialogue
|
||||
npc.brain.setMemory(CobblemonMemories.DIALOGUES, newDialogues)
|
||||
activeDialogue.completion.thenRun { onDialogueStopped(npc, activeDialogue) }
|
||||
return true
|
||||
}
|
||||
|
||||
fun onDialogueStopped(npc: NPCEntity, activeDialogue: ActiveDialogue) {
|
||||
val currentDialogues = npc.brain.getMemory(CobblemonMemories.DIALOGUES).orElse(mutableListOf())
|
||||
val newDialogues = currentDialogues - activeDialogue
|
||||
if (newDialogues.isEmpty()) {
|
||||
npc.brain.eraseMemory(CobblemonMemories.DIALOGUES)
|
||||
} else {
|
||||
npc.brain.setMemory(CobblemonMemories.DIALOGUES, newDialogues)
|
||||
}
|
||||
}
|
||||
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeResourceLocation(dialogue)
|
||||
}
|
||||
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.npc.partyproviders
|
||||
|
||||
import com.cobblemon.mod.common.api.npc.NPCPartyProvider
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
|
||||
import com.cobblemon.mod.common.entity.npc.NPCEntity
|
||||
import com.google.gson.JsonElement
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
|
||||
/**
|
||||
* A provider of a party for battling the NPC. It generates a [StaticNPCParty] but using a more complex process
|
||||
* that takes an input level and makes a randomized selection of Pokémon and movesets.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since July 12th, 2024
|
||||
*/
|
||||
class DynamicPartyProvider : NPCPartyProvider {
|
||||
companion object {
|
||||
val TYPE = "dynamic"
|
||||
}
|
||||
|
||||
class DynamicPool {
|
||||
val id = ResourceLocation.parse("cobblemon:pool")
|
||||
val pokemon: MutableList<DynamicPokemon> = mutableListOf()
|
||||
}
|
||||
|
||||
|
||||
class DynamicPokemon(
|
||||
val pokemon: PokemonProperties,
|
||||
val possibleLevels: IntRange,
|
||||
val selectableTimes: IntRange,
|
||||
val guaranteed: Boolean = false
|
||||
)
|
||||
|
||||
override val type = "dynamic"
|
||||
|
||||
override fun loadFromJSON(json: JsonElement) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun provide(npc: NPCEntity, level: Int): NPCParty {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.npc.partyproviders
|
||||
|
||||
import com.cobblemon.mod.common.api.storage.party.NPCPartyStore
|
||||
import com.cobblemon.mod.common.api.storage.party.PartyStore
|
||||
import com.cobblemon.mod.common.entity.npc.NPCEntity
|
||||
import com.cobblemon.mod.common.net.IntSize
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.util.DataKeys
|
||||
import com.cobblemon.mod.common.util.readSizedInt
|
||||
import com.cobblemon.mod.common.util.writeSizedInt
|
||||
import net.minecraft.core.RegistryAccess
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
|
||||
/**
|
||||
* Represents a party of Pokemon that an NPC can have. This isn't directly a party of Pokémon so that
|
||||
* a dynamically generated party can exist where a party is generated at the time of a challenge.
|
||||
*
|
||||
* This interface is sealed. Implementations should be either [StaticNPCParty] or [DynamicNPCParty].
|
||||
* If you want a custom type then you should implement [DynamicNPCParty] and register it in the
|
||||
* [DynamicNPCParty.types] map.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since July 12th, 2024
|
||||
*/
|
||||
sealed interface NPCParty {
|
||||
fun getParty(player: ServerPlayer, npc: NPCEntity): PartyStore?
|
||||
fun encode(buffer: RegistryFriendlyByteBuf)
|
||||
fun decode(buffer: RegistryFriendlyByteBuf)
|
||||
fun saveToNBT(nbt: CompoundTag, registryAccess: RegistryAccess)
|
||||
fun loadFromNBT(nbt: CompoundTag, registryAccess: RegistryAccess)
|
||||
}
|
||||
|
||||
/**
|
||||
* A simple wrapping around a [NPCPartyStore]. This is a straightforward party that is always the same.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since July 12th, 2024
|
||||
*/
|
||||
class StaticNPCParty(val party: NPCPartyStore) : NPCParty {
|
||||
override fun getParty(player: ServerPlayer, npc: NPCEntity) = party
|
||||
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeSizedInt(IntSize.U_BYTE, party.size())
|
||||
for (pokemon in party) {
|
||||
Pokemon.S2C_CODEC.encode(buffer, pokemon)
|
||||
}
|
||||
}
|
||||
|
||||
override fun decode(buffer: RegistryFriendlyByteBuf) {
|
||||
repeat(times = buffer.readSizedInt(IntSize.U_BYTE)) {
|
||||
party.add(Pokemon.S2C_CODEC.decode(buffer))
|
||||
}
|
||||
}
|
||||
|
||||
override fun saveToNBT(nbt: CompoundTag, registryAccess: RegistryAccess) {
|
||||
for ((index, pokemon) in party.withIndex()) {
|
||||
nbt.put(DataKeys.NPC_PARTY_POKEMON + index, pokemon.saveToNBT(registryAccess))
|
||||
}
|
||||
}
|
||||
|
||||
override fun loadFromNBT(nbt: CompoundTag, registryAccess: RegistryAccess) {
|
||||
var index = 0
|
||||
while (nbt.contains(DataKeys.NPC_PARTY_POKEMON + index)) {
|
||||
this.party.add(Pokemon().loadFromNBT(registryAccess, nbt.getCompound(DataKeys.NPC_PARTY_POKEMON + index)))
|
||||
index++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A dynamic party that is generated at the time of a challenge.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since July 12th, 2024
|
||||
*/
|
||||
interface DynamicNPCParty : NPCParty {
|
||||
companion object {
|
||||
val types = mutableMapOf<String, Class<out NPCParty>>()
|
||||
init {}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user