mirror of
https://github.com/MinecraftForge/MinecraftForge.git
synced 2026-11-14 09:05:17 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6dadc1d889 | ||
|
|
8a55f68a18 | ||
|
|
5645fa5847 | ||
|
|
ff0f00f64f | ||
|
|
7a34246dc9 | ||
|
|
62a6b52487 | ||
|
|
b845cde73d | ||
|
|
2c36dfbb34 | ||
|
|
acd880dd2a | ||
|
|
e6f57e5d94 | ||
|
|
b1de0fc17c | ||
|
|
ad4461932f | ||
|
|
3a94211377 | ||
|
|
9386e23b1f | ||
|
|
10b318c71d | ||
|
|
995d5b7b3a | ||
|
|
bbb12c84fd | ||
|
|
b50058ee47 | ||
|
|
4a0bfa937a | ||
|
|
4d1ec666dd | ||
|
|
b52e3d0e7d | ||
|
|
a1011c99a9 | ||
|
|
0ebd4f3d94 | ||
|
|
89c68c46a2 | ||
|
|
e4702cb09d | ||
|
|
6e64fd7a11 | ||
|
|
014b3f4ad5 | ||
|
|
7628c67883 | ||
|
|
54a322c09f | ||
|
|
aadf396244 | ||
|
|
81e18552e3 | ||
|
|
5686fd40a4 | ||
|
|
989ab3e96b | ||
|
|
88f1dc97b6 | ||
|
|
470a18522c | ||
|
|
002951804a | ||
|
|
fe7a832fad | ||
|
|
a2bc30b356 | ||
|
|
bae1f74681 | ||
|
|
887aa277a4 | ||
|
|
e17f2677c7 | ||
|
|
3b9972af39 | ||
|
|
5c96afec70 | ||
|
|
1bca393ecb | ||
|
|
27cf731552 | ||
|
|
94c84cd994 | ||
|
|
c2d3195e76 | ||
|
|
d0e7c9e2ea | ||
|
|
f3e1cac5a1 | ||
|
|
51fb513213 | ||
|
|
65c9fdd8d7 | ||
|
|
c1d4458acc | ||
|
|
ca1ca4f944 | ||
|
|
15ee8bf5a1 | ||
|
|
a08b5b19d5 | ||
|
|
8dac58ffc1 | ||
|
|
f0837070d6 | ||
|
|
dd7502a051 | ||
|
|
b36d4471e6 | ||
|
|
efb1066a88 | ||
|
|
dd39ae540b | ||
|
|
b39f808618 | ||
|
|
a2c059e562 | ||
|
|
19316a0d38 | ||
|
|
fbc7a5c063 | ||
|
|
e9cfd10e39 | ||
|
|
1424883773 | ||
|
|
6c746ec6d9 | ||
|
|
aacbfeb66e | ||
|
|
1513b369d3 | ||
|
|
35852a69fb | ||
|
|
96537dc091 | ||
|
|
e88ddc56ca | ||
|
|
f24ff07b30 | ||
|
|
3420ea7a2d | ||
|
|
87104f0e2d | ||
|
|
640446b868 | ||
|
|
2cf4917ded | ||
|
|
6394ee8714 | ||
|
|
7299e05fe1 | ||
|
|
c4bd0405fd | ||
|
|
89b8236a9c | ||
|
|
70f55c59c0 | ||
|
|
1c1716d833 | ||
|
|
d567f79652 | ||
|
|
ecd4e46a45 | ||
|
|
16fe495d18 | ||
|
|
4f70d23d0e | ||
|
|
290a3c94b7 | ||
|
|
9485dc5a96 | ||
|
|
e6abb69b0e | ||
|
|
e862052bb4 | ||
|
|
4071ad1278 | ||
|
|
60619643e6 | ||
|
|
b818769c1f | ||
|
|
12bc4bab0c | ||
|
|
8fccfa21df | ||
|
|
a697d043fc | ||
|
|
9d812f12cc | ||
|
|
869cf78e98 | ||
|
|
186680cd8c | ||
|
|
5aed6d995d | ||
|
|
3d7a665987 | ||
|
|
10a716969b | ||
|
|
0eb7180fc1 | ||
|
|
b1b4c61b80 | ||
|
|
359cfb5c98 | ||
|
|
8656fd50ce | ||
|
|
25a4dcb653 | ||
|
|
c90a853377 | ||
|
|
18069d8fd2 | ||
|
|
a40f4a75a9 | ||
|
|
5b6460b68c | ||
|
|
c0d1348e65 | ||
|
|
482c163344 | ||
|
|
221d1131b4 | ||
|
|
f19f426449 | ||
|
|
9dd9b6eb71 | ||
|
|
acb0b21d6d | ||
|
|
b17dd3c695 | ||
|
|
fa66ffaf3f | ||
|
|
b106420774 | ||
|
|
c971adb59b | ||
|
|
d6326deeb0 | ||
|
|
483667c919 | ||
|
|
8bef512803 | ||
|
|
501009c11f | ||
|
|
d3d430827f | ||
|
|
2d9b88bd52 | ||
|
|
93d5934ea7 | ||
|
|
180a279558 | ||
|
|
cf38461911 | ||
|
|
2c85539517 | ||
|
|
d651189581 | ||
|
|
f6a8cd556e | ||
|
|
3bde961dc7 | ||
|
|
6396beaef7 | ||
|
|
6bc6defb07 | ||
|
|
732861092f | ||
|
|
9fcc452ed3 | ||
|
|
26302a6ff2 | ||
|
|
62dbfb3837 | ||
|
|
b91cbe9794 | ||
|
|
93b8ba9576 | ||
|
|
23fdbbd03d | ||
|
|
d7a74d84ea | ||
|
|
58e6dd9794 | ||
|
|
907cf2d925 | ||
|
|
ee48a3673d | ||
|
|
c6f362b77f | ||
|
|
6e01c59635 | ||
|
|
d411f66903 | ||
|
|
0768dc1610 | ||
|
|
4c3db16842 | ||
|
|
805fd1dd90 | ||
|
|
c59996b24b | ||
|
|
e0a1e8293b | ||
|
|
e8af9c0233 | ||
|
|
a955d30d64 | ||
|
|
dbab3bb259 | ||
|
|
bd9c4ee99a | ||
|
|
a0cbd3755d | ||
|
|
12323e233f | ||
|
|
8a308db3d4 | ||
|
|
0583dc8b74 | ||
|
|
789a4a3659 | ||
|
|
a87d0451c8 | ||
|
|
82e9309d27 | ||
|
|
8deaa378c9 | ||
|
|
b5363e3552 | ||
|
|
28a10ac340 | ||
|
|
c349d51923 | ||
|
|
ef01745e09 | ||
|
|
c97d6a65d0 | ||
|
|
2062273504 | ||
|
|
6e6436ee41 | ||
|
|
38f4a22bc4 | ||
|
|
3a8b047e3c | ||
|
|
52483ee6bd | ||
|
|
dce1cbc096 | ||
|
|
46c563a9a8 | ||
|
|
1380c2ecce | ||
|
|
71a3818bdd | ||
|
|
e3a343c797 | ||
|
|
195b1a043e | ||
|
|
69e66c327f | ||
|
|
885637cc7d | ||
|
|
90a7c8f787 | ||
|
|
2171c0caa4 | ||
|
|
924a6f9254 | ||
|
|
ad4cffb0c6 | ||
|
|
cf77ffb89d | ||
|
|
b2fdcd7f1c | ||
|
|
094ce2ae18 | ||
|
|
e8cb2c1bfe | ||
|
|
9c6c56c49d | ||
|
|
0d5affede3 | ||
|
|
13f210f403 | ||
|
|
c61ad51883 | ||
|
|
c0842b0797 | ||
|
|
2851079ff0 | ||
|
|
5197524d1c | ||
|
|
78efd1acc6 | ||
|
|
eee0a99b88 | ||
|
|
10c96c394d | ||
|
|
07cc3fb2d9 | ||
|
|
e31f1433bf | ||
|
|
af06c97efd | ||
|
|
400de1d66e | ||
|
|
2a9285eee8 | ||
|
|
785bdde6bd | ||
|
|
071e2dc524 | ||
|
|
fc08d072a4 | ||
|
|
0019485aba | ||
|
|
e76f145b65 | ||
|
|
27d5937f4c | ||
|
|
868c4c5977 | ||
|
|
5a37929ceb | ||
|
|
b1dc2dbf8a | ||
|
|
ecfbef95c7 | ||
|
|
bfd8fbefee | ||
|
|
f8c36104ad | ||
|
|
e26230fb2d | ||
|
|
6417ad0a3c | ||
|
|
0f988d087c | ||
|
|
7c01b64aed | ||
|
|
03130c78a7 | ||
|
|
30ab326d2b | ||
|
|
8d1cba57f8 | ||
|
|
cbfd6c1a66 | ||
|
|
81cb3c82f4 | ||
|
|
e64296e109 | ||
|
|
5872b31781 | ||
|
|
51b801b1c6 | ||
|
|
9ef153c0b6 | ||
|
|
2e236faec7 | ||
|
|
129c356ecf | ||
|
|
d8316b0bdc | ||
|
|
1d3a92f3f1 | ||
|
|
81c858c719 | ||
|
|
341041aedb | ||
|
|
25256b2295 | ||
|
|
13874ba547 | ||
|
|
bde58add62 | ||
|
|
9112c63347 | ||
|
|
78fa2b8d78 | ||
|
|
6922c369f3 | ||
|
|
b0fd438a1d | ||
|
|
99f4f0c7d3 | ||
|
|
b09c1cd242 | ||
|
|
5ca3bf9362 | ||
|
|
c6a9884bde | ||
|
|
43825ca78e | ||
|
|
44eeadb211 | ||
|
|
7011da5fa9 | ||
|
|
c61ddfa9d1 | ||
|
|
e64b6dcb13 | ||
|
|
183dc236e4 | ||
|
|
ef5349dec2 | ||
|
|
b39afc0711 | ||
|
|
a8579b43ac | ||
|
|
fa92eca328 | ||
|
|
42165df29f | ||
|
|
9860569536 | ||
|
|
7aa48a167f | ||
|
|
6e3764da48 | ||
|
|
4d503d6925 | ||
|
|
8e04d40034 | ||
|
|
cb57cd02e0 | ||
|
|
22fe48e477 | ||
|
|
204f73cb05 | ||
|
|
28096abea5 | ||
|
|
2d7eb5cb7f | ||
|
|
e6d6932e21 | ||
|
|
406e5d64c0 | ||
|
|
13756aad9f | ||
|
|
c1a8b16f30 | ||
|
|
e3671285c3 | ||
|
|
b33cff3613 | ||
|
|
afc2a4a75c | ||
|
|
7c4583c87a | ||
|
|
f563815961 | ||
|
|
0ce38f747c | ||
|
|
efce8e916b | ||
|
|
44728c9f93 | ||
|
|
d96a81e4f2 | ||
|
|
f11844374e | ||
|
|
8c63203bb4 | ||
|
|
751299d5f1 | ||
|
|
7d479bf854 | ||
|
|
c812a4ede5 | ||
|
|
a826283111 | ||
|
|
f61f30c1e6 | ||
|
|
8f76e8ba8b | ||
|
|
537d89b9e0 | ||
|
|
0927aaa0f1 | ||
|
|
d17aad797d | ||
|
|
53e611a03a | ||
|
|
7ac1be8a9a | ||
|
|
dd7d70d619 | ||
|
|
b9d1d1e2f4 | ||
|
|
2dc00adec8 | ||
|
|
b97e937f28 | ||
|
|
c54c4e73e6 | ||
|
|
93528597f4 | ||
|
|
a85bb7bfdb | ||
|
|
0f2d00abf3 | ||
|
|
0e4c716177 | ||
|
|
85b77c3d12 | ||
|
|
03884b1aaa | ||
|
|
dbdc76e6ea | ||
|
|
b8aaed368b | ||
|
|
6ec3379153 | ||
|
|
b177aad1ee | ||
|
|
e050c7807d | ||
|
|
f3f7398a8b | ||
|
|
da4311dc74 | ||
|
|
59471f6cac | ||
|
|
d8b92064d7 | ||
|
|
8e96e60179 | ||
|
|
54877176a6 | ||
|
|
a3ad32a3e5 | ||
|
|
602a4f219c | ||
|
|
f24977dc3d | ||
|
|
4607f9ebb0 | ||
|
|
672f4a03f2 | ||
|
|
f0736ade3d | ||
|
|
4da48cea7a | ||
|
|
1b02ea0677 | ||
|
|
0d1bd4c5d0 | ||
|
|
3f08f1a94c | ||
|
|
1069366219 | ||
|
|
0002bd2875 | ||
|
|
823077dd7d | ||
|
|
34971ff3e0 | ||
|
|
965069ba3a | ||
|
|
43766751a4 | ||
|
|
a92da71c6b | ||
|
|
da47985361 | ||
|
|
68ae32c48c | ||
|
|
3373e33d4b | ||
|
|
2839e79ab0 | ||
|
|
5bffbfbe0d | ||
|
|
4080338c1b | ||
|
|
e06e9393c1 | ||
|
|
4bb9fd7226 | ||
|
|
7edc7d74d4 | ||
|
|
9a5dac605c | ||
|
|
c0a781c0bd | ||
|
|
719bea515e | ||
|
|
153eafdcb0 | ||
|
|
2f588cf6ef | ||
|
|
3ad3c474b5 | ||
|
|
73ba4b68be | ||
|
|
b786d8909a | ||
|
|
ab45ec9fa4 | ||
|
|
fcbe56b504 | ||
|
|
693ec7ddf6 | ||
|
|
61b83ab992 | ||
|
|
6ce9b1ab05 | ||
|
|
a5d58d79fc | ||
|
|
dac3249dc4 | ||
|
|
99eddbfa13 | ||
|
|
ea1fc8f358 | ||
|
|
bbb5a0e891 | ||
|
|
3f491fa7cb | ||
|
|
ae007fcebc | ||
|
|
8580a99728 | ||
|
|
3257d2595d | ||
|
|
5434b3ca24 | ||
|
|
1ea6ba273b | ||
|
|
039d9252c6 | ||
|
|
ca67d6eb6d | ||
|
|
7179edfba7 | ||
|
|
baec9785a2 | ||
|
|
ae2039c65d | ||
|
|
3f803653c4 | ||
|
|
6ff67693b9 | ||
|
|
5501d644b9 | ||
|
|
276fccb170 | ||
|
|
e2fac06f64 | ||
|
|
25def1ceaf | ||
|
|
c0f70309dd | ||
|
|
899c1f519c | ||
|
|
5c1363150e | ||
|
|
4153584392 | ||
|
|
2858731063 | ||
|
|
874a0c32e0 | ||
|
|
4f845befaa | ||
|
|
95194f1c5b | ||
|
|
df6bbaa7c5 | ||
|
|
b1ca21a161 | ||
|
|
bc42a54a51 | ||
|
|
1555bd8c53 | ||
|
|
649e3e7bc5 | ||
|
|
ead4e5255e | ||
|
|
5eafb71083 | ||
|
|
8ed36f583d | ||
|
|
3e311fd4c1 | ||
|
|
a4ce90a918 | ||
|
|
ba46389a87 | ||
|
|
f7e07ca7d8 | ||
|
|
3e80a9ee7d | ||
|
|
dfc6f7b1c1 | ||
|
|
753f5f7bc8 | ||
|
|
982271e8ec | ||
|
|
802ec3d86a | ||
|
|
f1b0e33694 | ||
|
|
1d64fb01bd | ||
|
|
086f575a41 | ||
|
|
3cda115cd5 | ||
|
|
d491502750 | ||
|
|
1d4c33d161 | ||
|
|
47a879a961 | ||
|
|
b59184424b | ||
|
|
a7803d1785 | ||
|
|
5415bf87ce | ||
|
|
a33f2dde77 | ||
|
|
bb7ef791de | ||
|
|
aa1a5d3c19 | ||
|
|
a53d8c926e | ||
|
|
714cd8d8df | ||
|
|
c9f7444d06 | ||
|
|
ea05777032 | ||
|
|
14fea4a3a3 | ||
|
|
0613858855 | ||
|
|
6687ed360b | ||
|
|
409506d2b2 | ||
|
|
b96d6e00c3 | ||
|
|
b6ae926fd3 | ||
|
|
508c986166 | ||
|
|
725201040e | ||
|
|
70d7c8fc68 | ||
|
|
05f9861da4 | ||
|
|
c588750c96 | ||
|
|
d00e229198 | ||
|
|
be1a80ebbd | ||
|
|
44706ae343 | ||
|
|
2af41e7c8c | ||
|
|
e5c29a75de | ||
|
|
2a36dc64bd | ||
|
|
dd128c8502 | ||
|
|
3812dc4464 | ||
|
|
851038679a | ||
|
|
146ee9b3c7 | ||
|
|
6c42a77411 | ||
|
|
7e24034fcc | ||
|
|
e6eb550bfd | ||
|
|
2dbb374869 | ||
|
|
e5efbea2ab | ||
|
|
bc74a16149 | ||
|
|
4cd6c58159 | ||
|
|
9e6fbea698 | ||
|
|
e796630120 | ||
|
|
cad5ce54dc | ||
|
|
3c3e4ca2ff | ||
|
|
b9b90c6eef | ||
|
|
747c6131bf | ||
|
|
5c65939330 | ||
|
|
cddcd9ffb3 | ||
|
|
1295c3863e | ||
|
|
99ce6e2dee | ||
|
|
a9d4a15a4f | ||
|
|
2fbf60a846 | ||
|
|
1838344b07 | ||
|
|
fd6aacd0fe | ||
|
|
4b142cbdcc | ||
|
|
802425b4d5 | ||
|
|
745d388cb0 | ||
|
|
1f52ee1dea | ||
|
|
1af7d7970a | ||
|
|
201edc0249 | ||
|
|
2f4a572a23 | ||
|
|
0cf8cca248 | ||
|
|
af4a2589a6 | ||
|
|
2d55491692 | ||
|
|
1007720589 | ||
|
|
b2f470464a | ||
|
|
683c99c8b6 | ||
|
|
428cf691f1 | ||
|
|
bfe54ef7e7 | ||
|
|
40dff18025 | ||
|
|
4d620d91e4 | ||
|
|
a502e1fc56 | ||
|
|
4f0c220d99 | ||
|
|
08a4b21460 | ||
|
|
9fd6f89fc3 | ||
|
|
11652d597f | ||
|
|
f943cd9b4b | ||
|
|
1e392e0bb3 | ||
|
|
e536c58f81 | ||
|
|
63c02cbe35 | ||
|
|
d9a8392723 | ||
|
|
ae52b91d13 | ||
|
|
370062cc55 | ||
|
|
43eae28f55 | ||
|
|
c2c27044b5 | ||
|
|
09722f3ffc | ||
|
|
2cf960b64d | ||
|
|
05b31bdd6e | ||
|
|
e115807351 | ||
|
|
f5b29d2726 | ||
|
|
dfac296402 | ||
|
|
9e2117c955 | ||
|
|
4fdf2ea290 | ||
|
|
10fb465525 | ||
|
|
d44822b7d0 | ||
|
|
18a35c1ab7 | ||
|
|
26cf077cfa | ||
|
|
c3379b44dd | ||
|
|
3ad305aa06 | ||
|
|
89d74da576 | ||
|
|
9ad4177bfa | ||
|
|
20c830c848 | ||
|
|
877bb029f9 | ||
|
|
cfb5cb1a2f | ||
|
|
245f562e1c | ||
|
|
68dc92f0e1 | ||
|
|
ee4089304a | ||
|
|
f3dfa1a955 | ||
|
|
2320e42163 | ||
|
|
bcc35775f4 | ||
|
|
3239536832 | ||
|
|
9c1c414ca7 | ||
|
|
20e5963059 | ||
|
|
70c57e2ad6 | ||
|
|
4639786521 | ||
|
|
71e873ed1f | ||
|
|
c416a82e64 | ||
|
|
539252053f | ||
|
|
da791ef721 | ||
|
|
49bca8998a | ||
|
|
6e14c67e82 | ||
|
|
7fddb9d59e | ||
|
|
006112f3d3 | ||
|
|
e075a430e2 | ||
|
|
134299b413 | ||
|
|
03059c5cd2 | ||
|
|
918d9d8687 | ||
|
|
5017f8b038 | ||
|
|
78052d2ce2 | ||
|
|
8a6b10607d | ||
|
|
034117e253 | ||
|
|
a3ddd6140b | ||
|
|
ac292296fe | ||
|
|
d50a66c8ba | ||
|
|
fb4d3b2ca9 | ||
|
|
fcdd2a9176 | ||
|
|
fa921f0aa9 | ||
|
|
ac221275d9 | ||
|
|
33f8b158a9 | ||
|
|
b9b33ebe79 | ||
|
|
a23816134b | ||
|
|
4e8e84244b | ||
|
|
a94316cc9e | ||
|
|
01a1bc9e6a | ||
|
|
d2b69b2b08 | ||
|
|
91fbba3873 | ||
|
|
a4f3bc853a | ||
|
|
b7ece58caa | ||
|
|
fe354c867d | ||
|
|
326d52f534 | ||
|
|
fbd9ac7d95 | ||
|
|
96018996fc | ||
|
|
9b205b1355 | ||
|
|
56f915eb66 | ||
|
|
46f8868961 | ||
|
|
15089f9d87 | ||
|
|
4783bfe01d | ||
|
|
7b894946bf | ||
|
|
a01e513822 | ||
|
|
3061fd3d8f | ||
|
|
9b281f0a3c | ||
|
|
e433708056 | ||
|
|
43eae51bb3 | ||
|
|
72edbe596e | ||
|
|
53b5533936 | ||
|
|
84c86fd475 | ||
|
|
a9d644e1e8 | ||
|
|
7ed6c7bd7f | ||
|
|
3fd23cee0f | ||
|
|
0665c93c2b | ||
|
|
cd741d961e | ||
|
|
ea855f82b4 | ||
|
|
d775f42703 | ||
|
|
0981d3106d | ||
|
|
a20c7f6f76 | ||
|
|
cf9b57d9fa | ||
|
|
7deedb26f5 | ||
|
|
4c2c7cb2f3 | ||
|
|
7ec180ee7c | ||
|
|
b1ee6c3c95 | ||
|
|
a36fccc9b0 | ||
|
|
36b05d9378 | ||
|
|
2b8ac71253 | ||
|
|
1ffb096508 | ||
|
|
7a66d88e9f | ||
|
|
42c5b9534a | ||
|
|
0b1f3b51e3 | ||
|
|
6646b573e8 | ||
|
|
201762ee50 | ||
|
|
99ee905038 | ||
|
|
d2afbd9216 | ||
|
|
5f49c5f646 | ||
|
|
d91c22ea24 | ||
|
|
4c9745f73c | ||
|
|
edb0ba811f | ||
|
|
a1ca27b997 | ||
|
|
285d187884 | ||
|
|
351c193b98 | ||
|
|
8586d8ae85 | ||
|
|
1a40f433a5 | ||
|
|
6c6f792c6b | ||
|
|
149fa8a577 | ||
|
|
f279476684 | ||
|
|
0ca8ace988 | ||
|
|
80f87ef569 | ||
|
|
904efdd4d8 | ||
|
|
874d3f0b17 | ||
|
|
603005ba18 | ||
|
|
6b286543d4 | ||
|
|
28992c6f13 | ||
|
|
174e208369 | ||
|
|
c632d5145e | ||
|
|
f3bee8c070 | ||
|
|
8bfeb5ac21 | ||
|
|
05dc6f8e4b | ||
|
|
2eb77acf73 | ||
|
|
f7cec9be38 | ||
|
|
8f8ee60eb1 | ||
|
|
8f14c7321b | ||
|
|
aedb80c251 | ||
|
|
e7224c7bda | ||
|
|
cceeb88c6d | ||
|
|
65f39a50c1 | ||
|
|
0a52ed381d | ||
|
|
78f2e8f38a | ||
|
|
9fdc403396 | ||
|
|
9c3a2f052d | ||
|
|
5f26a86bf7 | ||
|
|
b1d9f3d833 | ||
|
|
05ff62d85f | ||
|
|
b0774b89c7 | ||
|
|
1ec797cddb | ||
|
|
2ff2a78694 | ||
|
|
93664d10e6 | ||
|
|
10e5d42522 | ||
|
|
d531d70f1f | ||
|
|
95596bc198 | ||
|
|
b32a92df5b | ||
|
|
ac6c35d7c4 | ||
|
|
2ed8a8b807 | ||
|
|
759e92cc2a | ||
|
|
feede96d6d | ||
|
|
fc33249d32 | ||
|
|
ff48f13746 | ||
|
|
47e61610ca | ||
|
|
4f97aedbb2 | ||
|
|
51203e49f9 | ||
|
|
1906a085ad | ||
|
|
5a3ac6b96e | ||
|
|
1146660fc6 | ||
|
|
2888e1680e | ||
|
|
7bf22659e7 | ||
|
|
86f8bbd47d | ||
|
|
5bc8929795 | ||
|
|
b2853aa811 | ||
|
|
c06fc00f24 | ||
|
|
1e6eec768c | ||
|
|
33d7d77775 | ||
|
|
83b060b573 | ||
|
|
df656cb98d | ||
|
|
cb21ddc438 | ||
|
|
7b45203461 | ||
|
|
ecb07e2abb | ||
|
|
647c40ba5e | ||
|
|
9210fe1a57 | ||
|
|
9efb9741d1 | ||
|
|
87b5c870d5 | ||
|
|
bd34b97e9b | ||
|
|
c74e119993 | ||
|
|
96e23dda6b | ||
|
|
c6a0bc2487 | ||
|
|
d1efbce945 | ||
|
|
381b2b8aa1 | ||
|
|
72478fac83 | ||
|
|
c4fd53d628 | ||
|
|
ec4750f422 | ||
|
|
bc0caee371 | ||
|
|
8087bd82bf | ||
|
|
ec3fb620dc | ||
|
|
d6e5df9092 | ||
|
|
160399cee7 | ||
|
|
4b4e4b30a9 | ||
|
|
67ed21052f | ||
|
|
532f8cfce9 | ||
|
|
a45af9ac39 | ||
|
|
3b487511d7 | ||
|
|
a1cbb799be | ||
|
|
8b9545d622 | ||
|
|
cd325dc3fd | ||
|
|
9768774896 | ||
|
|
e1781bf2ae | ||
|
|
b566a7b692 | ||
|
|
e7aa295b47 | ||
|
|
2d44b44372 | ||
|
|
17e19b8cc6 | ||
|
|
e88b897635 | ||
|
|
7a0bd95113 | ||
|
|
be52c01b9f | ||
|
|
c02319cec1 | ||
|
|
f7507d3f79 | ||
|
|
31d2c84541 | ||
|
|
84d4f7765c | ||
|
|
aed6bcc737 | ||
|
|
73e2229fb4 | ||
|
|
a0633ae5e3 | ||
|
|
bdce70e891 | ||
|
|
3197817a76 | ||
|
|
0a7e8a8c3e | ||
|
|
b23bdc628b | ||
|
|
d727aed293 |
No files matched your search
+2
-18
@@ -1,23 +1,7 @@
|
||||
* text eol=lf
|
||||
*.bat text eol=crlf
|
||||
*.patch text eol=lf
|
||||
*.java text eol=lf
|
||||
*.gradle text eol=crlf
|
||||
*.patch text
|
||||
*.png binary
|
||||
*.gif binary
|
||||
*.exe binary
|
||||
*.dll binary
|
||||
*.jar binary
|
||||
*.lzma binary
|
||||
*.zip binary
|
||||
*.pyd binary
|
||||
*.cfg text eol=lf
|
||||
*.py text eol=lf
|
||||
*.jks binary
|
||||
|
||||
# Disable autocrlf on generated files, they always generate with LF
|
||||
src/generated/**/.cache/cache text eol=lf
|
||||
src/generated/**/*.json text eol=lf
|
||||
src/generated_test/**/.cache/cache text eol=lf
|
||||
src/generated_test/**/*.json text eol=lf
|
||||
|
||||
*.zip binary
|
||||
@@ -1,13 +0,0 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Want to request a feature?
|
||||
title: ''
|
||||
labels: Feature
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
<!-- Please note, feature requests that are submitted as GitHub issues here are rarely implemented. -->
|
||||
<!-- If you'd like to see something in Forge, you should be ready to implement it as a PR. -->
|
||||
<!-- If you're not sure, open a Draft PR or discuss it in the Discord server. -->
|
||||
<!-- Discord: https://discord.gg/UvedJ9m -->
|
||||
@@ -1,26 +0,0 @@
|
||||
---
|
||||
name: Issue report
|
||||
about: Visit the forum first for issues with crashes.
|
||||
title: ''
|
||||
labels: Triage
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
<!-- Thank you for reporting! -->
|
||||
|
||||
<!-- For support with crashes and issues, please create a post on the forum instead: -->
|
||||
<!-- https://www.minecraftforge.net/forum/forum/18-support-bug-reports/ -->
|
||||
|
||||
**Minecraft Version:** {Minecraft version}
|
||||
|
||||
**Forge Version:** {Forge version. *Version number, not latest/rb*}
|
||||
|
||||
**Logs:** {Link(s) to GitHub Gist with full latest.log and/or crash report}
|
||||
|
||||
**Steps to Reproduce:**
|
||||
1. Do this
|
||||
2. Then do that
|
||||
3. ...
|
||||
|
||||
**Description of issue:**
|
||||
@@ -1,43 +0,0 @@
|
||||
# Configuration for probot-stale - https://github.com/probot/stale
|
||||
|
||||
# Label to use when marking as stale
|
||||
staleLabel: Stale
|
||||
# Comment to post when removing the stale label. Set to `false` to disable
|
||||
unmarkComment: false
|
||||
# Limit the number of actions per hour, from 1-30. Default is 30
|
||||
limitPerRun: 1
|
||||
# Issues with these labels will never be considered stale. Set to `[]` to disable
|
||||
exemptLabels:
|
||||
- Assigned
|
||||
|
||||
pulls:
|
||||
# Number of days of inactivity before a Pull Request becomes stale
|
||||
daysUntilStale: 60
|
||||
# Number of days of inactivity before a stale Pull Request is closed
|
||||
daysUntilClose: 14
|
||||
# Comment to post when marking as stale. Set to `false` to disable
|
||||
markComment: >
|
||||
This pull request has been automatically marked as stale because it has not had recent
|
||||
activity, and will be closed if no further activity occurs. If this pull request was
|
||||
overlooked, forgotten, or should remain open for any other reason, please reply
|
||||
here to call attention to it and remove the stale status. Thank you for your contributions.
|
||||
# Comment to post when closing a stale Pull Request. Set to `false` to disable
|
||||
closeComment: >
|
||||
This pull request has been automatically closed because it has not had
|
||||
recent activity. Please feel free to update or reopen it.
|
||||
issues:
|
||||
# Number of days of inactivity before an Issue becomes stale
|
||||
daysUntilStale: 180
|
||||
# Number of days of inactivity before a stale Issue is closed
|
||||
daysUntilClose: 14
|
||||
# Comment to post when marking as stale. Set to `false` to disable
|
||||
markComment: >
|
||||
This issue has been automatically marked as stale because it has not had activity
|
||||
in a long time. If this issue is still relevant and should remain open, please reply
|
||||
with a short explanation (e.g. "I have checked the code and this issue is still relevant because ___."
|
||||
or "Here's a screenshot of this issue on the latest version").
|
||||
Thank you for your contributions!
|
||||
# Comment to post when closing a stale Issue. Set to `false` to disable
|
||||
closeComment: >
|
||||
This issue has been automatically closed because it has not had
|
||||
activity in a long time. Please feel free to reopen it or create a new issue.
|
||||
@@ -1,16 +0,0 @@
|
||||
# Configuration for support-requests - https://github.com/dessant/support-requests
|
||||
|
||||
# Label used to mark issues as support requests
|
||||
supportLabel: Forum
|
||||
# Comment to post on issues marked as support requests. Add a link
|
||||
# to a support page, or set to `false` to disable
|
||||
supportComment: >
|
||||
👋 We use the issue tracker exclusively for final bug reports and feature requests.
|
||||
However, this issue appears to be better suited for the
|
||||
[Forge Support Forums](http://www.minecraftforge.net/forum/forum/18-support-bug-reports/).
|
||||
Please create a new topic on the support forum with this issue, and the conversation can
|
||||
continue there.
|
||||
# Whether to close issues marked as support requests
|
||||
close: true
|
||||
# Whether to lock issues marked as support requests
|
||||
lock: true
|
||||
+10
-46
@@ -1,46 +1,10 @@
|
||||
#eclipse
|
||||
**/bin
|
||||
**/.settings
|
||||
**/.classpath
|
||||
*.project
|
||||
|
||||
#In case people make their workspace in the repo
|
||||
/eclipse/
|
||||
|
||||
#idea
|
||||
/.idea
|
||||
/*/out
|
||||
/classes
|
||||
*.iml
|
||||
|
||||
#gradle
|
||||
/build
|
||||
/.gradle
|
||||
/*/build
|
||||
/*/.gradle
|
||||
|
||||
# Projects repo, either ignore it, or ignore patches.
|
||||
/projects/mcp/
|
||||
/projects/clean/
|
||||
/projects/forge/
|
||||
/projects/fmlonly/
|
||||
#/patches/
|
||||
|
||||
#occupational hazards
|
||||
/projects/**/build/
|
||||
/projects/**/out/
|
||||
/projects/**/run/
|
||||
/projects/**/*.launch
|
||||
/repo/
|
||||
src/generated/resources/.cache/
|
||||
|
||||
#Patch rejects
|
||||
/patches-/
|
||||
#*.patch.rej
|
||||
/projects/*/rejects/
|
||||
|
||||
# FML changelog
|
||||
changelog.txt
|
||||
*.py
|
||||
*.7z
|
||||
/logs/
|
||||
/bin
|
||||
/minecraft_server
|
||||
/mods
|
||||
/fmlbuild.properties
|
||||
/fmlversion.properties
|
||||
/difflist.txt
|
||||
/target
|
||||
fmlbranding.properties
|
||||
/fernflower.zip
|
||||
/commands.py.bck
|
||||
-65
@@ -1,65 +0,0 @@
|
||||
Minecraft Forge: Credits/Thank You
|
||||
|
||||
Forge is a set of tools and modifications to the Minecraft base game code to assist
|
||||
mod developers in creating new and exciting content. It has been in development for
|
||||
several years now, but I would like to take this time thank a few people who have
|
||||
helped it along it's way.
|
||||
|
||||
First, the people who originally created the Forge projects way back in Minecraft
|
||||
alpha. Eloraam of RedPower, and SpaceToad of Buildcraft, without their acceptiance
|
||||
of me taking over the project, who knows what Minecraft modding would be today.
|
||||
|
||||
Secondly, someone who has worked with me, and developed some of the core features
|
||||
that allow modding to be as functional, and as simple as it is, cpw. For developing
|
||||
FML, which stabelized the client and server modding ecosystem. As well as the base
|
||||
loading system that allows us to modify Minecraft's code as elegently as possible.
|
||||
|
||||
Mezz, who has stepped up as the issue and pull request manager. Helping to keep me
|
||||
sane as well as guiding the community into creating better additions to Forge.
|
||||
|
||||
Searge, Bspks, Fesh0r, ProfMobious, and all the rest over on the MCP team {of which
|
||||
I am a part}. For creating some of the core tools needed to make Minecraft modding
|
||||
both possible, and as stable as can be.
|
||||
On that note, here is some specific information of the MCP data we use:
|
||||
* Minecraft Coder Pack (MCP) *
|
||||
Forge Mod Loader and Minecraft Forge have permission to distribute and automatically
|
||||
download components of MCP and distribute MCP data files. This permission is not
|
||||
transitive and others wishing to redistribute the Minecraft Forge source independently
|
||||
should seek permission of MCP or remove the MCP data files and request their users
|
||||
to download MCP separately.
|
||||
|
||||
And lastly, the countless community members who have spent time submitting bug reports,
|
||||
pull requests, and just helping out the community in general. Thank you.
|
||||
|
||||
--LexManos
|
||||
|
||||
=========================================================================
|
||||
|
||||
This is Forge Mod Loader.
|
||||
|
||||
You can find the source code at all times at https://github.com/MinecraftForge/MinecraftForge/tree/1.12.x/src/main/java/net/minecraftforge/fml
|
||||
|
||||
This minecraft mod is a clean open source implementation of a mod loader for minecraft servers
|
||||
and minecraft clients.
|
||||
|
||||
The code is authored by cpw.
|
||||
|
||||
It began by partially implementing an API defined by the client side ModLoader, authored by Risugami.
|
||||
http://www.minecraftforum.net/topic/75440-
|
||||
This support has been dropped as of Minecraft release 1.7, as Risugami no longer maintains ModLoader.
|
||||
|
||||
It also contains suggestions and hints and generous helpings of code from LexManos, author of MinecraftForge.
|
||||
http://www.minecraftforge.net/
|
||||
|
||||
Additionally, it contains an implementation of topological sort based on that
|
||||
published at http://keithschwarz.com/interesting/code/?dir=topological-sort
|
||||
|
||||
It also contains code from the Maven project for performing versioned dependency
|
||||
resolution. http://maven.apache.org/
|
||||
|
||||
It also contains a partial repackaging of the javaxdelta library from http://sourceforge.net/projects/javaxdelta/
|
||||
with credit to it's authors.
|
||||
|
||||
Forge Mod Loader downloads components from the Minecraft Coder Pack
|
||||
(http://mcp.ocean-labs.de/index.php/Main_Page) with kind permission from the MCP team.
|
||||
|
||||
Vendored
-125
@@ -1,125 +0,0 @@
|
||||
@Library('forge-shared-library')_
|
||||
|
||||
pipeline {
|
||||
options {
|
||||
disableConcurrentBuilds()
|
||||
}
|
||||
agent {
|
||||
docker {
|
||||
image 'gradle:7-jdk16'
|
||||
//args '-v forgegc:/home/gradle/.gradle_cache/'
|
||||
}
|
||||
}
|
||||
environment {
|
||||
GRADLE_ARGS = '--no-daemon --console=plain' // No daemon for now as FG3 kinda derps. //'-Dorg.gradle.daemon.idletimeout=5000'
|
||||
DISCORD_WEBHOOK = credentials('forge-discord-jenkins-webhook')
|
||||
DISCORD_PREFIX = "Job: Forge Branch: ${BRANCH_NAME} Build: #${BUILD_NUMBER}"
|
||||
JENKINS_HEAD = 'https://wiki.jenkins-ci.org/download/attachments/2916393/headshot.png'
|
||||
}
|
||||
|
||||
stages {
|
||||
stage('notify_start') {
|
||||
when {
|
||||
not {
|
||||
changeRequest()
|
||||
}
|
||||
}
|
||||
steps {
|
||||
discordSend(
|
||||
title: "${DISCORD_PREFIX} Started",
|
||||
successful: true,
|
||||
result: 'ABORTED', //White border
|
||||
thumbnail: JENKINS_HEAD,
|
||||
webhookURL: DISCORD_WEBHOOK
|
||||
)
|
||||
}
|
||||
}
|
||||
/*
|
||||
stage('pull_cache') {
|
||||
steps {
|
||||
sh 'cp -r /home/gradle/.gradle_cache/jdks/ /home/gradle/.gradle/jdks/'
|
||||
sh 'cp -r /home/gradle/.gradle_cache/wrapper/ /home/gradle/.gradle/wrapper/'
|
||||
sh 'cp -r /home/gradle/.gradle_cache/caches/ /home/gradle/.gradle/caches/'
|
||||
}
|
||||
}
|
||||
*/
|
||||
stage('setup') {
|
||||
steps {
|
||||
withGradle {
|
||||
sh './gradlew ${GRADLE_ARGS} --refresh-dependencies --continue setup'
|
||||
}
|
||||
script {
|
||||
env.MYVERSION = sh(returnStdout: true, script: './gradlew :forge:properties -q | grep "^version:" | cut -d" " -f2').trim()
|
||||
env.FMLONLY_VERSION = sh(returnStdout: true, script: './gradlew :fmlonly:properties -q | grep "^version:" | cut -d" " -f2').trim()
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('changelog') {
|
||||
when {
|
||||
not {
|
||||
changeRequest()
|
||||
}
|
||||
}
|
||||
steps {
|
||||
writeChangelog(currentBuild, 'build/changelog.txt')
|
||||
}
|
||||
}
|
||||
stage('publish') {
|
||||
when {
|
||||
not {
|
||||
changeRequest()
|
||||
}
|
||||
}
|
||||
environment {
|
||||
CROWDIN = credentials('forge-crowdin')
|
||||
KEYSTORE = credentials('forge-jenkins-keystore-old')
|
||||
KEYSTORE_KEYPASS = credentials('forge-jenkins-keystore-old-keypass')
|
||||
KEYSTORE_STOREPASS = credentials('forge-jenkins-keystore-old-keypass')
|
||||
}
|
||||
steps {
|
||||
withCredentials([usernamePassword(credentialsId: 'maven-forge-user', usernameVariable: 'MAVEN_USER', passwordVariable: 'MAVEN_PASSWORD')]) {
|
||||
withGradle {
|
||||
sh './gradlew ${GRADLE_ARGS} publish -PkeystoreKeyPass=${KEYSTORE_KEYPASS} -PkeystoreStorePass=${KEYSTORE_STOREPASS} -Pkeystore=${KEYSTORE} -PcrowdinKey=${CROWDIN}'
|
||||
}
|
||||
}
|
||||
}
|
||||
post {
|
||||
success {
|
||||
build job: 'filegenerator', parameters: [string(name: 'COMMAND', value: "promote net.minecraftforge:forge ${env.MYVERSION} latest")], propagate: false, wait: false
|
||||
build job: 'filegenerator', parameters: [string(name: 'COMMAND', value: "promote net.minecraftforge:fmlonly ${env.FMLONLY_VERSION} latest")], propagate: false, wait: false
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('test_publish_pr') { //Publish to local repo to test full process, but don't include credentials so it can't sign/publish to maven
|
||||
when {
|
||||
changeRequest()
|
||||
}
|
||||
environment {
|
||||
CROWDIN = credentials('forge-crowdin')
|
||||
}
|
||||
steps {
|
||||
withGradle {
|
||||
sh './gradlew ${GRADLE_ARGS} publish -PcrowdinKey=${CROWDIN}'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
post {
|
||||
always {
|
||||
script {
|
||||
archiveArtifacts artifacts: 'projects/forge/build/libs/**/*.*', fingerprint: true, onlyIfSuccessful: true, allowEmptyArchive: true
|
||||
|
||||
if (env.CHANGE_ID == null) { // This is unset for non-PRs
|
||||
discordSend(
|
||||
title: "${DISCORD_PREFIX} Finished ${currentBuild.currentResult}",
|
||||
description: '```\n' + getChanges(currentBuild) + '\n```',
|
||||
successful: currentBuild.resultIsBetterOrEqualTo("SUCCESS"),
|
||||
result: currentBuild.currentResult,
|
||||
thumbnail: JENKINS_HEAD,
|
||||
webhookURL: DISCORD_WEBHOOK
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,64 +1,15 @@
|
||||
Unless noted below, Minecraft Forge, Forge Mod Loader, and all
|
||||
parts herein are licensed under the terms of the LGPL 2.1 found
|
||||
here http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt and
|
||||
copied below.
|
||||
This minecraft mod, Forge Mod Loader, including all parts herein, is licensed
|
||||
under the GNU LGPL v2.1 or later.
|
||||
|
||||
Homepage: http://minecraftforge.net/
|
||||
https://github.com/MinecraftForge/MinecraftForge
|
||||
|
||||
Homepage: https://github.com/cpw/FML
|
||||
|
||||
A note on authorship:
|
||||
All source artifacts are property of their original author, with
|
||||
the exclusion of the contents of the patches directory and others
|
||||
copied from it from time to time. Authorship of the contents of
|
||||
the patches directory is retained by the Minecraft Forge project.
|
||||
This is because the patches are partially machine generated
|
||||
artifacts, and are changed heavily due to the way forge works.
|
||||
Individual attribution within them is impossible.
|
||||
|
||||
Consent:
|
||||
All contributions to Forge must consent to the release of any
|
||||
patch content to the Forge project.
|
||||
|
||||
A note on infectivity:
|
||||
The LGPL is chosen specifically so that projects may depend on Forge
|
||||
features without being infected with its license. That is the
|
||||
purpose of the LGPL. Mods and others using this code via ordinary
|
||||
Java mechanics for referencing libraries are specifically not bound
|
||||
by Forge's license for the Mod code.
|
||||
|
||||
|
||||
=== MCP Data ===
|
||||
This software includes data from the Minecraft Coder Pack (MCP), with kind permission
|
||||
from them. The license to MCP data is not transitive - distribution of this data by
|
||||
third parties requires independent licensing from the MCP team. This data is not
|
||||
redistributable without permission from the MCP team.
|
||||
|
||||
=== Sharing ===
|
||||
I grant permission for some parts of FML to be redistributed outside the terms of the LGPL, for the benefit of
|
||||
the minecraft modding community. All contributions to these parts should be licensed under the same additional grant.
|
||||
|
||||
-- Runtime patcher --
|
||||
License is granted to redistribute the runtime patcher code (src/main/java/net/minecraftforge/fml/common/patcher
|
||||
and subdirectories) under any alternative open source license as classified by the OSI (http://opensource.org/licenses)
|
||||
|
||||
-- ASM transformers --
|
||||
License is granted to redistribute the ASM transformer code (src/main/java/net/minecraftforge/common/asm/ and subdirectories)
|
||||
under any alternative open source license as classified by the OSI (http://opensource.org/licenses)
|
||||
|
||||
=========================================================================
|
||||
This software includes portions from the Apache Maven project at
|
||||
http://maven.apache.org/ specifically the ComparableVersion.java code. It is
|
||||
included based on guidelines at
|
||||
http://www.softwarefreedom.org/resources/2007/gpl-non-gpl-collaboration.html
|
||||
with notices intact. The only change is a non-functional change of package name.
|
||||
|
||||
This software contains a partial repackaging of javaxdelta, a BSD licensed program for generating
|
||||
binary differences and applying them, sourced from the subversion at http://sourceforge.net/projects/javaxdelta/
|
||||
authored by genman, heikok, pivot.
|
||||
The only changes are to replace some Trove collection types with standard Java collections, and repackaged.
|
||||
=========================================================================
|
||||
|
||||
========
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
@@ -68,10 +19,6 @@ The only changes are to replace some Trove collection types with standard Java c
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the Lesser GPL. It also counts
|
||||
as the successor of the GNU Library Public License, version 2, hence
|
||||
the version number 2.1.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
@@ -117,7 +64,7 @@ modified by someone else and passed on, the recipients should know
|
||||
that what they have is not the original version, so that the original
|
||||
author's reputation will not be affected by problems that might be
|
||||
introduced by others.
|
||||
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of
|
||||
any free program. We wish to make sure that a company cannot
|
||||
effectively restrict the users of a free program by obtaining a
|
||||
@@ -173,7 +120,7 @@ modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
@@ -220,7 +167,7 @@ Library.
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
@@ -278,7 +225,7 @@ instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
@@ -329,7 +276,7 @@ Library will still fall under Section 6.)
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
|
||||
6. As an exception to the Sections above, you may also combine or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
@@ -391,7 +338,7 @@ restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
@@ -432,7 +379,7 @@ subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties with
|
||||
this License.
|
||||
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
@@ -484,7 +431,7 @@ conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
@@ -1,16 +0,0 @@
|
||||
Minecraft Forge
|
||||
Copyright (c) 2016-${year}.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation version 2.1
|
||||
of the License.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
@@ -0,0 +1,14 @@
|
||||
import os, sys
|
||||
|
||||
def main():
|
||||
fml_dir = os.path.abspath(sys.argv[1])
|
||||
work_dir = os.path.normpath(sys.argv[2])
|
||||
mcp_dir = os.path.normpath(sys.argv[3])
|
||||
|
||||
sys.path.append(os.path.join(fml_dir, 'install'))
|
||||
from fml import apply_fml_patches
|
||||
|
||||
apply_fml_patches(fml_dir, mcp_dir, work_dir, False)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
-1421
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,367 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- ======================================================================
|
||||
30 Mar 2012 13:35:40
|
||||
|
||||
FML
|
||||
The Forge Mod Loader
|
||||
|
||||
cpw
|
||||
====================================================================== -->
|
||||
<project name="FML" default="jenkinsbuild">
|
||||
<description>The Forge Mod Loader</description>
|
||||
<macrodef name="side">
|
||||
<attribute name="prop" />
|
||||
<attribute name="src" />
|
||||
<attribute name="side" />
|
||||
<sequential>
|
||||
<property name="@{prop}" value="${@{side}.@{src}}" />
|
||||
<condition property="is.client">
|
||||
<equals arg1="@{side}" arg2="client" />
|
||||
</condition>
|
||||
<condition property="is.server">
|
||||
<equals arg1="@{side}" arg2="server" />
|
||||
</condition>
|
||||
</sequential>
|
||||
</macrodef>
|
||||
<target name="writeversion" depends="buildenvsetup">
|
||||
<exec executable="${python.exe}" dir="${basedir}" failonerror="true">
|
||||
<arg value="${basedir}/getversion.py" />
|
||||
<arg value="${mcp.home}" />
|
||||
</exec>
|
||||
<propertyfile file="fmlversion.properties">
|
||||
<entry key="fmlbuild.build.number" type="int" value="${version.build}"/>
|
||||
</propertyfile>
|
||||
</target>
|
||||
|
||||
<target name="buildenvsetup">
|
||||
<tstamp>
|
||||
<format pattern="yyMMddHHmmss" property="timestamp" />
|
||||
</tstamp>
|
||||
<property environment="env" />
|
||||
<property file="fmlbuild.properties" />
|
||||
<property name="modname" value="fml" />
|
||||
<condition property="dev.home" value="${env.WORKSPACE}" else="${default.dev.home}">
|
||||
<isset property="env.WORKSPACE" />
|
||||
</condition>
|
||||
<condition property="mcp.home" value="${env.WORKSPACE}/mcpworkspace" else="${default.mcp.home}">
|
||||
<isset property="env.WORKSPACE" />
|
||||
</condition>
|
||||
<condition property="python.exe" value="${mcp.home}/runtime/bin/python/python_mcp" else="python">
|
||||
<os family="Windows" />
|
||||
</condition>
|
||||
<property name="mcp.obfoutput" location="${mcp.home}/reobf" />
|
||||
<property name="client.mcp.obfoutput" location="${mcp.obfoutput}/minecraft" />
|
||||
<property name="mcp.srcdir" location="${mcp.home}/src" />
|
||||
<property name="common.mcp.srcdir" location="${mcp.srcdir}/common" />
|
||||
<property name="client.mcp.srcdir" location="${mcp.srcdir}/minecraft" />
|
||||
<property name="clean.mcp.srcdir" location="${mcp.home}/src-base" />
|
||||
<property name="patch.mcp.srcdir" location="${mcp.home}/src-work" />
|
||||
<property name="tmp.mcp.srcdir" location="${mcp.home}/src-tmp" />
|
||||
<property name="renamed.mcp.srcdir" location="${mcp.home}/src-renamed" />
|
||||
<property name="common.src.dir" location="${basedir}/common" />
|
||||
<property name="client.src.dir" location="${basedir}/client" />
|
||||
<property name="patch.src.dir" location="${basedir}/patches" />
|
||||
<property name="fml.conf.dir" location="${basedir}/conf" />
|
||||
<condition property="version.build" value="${env.BUILD_NUMBER}" else="1">
|
||||
<isset property="env.BUILD_NUMBER" />
|
||||
</condition>
|
||||
</target>
|
||||
|
||||
<target name="makeversion" depends="buildenvsetup">
|
||||
<antcall target="writeversion" />
|
||||
<property file="fmlversion.properties" />
|
||||
<property name="build.number" value="${fmlbuild.major.number}.${fmlbuild.minor.number}.${fmlbuild.revision.number}" />
|
||||
<property name="version.major" value="${fmlbuild.major.number}" />
|
||||
<property name="version.minor" value="${fmlbuild.minor.number}" />
|
||||
<property name="version.rev" value="${fmlbuild.revision.number}" />
|
||||
<property name="version" value="${version.major}.${version.minor}.${version.rev}.${version.build}" />
|
||||
</target>
|
||||
|
||||
<target name="clean" depends="buildenvsetup">
|
||||
<exec executable="${python.exe}" dir="${mcp.home}">
|
||||
<arg value="${mcp.home}/runtime/cleanup.py" />
|
||||
<arg value="-f" />
|
||||
</exec>
|
||||
<exec executable="${python.exe}" dir="${mcp.home}">
|
||||
<arg value="${mcp.home}/runtime/decompile.py" />
|
||||
<arg value="-d" />
|
||||
<arg value="-n" />
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
<target name="reobfuscate" depends="buildenvsetup,recompile">
|
||||
<exec executable="${python.exe}" dir="${mcp.home}" failonerror="true">
|
||||
<arg value="${mcp.home}/runtime/reobfuscate.py" />
|
||||
</exec>
|
||||
<fail message="Reobfuscation failed">
|
||||
<condition>
|
||||
<not>
|
||||
<and>
|
||||
<available file="${mcp.home}/temp/client.md5"/>
|
||||
<available file="${mcp.home}/temp/client_reobf.md5"/>
|
||||
</and>
|
||||
</not>
|
||||
</condition>
|
||||
</fail>
|
||||
<exec executable="${python.exe}" dir="${mcp.home}">
|
||||
<arg value="${basedir}/generatechangedfilelist.py"/>
|
||||
<arg value="${mcp.home}"/>
|
||||
<arg value="${basedir}/difflist.txt"/>
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
<target name="recompile" depends="buildenvsetup">
|
||||
<exec executable="${python.exe}" dir="${mcp.home}" failonerror="true">
|
||||
<arg value="${mcp.home}/runtime/recompile.py" />
|
||||
</exec>
|
||||
<fail message="Compilation failed">
|
||||
<condition>
|
||||
<not>
|
||||
<available file="${mcp.home}/bin/minecraft/net/minecraft/client/Minecraft.class"/>
|
||||
</not>
|
||||
</condition>
|
||||
</fail>
|
||||
</target>
|
||||
|
||||
<target name="merge-client" depends="buildenvsetup">
|
||||
<copy todir="${client.mcp.srcdir}" overwrite="true" verbose="true">
|
||||
<fileset dir="${client.src.dir}" includes="**/*.java" />
|
||||
</copy>
|
||||
</target>
|
||||
|
||||
<target name="merge-common">
|
||||
<copy todir="${common.mcp.srcdir}" overwrite="true" verbose="true">
|
||||
<fileset dir="${common.src.dir}" includes="**/*.java" />
|
||||
</copy>
|
||||
</target>
|
||||
|
||||
<target name="merge-source" depends="buildenvsetup,merge-client,merge-common" />
|
||||
|
||||
<target name="build-client" depends="buildenvsetup,merge-client,merge-common,reobfuscate,makeversion"/>
|
||||
|
||||
<target name="extract-built-jar">
|
||||
<side prop="output" src="mcp.obfoutput" side="${side}" />
|
||||
<property name="jarname" value="${modname}-${side}-${version}" />
|
||||
<mkdir dir="${basedir}/target" />
|
||||
<zip destfile="${basedir}/target/${jarname}.zip">
|
||||
<fileset dir="${output}" includes="**/*.class" />
|
||||
<zipfileset dir="${basedir}" includes="fmlversion.properties"/>
|
||||
<zipfileset dir="${basedir}" includes="LICENSE-fml.txt" />
|
||||
<zipfileset dir="${basedir}" includes="install/CREDITS-fml.txt" fullpath="CREDITS-fml.txt"/>
|
||||
<zipfileset dir="${common.src.dir}" includes="*.cfg" />
|
||||
<mappedresources>
|
||||
<concat>
|
||||
<fileset dir="${basedir}/install" includes="README.txt" />
|
||||
<filterchain>
|
||||
<replacetokens>
|
||||
<token key="MAJOR" value="${version.major}" />
|
||||
<token key="MINOR" value="${version.minor}" />
|
||||
<token key="REV" value="${version.rev}" />
|
||||
<token key="BUILD" value="${version.build}" />
|
||||
<token key="MCVERSION" value="${version.minecraft}" />
|
||||
</replacetokens>
|
||||
</filterchain>
|
||||
</concat>
|
||||
<mergemapper to="README-fml.txt" />
|
||||
</mappedresources>
|
||||
</zip>
|
||||
</target>
|
||||
|
||||
<target name="build-universal" depends="build-client">
|
||||
<property name="universal.jarname" value="${modname}-universal-${version}" />
|
||||
<mkdir dir="${basedir}/target" />
|
||||
<jar destfile="${basedir}/target/${universal.jarname}.zip" duplicate="preserve">
|
||||
<manifest>
|
||||
<attribute name="Main-Class" value="net.minecraft.server.MinecraftServer"/>
|
||||
<attribute name="Class-Path" value="minecraft_server.jar"/>
|
||||
</manifest>
|
||||
<fileset dir="${client.mcp.obfoutput}" includes="**/*.class" />
|
||||
<zipfileset dir="${basedir}" includes="fmlversion.properties"/>
|
||||
<zipfileset dir="${basedir}" includes="LICENSE-fml.txt" />
|
||||
<zipfileset dir="${basedir}" includes="install/CREDITS-fml.txt" fullpath="CREDITS-fml.txt"/>
|
||||
<zipfileset dir="${common.src.dir}" includes="*.cfg" />
|
||||
<mappedresources>
|
||||
<concat>
|
||||
<fileset dir="${basedir}/install" includes="README.txt" />
|
||||
<filterchain>
|
||||
<replacetokens>
|
||||
<token key="MAJOR" value="${version.major}" />
|
||||
<token key="MINOR" value="${version.minor}" />
|
||||
<token key="REV" value="${version.rev}" />
|
||||
<token key="BUILD" value="${version.build}" />
|
||||
<token key="MCVERSION" value="${version.minecraft}" />
|
||||
</replacetokens>
|
||||
</filterchain>
|
||||
</concat>
|
||||
<mergemapper to="README-fml.txt" />
|
||||
</mappedresources>
|
||||
</jar>
|
||||
</target>
|
||||
|
||||
<target name="build-source-pack" depends="makeversion">
|
||||
<property name="srcpack.jarname" value="${modname}-src-${version}" />
|
||||
<zip destfile="${basedir}/target/${srcpack.jarname}.zip">
|
||||
<zipfileset dir="${basedir}" includes="LICENSE-fml.txt,difflist.txt,commands.patch,mcp_merge.cfg" prefix="fml" />
|
||||
<zipfileset dir="${common.src.dir}" includes="**/*.java" prefix="fml/common" />
|
||||
<zipfileset dir="${client.src.dir}" includes="**/*.java" prefix="fml/client" />
|
||||
<zipfileset dir="${basedir}" includes="fmlversion.properties" prefix="fml/common" />
|
||||
<zipfileset dir="${common.src.dir}" includes="*.cfg" prefix="fml/common" />
|
||||
<zipfileset dir="${patch.src.dir}" includes="**/*.patch" prefix="fml/patches" />
|
||||
<zipfileset dir="${fml.conf.dir}" prefix="fml/conf" />
|
||||
<mappedresources>
|
||||
<concat>
|
||||
<fileset dir="${basedir}/install" includes="README.txt" />
|
||||
<filterchain>
|
||||
<replacetokens>
|
||||
<token key="MAJOR" value="${version.major}" />
|
||||
<token key="MINOR" value="${version.minor}" />
|
||||
<token key="REV" value="${version.rev}" />
|
||||
<token key="BUILD" value="${version.build}" />
|
||||
<token key="MCVERSION" value="${version.minecraft}" />
|
||||
</replacetokens>
|
||||
</filterchain>
|
||||
</concat>
|
||||
<mergemapper to="fml/README-fml.txt" />
|
||||
</mappedresources>
|
||||
<zipfileset dir="${basedir}/install" excludes="README.txt,fml.pyc" prefix="fml" />
|
||||
</zip>
|
||||
</target>
|
||||
|
||||
<target name="build" depends="buildenvsetup,merge-client,merge-common,build-client,build-universal,build-source-pack" />
|
||||
|
||||
<target name="jenkinsbuild" depends="buildenvsetup,jenkinsfmldecompile,patch,build"/>
|
||||
|
||||
<target name="patch" depends="buildenvsetup">
|
||||
<exec executable="${python.exe}" dir="${basedir}">
|
||||
<arg value="${basedir}/applypatches.py" />
|
||||
<arg value="${basedir}" />
|
||||
<arg value="${mcp.srcdir}" />
|
||||
<arg value="${mcp.home}" />
|
||||
</exec>
|
||||
|
||||
</target>
|
||||
|
||||
<target name="setupenvironment" depends="buildenvsetup">
|
||||
<input message="This will clean the mcp environment at ${mcp.home} and backup any src-work folder there (src-base will be erased). Continue?" validargs="y,n" addproperty="do.continue" />
|
||||
<condition property="do.not.continue">
|
||||
<equals arg1="n" arg2="${do.continue}" />
|
||||
</condition>
|
||||
<fail if="do.not.continue">You have decided not to continue. This script will stop now.</fail>
|
||||
<echo>Preparing the MCP environment at ${mcp.home}</echo>
|
||||
<antcall target="fmldecompile"/>
|
||||
<echo>Moving old patched sources at ${patch.mcp.srcdir} out of the way</echo>
|
||||
<move todir="${mcp.home}/src-work${timestamp}" failonerror="false" verbose="true">
|
||||
<fileset dir="${patch.mcp.srcdir}"/>
|
||||
</move>
|
||||
<echo>Deleting old patch references at ${clean.mcp.srcdir}</echo>
|
||||
<delete dir="${clean.mcp.srcdir}" failonerror="false"/>
|
||||
<echo>Creating new patch references at ${clean.mcp.srcdir}</echo>
|
||||
<copy todir="${clean.mcp.srcdir}">
|
||||
<fileset dir="${mcp.srcdir}"/>
|
||||
</copy>
|
||||
<antcall target="cleanargo"/>
|
||||
<antcall target="patch"/>
|
||||
<echo>Creating clean patched references at ${patch.mcp.srcdir}</echo>
|
||||
<copy todir="${patch.mcp.srcdir}">
|
||||
<fileset dir="${mcp.srcdir}"/>
|
||||
</copy>
|
||||
<antcall target="writeversion"/>
|
||||
<echo>Setup complete! You should now be able to open ${basedir}/eclipse as a workspace in eclipse and import/refresh the FML-Server and FML-Client projects</echo>
|
||||
</target>
|
||||
|
||||
<target name="fmldecompile" depends="buildenvsetup">
|
||||
<exec executable="${python.exe}" dir="${mcp.home}">
|
||||
<arg value="${mcp.home}/runtime/cleanup.py" />
|
||||
<arg value="-f" />
|
||||
</exec>
|
||||
<exec executable="${python.exe}" dir="${basedir}">
|
||||
<arg value="${basedir}/decompile.py" />
|
||||
<arg value="${mcp.home}" />
|
||||
<arg value="${basedir}" />
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
<target name="jenkinsfmldecompile" depends="buildenvsetup">
|
||||
<exec executable="${python.exe}" dir="${mcp.home}">
|
||||
<arg value="${mcp.home}/runtime/cleanup.py" />
|
||||
<arg value="-f" />
|
||||
</exec>
|
||||
<exec executable="${python.exe}" dir="${basedir}">
|
||||
<arg value="${basedir}/decompile.py" />
|
||||
<arg value="${mcp.home}" />
|
||||
<arg value="${basedir}" />
|
||||
<arg value="-no_gen_conf" />
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
<target name="repatch" depends="buildenvsetup,checkpatches">
|
||||
<echo>Moving old patched sources at ${mcp.home}/src-work out of the way</echo>
|
||||
<move todir="${mcp.home}/src-work${timestamp}" failonerror="false" verbose="true">
|
||||
<fileset dir="${patch.mcp.srcdir}"/>
|
||||
</move>
|
||||
<delete dir="${mcp.srcdir}"/>
|
||||
<copy todir="${mcp.srcdir}">
|
||||
<fileset dir="${clean.mcp.srcdir}"/>
|
||||
</copy>
|
||||
|
||||
<antcall target="cleanargo"/>
|
||||
|
||||
<antcall target="patch"/>
|
||||
<copy todir="${patch.mcp.srcdir}">
|
||||
<fileset dir="${mcp.srcdir}"/>
|
||||
</copy>
|
||||
</target>
|
||||
|
||||
<target name="repatchclean" depends="buildenvsetup">
|
||||
<delete dir="${mcp.srcdir}"/>
|
||||
<copy todir="${mcp.srcdir}">
|
||||
<fileset dir="${clean.mcp.srcdir}"/>
|
||||
</copy>
|
||||
|
||||
<antcall target="cleanargo"/>
|
||||
|
||||
<antcall target="patch"/>
|
||||
</target>
|
||||
|
||||
<target name="cleanargo" depends="buildenvsetup">
|
||||
<delete dir="${client.mcp.srcdir}/argo"/>
|
||||
</target>
|
||||
|
||||
<target name="checkpatches" depends="buildenvsetup">
|
||||
<uptodate property="checkUptodate.uptodate">
|
||||
<srcfiles dir="${patch.mcp.srcdir}" includes="**/*.java">
|
||||
<present targetdir="${patch.src.dir}">
|
||||
<globmapper from="*.java" to="*.java.patch"/>
|
||||
</present>
|
||||
</srcfiles>
|
||||
<globmapper from="*.java" to="${patch.src.dir}/*.java.patch"/>
|
||||
</uptodate>
|
||||
<fail unless="checkUptodate.uptodate">
|
||||
A patch is out of date. Update your patches!
|
||||
</fail>
|
||||
</target>
|
||||
|
||||
<target name="updatepatches" depends="buildenvsetup">
|
||||
<exec executable="${python.exe}" dir="${basedir}">
|
||||
<arg value="${basedir}/update_patches.py" />
|
||||
<arg value="${mcp.home}"/>
|
||||
<arg value="${basedir}"/>
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
<target name="makerenamedsource" depends="buildenvsetup,repatch,merge-client,merge-common,reobfuscate">
|
||||
<copy todir="${tmp.mcp.srcdir}">
|
||||
<fileset dir="${mcp.srcdir}"/>
|
||||
</copy>
|
||||
<exec executable="${python.exe}" dir="${mcp.home}">
|
||||
<arg value="${mcp.home}/runtime/updatenames.py" />
|
||||
<arg value="-f" />
|
||||
</exec>
|
||||
<copy todir="${renamed.mcp.srcdir}">
|
||||
<fileset dir="${mcp.srcdir}"/>
|
||||
</copy>
|
||||
<move todir="${mcp.srcdir}">
|
||||
<fileset dir="${tmp.mcp.srcdir}"/>
|
||||
</move>
|
||||
</target>
|
||||
</project>
|
||||
@@ -1,3 +0,0 @@
|
||||
/.gradle/
|
||||
/build/
|
||||
/out/
|
||||
@@ -1,9 +0,0 @@
|
||||
repositories {
|
||||
maven { url = 'https://maven.minecraftforge.net/' }
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
implementation 'org.ow2.asm:asm:9.1'
|
||||
implementation 'org.ow2.asm:asm-tree:9.1'
|
||||
implementation 'net.minecraftforge:srgutils:0.4.+'
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
package net.minecraftforge.forge.tasks
|
||||
|
||||
import groovy.json.JsonBuilder
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.tasks.InputFile
|
||||
import org.gradle.api.tasks.OutputFile
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
import org.objectweb.asm.ClassReader
|
||||
import org.objectweb.asm.Opcodes
|
||||
import org.objectweb.asm.tree.ClassNode
|
||||
import org.objectweb.asm.tree.FieldNode
|
||||
import org.objectweb.asm.tree.MethodNode
|
||||
|
||||
import java.util.zip.ZipEntry
|
||||
import java.util.zip.ZipInputStream
|
||||
|
||||
abstract class BytecodeFinder extends DefaultTask {
|
||||
@InputFile abstract RegularFileProperty getJar()
|
||||
@OutputFile abstract RegularFileProperty getOutput()
|
||||
|
||||
BytecodeFinder() {
|
||||
output.convention(project.layout.buildDirectory.dir(name).map { it.file("output.json") })
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
protected void exec() {
|
||||
Util.init()
|
||||
|
||||
def outputFile = output.get().asFile
|
||||
if (outputFile.exists())
|
||||
outputFile.delete()
|
||||
|
||||
pre()
|
||||
|
||||
jar.get().asFile.withInputStream { i ->
|
||||
new ZipInputStream(i).withCloseable { zin ->
|
||||
ZipEntry zein
|
||||
while ((zein = zin.nextEntry) != null) {
|
||||
if (zein.name.endsWith('.class')) {
|
||||
def node = new ClassNode(Opcodes.ASM9)
|
||||
new ClassReader(zin).accept(node, 0)
|
||||
process(node)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
post()
|
||||
outputFile.text = new JsonBuilder(getData()).toPrettyString()
|
||||
}
|
||||
|
||||
|
||||
protected process(ClassNode node) {
|
||||
if (node.fields != null) node.fields.each { process(node, it) }
|
||||
if (node.methods != null) node.methods.each { process(node, it) }
|
||||
}
|
||||
|
||||
protected pre() {}
|
||||
protected process(ClassNode parent, FieldNode node) {}
|
||||
protected process(ClassNode parent, MethodNode node) {}
|
||||
protected post() {}
|
||||
protected abstract Object getData()
|
||||
}
|
||||
@@ -1,267 +0,0 @@
|
||||
package net.minecraftforge.forge.tasks
|
||||
|
||||
import net.minecraftforge.srgutils.IMappingFile
|
||||
import org.gradle.api.file.ConfigurableFileCollection
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.tasks.InputFile
|
||||
import org.gradle.api.tasks.InputFiles
|
||||
import org.gradle.api.tasks.Optional
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
import org.objectweb.asm.Opcodes
|
||||
|
||||
abstract class CheckATs extends DefaultTask {
|
||||
@InputFile abstract RegularFileProperty getInheritance()
|
||||
@InputFiles abstract ConfigurableFileCollection getAts()
|
||||
@InputFile @Optional abstract RegularFileProperty getMappings()
|
||||
|
||||
@TaskAction
|
||||
protected void exec() {
|
||||
def mappings = mappings.map { IMappingFile.load(it.asFile) }.getOrNull()
|
||||
Util.init()
|
||||
def parse = { line ->
|
||||
def idx = line.indexOf('#')
|
||||
def comment = idx == -1 ? null : line.substring(idx)
|
||||
if (idx != -1) line = line.substring(0, idx - 1)
|
||||
def (modifier, cls, desc) = (line.trim() + ' ').split(' ', -1)
|
||||
def key = cls + (desc.isEmpty() ? '' : ' ' + desc)
|
||||
return [modifier, cls, desc, comment, key]
|
||||
}
|
||||
def accessLevel = { access ->
|
||||
if ((access & Opcodes.ACC_PUBLIC) != 0) return 3
|
||||
if ((access & Opcodes.ACC_PROTECTED) != 0) return 2
|
||||
if ((access & Opcodes.ACC_PRIVATE) != 0) return 0
|
||||
return 1
|
||||
}
|
||||
def accessStr = { access ->
|
||||
if (access.endsWith('-f') || access.endsWith('+f'))
|
||||
return 4
|
||||
switch (access.toLowerCase()) {
|
||||
case 'public': return 3
|
||||
case 'protected': return 2
|
||||
case 'default': return 1
|
||||
case 'private': return 0
|
||||
default: return -1
|
||||
}
|
||||
}
|
||||
def json = inheritance.get().asFile.json()
|
||||
|
||||
ats.each { f ->
|
||||
TreeMap lines = [:]
|
||||
def group = null
|
||||
for (def line : f.readLines()) {
|
||||
if (line.isEmpty()) continue
|
||||
if (line.startsWith('#group ')) {
|
||||
def (modifier, cls, desc, comment, key) = parse.call(line.substring(7))
|
||||
|
||||
if (desc != '*' && desc != '*()' && desc != '<init>')
|
||||
throw new IllegalStateException('Invalid group: ' + line)
|
||||
|
||||
group = [modifier: modifier, cls: cls, desc: desc, comment: comment,
|
||||
existing: [] as Set,
|
||||
children: [] as TreeSet,
|
||||
group: true
|
||||
]
|
||||
if (lines.containsKey(key))
|
||||
throw new IllegalStateException('Duplicate group: ' + line)
|
||||
|
||||
lines[key] = group
|
||||
} else if (group != null) {
|
||||
if (line.startsWith('#endgroup')) {
|
||||
group = null
|
||||
} else {
|
||||
def (modifier, cls, desc, comment, key) = parse.call(line)
|
||||
group['existing'].add(key)
|
||||
}
|
||||
} else if (line.startsWith('#endgroup')) {
|
||||
throw new IllegalStateException('Invalid group ending: ' + line)
|
||||
} else if (line.startsWith('#')) {
|
||||
//Nom
|
||||
} else {
|
||||
def (modifier, cls, desc, comment, key) = parse.call(line)
|
||||
if (lines.containsKey(key)) {
|
||||
println('Duplicate: ' + line)
|
||||
continue
|
||||
}
|
||||
lines[key] = [modifier: modifier, cls: cls, desc: desc, comment: comment, group: false]
|
||||
}
|
||||
}
|
||||
|
||||
// Process Groups, this will remove any entries outside the group that is covered by the group
|
||||
for (def key : new ArrayList<>(lines.keySet())) {
|
||||
def entry = lines.get(key)
|
||||
if (entry != null && entry['group']) {
|
||||
def cls = entry['cls']
|
||||
def jcls = json.get(cls.replaceAll('\\.', '/'))
|
||||
if (jcls == null) {
|
||||
lines.remove(key)
|
||||
println('Invalid Group: ' + key)
|
||||
} else if ('*' == entry['desc']) {
|
||||
if (!jcls.containsKey('fields')) {
|
||||
lines.remove(key)
|
||||
println('Invalid Group, Class has no fields: ' + key)
|
||||
} else {
|
||||
jcls['fields'].each { field, value ->
|
||||
def fkey = cls + ' ' + field
|
||||
if (accessLevel.call(value['access']) < accessStr.call(entry['modifier'])) {
|
||||
if (lines.containsKey(fkey)) {
|
||||
lines.remove(fkey)
|
||||
} else if (!entry['existing'].contains(fkey)) {
|
||||
println('Added: ' + fkey)
|
||||
}
|
||||
entry['children'].add(fkey)
|
||||
} else if (lines.containsKey(fkey)) {
|
||||
lines.remove(fkey)
|
||||
println('Removed: ' + fkey)
|
||||
}
|
||||
}
|
||||
entry['existing'].stream().findAll{ !entry['children'].contains(it) }.each{ println('Removed: ' + it) }
|
||||
}
|
||||
} else if ('*()' == entry['desc']) {
|
||||
if (!jcls.containsKey('methods')) {
|
||||
lines.remove(key)
|
||||
println('Invalid Group, Class has no methods: ' + key)
|
||||
} else {
|
||||
jcls['methods'].each{ mtd, value ->
|
||||
if (mtd.startsWith('<clinit>') || mtd.startsWith('lambda$'))
|
||||
return
|
||||
key = cls + ' ' + mtd.replace(' ', '')
|
||||
if (accessLevel.call(value['access']) < accessStr.call(entry['modifier'])) {
|
||||
if (lines.containsKey(key)) {
|
||||
lines.remove(key)
|
||||
} else if (!entry['existing'].contains(key)) {
|
||||
println('Added: ' + key)
|
||||
}
|
||||
entry['children'].add(key)
|
||||
} else if (lines.containsKey(key)) {
|
||||
lines.remove(key)
|
||||
println('Removed: ' + key)
|
||||
}
|
||||
}
|
||||
entry['existing'].stream().findAll{ !entry['children'].contains(it) }.each{ println('Removed: ' + it) }
|
||||
}
|
||||
} else if ('<init>' == entry['desc']) { //Make all public non-abstract subclasses
|
||||
json.each{ tcls,value ->
|
||||
if (!value.containsKey('methods') || ((value['access'] & Opcodes.ACC_ABSTRACT) != 0))
|
||||
return
|
||||
def parents = [] as Set
|
||||
def parent = tcls
|
||||
while (parent != null && json.containsKey(parent)) {
|
||||
parents.add(parent)
|
||||
def p = json[parent]
|
||||
parent = p == null ? null : p['superName']
|
||||
}
|
||||
if (parents.contains(cls.replaceAll('\\.', '/'))) {
|
||||
value['methods'].each{ mtd, v ->
|
||||
if (mtd.startsWith('<init>')) {
|
||||
def child = tcls.replaceAll('/', '\\.') + ' ' + mtd.replace(' ', '')
|
||||
if (accessLevel.call(v['access']) < 3) {
|
||||
if (lines.containsKey(child)) {
|
||||
lines.remove(child)
|
||||
} else if (!entry['existing'].contains(child)) {
|
||||
println('Added: ' + child)
|
||||
}
|
||||
entry['children'].add(child)
|
||||
} else if (lines.containsKey(child)) {
|
||||
lines.remove(child)
|
||||
println('Removed: ' + child)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
entry['existing'].stream().findAll{ !entry['children'].contains(it) }.each{ println('Removed: ' + it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Process normal lines, remove invalid and remove narrowing
|
||||
for (def key : new ArrayList<>(lines.keySet())) {
|
||||
def entry = lines.get(key)
|
||||
if (entry != null && !entry['group']) {
|
||||
def cls = entry['cls']
|
||||
def jcls = json.get(cls.replaceAll('\\.', '/'))
|
||||
if (jcls == null) {
|
||||
lines.remove(key)
|
||||
println('Invalid: ' + key)
|
||||
} else if (entry['desc'] == '') {
|
||||
if (accessLevel.call(jcls['access']) > accessStr.call(entry['modifier']) && (entry.comment == null || !entry.comment.startsWith('#force '))) {
|
||||
lines.remove(key)
|
||||
println('Invalid Narrowing: ' + key)
|
||||
}
|
||||
} else if (!entry['desc'].contains('(')) {
|
||||
if (!jcls.containsKey('fields') || !jcls['fields'].containsKey(entry['desc'])) {
|
||||
lines.remove(key)
|
||||
println('Invalid: ' + key)
|
||||
} else {
|
||||
def value = jcls['fields'][entry['desc']]
|
||||
if (accessLevel.call(value['access']) > accessStr.call(entry['modifier']) && (entry.comment == null || !entry.comment.startsWith('#force '))) {
|
||||
lines.remove(key)
|
||||
println('Invalid Narrowing: ' + key)
|
||||
println(entry.comment)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
def jdesc = entry['desc'].replace('(', ' (')
|
||||
if (!jcls.containsKey('methods') || !jcls['methods'].containsKey(jdesc)) {
|
||||
lines.remove(key)
|
||||
println('Invalid: ' + key)
|
||||
} else {
|
||||
def value = jcls['methods'][jdesc]
|
||||
if (accessLevel.call(value['access']) > accessStr.call(entry['modifier']) && (entry.comment == null || !entry.comment.startsWith('#force '))) {
|
||||
lines.remove(key)
|
||||
println('Invalid Narrowing: ' + key)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def data = []
|
||||
def remapComment = { entry ->
|
||||
if (!mappings || !entry || !entry.desc) return null
|
||||
def comment = entry.comment?.substring(1)?.trim()
|
||||
def jsonCls = json.get(entry.cls.replaceAll('\\.', '/'))
|
||||
def mappingsClass = mappings?.getClass(jsonCls.name)
|
||||
if (!mappingsClass) return entry.comment
|
||||
def idx = entry.desc.indexOf('(')
|
||||
def mappedName = idx == -1
|
||||
? mappingsClass.remapField(entry.desc)
|
||||
: mappingsClass.remapMethod(entry.desc.substring(0, idx), entry.desc.substring(idx))
|
||||
if (!mappedName) return entry.comment
|
||||
if (mappedName == '<init>')
|
||||
mappedName = 'constructor'
|
||||
|
||||
if (comment?.startsWith(mappedName))
|
||||
return '# ' + comment
|
||||
if (comment && comment.indexOf(' ') != -1) {
|
||||
def split = comment.split(" - ").toList()
|
||||
if (split[0].indexOf(' ') != -1)
|
||||
// The first string is more than one word, so append before it
|
||||
return "# ${mappedName} - ${comment}"
|
||||
split.remove(0)
|
||||
return "# ${mappedName} - ${String.join(' - ', split)}"
|
||||
}
|
||||
return '# ' + mappedName
|
||||
}
|
||||
lines.each { key,value ->
|
||||
if (!value.group) {
|
||||
def comment = remapComment.call(value)
|
||||
data.add(value.modifier + ' ' + key + (comment ? ' ' + comment : ''))
|
||||
} else {
|
||||
data.add('#group ' + value.modifier + ' ' + key + (value.comment == null ? '' : ' ' + value.comment))
|
||||
value.children.each {
|
||||
def line = value.modifier + ' ' + it
|
||||
def (modifier, cls, desc, comment) = parse.call(line)
|
||||
comment = remapComment.call([modifier: modifier, cls: cls, desc: desc, comment: comment])
|
||||
data.add(line + (comment ? ' ' + comment : ''))
|
||||
}
|
||||
data.add('#endgroup')
|
||||
}
|
||||
}
|
||||
f.text = data.join('\n')
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
package net.minecraftforge.forge.tasks
|
||||
|
||||
import org.gradle.api.file.ConfigurableFileCollection
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.tasks.InputFile
|
||||
import org.gradle.api.tasks.InputFiles
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
|
||||
import org.objectweb.asm.ClassReader
|
||||
import org.objectweb.asm.ClassVisitor
|
||||
import org.objectweb.asm.MethodVisitor
|
||||
import org.objectweb.asm.Opcodes
|
||||
import org.objectweb.asm.Type
|
||||
|
||||
import java.util.zip.ZipEntry
|
||||
import java.util.zip.ZipInputStream
|
||||
|
||||
abstract class CheckExcs extends DefaultTask {
|
||||
@InputFile abstract RegularFileProperty getBinary()
|
||||
@InputFiles abstract ConfigurableFileCollection getExcs()
|
||||
|
||||
@TaskAction
|
||||
protected void exec() {
|
||||
Util.init()
|
||||
def known = []
|
||||
binary.get().asFile.withInputStream { i ->
|
||||
new ZipInputStream(i).withCloseable { zin ->
|
||||
def visitor = new ClassVisitor(Opcodes.ASM9) {
|
||||
private String cls
|
||||
@Override
|
||||
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
|
||||
this.cls = name
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
|
||||
known.add(this.cls + '.' + name + descriptor)
|
||||
super.visitMethod(access, name, descriptor, signature, exceptions)
|
||||
}
|
||||
}
|
||||
ZipEntry zein
|
||||
while ((zein = zin.nextEntry) != null) {
|
||||
if (zein.name.endsWith('.class')) {
|
||||
ClassReader reader = new ClassReader(zin)
|
||||
reader.accept(visitor, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
excs.each { f ->
|
||||
def lines = []
|
||||
f.eachLine { line ->
|
||||
def idx = line.indexOf('#')
|
||||
if (idx == 0 || line.isEmpty()) {
|
||||
return
|
||||
}
|
||||
|
||||
def comment = idx == -1 ? null : line.substring(idx)
|
||||
if (idx != -1) line = line.substring(0, idx - 1)
|
||||
|
||||
if (!line.contains('=')) {
|
||||
println('Invalid: ' + line)
|
||||
return
|
||||
}
|
||||
|
||||
def (key, value) = line.split('=', 2)
|
||||
if (!known.contains(key)) {
|
||||
println('Unknown: ' + line)
|
||||
return
|
||||
}
|
||||
|
||||
def (cls, desc) = key.split('\\.', 2)
|
||||
if (!desc.contains('(')) {
|
||||
println('Invalid: ' + line)
|
||||
return
|
||||
}
|
||||
def name = desc.split('\\(', 2)[0]
|
||||
desc = '(' + desc.split('\\(', 2)[1]
|
||||
|
||||
def (exceptions, args) = value.contains('|') ? value.split('|', 2) : [value, '']
|
||||
|
||||
if (args.split(',').length != Type.getArgumentTypes(desc).length) {
|
||||
println('Invalid: ' + line)
|
||||
return
|
||||
}
|
||||
lines.add(line)
|
||||
}
|
||||
f.text = lines.sort().join('\n')
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,219 +0,0 @@
|
||||
package net.minecraftforge.forge.tasks
|
||||
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.file.DirectoryProperty
|
||||
import org.gradle.api.tasks.Input
|
||||
import org.gradle.api.tasks.InputDirectory
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Paths
|
||||
import java.util.regex.Pattern
|
||||
|
||||
abstract class CheckPatches extends DefaultTask {
|
||||
@InputDirectory abstract DirectoryProperty getPatchDir()
|
||||
@Input boolean autoFix = false
|
||||
|
||||
@TaskAction
|
||||
protected void exec() {
|
||||
def hasS2SArtifact = [
|
||||
Paths.get("patches/minecraft/net/minecraft/client/renderer/ViewArea.java.patch"),
|
||||
Paths.get("patches/minecraft/net/minecraft/data/models/blockstates/Variant.java.patch")
|
||||
]
|
||||
|
||||
def verified = true;
|
||||
patchDir.get().asFileTree.each { patch ->
|
||||
def patchPath = project.rootDir.toPath().relativize(patch.toPath())
|
||||
verified &= verifyPatch(patch, autoFix, patchPath.toString(), hasS2SArtifact.contains(patchPath))
|
||||
}
|
||||
|
||||
if (!verified)
|
||||
throw new RuntimeException('One or more patches failed verification. Check the log for errors.')
|
||||
}
|
||||
|
||||
def verifyPatch(patch, fix, patchPath, hasS2SArtifact) {
|
||||
def hunk_start_pattern = Pattern.compile('^@@ -[0-9,]* \\+[0-9,_]* @@$')
|
||||
def white_space_pattern = Pattern.compile('^[+\\-]\\s*$')
|
||||
def import_pattern = Pattern.compile('^[+\\-]\\s*import.*')
|
||||
def field_pattern = Pattern.compile('^[+\\-][\\s]*((public|protected|private)[\\s]*)?(static[\\s]*)?(final)?([^=;]*)(=.*)?;\\s*$')
|
||||
def method_pattern = Pattern.compile('^[+\\-][\\s]*((public|protected|private)[\\s]*)?(static[\\s]*)?(final)?([^(]*)[(]([^)]*)?[)]\\s*[{]\\s*$')
|
||||
def class_pattern = Pattern.compile('^[+\\-][\\s]*((public|protected|private)[\\s]*)?(static[\\s]*)?(final[\\s]*)?(class|interface)([^{]*)[{]\\s*$')
|
||||
|
||||
def accessMap = [("private"):0, (null):1, ("protected"):2, ("public"):3]
|
||||
|
||||
def hasProblem = false;
|
||||
def lines = patch.readLines()
|
||||
|
||||
def hunksStart = 0
|
||||
def onlyWhiteSpace = false
|
||||
|
||||
def didFix = false
|
||||
def newLines = []
|
||||
def whiteSpaceErrors = []
|
||||
|
||||
// First two lines are file name ++/-- and we do not care
|
||||
newLines.add(lines[0] + '\n')
|
||||
newLines.add(lines[1] + '\n')
|
||||
|
||||
int i = 2
|
||||
for (; i < lines.size(); ++i) {
|
||||
def line = lines[i]
|
||||
newLines.add(line + '\n')
|
||||
|
||||
if (hunk_start_pattern.matcher(line).find()) {
|
||||
if (onlyWhiteSpace) {
|
||||
if (fix || hasS2SArtifact) {
|
||||
logger.lifecycle("Removing white space hunk starting at line {}, file: {}", hunksStart + 1, patchPath)
|
||||
def toRemove = i - hunksStart;
|
||||
while (toRemove-- > 0)
|
||||
newLines.remove(newLines.size() - 1)
|
||||
didFix = true
|
||||
}
|
||||
else {
|
||||
logger.lifecycle("Patch contains only white space hunk starting at line {}, file: {}", hunksStart + 1, patchPath)
|
||||
hasProblem = true
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!whiteSpaceErrors.empty)
|
||||
hasProblem = true
|
||||
whiteSpaceErrors.each { error -> logger.lifecycle(error) }
|
||||
whiteSpaceErrors.clear()
|
||||
}
|
||||
hunksStart = i
|
||||
onlyWhiteSpace = true
|
||||
continue
|
||||
}
|
||||
|
||||
if (line.startsWithAny('+','-')) {
|
||||
def prefixChange = false
|
||||
def prevLine = lines[i - 1]
|
||||
|
||||
if (line.charAt(0) == (char)'+' && prevLine.charAt(0) == (char)'-') {
|
||||
def prevTrim = prevLine.substring(1).replaceAll("\\s", "")
|
||||
def currTrim = line.substring(1).replaceAll("\\s", "")
|
||||
|
||||
if (prevTrim.equals(currTrim)) {
|
||||
prefixChange = true
|
||||
}
|
||||
|
||||
def pMatcher = field_pattern.matcher(prevLine)
|
||||
def cMatcher = field_pattern.matcher(line)
|
||||
|
||||
if (pMatcher.find() && cMatcher.find() &&
|
||||
pMatcher.group(6) == cMatcher.group(6) && // = ...
|
||||
pMatcher.group(5) == cMatcher.group(5) && // field name
|
||||
pMatcher.group(3) == cMatcher.group(3) && // static
|
||||
(accessMap[pMatcher.group(2)] < accessMap[cMatcher.group(2)] || pMatcher.group(4) != cMatcher.group(4))) {
|
||||
logger.lifecycle("Patch contains access changes or final removal at line {}, file: {}", i + 1, patchPath)
|
||||
hasProblem = true
|
||||
}
|
||||
|
||||
pMatcher = method_pattern.matcher(prevLine)
|
||||
cMatcher = method_pattern.matcher(line)
|
||||
|
||||
if (pMatcher.find() && cMatcher.find() &&
|
||||
pMatcher.group(6) == cMatcher.group(6) && // params
|
||||
pMatcher.group(5) == cMatcher.group(5) && // <T> void name
|
||||
pMatcher.group(3) == cMatcher.group(3) && // static
|
||||
(accessMap[pMatcher.group(2)] < accessMap[cMatcher.group(2)] || pMatcher.group(4) != cMatcher.group(4))) {
|
||||
logger.lifecycle("Patch contains access changes or final removal at line {}, file: {}", i + 1, patchPath)
|
||||
hasProblem = true
|
||||
}
|
||||
|
||||
pMatcher = class_pattern.matcher(prevLine)
|
||||
cMatcher = class_pattern.matcher(line)
|
||||
|
||||
if (pMatcher.find() && cMatcher.find() &&
|
||||
pMatcher.group(6) == cMatcher.group(6) && // ClassName<> extends ...
|
||||
pMatcher.group(5) == cMatcher.group(5) && // class | interface
|
||||
pMatcher.group(3) == cMatcher.group(3) && // static
|
||||
(accessMap[pMatcher.group(2)] < accessMap[cMatcher.group(2)] || pMatcher.group(4) != cMatcher.group(4))) {
|
||||
logger.lifecycle("Patch contains access changes or final removal at line {}, file: {}", i + 1, patchPath)
|
||||
hasProblem = true
|
||||
}
|
||||
}
|
||||
|
||||
if (line.charAt(0) == (char)'-' && i + 1 < lines.size()) {
|
||||
def nextLine = lines[i + 1]
|
||||
if (nextLine.charAt(0) == (char)'+') {
|
||||
def nextTrim = nextLine.substring(1).replaceAll("\\s", "")
|
||||
def currTrim = line.substring(1).replaceAll("\\s", "")
|
||||
|
||||
if (nextTrim.equals(currTrim)) {
|
||||
prefixChange = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def isWhiteSpaceChange = white_space_pattern.matcher(line).find()
|
||||
|
||||
if (!prefixChange && !isWhiteSpaceChange) {
|
||||
onlyWhiteSpace = hasS2SArtifact && import_pattern.matcher(line).find()
|
||||
}
|
||||
else if (isWhiteSpaceChange) {
|
||||
def prevLineChange = prevLine.startsWithAny('+','-')
|
||||
def nextLineChange = i + 1 < lines.size() && lines[i + 1].startsWithAny('+','-')
|
||||
|
||||
if (!prevLineChange && !nextLineChange) {
|
||||
whiteSpaceErrors.add(String.format("Patch contains white space change in valid hunk at line %d (cannot auto fix), file: %s", i + 1, patchPath))
|
||||
}
|
||||
}
|
||||
|
||||
if (line.contains("\t")) {
|
||||
if (!fix) {
|
||||
logger.lifecycle("Patch contains tabs on line {}, file: {}", i + 1, patchPath)
|
||||
hasProblem = true
|
||||
}
|
||||
else {
|
||||
logger.lifecycle("Fixing tabs on line {}, file: {}", i + 1, patchPath)
|
||||
line = line.replaceAll('\t', ' ')
|
||||
newLines.remove(newLines.size() - 1)
|
||||
newLines.add(line + '\n')
|
||||
didFix = true
|
||||
}
|
||||
}
|
||||
|
||||
if (import_pattern.matcher(line).find() && !hasS2SArtifact) {
|
||||
logger.lifecycle("Patch contains import change on line {}, file: {}", i + 1, patchPath)
|
||||
hasProblem = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (onlyWhiteSpace) {
|
||||
if (fix || hasS2SArtifact) {
|
||||
logger.lifecycle("Removing white space hunk starting at line {}, file: {}", hunksStart + 1, patchPath)
|
||||
def toRemove = i - hunksStart;
|
||||
while (toRemove-- > 0)
|
||||
newLines.remove(newLines.size() - 1)
|
||||
didFix = true
|
||||
}
|
||||
else {
|
||||
logger.lifecycle("Patch contains only white space hunk starting at line {}, file: {}", hunksStart + 1, patchPath)
|
||||
hasProblem = true
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!whiteSpaceErrors.empty)
|
||||
hasProblem = true
|
||||
whiteSpaceErrors.each { error -> logger.lifecycle(error) }
|
||||
}
|
||||
|
||||
if (didFix) {
|
||||
if (newLines.size() <= 2) {
|
||||
logger.lifecycle("Patch is now empty removing, file: {}", patchPath)
|
||||
Files.delete(patch.toPath())
|
||||
}
|
||||
else {
|
||||
if (!hasS2SArtifact)
|
||||
logger.lifecycle("*** Updating patch file. Please run setup then genPatches again. ***")
|
||||
patch.withWriter('UTF-8') { writer ->
|
||||
newLines.each { l -> writer.write(l) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return !hasProblem
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
package net.minecraftforge.forge.tasks
|
||||
|
||||
import org.gradle.api.file.ConfigurableFileCollection
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.tasks.InputFile
|
||||
import org.gradle.api.tasks.InputFiles
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
|
||||
abstract class CheckSAS extends DefaultTask {
|
||||
@InputFile abstract RegularFileProperty getInheritance()
|
||||
@InputFiles abstract ConfigurableFileCollection getSass()
|
||||
|
||||
@TaskAction
|
||||
protected void exec() {
|
||||
Util.init()
|
||||
def json = inheritance.get().asFile.json()
|
||||
|
||||
sass.each { f ->
|
||||
def lines = []
|
||||
f.eachLine { line ->
|
||||
if (line[0] == '\t') return //Skip any tabbed lines, those are ones we add
|
||||
def idx = line.indexOf('#')
|
||||
if (idx == 0 || line.isEmpty()) {
|
||||
lines.add(line)
|
||||
return
|
||||
}
|
||||
def comment = idx == -1 ? null : line.substring(idx)
|
||||
if (idx != -1) line = line.substring(0, idx - 1)
|
||||
def (cls, desc) = (line.trim() + ' ').split(' ', -1)
|
||||
cls = cls.replaceAll('\\.', '/')
|
||||
desc = desc.replace('(', ' (')
|
||||
|
||||
if (json[cls] == null || (!desc.isEmpty() && (json[cls]['methods'] == null || json[cls]['methods'][desc] == null))) {
|
||||
println('Invalid: ' + line)
|
||||
return
|
||||
}
|
||||
|
||||
//Class SAS
|
||||
if (desc.isEmpty()) {
|
||||
lines.add(cls + (comment == null ? '' : ' ' + comment))
|
||||
if (json[cls]['methods'] != null)
|
||||
(json[cls]['methods'] as TreeMap).each {
|
||||
findChildMethods(json, cls, it.key).each { lines.add('\t' + it) }
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
//Method SAS
|
||||
lines.add(cls + ' ' + desc.replace(' ', '') + (comment == null ? '' : ' ' + comment))
|
||||
findChildMethods(json, cls, desc).each { lines.add('\t' + it) }
|
||||
}
|
||||
f.text = lines.join('\n')
|
||||
}
|
||||
}
|
||||
|
||||
protected static findChildMethods(json, cls, desc)
|
||||
{
|
||||
return json.values().findAll{ it.methods != null && it.methods[desc] != null && it.methods[desc].override == cls}
|
||||
.collect { it.name + ' ' + desc.replace(' ', '') } as TreeSet
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
package net.minecraftforge.forge.tasks
|
||||
|
||||
import java.util.function.BiConsumer
|
||||
|
||||
public class ClosureHelper {
|
||||
BiConsumer<String, Closure> callback
|
||||
|
||||
public ClosureHelper(Closure cl, BiConsumer<String, Closure> callback) {
|
||||
this.callback = callback
|
||||
apply(this, cl)
|
||||
}
|
||||
|
||||
|
||||
def methodMissing(String name, Object args) {
|
||||
if (!args.class.isArray()) return
|
||||
Object[] aargs = (Object[])args
|
||||
|
||||
if (aargs.length == 1 && aargs[0] instanceof Closure) {
|
||||
this.callback.accept(name, (Closure)aargs[0])
|
||||
} else {
|
||||
throw new IllegalArgumentException('Unknown method: "' + name + '" with arguments ' + args + ' for ' + this)
|
||||
}
|
||||
}
|
||||
|
||||
static <T> T apply(T obj, Closure cl) {
|
||||
cl.delegate = obj
|
||||
cl.resolveStrategy = Closure.DELEGATE_FIRST
|
||||
cl()
|
||||
return obj
|
||||
}
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
package net.minecraftforge.forge.tasks
|
||||
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.provider.Property
|
||||
import org.gradle.api.tasks.Input
|
||||
import org.gradle.api.tasks.Optional
|
||||
import org.gradle.api.tasks.OutputFile
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
|
||||
import java.util.zip.ZipEntry
|
||||
import java.util.zip.ZipInputStream
|
||||
import java.util.zip.ZipOutputStream
|
||||
|
||||
abstract class Crowdin extends DefaultTask {
|
||||
@Input abstract Property<String> getId()
|
||||
@Input @Optional abstract Property<String> getKey()
|
||||
@Input boolean json = true
|
||||
@OutputFile abstract RegularFileProperty getOutput()
|
||||
@OutputFile abstract RegularFileProperty getExport()
|
||||
|
||||
Crowdin() {
|
||||
outputs.upToDateWhen{ false }
|
||||
id.convention('minecraft-forge')
|
||||
output.convention(project.layout.buildDirectory.dir(name).map {it.file("output.zip") })
|
||||
export.convention(project.layout.buildDirectory.dir(name).map {it.file("export.json") })
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
def run() {
|
||||
File outputFile = output.get().asFile
|
||||
File exportFile = export.get().asFile
|
||||
if (outputFile.exists())
|
||||
outputFile.delete()
|
||||
|
||||
if (!key.isPresent())
|
||||
return
|
||||
String key = this.key.get()
|
||||
String id = this.id.get()
|
||||
|
||||
// Force an export
|
||||
new URL("https://api.crowdin.com/api/project/${id}/export?key=${key}").withInputStream { i ->
|
||||
exportFile.withOutputStream { it << i }
|
||||
}
|
||||
|
||||
if (!exportFile.text.contains('success')) {
|
||||
throw new RuntimeException("Crowdin export failed, see ${exportFile} for more info")
|
||||
}
|
||||
|
||||
new URL("https://api.crowdin.com/api/project/${id}/download/all.zip?key=${key}").withInputStream { i ->
|
||||
new ZipInputStream(i).withCloseable { zin ->
|
||||
outputFile.withOutputStream { out ->
|
||||
new ZipOutputStream(out).withCloseable { zout ->
|
||||
ZipEntry zein
|
||||
while ((zein = zin.nextEntry) != null) {
|
||||
if (zein.isDirectory()) {
|
||||
zout.putNextEntry(new ZipEntry(zein.name))
|
||||
} else {
|
||||
// 1.13+ uses json
|
||||
if (zein.name.endsWith('.json') == json) {
|
||||
ZipEntry zeout = new ZipEntry(json ? zein.name.toLowerCase() : zein.name)
|
||||
zeout.time = 1
|
||||
zout.putNextEntry(zeout)
|
||||
zout << zin
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
package net.minecraftforge.forge.tasks
|
||||
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.file.ConfigurableFileCollection
|
||||
import org.gradle.api.file.DirectoryProperty
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.tasks.InputFile
|
||||
import org.gradle.api.tasks.Internal
|
||||
import org.gradle.api.tasks.OutputFile
|
||||
import org.gradle.api.tasks.OutputFiles
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
import org.gradle.api.tasks.OutputDirectory
|
||||
|
||||
import java.nio.file.Files
|
||||
|
||||
abstract class DownloadLibraries extends DefaultTask {
|
||||
@InputFile abstract RegularFileProperty getInput()
|
||||
@OutputDirectory abstract DirectoryProperty getOutput()
|
||||
@OutputFile abstract RegularFileProperty getLibrariesOutput()
|
||||
|
||||
DownloadLibraries() {
|
||||
output.convention(project.layout.buildDirectory.dir(name))
|
||||
librariesOutput.convention(project.layout.buildDirectory.dir(name).map(d -> d.file('libraries.txt')))
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
def run() {
|
||||
Util.init()
|
||||
File outputDir = output.get().asFile
|
||||
def libraries = new ArrayList()
|
||||
|
||||
def json = input.get().asFile.json().libraries.each { lib ->
|
||||
//TODO: Thread?
|
||||
def artifacts = [lib.downloads.artifact] + lib.downloads.get('classifiers', [:]).values()
|
||||
artifacts.each{ art ->
|
||||
def target = new File(outputDir, art.path)
|
||||
libraries.add(target.absolutePath)
|
||||
if (!target.exists() || !art.sha1.equals(target.sha1())) {
|
||||
project.logger.lifecycle("Downloading ${art.url}")
|
||||
if (!target.parentFile.exists()) {
|
||||
target.parentFile.mkdirs()
|
||||
}
|
||||
new URL(art.url).withInputStream { i ->
|
||||
target.withOutputStream { it << i }
|
||||
}
|
||||
if (!art.sha1.equals(target.sha1())) {
|
||||
throw new IllegalStateException("Failed to download ${art.url} to ${target.canonicalPath} SHA Mismatch")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Files.write(librariesOutput.get().asFile.toPath(), libraries)
|
||||
}
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
package net.minecraftforge.forge.tasks
|
||||
|
||||
import groovy.transform.EqualsAndHashCode
|
||||
|
||||
import java.util.ArrayList
|
||||
import java.util.HashMap
|
||||
import java.util.TreeMap
|
||||
import java.util.TreeSet
|
||||
import java.util.function.BiConsumer
|
||||
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.tasks.*
|
||||
|
||||
import org.objectweb.asm.Opcodes
|
||||
import org.objectweb.asm.Type
|
||||
import org.objectweb.asm.tree.ClassNode
|
||||
import org.objectweb.asm.tree.FieldNode
|
||||
import org.objectweb.asm.tree.MethodNode
|
||||
|
||||
import static org.objectweb.asm.Opcodes.*
|
||||
|
||||
abstract class FieldCompareFinder extends BytecodeFinder {
|
||||
@Nested
|
||||
Map<String, Search> fields = [:] as HashMap
|
||||
@Internal
|
||||
Map<Search, String> fieldsReverse = [:] as HashMap
|
||||
@Internal
|
||||
Map<String, Set<ObjectTarget>> targets = [:] as TreeMap
|
||||
|
||||
@Override
|
||||
protected pre() {
|
||||
//fields.each{ k,v -> logger.lifecycle("Fields: " + k + ' ' + v) }
|
||||
}
|
||||
|
||||
@Override
|
||||
protected process(ClassNode parent, MethodNode node) {
|
||||
def last = null
|
||||
def parentInstance = new ObjectTarget(owner: parent.name, name: '', desc: '')
|
||||
for (int x = 0; x < node.instructions.size(); x++) {
|
||||
def current = node.instructions.get(x)
|
||||
if (current.opcode == IF_ACMPEQ || current.opcode == IF_ACMPNE) {
|
||||
if (last != null && (last.opcode == GETSTATIC || last.opcode == GETFIELD)) {
|
||||
def target = new Search(cls: last.owner, name: last.name)
|
||||
def wanted = fieldsReverse.get(target)
|
||||
def original = fields.get(wanted)
|
||||
def instance = new ObjectTarget(owner: parent.name, name: node.name, desc: node.desc)
|
||||
if (wanted != null && (original.blacklist == null || (!original.blacklist.contains(instance) && !original.blacklist.contains(parentInstance)))) {
|
||||
targets.computeIfAbsent(wanted, { k -> new TreeSet() }).add(instance)
|
||||
}
|
||||
}
|
||||
}
|
||||
last = current
|
||||
}
|
||||
}
|
||||
|
||||
@Internal
|
||||
@Override
|
||||
protected Object getData() {
|
||||
def ret = [:] as HashMap
|
||||
targets.forEach{ k, v ->
|
||||
def e = fields.get(k)
|
||||
ret[k] = [
|
||||
cls: e.cls,
|
||||
name: e.name,
|
||||
replacement: e.replacement,
|
||||
targets: v
|
||||
]
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
@EqualsAndHashCode(excludes = ['replacement', 'blacklist'])
|
||||
public static class Search {
|
||||
@Input
|
||||
String cls
|
||||
|
||||
@Input
|
||||
String name
|
||||
|
||||
@Input
|
||||
String replacement
|
||||
|
||||
@Nested
|
||||
@Optional
|
||||
Set<ObjectTarget> blacklist
|
||||
|
||||
@Override
|
||||
String toString() {
|
||||
return cls + '.' + name
|
||||
}
|
||||
|
||||
def blacklist(def owner, def name, def desc) {
|
||||
if (blacklist == null)
|
||||
blacklist = new HashSet()
|
||||
blacklist.add(new ObjectTarget(owner: owner, name: name, desc: desc))
|
||||
}
|
||||
def blacklist(def owner) {
|
||||
blacklist(owner, '', '')
|
||||
}
|
||||
}
|
||||
|
||||
def fields(Closure cl) {
|
||||
new ClosureHelper(cl, {name, ccl ->
|
||||
def search = ClosureHelper.apply(new Search(), ccl)
|
||||
this.fields.put(name, search)
|
||||
this.fieldsReverse.put(search, name)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
package net.minecraftforge.forge.tasks
|
||||
|
||||
import org.gradle.api.tasks.bundling.Zip
|
||||
import org.gradle.api.tasks.*
|
||||
import org.gradle.api.provider.SetProperty
|
||||
|
||||
abstract class InstallerJar extends Zip {
|
||||
@Input @Optional abstract SetProperty<String> getPackedDependencies()
|
||||
|
||||
InstallerJar() {
|
||||
archiveClassifier.set('installer')
|
||||
archiveExtension.set('jar') // Needs to be Zip task to not override Manifest, so set extension
|
||||
destinationDirectory.set(project.layout.buildDirectory.dir('libs'))
|
||||
|
||||
def installerJson = project.tasks.installerJson
|
||||
def launcherJson = project.tasks.launcherJson
|
||||
def downloadInstaller = project.tasks.downloadInstaller
|
||||
|
||||
dependsOn(installerJson, launcherJson, downloadInstaller)
|
||||
from(installerJson, launcherJson)
|
||||
|
||||
from(project.rootProject.file('/src/main/resources/url.png'))
|
||||
project.afterEvaluate {
|
||||
from(project.zipTree(downloadInstaller.output)) {
|
||||
duplicatesStrategy = 'exclude'
|
||||
}
|
||||
|
||||
if (!System.env.MAVEN_USER) {
|
||||
dependsOn(project.universalJar)
|
||||
from(project.universalJar) {
|
||||
into '/maven/' + project.group.replace('.', '/') + '/' + project.universalJar.archiveBaseName.get() + '/' + project.version + '/'
|
||||
}
|
||||
|
||||
packedDependencies.get().forEach {
|
||||
def jarTask = project.rootProject.getTasks().findByPath(it)
|
||||
dependsOn(jarTask)
|
||||
from(jarTask) {
|
||||
into '/maven/' + jarTask.project.group.replace('.', '/') + '/' + jarTask.archiveBaseName.get() + '/' + jarTask.project.version + '/'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
package net.minecraftforge.forge.tasks
|
||||
|
||||
import groovy.json.JsonBuilder
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.file.ConfigurableFileCollection
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.provider.Property
|
||||
import org.gradle.api.provider.SetProperty
|
||||
import org.gradle.api.tasks.*
|
||||
|
||||
import java.nio.file.Files
|
||||
|
||||
abstract class InstallerJson extends DefaultTask {
|
||||
@OutputFile abstract RegularFileProperty getOutput()
|
||||
@InputFiles abstract ConfigurableFileCollection getInput()
|
||||
@Input @Optional abstract SetProperty<String> getPackedDependencies()
|
||||
@Input @Optional final Map<String, Object> libraries = new LinkedHashMap<>()
|
||||
@Input Map<String, Object> json = new LinkedHashMap<>()
|
||||
@InputFile abstract RegularFileProperty getIcon()
|
||||
@Input abstract Property<String> getLauncherJsonName()
|
||||
@Input abstract Property<String> getLogo()
|
||||
@Input abstract Property<String> getMirrors()
|
||||
@Input abstract Property<String> getWelcome()
|
||||
|
||||
InstallerJson() {
|
||||
getLauncherJsonName().convention('/version.json')
|
||||
getLogo().convention('/big_logo.png')
|
||||
getMirrors().convention('https://files.minecraftforge.net/mirrors-2.0.json')
|
||||
getWelcome().convention("Welcome to the simple ${project.name.capitalize()} installer.")
|
||||
|
||||
getOutput().convention(project.layout.buildDirectory.file('install_profile.json'))
|
||||
|
||||
['client', 'server'].each { side ->
|
||||
['slim', 'extra'].each { type ->
|
||||
def tsk = project.tasks.getByName("download${side.capitalize()}${type.capitalize()}")
|
||||
dependsOn(tsk)
|
||||
input.from(tsk.output)
|
||||
}
|
||||
def tsk = project.tasks.getByName("create${side.capitalize()}SRG")
|
||||
dependsOn(tsk)
|
||||
input.from(tsk.output)
|
||||
}
|
||||
|
||||
|
||||
project.afterEvaluate {
|
||||
(packedDependencies.get().collect{ project.rootProject.tasks.findByPath(it) } + [project.universalJar]).forEach {
|
||||
dependsOn(it)
|
||||
input.from it.archiveFile
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
protected void exec() {
|
||||
def libs = libraries
|
||||
for (def child : packedDependencies.get().collect{ project.rootProject.tasks.findByPath(it) } + [project.universalJar]) {
|
||||
def dep = Util.getMavenDep(child)
|
||||
def path = Util.getMavenPath(child)
|
||||
libs.put(dep.toString(), [
|
||||
name: dep,
|
||||
downloads: [
|
||||
artifact: [
|
||||
path: path,
|
||||
url: "https://maven.minecraftforge.net/${path}",
|
||||
sha1: child.archiveFile.get().asFile.sha1(),
|
||||
size: child.archiveFile.get().asFile.length()
|
||||
]
|
||||
]
|
||||
])
|
||||
}
|
||||
json.libraries = libs.values().sort{a,b -> a.name.compareTo(b.name)}
|
||||
json.icon = "data:image/png;base64," + new String(Base64.getEncoder().encode(Files.readAllBytes(icon.get().asFile.toPath())))
|
||||
json.json = launcherJsonName.get()
|
||||
json.logo = logo.get()
|
||||
if (!mirrors.get().isEmpty())
|
||||
json.mirrorList = mirrors.get()
|
||||
json.welcome = welcome.get()
|
||||
|
||||
Files.writeString(output.get().getAsFile().toPath(), new JsonBuilder(json).toPrettyString())
|
||||
}
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
package net.minecraftforge.forge.tasks
|
||||
|
||||
import groovy.json.JsonBuilder
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.file.ConfigurableFileCollection
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.provider.SetProperty
|
||||
import org.gradle.api.tasks.*
|
||||
|
||||
import java.nio.file.Files
|
||||
|
||||
import static net.minecraftforge.forge.tasks.Util.getArtifacts
|
||||
import static net.minecraftforge.forge.tasks.Util.iso8601Now
|
||||
|
||||
abstract class LauncherJson extends DefaultTask {
|
||||
@OutputFile abstract RegularFileProperty getOutput()
|
||||
@InputFiles abstract ConfigurableFileCollection getInput()
|
||||
@Input Map<String, Object> json = new LinkedHashMap<>()
|
||||
@Input @Optional abstract SetProperty<String> getPackedDependencies()
|
||||
|
||||
@Internal final vanilla = project.project(':mcp').file('build/mcp/downloadJson/version.json')
|
||||
@Internal final timestamp = iso8601Now()
|
||||
@Internal final comment = [
|
||||
"Please do not automate the download and installation of Forge.",
|
||||
"Our efforts are supported by ads from the download page.",
|
||||
"If you MUST automate this, please consider supporting the project through https://www.patreon.com/LexManos/"
|
||||
]
|
||||
@Internal final id = "${project.rootProject.ext.MC_VERSION}-${project.name}${project.version.substring(project.rootProject.ext.MC_VERSION.length())}"
|
||||
|
||||
LauncherJson() {
|
||||
getOutput().convention(project.layout.buildDirectory.file('version.json'))
|
||||
|
||||
dependsOn(':fmlloader:jar', 'universalJar')
|
||||
getInput().from(project.tasks.universalJar.archiveFile,
|
||||
project.project(':fmlloader').jar.archiveFile,
|
||||
vanilla)
|
||||
|
||||
project.afterEvaluate {
|
||||
packedDependencies.get().forEach {
|
||||
def jarTask = project.rootProject.tasks.findByPath(it)
|
||||
dependsOn(jarTask)
|
||||
input.from jarTask.archiveFile
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
protected void exec() {
|
||||
if (!json.libraries)
|
||||
json.libraries = []
|
||||
def libs = [:]
|
||||
getArtifacts(project, project.configurations.installer, false).each { key, lib -> libs[key] = lib }
|
||||
getArtifacts(project, project.configurations.moduleonly, false).each { key, lib -> libs[key] = lib }
|
||||
|
||||
packedDependencies.get().collect{ project.rootProject.tasks.findByPath(it) }.forEach {
|
||||
def path = Util.getMavenPath(it)
|
||||
def key = Util.getMavenDep(it)
|
||||
|
||||
libs[key] = [
|
||||
name: key,
|
||||
downloads: [
|
||||
artifact: [
|
||||
path: path,
|
||||
url: "https://maven.minecraftforge.net/${path}",
|
||||
sha1: it.archiveFile.get().asFile.sha1(),
|
||||
size: it.archiveFile.get().asFile.length()
|
||||
]
|
||||
]
|
||||
]
|
||||
}
|
||||
libs.each { key, lib -> json.libraries.add(lib) }
|
||||
Files.writeString(output.get().asFile.toPath(), new JsonBuilder(json).toPrettyString())
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
package net.minecraftforge.forge.tasks
|
||||
|
||||
import groovy.transform.EqualsAndHashCode
|
||||
|
||||
import org.gradle.api.tasks.Input
|
||||
import org.gradle.api.tasks.Nested
|
||||
import org.gradle.api.tasks.Optional
|
||||
|
||||
@EqualsAndHashCode
|
||||
public class ObjectTarget implements Comparable<ObjectTarget> {
|
||||
@Input
|
||||
String owner
|
||||
|
||||
@Input
|
||||
String name
|
||||
|
||||
@Input
|
||||
@Optional
|
||||
String desc
|
||||
|
||||
@Override
|
||||
String toString() {
|
||||
if (desc == null)
|
||||
return owner + '.' + name
|
||||
return owner + '.' + name + desc
|
||||
}
|
||||
|
||||
@Override
|
||||
int compareTo(ObjectTarget o) {
|
||||
return toString().compareTo(o.toString())
|
||||
}
|
||||
}
|
||||
@@ -1,141 +0,0 @@
|
||||
package net.minecraftforge.forge.tasks
|
||||
|
||||
import groovy.json.JsonSlurper
|
||||
|
||||
import java.io.File
|
||||
import java.security.MessageDigest
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
|
||||
public class Util {
|
||||
static void init() {
|
||||
File.metaClass.sha1 = { ->
|
||||
MessageDigest md = MessageDigest.getInstance('SHA-1')
|
||||
delegate.eachByte 4096, {bytes, size ->
|
||||
md.update(bytes, 0, size)
|
||||
}
|
||||
return md.digest().collect {String.format "%02x", it}.join()
|
||||
}
|
||||
|
||||
File.metaClass.json = { -> new JsonSlurper().parseText(delegate.text) }
|
||||
|
||||
Date.metaClass.iso8601 = { ->
|
||||
def format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
|
||||
def result = format.format(delegate)
|
||||
return result[0..21] + ':' + result[22..-1]
|
||||
}
|
||||
|
||||
String.metaClass.rsplit = { String del, int limit = -1 ->
|
||||
def lst = new ArrayList()
|
||||
def x = 0, idx
|
||||
def tmp = delegate
|
||||
while ((idx = tmp.lastIndexOf(del)) != -1 && (limit == -1 || x++ < limit)) {
|
||||
lst.add(0, tmp.substring(idx + del.length(), tmp.length()))
|
||||
tmp = tmp.substring(0, idx)
|
||||
}
|
||||
lst.add(0, tmp)
|
||||
return lst
|
||||
}
|
||||
}
|
||||
|
||||
public static String[] getClasspath(project, libs, artifact) {
|
||||
def ret = []
|
||||
artifactTree(project, artifact).each { key, lib ->
|
||||
libs[lib.name] = lib
|
||||
if (lib.name != artifact)
|
||||
ret.add(lib.name)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
public static def getArtifacts(project, config, classifiers) {
|
||||
def ret = [:]
|
||||
config.resolvedConfiguration.resolvedArtifacts.each {
|
||||
def art = [
|
||||
group: it.moduleVersion.id.group,
|
||||
name: it.moduleVersion.id.name,
|
||||
version: it.moduleVersion.id.version,
|
||||
classifier: it.classifier,
|
||||
extension: it.extension,
|
||||
file: it.file
|
||||
]
|
||||
def key = art.group + ':' + art.name
|
||||
def folder = "${art.group.replace('.', '/')}/${art.name}/${art.version}/"
|
||||
def filename = "${art.name}-${art.version}"
|
||||
if (art.classifier != null)
|
||||
filename += "-${art.classifier}"
|
||||
filename += ".${art.extension}"
|
||||
def path = "${folder}${filename}"
|
||||
def url = "https://libraries.minecraft.net/${path}"
|
||||
if (!checkExists(url)) {
|
||||
url = "https://maven.minecraftforge.net/${path}"
|
||||
}
|
||||
//TODO remove when Mojang launcher is updated
|
||||
if (!classifiers && art.classifier != null) {
|
||||
//Mojang launcher doesn't currently support classifiers, so... move it to part of the version, and force the extension to 'jar'
|
||||
// However, keep the path normal so that our mirror system works.
|
||||
art.version = "${art.version}-${art.classifier}"
|
||||
art.classifier = null
|
||||
art.extension = 'jar'
|
||||
}
|
||||
ret[key] = [
|
||||
name: "${art.group}:${art.name}:${art.version}" + (art.classifier == null ? '' : ":${art.classifier}") + (art.extension == 'jar' ? '' : "@${art.extension}"),
|
||||
downloads: [
|
||||
artifact: [
|
||||
path: path,
|
||||
url: url,
|
||||
sha1: sha1(art.file),
|
||||
size: art.file.length()
|
||||
]
|
||||
]
|
||||
]
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
public static def getMavenPath(task) {
|
||||
def classifier = task.archiveClassifier.get()
|
||||
def dep = "${task.project.group}:${task.project.name}:${task.project.version}" + (classifier == '' ? '' : ':' + classifier)
|
||||
return "${task.project.group.replace('.', '/')}/${task.project.name}/${task.project.version}/${task.project.name}-${task.project.version}".toString() + (classifier == '' ? '' : '-' + classifier) + '.jar'
|
||||
}
|
||||
|
||||
public static def getMavenDep(task) {
|
||||
def classifier = task.archiveClassifier.get()
|
||||
return "${task.project.group}:${task.project.name}:${task.project.version}" + (classifier == '' ? '' : ':' + classifier)
|
||||
}
|
||||
|
||||
public static def iso8601Now() { new Date().iso8601() }
|
||||
|
||||
public static def sha1(file) {
|
||||
MessageDigest md = MessageDigest.getInstance('SHA-1')
|
||||
file.eachByte 4096, {bytes, size ->
|
||||
md.update(bytes, 0, size)
|
||||
}
|
||||
return md.digest().collect {String.format "%02x", it}.join()
|
||||
}
|
||||
|
||||
private static def artifactTree(project, artifact) {
|
||||
if (!project.ext.has('tree_resolver'))
|
||||
project.ext.tree_resolver = 1
|
||||
def cfg = project.configurations.create('tree_resolver_' + project.ext.tree_resolver++)
|
||||
def dep = project.dependencies.create(artifact)
|
||||
cfg.dependencies.add(dep)
|
||||
def files = cfg.resolve()
|
||||
return getArtifacts(project, cfg, true)
|
||||
}
|
||||
|
||||
private static boolean checkExists(url) {
|
||||
try {
|
||||
def code = new URL(url).openConnection().with {
|
||||
requestMethod = 'HEAD'
|
||||
connect()
|
||||
responseCode
|
||||
}
|
||||
return code == 200
|
||||
} catch (Exception e) {
|
||||
if (e.toString().contains('unable to find valid certification path to requested target'))
|
||||
throw new RuntimeException('Failed to connect to ' + url + ': Missing certificate root authority, try updating java')
|
||||
throw e
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,637 @@
|
||||
/*
|
||||
* The FML Forge Mod Loader suite. Copyright (C) 2012 cpw
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package cpw.mods.fml.server;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.Random;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.bukkit.Material;
|
||||
|
||||
import net.minecraft.server.Block;
|
||||
import net.minecraft.server.Item;
|
||||
import net.minecraft.server.LocaleLanguage;
|
||||
import net.minecraft.server.MLProp;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.BaseMod;
|
||||
import net.minecraft.server.BiomeBase;
|
||||
import net.minecraft.server.EntityItem;
|
||||
import net.minecraft.server.EntityHuman;
|
||||
import net.minecraft.server.IChunkProvider;
|
||||
import net.minecraft.server.ICommandListener;
|
||||
import net.minecraft.server.IInventory;
|
||||
import net.minecraft.server.ItemStack;
|
||||
import net.minecraft.server.NetworkManager;
|
||||
import net.minecraft.server.Packet1Login;
|
||||
import net.minecraft.server.Packet250CustomPayload;
|
||||
import net.minecraft.server.Packet3Chat;
|
||||
import net.minecraft.server.BukkitRegistry;
|
||||
import net.minecraft.server.SidedProxy;
|
||||
import net.minecraft.server.World;
|
||||
import net.minecraft.server.WorldType;
|
||||
import cpw.mods.fml.common.FMLCommonHandler;
|
||||
import cpw.mods.fml.common.IFMLSidedHandler;
|
||||
import cpw.mods.fml.common.Loader;
|
||||
import cpw.mods.fml.common.ModContainer;
|
||||
import cpw.mods.fml.common.ModMetadata;
|
||||
import cpw.mods.fml.common.ProxyInjector;
|
||||
import cpw.mods.fml.common.Side;
|
||||
import cpw.mods.fml.common.TickType;
|
||||
import cpw.mods.fml.common.modloader.ModLoaderModContainer;
|
||||
import cpw.mods.fml.common.modloader.ModProperty;
|
||||
import cpw.mods.fml.common.registry.FMLRegistry;
|
||||
|
||||
/**
|
||||
* Handles primary communication from hooked code into the system
|
||||
*
|
||||
* The FML entry point is {@link #onPreLoad(MinecraftServer)} called from {@link MinecraftServer}
|
||||
*
|
||||
* Obfuscated code should focus on this class and other members of the "server" (or "client") code
|
||||
*
|
||||
* The actual mod loading is handled at arms length by {@link Loader}
|
||||
*
|
||||
* It is expected that a similar class will exist for each target environment: Bukkit and Client side.
|
||||
*
|
||||
* It should not be directly modified.
|
||||
*
|
||||
* @author cpw
|
||||
*
|
||||
*/
|
||||
public class FMLBukkitHandler implements IFMLSidedHandler
|
||||
{
|
||||
/**
|
||||
* The singleton
|
||||
*/
|
||||
private static final FMLBukkitHandler INSTANCE = new FMLBukkitHandler();
|
||||
|
||||
/**
|
||||
* A reference to the server itself
|
||||
*/
|
||||
private MinecraftServer server;
|
||||
|
||||
/**
|
||||
* A handy list of the default overworld biomes
|
||||
*/
|
||||
private BiomeBase[] defaultOverworldBiomes;
|
||||
|
||||
FMLBukkitProfiler profiler;
|
||||
|
||||
/**
|
||||
* Called to start the whole game off from {@link MinecraftServer#startServer}
|
||||
* @param minecraftServer
|
||||
*/
|
||||
public void onPreLoad(MinecraftServer minecraftServer)
|
||||
{
|
||||
try
|
||||
{
|
||||
Class.forName("BaseModMp", false, getClass().getClassLoader());
|
||||
MinecraftServer.log.severe(""
|
||||
+ "Forge Mod Loader has detected that this server has an ModLoaderMP installed alongside Forge Mod Loader.\n"
|
||||
+ "This will cause a serious problem with compatibility. To protect your worlds, this minecraft server will now shutdown.\n"
|
||||
+ "You should follow the installation instructions of either Minecraft Forge of Forge Mod Loader and NOT install ModLoaderMP \n"
|
||||
+ "into the minecraft_server.jar file "
|
||||
+ "before this server will be allowed to start up.\n\nFailure to do so will simply result in more startup failures.\n\n"
|
||||
+ "The authors of Minecraft Forge and Forge Mod Loader strongly suggest you talk to your mod's authors and get them to\nupdate their "
|
||||
+ "requirements. ModLoaderMP is not compatible with Minecraft Forge on the server and they will need to update their mod\n"
|
||||
+ "for Minecraft Forge and other server compatibility, unless they are Minecraft Forge mods, in which case they already\n"
|
||||
+ "don't need ModLoaderMP and the mod author simply has failed to update his requirements and should be informed appropriately.\n\n"
|
||||
+ "The authors of Forge Mod Loader would like to be compatible with ModLoaderMP but it is closed source and owned by SDK.\n"
|
||||
+ "SDK, the author of ModLoaderMP, has a standing invitation to submit compatibility patches \n"
|
||||
+ "to the open source community project that is Forge Mod Loader so that this incompatibility doesn't last. \n"
|
||||
+ "Users who wish to enjoy mods of both types are "
|
||||
+ "encouraged to request of SDK that he submit a\ncompatibility patch to the Forge Mod Loader project at \n"
|
||||
+ "http://github.com/cpw/FML.\nPosting on the minecraft forums at\nhttp://www.minecraftforum.net/topic/86765- (the MLMP thread)\n"
|
||||
+ "may encourage him in this effort. However, I ask that your requests be polite.\n"
|
||||
+ "Now, the server has to shutdown so you can reinstall your minecraft_server.jar\nproperly, until such time as we can work together.");
|
||||
throw new RuntimeException(
|
||||
"This FML based server has detected an installation of ModLoaderMP alongside. This will cause serious compatibility issues, so the server will now shut down.");
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
{
|
||||
// We're safe. continue
|
||||
}
|
||||
server = minecraftServer;
|
||||
FMLCommonHandler.instance().beginLoading(this);
|
||||
FMLRegistry.registerRegistry(new BukkitRegistry());
|
||||
Loader.instance().loadMods();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called a bit later on during server initialization to finish loading mods
|
||||
*/
|
||||
public void onLoadComplete()
|
||||
{
|
||||
Loader.instance().initializeMods();
|
||||
for (Item i : Item.byId) {
|
||||
if (i!=null && Material.getMaterial(i.id).name().startsWith("X")) {
|
||||
Material.setMaterialName(i.id, i.l());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void onWorldLoadTick()
|
||||
{
|
||||
FMLCommonHandler.instance().tickStart(EnumSet.of(TickType.WORLDLOAD));
|
||||
}
|
||||
|
||||
/**
|
||||
* Every tick just before world and other ticks occur
|
||||
*/
|
||||
public void onPreWorldTick(World world)
|
||||
{
|
||||
FMLCommonHandler.instance().tickStart(EnumSet.of(TickType.WORLD),world);
|
||||
}
|
||||
|
||||
/**
|
||||
* Every tick just after world and other ticks occur
|
||||
*/
|
||||
public void onPostWorldTick(World world)
|
||||
{
|
||||
FMLCommonHandler.instance().tickEnd(EnumSet.of(TickType.WORLD), world);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the server instance
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public MinecraftServer getServer()
|
||||
{
|
||||
return server;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a handle to the server's logger instance
|
||||
*/
|
||||
public Logger getMinecraftLogger()
|
||||
{
|
||||
return MinecraftServer.log;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called from ChunkProviderServer when a chunk needs to be populated
|
||||
*
|
||||
* To avoid polluting the worldgen seed, we generate a new random from the world seed and
|
||||
* generate a seed from that
|
||||
*
|
||||
* @param chunkProvider
|
||||
* @param chunkX
|
||||
* @param chunkZ
|
||||
* @param world
|
||||
* @param generator
|
||||
*/
|
||||
public void onChunkPopulate(IChunkProvider chunkProvider, int chunkX, int chunkZ, World world, IChunkProvider generator)
|
||||
{
|
||||
FMLCommonHandler.instance().handleWorldGeneration(chunkX, chunkZ, world.getSeed(), world, generator, chunkProvider);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called from the furnace to lookup fuel values
|
||||
*
|
||||
* @param itemId
|
||||
* @param itemDamage
|
||||
* @return
|
||||
*/
|
||||
public int fuelLookup(int itemId, int itemDamage)
|
||||
{
|
||||
int fv = 0;
|
||||
|
||||
for (ModContainer mod : Loader.getModList())
|
||||
{
|
||||
fv = Math.max(fv, mod.lookupFuelValue(itemId, itemDamage));
|
||||
}
|
||||
|
||||
return fv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the offered class and instance of BaseMod and therefore a ModLoader mod?
|
||||
*/
|
||||
public boolean isModLoaderMod(Class<?> clazz)
|
||||
{
|
||||
return BaseMod.class.isAssignableFrom(clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the supplied mod class into a mod container
|
||||
*/
|
||||
public ModContainer loadBaseModMod(Class<?> clazz, File canonicalFile)
|
||||
{
|
||||
@SuppressWarnings("unchecked")
|
||||
Class <? extends BaseMod > bmClazz = (Class <? extends BaseMod >) clazz;
|
||||
return new ModLoaderModContainer(bmClazz, canonicalFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to notify that an item was picked up from the world
|
||||
*
|
||||
* @param entityItem
|
||||
* @param entityPlayer
|
||||
*/
|
||||
public void notifyItemPickup(EntityItem entityItem, EntityHuman entityPlayer)
|
||||
{
|
||||
for (ModContainer mod : Loader.getModList())
|
||||
{
|
||||
if (mod.wantsPickupNotification())
|
||||
{
|
||||
mod.getPickupNotifier().notifyPickup(entityItem, entityPlayer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Raise an exception
|
||||
*
|
||||
* @param exception
|
||||
* @param message
|
||||
* @param stopGame
|
||||
*/
|
||||
public void raiseException(Throwable exception, String message, boolean stopGame)
|
||||
{
|
||||
FMLCommonHandler.instance().getFMLLogger().throwing("FMLHandler", "raiseException", exception);
|
||||
throw new RuntimeException(exception);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to dispense the item as an entity other than just as a the item itself
|
||||
*
|
||||
* @param world
|
||||
* @param x
|
||||
* @param y
|
||||
* @param z
|
||||
* @param xVelocity
|
||||
* @param zVelocity
|
||||
* @param item
|
||||
* @return
|
||||
*/
|
||||
public boolean tryDispensingEntity(World world, double x, double y, double z, byte xVelocity, byte zVelocity, ItemStack item)
|
||||
{
|
||||
for (ModContainer mod : Loader.getModList())
|
||||
{
|
||||
if (mod.wantsToDispense() && mod.getDispenseHandler().dispense(x, y, z, xVelocity, zVelocity, world, item))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the instance
|
||||
*/
|
||||
public static FMLBukkitHandler instance()
|
||||
{
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a list of default overworld biomes
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public BiomeBase[] getDefaultOverworldBiomes()
|
||||
{
|
||||
if (defaultOverworldBiomes == null)
|
||||
{
|
||||
ArrayList<BiomeBase> biomes = new ArrayList<BiomeBase>(20);
|
||||
|
||||
for (int i = 0; i < 23; i++)
|
||||
{
|
||||
if ("Sky".equals(BiomeBase.biomes[i].y) || "Hell".equals(BiomeBase.biomes[i].y))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
biomes.add(BiomeBase.biomes[i]);
|
||||
}
|
||||
|
||||
defaultOverworldBiomes = new BiomeBase[biomes.size()];
|
||||
biomes.toArray(defaultOverworldBiomes);
|
||||
}
|
||||
|
||||
return defaultOverworldBiomes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when an item is crafted
|
||||
*
|
||||
* @param player
|
||||
* @param craftedItem
|
||||
* @param craftingGrid
|
||||
*/
|
||||
public void onItemCrafted(EntityHuman player, ItemStack craftedItem, IInventory craftingGrid)
|
||||
{
|
||||
for (ModContainer mod : Loader.getModList())
|
||||
{
|
||||
if (mod.wantsCraftingNotification())
|
||||
{
|
||||
mod.getCraftingHandler().onCrafting(player, craftedItem, craftingGrid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when an item is smelted
|
||||
*
|
||||
* @param player
|
||||
* @param smeltedItem
|
||||
*/
|
||||
public void onItemSmelted(EntityHuman player, ItemStack smeltedItem)
|
||||
{
|
||||
for (ModContainer mod : Loader.getModList())
|
||||
{
|
||||
if (mod.wantsCraftingNotification())
|
||||
{
|
||||
mod.getCraftingHandler().onSmelting(player, smeltedItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a chat packet is received
|
||||
*
|
||||
* @param chat
|
||||
* @param player
|
||||
* @return true if you want the packet to stop processing and not echo to the rest of the world
|
||||
*/
|
||||
public boolean handleChatPacket(Packet3Chat chat, EntityHuman player)
|
||||
{
|
||||
for (ModContainer mod : Loader.getModList())
|
||||
{
|
||||
if (mod.wantsNetworkPackets() && mod.getNetworkHandler().onChat(chat, player))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a packet 250 packet is received from the player
|
||||
*
|
||||
* @param packet
|
||||
* @param player
|
||||
*/
|
||||
public void handlePacket250(Packet250CustomPayload packet, EntityHuman player)
|
||||
{
|
||||
if ("REGISTER".equals(packet.tag) || "UNREGISTER".equals(packet.tag))
|
||||
{
|
||||
handleClientRegistration(packet, player);
|
||||
return;
|
||||
}
|
||||
|
||||
ModContainer mod = FMLCommonHandler.instance().getModForChannel(packet.tag);
|
||||
|
||||
if (mod != null)
|
||||
{
|
||||
mod.getNetworkHandler().onPacket250Packet(packet, player);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle register requests for packet 250 channels
|
||||
*
|
||||
* @param packet
|
||||
*/
|
||||
private void handleClientRegistration(Packet250CustomPayload packet, EntityHuman player)
|
||||
{
|
||||
if (packet.data==null) {
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
for (String channel : new String(packet.data, "UTF8").split("\0"))
|
||||
{
|
||||
// Skip it if we don't know it
|
||||
if (FMLCommonHandler.instance().getModForChannel(channel) == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ("REGISTER".equals(packet.tag))
|
||||
{
|
||||
FMLCommonHandler.instance().activateChannel(player, channel);
|
||||
}
|
||||
else
|
||||
{
|
||||
FMLCommonHandler.instance().deactivateChannel(player, channel);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (UnsupportedEncodingException e)
|
||||
{
|
||||
getMinecraftLogger().warning("Received invalid registration packet");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a login
|
||||
*
|
||||
* @param loginPacket
|
||||
* @param networkManager
|
||||
*/
|
||||
public void handleLogin(Packet1Login loginPacket, NetworkManager networkManager)
|
||||
{
|
||||
Packet250CustomPayload packet = new Packet250CustomPayload();
|
||||
packet.tag = "REGISTER";
|
||||
packet.data = FMLCommonHandler.instance().getPacketRegistry();
|
||||
packet.length = packet.data.length;
|
||||
if (packet.length>0) {
|
||||
networkManager.queue(packet);
|
||||
}
|
||||
}
|
||||
|
||||
public void announceLogin(EntityHuman player) {
|
||||
for (ModContainer mod : Loader.getModList())
|
||||
{
|
||||
if (mod.wantsPlayerTracking())
|
||||
{
|
||||
mod.getPlayerTracker().onPlayerLogin(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getMinecraftRootDirectory()
|
||||
{
|
||||
try {
|
||||
return server.a(".").getCanonicalFile();
|
||||
} catch (IOException ioe) {
|
||||
return new File(".");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param var2
|
||||
* @return
|
||||
*/
|
||||
public boolean handleServerCommand(String command, String player, ICommandListener listener)
|
||||
{
|
||||
for (ModContainer mod : Loader.getModList()) {
|
||||
if (mod.wantsConsoleCommands() && mod.getConsoleHandler().handleCommand(command, player, listener)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param player
|
||||
*/
|
||||
public void announceLogout(EntityHuman player)
|
||||
{
|
||||
for (ModContainer mod : Loader.getModList())
|
||||
{
|
||||
if (mod.wantsPlayerTracking())
|
||||
{
|
||||
mod.getPlayerTracker().onPlayerLogout(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param p_28168_1_
|
||||
*/
|
||||
public void announceDimensionChange(EntityHuman player)
|
||||
{
|
||||
for (ModContainer mod : Loader.getModList())
|
||||
{
|
||||
if (mod.wantsPlayerTracking())
|
||||
{
|
||||
mod.getPlayerTracker().onPlayerChangedDimension(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param biome
|
||||
*/
|
||||
public void addBiomeToDefaultWorldGenerator(BiomeBase biome)
|
||||
{
|
||||
WorldType.NORMAL.addNewBiome(biome);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param biome
|
||||
*/
|
||||
public void removeBiomeFromDefaultWorldGenerator(BiomeBase biome)
|
||||
{
|
||||
WorldType.NORMAL.removeBiome(biome);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getMinecraftInstance() {
|
||||
return server;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCurrentLanguage()
|
||||
{
|
||||
return LocaleLanguage.a().getCurrentLanguage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Properties getCurrentLanguageTable()
|
||||
{
|
||||
return LocaleLanguage.a().getCurrentLanguageTable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getObjectName(Object instance)
|
||||
{
|
||||
String objectName;
|
||||
if (instance instanceof Item) {
|
||||
objectName=((Item)instance).getName();
|
||||
} else if (instance instanceof Block) {
|
||||
objectName=((Block)instance).getName();
|
||||
} else if (instance instanceof ItemStack) {
|
||||
objectName=Item.byId[((ItemStack)instance).id].a((ItemStack)instance);
|
||||
} else {
|
||||
throw new IllegalArgumentException(String.format("Illegal object for naming %s",instance));
|
||||
}
|
||||
objectName+=".name";
|
||||
return objectName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModMetadata readMetadataFrom(InputStream input, ModContainer mod) throws Exception {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void profileStart(String profileLabel) {
|
||||
if (profiler!=null)
|
||||
{
|
||||
profiler.start(profileLabel);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void profileEnd() {
|
||||
if (profiler!=null)
|
||||
{
|
||||
profiler.end();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModProperty getModLoaderPropertyFor(Field f) {
|
||||
if (f.isAnnotationPresent(MLProp.class)) {
|
||||
MLProp prop = f.getAnnotation(MLProp.class);
|
||||
return new ModProperty(prop.info(), prop.min(), prop.max(), prop.name());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getAdditionalBrandingInformation() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Side getSide() {
|
||||
return Side.BUKKIT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProxyInjector findSidedProxyOn(cpw.mods.fml.common.modloader.BaseMod mod) {
|
||||
for (Field f : mod.getClass().getDeclaredFields())
|
||||
{
|
||||
if (f.isAnnotationPresent(SidedProxy.class))
|
||||
{
|
||||
SidedProxy sp = f.getAnnotation(SidedProxy.class);
|
||||
return new ProxyInjector(sp.clientSide(), sp.serverSide(), sp.bukkitSide(), f);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void onServerPostTick() {
|
||||
FMLCommonHandler.instance().tickEnd(EnumSet.of(TickType.GAME));
|
||||
}
|
||||
|
||||
public void onServerPreTick() {
|
||||
FMLCommonHandler.instance().tickStart(EnumSet.of(TickType.GAME));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
package cpw.mods.fml.server;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.collect.ImmutableMultiset;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Multiset;
|
||||
import com.google.common.collect.Multiset.Entry;
|
||||
import com.google.common.collect.Multisets;
|
||||
import com.google.common.collect.TreeMultiset;
|
||||
import com.google.common.primitives.Ints;
|
||||
|
||||
public class FMLBukkitProfiler {
|
||||
private static FMLBukkitProfiler lastInstance;
|
||||
private static long endTime;
|
||||
private LinkedList<String> profiles = new LinkedList<String>();
|
||||
private TreeMultiset<String> hitCounter = TreeMultiset.create();
|
||||
private TreeMultiset<String> timings = TreeMultiset.create();
|
||||
private long timestamp;
|
||||
|
||||
public static long beginProfiling(int seconds)
|
||||
{
|
||||
long now = System.currentTimeMillis();
|
||||
if (lastInstance == null)
|
||||
{
|
||||
lastInstance = new FMLBukkitProfiler();
|
||||
FMLBukkitHandler.instance().profiler = lastInstance;
|
||||
endTime = now + seconds * 1000;
|
||||
}
|
||||
if (endTime > now)
|
||||
{
|
||||
return (endTime - now) / 1000;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static long endProfiling()
|
||||
{
|
||||
FMLBukkitHandler.instance().profiler = null;
|
||||
return endTime - System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public static void resetProfiling()
|
||||
{
|
||||
endProfiling();
|
||||
lastInstance = null;
|
||||
}
|
||||
|
||||
public void start(String profileLabel)
|
||||
{
|
||||
profiles.push(profileLabel);
|
||||
timestamp = System.nanoTime();
|
||||
}
|
||||
|
||||
public void end()
|
||||
{
|
||||
int timing = (int)((System.nanoTime() - timestamp)/1000L);
|
||||
String label = Joiner.on('.').join(profiles);
|
||||
profiles.pop();
|
||||
hitCounter.add(label);
|
||||
timings.add(label,timing);
|
||||
if (System.currentTimeMillis()>endTime)
|
||||
{
|
||||
endProfiling();
|
||||
}
|
||||
}
|
||||
|
||||
public static String[] dumpProfileData(int count)
|
||||
{
|
||||
if (lastInstance == null)
|
||||
{
|
||||
return new String[] { "No profile data available" };
|
||||
}
|
||||
|
||||
if (endTime > System.currentTimeMillis())
|
||||
{
|
||||
return new String[] { String.format("Timing is being gathered for another %d seconds", endTime - System.currentTimeMillis()) };
|
||||
}
|
||||
return lastInstance.profileData(count);
|
||||
}
|
||||
|
||||
private String[] profileData(int count) {
|
||||
List<Entry<String>> sortedTiming = getEntriesSortedByFrequency(timings, false);
|
||||
ArrayList<String> timeLine = new ArrayList<String>();
|
||||
|
||||
double totalTime = timings.size();
|
||||
|
||||
for (Entry<String> hit : sortedTiming)
|
||||
{
|
||||
if (--count == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
timeLine.add(String.format("%s : %d microseconds, %d invocations. %.2f %% of overall time",hit.getElement(), hit.getCount(), hitCounter.count(hit.getElement()), 100.0 * hit.getCount()/totalTime));
|
||||
}
|
||||
return timeLine.toArray(new String[0]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Code from http://stackoverflow.com/questions/4345633/simplest-way-to-iterate-through-a-multiset-in-the-order-of-element-frequency
|
||||
*/
|
||||
private enum EntryComp implements Comparator<Multiset.Entry<?>>{
|
||||
DESCENDING{
|
||||
@Override
|
||||
public int compare(final Entry<?> a, final Entry<?> b){
|
||||
return Ints.compare(b.getCount(), a.getCount());
|
||||
}
|
||||
},
|
||||
ASCENDING{
|
||||
@Override
|
||||
public int compare(final Entry<?> a, final Entry<?> b){
|
||||
return Ints.compare(a.getCount(), b.getCount());
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
private static <E> List<Entry<E>> getEntriesSortedByFrequency(final Multiset<E> ms, final boolean ascending) {
|
||||
final List<Entry<E>> entryList = Lists.newArrayList(ms.entrySet());
|
||||
Collections.sort(entryList, ascending ? EntryComp.ASCENDING : EntryComp.DESCENDING);
|
||||
return entryList;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,409 @@
|
||||
/*
|
||||
* The FML Forge Mod Loader suite. Copyright (C) 2012 cpw
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.minecraft.server;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
import org.bukkit.craftbukkit.generator.NetherChunkGenerator;
|
||||
import org.bukkit.craftbukkit.generator.NormalChunkGenerator;
|
||||
|
||||
import cpw.mods.fml.common.TickType;
|
||||
|
||||
public abstract class BaseMod implements cpw.mods.fml.common.modloader.BaseMod
|
||||
{
|
||||
// CALLBACK MECHANISMS
|
||||
|
||||
/**
|
||||
* @param minecraftInstance
|
||||
* @return
|
||||
*/
|
||||
public final boolean doTickInGame(TickType tick, boolean tickEnd, Object minecraftInstance, Object... data)
|
||||
{
|
||||
if (tick==TickType.GAME && tickEnd) {
|
||||
return onTickInGame((MinecraftServer)minecraftInstance);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onCrafting(Object... craftingParameters)
|
||||
{
|
||||
takenFromCrafting((EntityHuman)craftingParameters[0], (ItemStack)craftingParameters[1], (IInventory)craftingParameters[2]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onSmelting(Object... smeltingParameters)
|
||||
{
|
||||
takenFromFurnace((EntityHuman)smeltingParameters[0], (ItemStack)smeltingParameters[1]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean dispense(double x, double y, double z, byte xVelocity, byte zVelocity, Object... data)
|
||||
{
|
||||
return dispenseEntity((World)data[0], x, y, z, xVelocity, zVelocity, (ItemStack)data[1]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean onChat(Object... data)
|
||||
{
|
||||
return onChatMessageReceived((EntityHuman)data[1], (Packet3Chat)data[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onServerLogin(Object handler) {
|
||||
// NOOP
|
||||
}
|
||||
|
||||
public final void onServerLogout() {
|
||||
// NOOP
|
||||
}
|
||||
@Override
|
||||
public final void onPlayerLogin(Object player)
|
||||
{
|
||||
onClientLogin((EntityHuman) player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onPlayerLogout(Object player)
|
||||
{
|
||||
onClientLogout((EntityHuman)player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onPlayerChangedDimension(Object player)
|
||||
{
|
||||
onClientDimensionChanged((EntityHuman)player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onPacket250Packet(Object... data)
|
||||
{
|
||||
onPacket250Received((EntityHuman)data[1], (Packet250CustomPayload)data[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void notifyPickup(Object... pickupData)
|
||||
{
|
||||
EntityItem item = (EntityItem) pickupData[0];
|
||||
EntityHuman player = (EntityHuman) pickupData[1];
|
||||
onItemPickup(player, item.itemStack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void generate(Random random, int chunkX, int chunkZ, Object... additionalData)
|
||||
{
|
||||
World w = (World) additionalData[0];
|
||||
IChunkProvider cp = (IChunkProvider) additionalData[1];
|
||||
|
||||
if (cp instanceof ChunkProviderHell || cp instanceof NetherChunkGenerator)
|
||||
{
|
||||
generateNether(w, random, chunkX << 4, chunkZ << 4);
|
||||
}
|
||||
else if (cp instanceof ChunkProviderGenerate || cp instanceof NormalChunkGenerator)
|
||||
{
|
||||
generateSurface(w, random, chunkX << 4, chunkZ << 4);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* NO-OP on client side
|
||||
*/
|
||||
@Override
|
||||
public final boolean handleCommand(String command, Object... data)
|
||||
{
|
||||
return onServerCommand(command, (String)data[0], (ICommandListener)data[1]);
|
||||
}
|
||||
@Override
|
||||
public void onRegisterAnimations() {
|
||||
// NOOP on servers
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRenderHarvest(@SuppressWarnings("rawtypes") Map renderers) {
|
||||
// NOOP on servers
|
||||
}
|
||||
|
||||
// BASEMOD API
|
||||
/**
|
||||
* Override if you wish to provide a fuel item for the furnace and return the fuel value of the item
|
||||
*
|
||||
* @param id
|
||||
* @param metadata
|
||||
* @return
|
||||
*/
|
||||
public int addFuel(int id, int metadata)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void addRenderer(Map<Class<? extends Entity>, Object> renderers)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Override if you wish to perform some action other than just dispensing the item from the dispenser
|
||||
*
|
||||
* @param world
|
||||
* @param x
|
||||
* @param y
|
||||
* @param z
|
||||
* @param xVel
|
||||
* @param zVel
|
||||
* @param item
|
||||
* @return
|
||||
*/
|
||||
public boolean dispenseEntity(World world, double x, double y, double z, int xVel, int zVel, ItemStack item)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override if you wish to generate Nether (Hell biome) blocks
|
||||
*
|
||||
* @param world
|
||||
* @param random
|
||||
* @param chunkX
|
||||
* @param chunkZ
|
||||
*/
|
||||
public void generateNether(World world, Random random, int chunkX, int chunkZ)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Override if you wish to generate Overworld (not hell or the end) blocks
|
||||
*
|
||||
* @param world
|
||||
* @param random
|
||||
* @param chunkX
|
||||
* @param chunkZ
|
||||
*/
|
||||
public void generateSurface(World world, Random random, int chunkX, int chunkZ)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of your mod. Defaults to the class name
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getName()
|
||||
{
|
||||
return getClass().getSimpleName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get your mod priorities
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getPriorities()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the version of your mod
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public abstract String getVersion();
|
||||
|
||||
public void keyboardEvent(Object event)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Load your mod
|
||||
*/
|
||||
public abstract void load();
|
||||
|
||||
/**
|
||||
* Finish loading your mod
|
||||
*/
|
||||
public void modsLoaded()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle item pickup
|
||||
*
|
||||
* @param player
|
||||
* @param item
|
||||
*/
|
||||
public void onItemPickup(EntityHuman player, ItemStack item)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Ticked every game tick if you have subscribed to tick events through {@link ModLoader#setInGameHook(BaseMod, boolean, boolean)}
|
||||
*
|
||||
* @param minecraftServer the server
|
||||
* @return true to continue receiving ticks
|
||||
*/
|
||||
public boolean onTickInGame(MinecraftServer minecraftServer)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean onTickInGUI(float tick, Object game, Object gui)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Only implemented on the client side
|
||||
* {@link #onChatMessageReceived(EntityPlayer, Packet3Chat)}
|
||||
*
|
||||
* @param text
|
||||
*/
|
||||
public void receiveChatPacket(String text)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Only called on the client side
|
||||
* {@link #onPacket250Received(EntityPlayer, Packet250CustomPayload)}
|
||||
*
|
||||
* @param packet
|
||||
*/
|
||||
public void receiveCustomPacket(Packet250CustomPayload packet)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void registerAnimation(Object game)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void renderInvBlock(Object renderer, Block block, int metadata, int modelID)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public boolean renderWorldBlock(Object renderer, IBlockAccess world, int x, int y, int z, Block block, int modelID)
|
||||
{
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when someone crafts an item from a crafting table
|
||||
*
|
||||
* @param player
|
||||
* @param item
|
||||
* @param matrix
|
||||
*/
|
||||
public void takenFromCrafting(EntityHuman player, ItemStack item, IInventory matrix)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when someone takes a smelted item from a furnace
|
||||
*
|
||||
* @param player
|
||||
* @param item
|
||||
*/
|
||||
public void takenFromFurnace(EntityHuman player, ItemStack item)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* The identifier string for the mod- used in client<->server negotiation
|
||||
*/
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return getName() + " " + getVersion();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a 250 packet is received on a channel registered to this mod
|
||||
*
|
||||
* @param source
|
||||
* @param payload
|
||||
*/
|
||||
public void onPacket250Received(EntityHuman source, Packet250CustomPayload payload)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a chat message is received. Return true to stop further processing
|
||||
*
|
||||
* @param source
|
||||
* @param chat
|
||||
* @return true if you want to consume the message so it is not available for further processing
|
||||
*/
|
||||
public boolean onChatMessageReceived(EntityHuman source, Packet3Chat chat)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Called when a server command is received
|
||||
* @param command
|
||||
* @return true if you want to consume the message so it is not available for further processing
|
||||
*/
|
||||
public boolean onServerCommand(String command, String sender, ICommandListener listener)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a new client logs in.
|
||||
*
|
||||
* @param player
|
||||
*/
|
||||
public void onClientLogin(EntityHuman player)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a client logs out of the server.
|
||||
*
|
||||
* @param player
|
||||
*/
|
||||
public void onClientLogout(EntityHuman player)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Called when a client changes dimensions on the server.
|
||||
*
|
||||
* @param player
|
||||
*/
|
||||
public void onClientDimensionChanged(EntityHuman player)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// Spare client junk
|
||||
// -------
|
||||
// void addRenderer(Map<Class<? extends Entity>, Render> renderers);
|
||||
// void registerAnimation(Minecraft game);
|
||||
// void renderInvBlock(RenderBlocks renderer, Block block, int metadata, int modelID);
|
||||
// boolean renderWorldBlock(RenderBlocks renderer, IBlockAccess world, int x, int y, int z, Block block, int modelID);
|
||||
// boolean onTickInGUI(float tick, Minecraft game, GuiScreen gui);
|
||||
// void keyboardEvent(KeyBinding event);
|
||||
|
||||
@Override
|
||||
public void keyBindingEvent(Object keybinding) {
|
||||
// NOOP on server
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
package net.minecraft.server;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.src.BiomeGenBase;
|
||||
|
||||
import cpw.mods.fml.common.registry.IMinecraftRegistry;
|
||||
import cpw.mods.fml.server.FMLBukkitHandler;
|
||||
|
||||
public class BukkitRegistry implements IMinecraftRegistry
|
||||
{
|
||||
|
||||
@Override
|
||||
public void addRecipe(net.minecraft.src.ItemStack output, Object... params)
|
||||
{
|
||||
CraftingManager.getInstance().registerShapedRecipe((ItemStack) output, params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addShapelessRecipe(net.minecraft.src.ItemStack output, Object... params)
|
||||
{
|
||||
CraftingManager.getInstance().registerShapelessRecipe((ItemStack) output, params);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void addRecipe(net.minecraft.src.IRecipe recipe)
|
||||
{
|
||||
CraftingManager.getInstance().getRecipies().add(recipe);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSmelting(int input, net.minecraft.src.ItemStack output)
|
||||
{
|
||||
FurnaceRecipes.getInstance().registerRecipe(input, (ItemStack) output);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerBlock(net.minecraft.src.Block block)
|
||||
{
|
||||
registerBlock(block, ItemBlock.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerBlock(net.minecraft.src.Block block, Class <? extends net.minecraft.src.ItemBlock > itemclass)
|
||||
{
|
||||
try
|
||||
{
|
||||
assert block != null : "registerBlock: block cannot be null";
|
||||
assert itemclass != null : "registerBlock: itemclass cannot be null";
|
||||
int blockItemId = ((Block)block).id - 256;
|
||||
itemclass.getConstructor(int.class).newInstance(blockItemId);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
//HMMM
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void registerEntityID(Class <? extends net.minecraft.src.Entity > entityClass, String entityName, int id)
|
||||
{
|
||||
EntityTypes.addNewEntityListMapping((Class<? extends Entity>) entityClass, entityName, id);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void registerEntityID(Class <? extends net.minecraft.src.Entity > entityClass, String entityName, int id, int backgroundEggColour, int foregroundEggColour)
|
||||
{
|
||||
EntityTypes.addNewEntityListMapping((Class<? extends Entity>) entityClass, entityName, id, backgroundEggColour, foregroundEggColour);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void registerTileEntity(Class <? extends net.minecraft.src.TileEntity > tileEntityClass, String id)
|
||||
{
|
||||
TileEntity.addNewTileEntityMapping((Class<? extends TileEntity>) tileEntityClass, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBiome(BiomeGenBase biome)
|
||||
{
|
||||
FMLBukkitHandler.instance().addBiomeToDefaultWorldGenerator((BiomeBase) biome);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSpawn(Class <? extends net.minecraft.src.EntityLiving > entityClass, int weightedProb, int min, int max, net.minecraft.src.EnumCreatureType typeOfCreature, BiomeGenBase... biomes)
|
||||
{
|
||||
BiomeBase[] realBiomes=(BiomeBase[]) biomes;
|
||||
for (BiomeBase biome : realBiomes)
|
||||
{
|
||||
@SuppressWarnings("unchecked")
|
||||
List<BiomeMeta> spawns = ((BiomeBase)biome).getMobs((EnumCreatureType)typeOfCreature);
|
||||
|
||||
for (BiomeMeta entry : spawns)
|
||||
{
|
||||
//Adjusting an existing spawn entry
|
||||
if (entry.a == entityClass)
|
||||
{
|
||||
entry.d = weightedProb;
|
||||
entry.b = min;
|
||||
entry.c = max;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
spawns.add(new BiomeMeta(entityClass, weightedProb, min, max));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void addSpawn(String entityName, int weightedProb, int min, int max, net.minecraft.src.EnumCreatureType spawnList, BiomeGenBase... biomes)
|
||||
{
|
||||
Class <? extends Entity > entityClazz = EntityTypes.getEntityToClassMapping().get(entityName);
|
||||
|
||||
if (EntityLiving.class.isAssignableFrom(entityClazz))
|
||||
{
|
||||
addSpawn((Class <? extends net.minecraft.src.EntityLiving >) entityClazz, weightedProb, min, max, spawnList, biomes);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeBiome(BiomeGenBase biome)
|
||||
{
|
||||
FMLBukkitHandler.instance().removeBiomeFromDefaultWorldGenerator((BiomeBase)biome);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeSpawn(Class <? extends net.minecraft.src.EntityLiving > entityClass, net.minecraft.src.EnumCreatureType typeOfCreature, BiomeGenBase... biomesO)
|
||||
{
|
||||
BiomeBase[] biomes=(BiomeBase[]) biomesO;
|
||||
for (BiomeBase biome : biomes)
|
||||
{
|
||||
@SuppressWarnings("unchecked")
|
||||
List<BiomeMeta> spawns = ((BiomeBase)biome).getMobs((EnumCreatureType) typeOfCreature);
|
||||
|
||||
Iterator<BiomeMeta> entries = spawns.iterator();
|
||||
while (entries.hasNext())
|
||||
{
|
||||
BiomeMeta entry = entries.next();
|
||||
if (entry.a == entityClass)
|
||||
{
|
||||
entries.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void removeSpawn(String entityName, net.minecraft.src.EnumCreatureType spawnList, BiomeGenBase... biomes)
|
||||
{
|
||||
Class <? extends Entity > entityClazz = EntityTypes.getEntityToClassMapping().get(entityName);
|
||||
|
||||
if (EntityLiving.class.isAssignableFrom(entityClazz))
|
||||
{
|
||||
removeSpawn((Class <? extends net.minecraft.src.EntityLiving >) entityClazz, spawnList, biomes);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* The FML Forge Mod Loader suite. Copyright (C) 2012 cpw
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.minecraft.server;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
import static java.lang.annotation.RetentionPolicy.*;
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
|
||||
/**
|
||||
* @author cpw
|
||||
*
|
||||
*/
|
||||
@Retention(value = RUNTIME)
|
||||
@Target(value = FIELD)
|
||||
public @interface MLProp
|
||||
{
|
||||
/**
|
||||
* Adds additional help to top of configuration file.
|
||||
*/
|
||||
String info() default "";
|
||||
|
||||
/**
|
||||
* Maximum value allowed if field is a number.
|
||||
*/
|
||||
double max() default Double.MAX_VALUE;
|
||||
|
||||
/**
|
||||
* Minimum value allowed if field is a number.
|
||||
*/
|
||||
double min() default Double.MIN_VALUE;
|
||||
|
||||
/**
|
||||
* Overrides the field name for property key.
|
||||
*/
|
||||
String name() default "";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,780 @@
|
||||
/*
|
||||
* The FML Forge Mod Loader suite. Copyright (C) 2012 cpw
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.minecraft.server;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import cpw.mods.fml.common.FMLCommonHandler;
|
||||
import cpw.mods.fml.common.Loader;
|
||||
import cpw.mods.fml.common.ReflectionHelper;
|
||||
import cpw.mods.fml.common.modloader.ModLoaderHelper;
|
||||
import cpw.mods.fml.common.modloader.ModLoaderModContainer;
|
||||
import cpw.mods.fml.common.registry.FMLRegistry;
|
||||
import cpw.mods.fml.server.FMLBukkitHandler;
|
||||
|
||||
public class ModLoader
|
||||
{
|
||||
/**
|
||||
* Not used on the server.
|
||||
*
|
||||
* @param achievement
|
||||
* @param name
|
||||
* @param description
|
||||
*/
|
||||
public static void addAchievementDesc(Achievement achievement, String name, String description)
|
||||
{
|
||||
String achName=achievement.getName();
|
||||
addLocalization(achName, name);
|
||||
addLocalization(achName+".desc", description);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is a call in hook from modified external code. Implemented elsewhere.
|
||||
*
|
||||
* {@link FMLCommonHandler#fuelLookup(int, int)}
|
||||
*
|
||||
* @param id
|
||||
* @param metadata
|
||||
* @return
|
||||
*/
|
||||
@Deprecated
|
||||
public static int addAllFuel(int id, int metadata)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static void addAllRenderers(Map<Class<? extends Entity>, Object> renderers)
|
||||
{
|
||||
}
|
||||
|
||||
public static void addAnimation(Object anim)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is unimplemented in server versions to date.
|
||||
*
|
||||
* @param armor
|
||||
* @return
|
||||
*/
|
||||
public static int addArmor(String armor)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method adds the supplied biome to the set of candidate biomes for the default world generator type.
|
||||
*
|
||||
* @param biome
|
||||
*/
|
||||
public static void addBiome(BiomeBase biome)
|
||||
{
|
||||
FMLRegistry.addBiome(biome);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add localization for the specified string
|
||||
*
|
||||
* @param key
|
||||
* @param value
|
||||
*/
|
||||
public static void addLocalization(String key, String value)
|
||||
{
|
||||
addLocalization(key, "en_US", value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add localization for the specified string
|
||||
*
|
||||
* @param key
|
||||
* @param lang
|
||||
* @param value
|
||||
*/
|
||||
public static void addLocalization(String key, String lang, String value)
|
||||
{
|
||||
FMLCommonHandler.instance().addStringLocalization(key, lang, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Name the specified minecraft object with the supplied name
|
||||
*
|
||||
* @param instance
|
||||
* @param name
|
||||
*/
|
||||
public static void addName(Object instance, String name)
|
||||
{
|
||||
addName(instance,"en_US",name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unimplemented on the server as it does not generate names
|
||||
*
|
||||
* @param instance
|
||||
* @param lang
|
||||
* @param name
|
||||
*/
|
||||
public static void addName(Object instance, String lang, String name)
|
||||
{
|
||||
FMLCommonHandler.instance().addNameForObject(instance, lang, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unimplemented on the server as it does not render textures
|
||||
*
|
||||
* @param fileToOverride
|
||||
* @param fileToAdd
|
||||
* @return
|
||||
*/
|
||||
public static int addOverride(String fileToOverride, String fileToAdd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unimplemented on the server as it does not render textures
|
||||
*
|
||||
* @param path
|
||||
* @param overlayPath
|
||||
* @param index
|
||||
*/
|
||||
public static void addOverride(String path, String overlayPath, int index)
|
||||
{
|
||||
// NOOP
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a Shaped Recipe
|
||||
*
|
||||
* @param output
|
||||
* @param params
|
||||
*/
|
||||
public static void addRecipe(ItemStack output, Object... params)
|
||||
{
|
||||
FMLRegistry.addRecipe(output, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a shapeless recipe
|
||||
*
|
||||
* @param output
|
||||
* @param params
|
||||
*/
|
||||
public static void addShapelessRecipe(ItemStack output, Object... params)
|
||||
{
|
||||
FMLRegistry.addShapelessRecipe(output, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new product to be smelted
|
||||
*
|
||||
* @param input
|
||||
* @param output
|
||||
*/
|
||||
public static void addSmelting(int input, ItemStack output)
|
||||
{
|
||||
FMLRegistry.addSmelting(input, output);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a mob to the spawn list
|
||||
*
|
||||
* @param entityClass
|
||||
* @param weightedProb
|
||||
* @param min
|
||||
* @param max
|
||||
* @param spawnList
|
||||
*/
|
||||
public static void addSpawn(Class <? extends EntityLiving > entityClass, int weightedProb, int min, int max, EnumCreatureType spawnList)
|
||||
{
|
||||
FMLRegistry.addSpawn(entityClass, weightedProb, min, max, spawnList, FMLBukkitHandler.instance().getDefaultOverworldBiomes());
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a mob to the spawn list
|
||||
* @param entityClass
|
||||
* @param weightedProb
|
||||
* @param min
|
||||
* @param max
|
||||
* @param spawnList
|
||||
* @param biomes
|
||||
*/
|
||||
public static void addSpawn(Class <? extends EntityLiving > entityClass, int weightedProb, int min, int max, EnumCreatureType spawnList, BiomeBase... biomes)
|
||||
{
|
||||
FMLRegistry.addSpawn(entityClass, weightedProb, min, max, spawnList, biomes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a mob to the spawn list
|
||||
*
|
||||
* @param entityName
|
||||
* @param weightedProb
|
||||
* @param min
|
||||
* @param max
|
||||
* @param spawnList
|
||||
*/
|
||||
public static void addSpawn(String entityName, int weightedProb, int min, int max, EnumCreatureType spawnList)
|
||||
{
|
||||
FMLRegistry.addSpawn(entityName, weightedProb, min, max, spawnList, FMLBukkitHandler.instance().getDefaultOverworldBiomes());
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a mob to the spawn list
|
||||
* @param entityName
|
||||
* @param weightedProb
|
||||
* @param min
|
||||
* @param max
|
||||
* @param spawnList
|
||||
* @param biomes
|
||||
*/
|
||||
public static void addSpawn(String entityName, int weightedProb, int min, int max, EnumCreatureType spawnList, BiomeBase... biomes)
|
||||
{
|
||||
FMLRegistry.addSpawn(entityName, weightedProb, min, max, spawnList, biomes);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is a call in hook from modified external code. Implemented elsewhere.
|
||||
* {@link FMLBukkitHandler#tryDispensingEntity(World, double, double, double, byte, byte, ItemStack)}
|
||||
*
|
||||
* @param world
|
||||
* @param x
|
||||
* @param y
|
||||
* @param z
|
||||
* @param xVel
|
||||
* @param zVel
|
||||
* @param item
|
||||
* @return
|
||||
*/
|
||||
@Deprecated
|
||||
public static boolean dispenseEntity(World world, double x, double y, double z, int xVel, int zVel, ItemStack item)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a container and drop all the items in it on the ground around
|
||||
*
|
||||
* @param world
|
||||
* @param x
|
||||
* @param y
|
||||
* @param z
|
||||
*/
|
||||
public static void genericContainerRemoval(World world, int x, int y, int z)
|
||||
{
|
||||
TileEntity te = world.getTileEntity(x, y, z);
|
||||
|
||||
if (!(te instanceof IInventory))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
IInventory inv = (IInventory)te;
|
||||
|
||||
for (int l = 0; l < inv.getSize(); l++)
|
||||
{
|
||||
ItemStack itemstack = inv.getItem(l);
|
||||
|
||||
if (itemstack == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
float f = world.random.nextFloat() * 0.8F + 0.1F;
|
||||
float f1 = world.random.nextFloat() * 0.8F + 0.1F;
|
||||
float f2 = world.random.nextFloat() * 0.8F + 0.1F;
|
||||
|
||||
while (itemstack.count > 0)
|
||||
{
|
||||
int i1 = world.random.nextInt(21) + 10;
|
||||
|
||||
if (i1 > itemstack.count)
|
||||
{
|
||||
i1 = itemstack.count ;
|
||||
}
|
||||
|
||||
itemstack.count -= i1;
|
||||
EntityItem entityitem = new EntityItem(world, (float)te.x + f, (float)te.y + f1, (float)te.z + f2, new ItemStack(itemstack.id, i1, itemstack.getData()));
|
||||
float f3 = 0.05F;
|
||||
entityitem.motX = (float)world.random.nextGaussian() * f3;
|
||||
entityitem.motY = (float)world.random.nextGaussian() * f3 + 0.2F;
|
||||
entityitem.motZ = (float)world.random.nextGaussian() * f3;
|
||||
|
||||
if (itemstack.hasTag())
|
||||
{
|
||||
entityitem.itemStack.setTag((NBTTagCompound)itemstack.getTag().clone());
|
||||
}
|
||||
|
||||
world.addEntity(entityitem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of all BaseMod loaded into the system
|
||||
* {@link ModLoaderModContainer#findAll}
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static List<BaseMod> getLoadedMods()
|
||||
{
|
||||
return ModLoaderModContainer.findAll(BaseMod.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a logger instance {@link FMLCommonHandler#getFMLLogger()}
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static Logger getLogger()
|
||||
{
|
||||
return FMLCommonHandler.instance().getFMLLogger();
|
||||
}
|
||||
|
||||
public static Object getMinecraftInstance()
|
||||
{
|
||||
return getMinecraftServerInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the minecraft server instance
|
||||
* {@link FMLServerHandler#getServer()}
|
||||
* @return
|
||||
*/
|
||||
public static MinecraftServer getMinecraftServerInstance()
|
||||
{
|
||||
return FMLBukkitHandler.instance().getServer();
|
||||
}
|
||||
/**
|
||||
* Get a value from a field using reflection
|
||||
* {@link ReflectionHelper#getPrivateValue(Class, Object, int)}
|
||||
*
|
||||
* @param instanceclass
|
||||
* @param instance
|
||||
* @param fieldindex
|
||||
* @return
|
||||
*/
|
||||
public static <T, E> T getPrivateValue(Class <? super E > instanceclass, E instance, int fieldindex)
|
||||
{
|
||||
return ReflectionHelper.getPrivateValue(instanceclass, instance, fieldindex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a value from a field using reflection
|
||||
* {@link ReflectionHelper#getPrivateValue(Class, Object, String)}
|
||||
*
|
||||
* @param instanceclass
|
||||
* @param instance
|
||||
* @param field
|
||||
* @return
|
||||
*/
|
||||
public static <T, E> T getPrivateValue(Class <? super E > instanceclass, E instance, String field)
|
||||
{
|
||||
return ReflectionHelper.getPrivateValue(instanceclass, instance, field);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stubbed method on the server to return a unique model id
|
||||
*
|
||||
*/
|
||||
public static int getUniqueBlockModelID(BaseMod mod, boolean inventoryRenderer)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a new unique entity id
|
||||
* {@link Entity#getNextId()}
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static int getUniqueEntityId()
|
||||
{
|
||||
return FMLCommonHandler.instance().nextUniqueEntityListId();
|
||||
}
|
||||
|
||||
public static int getUniqueSpriteIndex(String path)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* To properly implement packet 250 protocol you should always check your
|
||||
* channel is active prior to sending the packet
|
||||
*
|
||||
* @param player
|
||||
* @param channel
|
||||
* @return
|
||||
*/
|
||||
public static boolean isChannelActive(EntityPlayer player, String channel)
|
||||
{
|
||||
return FMLCommonHandler.instance().isChannelActive(channel, player);
|
||||
}
|
||||
|
||||
public static boolean isGUIOpen(Class<?> gui)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the named mod loaded?
|
||||
* {@link Loader#isModLoaded(String)}
|
||||
*
|
||||
* @param modname
|
||||
* @return
|
||||
*/
|
||||
public static boolean isModLoaded(String modname)
|
||||
{
|
||||
return Loader.isModLoaded(modname);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implemented elsewhere
|
||||
*/
|
||||
@Deprecated
|
||||
public static void loadConfig()
|
||||
{
|
||||
}
|
||||
|
||||
public static Object loadImage(Object renderEngine, String path) throws Exception
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call in from elsewhere. Unimplemented here.
|
||||
* @param player
|
||||
* @param item
|
||||
*/
|
||||
@Deprecated
|
||||
public static void onItemPickup(EntityPlayer player, ItemStack item)
|
||||
{
|
||||
}
|
||||
/**
|
||||
* Call in from elsewhere. Unimplemented here.
|
||||
*/
|
||||
@Deprecated
|
||||
public static void onTick(float tick, Object game)
|
||||
{
|
||||
}
|
||||
|
||||
public static void openGUI(EntityPlayer player, Object gui)
|
||||
{
|
||||
// NOOP
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void populateChunk(IChunkProvider generator, int chunkX, int chunkZ, World world)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is a call in hook from modified external code. Implemented elsewhere.
|
||||
* {@link FMLBukkitHandler#handlePacket250(Packet250CustomPayload, EntityHuman)}
|
||||
*
|
||||
* @param packet
|
||||
*/
|
||||
@Deprecated
|
||||
public static void receivePacket(Packet250CustomPayload packet)
|
||||
{
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static Object[] registerAllKeys(Object[] keys)
|
||||
{
|
||||
return keys;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void registerAllTextureOverrides(Object cache)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a new block
|
||||
*
|
||||
* @param block
|
||||
*/
|
||||
public static void registerBlock(Block block)
|
||||
{
|
||||
FMLRegistry.registerBlock(block);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a new block
|
||||
*
|
||||
* @param block
|
||||
* @param itemclass
|
||||
*/
|
||||
public static void registerBlock(Block block, Class <? extends ItemBlock > itemclass)
|
||||
{
|
||||
FMLRegistry.registerBlock(block, itemclass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a new entity ID
|
||||
*
|
||||
* @param entityClass
|
||||
* @param entityName
|
||||
* @param id
|
||||
*/
|
||||
public static void registerEntityID(Class <? extends Entity > entityClass, String entityName, int id)
|
||||
{
|
||||
FMLRegistry.registerEntityID(entityClass, entityName, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a new entity ID
|
||||
*
|
||||
* @param entityClass
|
||||
* @param entityName
|
||||
* @param id
|
||||
* @param background
|
||||
* @param foreground
|
||||
*/
|
||||
public static void registerEntityID(Class <? extends Entity > entityClass, String entityName, int id, int background, int foreground)
|
||||
{
|
||||
FMLRegistry.registerEntityID(entityClass, entityName, id, background, foreground);
|
||||
}
|
||||
|
||||
public static void registerKey(BaseMod mod, Object keyHandler, boolean allowRepeat)
|
||||
{
|
||||
// NOOP
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the mod for packets on this channel. This only registers the
|
||||
* channel with Forge Mod Loader, not with clients connecting- use
|
||||
* BaseMod.onClientLogin to tell them about your custom channel
|
||||
* {@link FMLCommonHandler#registerChannel(cpw.mods.fml.common.ModContainer, String)}
|
||||
*
|
||||
* @param mod
|
||||
* @param channel
|
||||
*/
|
||||
public static void registerPacketChannel(BaseMod mod, String channel)
|
||||
{
|
||||
FMLCommonHandler.instance().registerChannel(ModLoaderModContainer.findContainerFor(mod), channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a new tile entity class
|
||||
*
|
||||
* @param tileEntityClass
|
||||
* @param id
|
||||
*/
|
||||
public static void registerTileEntity(Class <? extends TileEntity > tileEntityClass, String id)
|
||||
{
|
||||
FMLRegistry.registerTileEntity(tileEntityClass, id);
|
||||
}
|
||||
|
||||
public static void registerTileEntity(Class<? extends TileEntity> tileEntityClass, String id, Object renderer)
|
||||
{
|
||||
FMLRegistry.instance().registerTileEntity(tileEntityClass, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a biome from the list of generated biomes
|
||||
*
|
||||
* @param biome
|
||||
*/
|
||||
public static void removeBiome(BiomeBase biome)
|
||||
{
|
||||
FMLRegistry.removeBiome(biome);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a spawn
|
||||
*
|
||||
* @param entityClass
|
||||
* @param spawnList
|
||||
*/
|
||||
public static void removeSpawn(Class <? extends EntityLiving > entityClass, EnumCreatureType spawnList)
|
||||
{
|
||||
FMLRegistry.removeSpawn(entityClass, spawnList, FMLBukkitHandler.instance().getDefaultOverworldBiomes());
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a spawn
|
||||
*
|
||||
* @param entityClass
|
||||
* @param spawnList
|
||||
* @param biomes
|
||||
*/
|
||||
public static void removeSpawn(Class <? extends EntityLiving > entityClass, EnumCreatureType spawnList, BiomeBase... biomes)
|
||||
{
|
||||
FMLRegistry.removeSpawn(entityClass, spawnList, biomes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a spawn
|
||||
*
|
||||
* @param entityName
|
||||
* @param spawnList
|
||||
*/
|
||||
public static void removeSpawn(String entityName, EnumCreatureType spawnList)
|
||||
{
|
||||
FMLRegistry.removeSpawn(entityName, spawnList, FMLBukkitHandler.instance().getDefaultOverworldBiomes());
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a spawn
|
||||
*
|
||||
* @param entityName
|
||||
* @param spawnList
|
||||
* @param biomes
|
||||
*/
|
||||
public static void removeSpawn(String entityName, EnumCreatureType spawnList, BiomeBase... biomes)
|
||||
{
|
||||
FMLRegistry.removeSpawn(entityName, spawnList, biomes);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static boolean renderBlockIsItemFull3D(int modelID)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void renderInvBlock(Object renderer, Block block, int metadata, int modelID)
|
||||
{
|
||||
// NOOP
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static boolean renderWorldBlock(Object renderer, IBlockAccess world, int x, int y, int z, Block block, int modelID)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configuration is handled elsewhere
|
||||
* {@link ModLoaderModContainer}
|
||||
*/
|
||||
@Deprecated
|
||||
public static void saveConfig()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a chat message to the server
|
||||
* {@link FMLServerHandler#handleChatPacket(Packet3Chat, EntityPlayer)}
|
||||
*
|
||||
* @param text
|
||||
*/
|
||||
@Deprecated
|
||||
public static void serverChat(String text)
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void serverLogin(Object handler, Packet1Login loginPacket)
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate that you want to receive ticks
|
||||
*
|
||||
* @param mod receiving the events
|
||||
* @param enable indicates whether you want to recieve them or not
|
||||
* @param useClock Not used in server side: all ticks are sent on the server side (no render subticks)
|
||||
*/
|
||||
public static void setInGameHook(BaseMod mod, boolean enable, boolean useClock)
|
||||
{
|
||||
ModLoaderHelper.updateStandardTicks(mod, enable, useClock);
|
||||
}
|
||||
|
||||
|
||||
public static void setInGUIHook(BaseMod mod, boolean enable, boolean useClock)
|
||||
{
|
||||
ModLoaderHelper.updateGUITicks(mod, enable, useClock);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a private field to a value using reflection
|
||||
* {@link ReflectionHelper#setPrivateValue(Class, Object, int, Object)}
|
||||
*
|
||||
* @param instanceclass
|
||||
* @param instance
|
||||
* @param fieldindex
|
||||
* @param value
|
||||
*/
|
||||
public static <T, E> void setPrivateValue(Class <? super T > instanceclass, T instance, int fieldindex, E value)
|
||||
{
|
||||
ReflectionHelper.setPrivateValue(instanceclass, instance, fieldindex, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a private field to a value using reflection
|
||||
* {@link ReflectionHelper#setPrivateValue(Class, Object, String, Object)}
|
||||
*
|
||||
* @param instanceclass
|
||||
* @param instance
|
||||
* @param field
|
||||
* @param value
|
||||
*/
|
||||
public static <T, E> void setPrivateValue(Class <? super T > instanceclass, T instance, String field, E value)
|
||||
{
|
||||
ReflectionHelper.setPrivateValue(instanceclass, instance, field, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is a call in hook from modified external code. Implemented elsewhere.
|
||||
* {@link FMLBukkitHandler#onItemCrafted(EntityHuman, ItemStack, IInventory)}
|
||||
*
|
||||
* @param player
|
||||
* @param item
|
||||
* @param matrix
|
||||
*/
|
||||
@Deprecated
|
||||
public static void takenFromCrafting(EntityHuman player, ItemStack item, IInventory matrix)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is a call in hook from modified external code. Implemented elsewhere.
|
||||
* {@link FMLBukkitHandler#onItemSmelted(EntityHuman, ItemStack)}
|
||||
*
|
||||
* @param player
|
||||
* @param item
|
||||
*/
|
||||
@Deprecated
|
||||
public static void takenFromFurnace(EntityHuman player, ItemStack item)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw the offered exception. Likely will stop the game.
|
||||
* {@link FMLBukkitHandler#raiseException(Throwable, String, boolean)}
|
||||
* @param message
|
||||
* @param e
|
||||
*/
|
||||
public static void throwException(String message, Throwable e)
|
||||
{
|
||||
FMLBukkitHandler.instance().raiseException(e, message, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* To properly implement packet 250 protocol you should always check your channel
|
||||
* is active prior to sending the packet
|
||||
*
|
||||
* @param player
|
||||
* @param channel
|
||||
* @return
|
||||
*/
|
||||
public static boolean isChannelActive(EntityHuman player, String channel)
|
||||
{
|
||||
return FMLCommonHandler.instance().isChannelActive(channel, player);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* The FML Forge Mod Loader suite.
|
||||
* Copyright (C) 2012 cpw
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package net.minecraft.server;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* @author cpw
|
||||
*
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
public @interface SidedProxy
|
||||
{
|
||||
/**
|
||||
* The name of the client side class to load and populate
|
||||
* @return
|
||||
*/
|
||||
String clientSide() default "";
|
||||
|
||||
/**
|
||||
* The name of the server side class to load and populate
|
||||
* @return
|
||||
*/
|
||||
String serverSide() default "";
|
||||
|
||||
/**
|
||||
* The name of the a special bukkit plugin class to load and populate
|
||||
*/
|
||||
String bukkitSide() default "";
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package net.minecraft.src;
|
||||
|
||||
public interface BiomeGenBase {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package net.minecraft.src;
|
||||
|
||||
public interface Block {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package net.minecraft.src;
|
||||
|
||||
public interface Entity {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package net.minecraft.src;
|
||||
|
||||
public interface EntityLiving {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package net.minecraft.src;
|
||||
|
||||
public interface EnumCreatureType {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package net.minecraft.src;
|
||||
|
||||
public interface IRecipe {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package net.minecraft.src;
|
||||
|
||||
public interface ItemBlock {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package net.minecraft.src;
|
||||
|
||||
public interface ItemStack {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package net.minecraft.src;
|
||||
|
||||
public interface TileEntity {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
import sys
|
||||
import os, os.path, shutil
|
||||
import fnmatch
|
||||
import re
|
||||
|
||||
def main():
|
||||
sys.stdout.flush()
|
||||
for x in range(1, len(sys.argv)):
|
||||
cleanup_source(sys.argv[x])
|
||||
|
||||
count = 0
|
||||
def cleanup_source(path):
|
||||
path = os.path.normpath(path)
|
||||
regex_cases_before = re.compile(r'((case|default).+\r?\n)\r?\n', re.MULTILINE) #Fixes newline after case before case body
|
||||
regex_cases_after = re.compile(r'\r?\n(\r?\n[ \t]+(case|default))', re.MULTILINE) #Fixes newline after case body before new case
|
||||
|
||||
def updatefile(src_file):
|
||||
global count
|
||||
tmp_file = src_file + '.tmp'
|
||||
count = 0
|
||||
with open(src_file, 'r') as fh:
|
||||
buf = fh.read()
|
||||
|
||||
def fix_cases(match):
|
||||
global count
|
||||
count += 1
|
||||
return match.group(1)
|
||||
|
||||
buf = regex_cases_before.sub(fix_cases, buf)
|
||||
buf = regex_cases_after.sub(fix_cases, buf)
|
||||
if count > 0:
|
||||
with open(tmp_file, 'w') as fh:
|
||||
fh.write(buf)
|
||||
shutil.move(tmp_file, src_file)
|
||||
|
||||
for path, _, filelist in os.walk(path, followlinks=True):
|
||||
sub_dir = os.path.relpath(path, path)
|
||||
for cur_file in fnmatch.filter(filelist, '*.java'):
|
||||
src_file = os.path.normpath(os.path.join(path, cur_file))
|
||||
updatefile(src_file)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -0,0 +1,43 @@
|
||||
package cpw.mods.fml.client;
|
||||
|
||||
import cpw.mods.fml.common.IFMLHandledException;
|
||||
import cpw.mods.fml.common.Side;
|
||||
import cpw.mods.fml.common.asm.SideOnly;
|
||||
import net.minecraft.src.FontRenderer;
|
||||
import net.minecraft.src.GuiErrorScreen;
|
||||
|
||||
/**
|
||||
* If a mod throws this exception during loading, it will be called back to render
|
||||
* the error screen through the methods below. This error will not be cleared, and will
|
||||
* not allow the game to carry on, but might be useful if your mod wishes to report
|
||||
* a fatal configuration error in a pretty way.
|
||||
*
|
||||
* Throw this through a proxy. It won't work on the dedicated server environment.
|
||||
* @author cpw
|
||||
*
|
||||
*/
|
||||
@SideOnly(Side.CLIENT)
|
||||
public abstract class CustomModLoadingErrorDisplayException extends RuntimeException implements IFMLHandledException
|
||||
{
|
||||
/**
|
||||
* Called after the GUI is inited by the parent code. You can do extra stuff here, maybe?
|
||||
*
|
||||
* @param errorScreen The error screen we're painting
|
||||
* @param fontRenderer A font renderer for you
|
||||
*/
|
||||
public abstract void initGui(GuiErrorScreen errorScreen, FontRenderer fontRenderer);
|
||||
|
||||
/**
|
||||
* Draw your error to the screen.
|
||||
*
|
||||
* <br/><em>Warning: Minecraft is in a deep error state.</em> <strong>All</strong> it can do is stop.
|
||||
* Do not try and do anything involving complex user interaction here.
|
||||
*
|
||||
* @param errorScreen The error screen to draw to
|
||||
* @param fontRenderer A font renderer for you
|
||||
* @param mouseRelX Mouse X
|
||||
* @param mouseRelY Mouse Y
|
||||
* @param tickTime tick time
|
||||
*/
|
||||
public abstract void drawScreen(GuiErrorScreen errorScreen, FontRenderer fontRenderer, int mouseRelX, int mouseRelY, float tickTime);
|
||||
}
|
||||
@@ -0,0 +1,451 @@
|
||||
/*
|
||||
* The FML Forge Mod Loader suite. Copyright (C) 2012 cpw
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package cpw.mods.fml.client;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.src.CrashReport;
|
||||
import net.minecraft.src.Entity;
|
||||
import net.minecraft.src.EntityLiving;
|
||||
import net.minecraft.src.EntityPlayer;
|
||||
import net.minecraft.src.GuiScreen;
|
||||
import net.minecraft.src.NetClientHandler;
|
||||
import net.minecraft.src.NetHandler;
|
||||
import net.minecraft.src.Packet;
|
||||
import net.minecraft.src.Packet131MapData;
|
||||
import net.minecraft.src.Render;
|
||||
import net.minecraft.src.RenderManager;
|
||||
import net.minecraft.src.World;
|
||||
import net.minecraft.src.WorldClient;
|
||||
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import cpw.mods.fml.client.modloader.ModLoaderClientHelper;
|
||||
import cpw.mods.fml.client.registry.KeyBindingRegistry;
|
||||
import cpw.mods.fml.client.registry.RenderingRegistry;
|
||||
import cpw.mods.fml.common.DummyModContainer;
|
||||
import cpw.mods.fml.common.FMLCommonHandler;
|
||||
import cpw.mods.fml.common.FMLLog;
|
||||
import cpw.mods.fml.common.IFMLSidedHandler;
|
||||
import cpw.mods.fml.common.Loader;
|
||||
import cpw.mods.fml.common.LoaderException;
|
||||
import cpw.mods.fml.common.MetadataCollection;
|
||||
import cpw.mods.fml.common.MissingModsException;
|
||||
import cpw.mods.fml.common.ModContainer;
|
||||
import cpw.mods.fml.common.ModMetadata;
|
||||
import cpw.mods.fml.common.ObfuscationReflectionHelper;
|
||||
import cpw.mods.fml.common.Side;
|
||||
import cpw.mods.fml.common.WrongMinecraftVersionException;
|
||||
import cpw.mods.fml.common.network.EntitySpawnAdjustmentPacket;
|
||||
import cpw.mods.fml.common.network.EntitySpawnPacket;
|
||||
import cpw.mods.fml.common.network.ModMissingPacket;
|
||||
import cpw.mods.fml.common.registry.EntityRegistry.EntityRegistration;
|
||||
import cpw.mods.fml.common.registry.IEntityAdditionalSpawnData;
|
||||
import cpw.mods.fml.common.registry.IThrowableEntity;
|
||||
import cpw.mods.fml.common.registry.LanguageRegistry;
|
||||
|
||||
|
||||
/**
|
||||
* Handles primary communication from hooked code into the system
|
||||
*
|
||||
* The FML entry point is {@link #beginMinecraftLoading(Minecraft)} called from
|
||||
* {@link Minecraft}
|
||||
*
|
||||
* Obfuscated code should focus on this class and other members of the "server"
|
||||
* (or "client") code
|
||||
*
|
||||
* The actual mod loading is handled at arms length by {@link Loader}
|
||||
*
|
||||
* It is expected that a similar class will exist for each target environment:
|
||||
* Bukkit and Client side.
|
||||
*
|
||||
* It should not be directly modified.
|
||||
*
|
||||
* @author cpw
|
||||
*
|
||||
*/
|
||||
public class FMLClientHandler implements IFMLSidedHandler
|
||||
{
|
||||
/**
|
||||
* The singleton
|
||||
*/
|
||||
private static final FMLClientHandler INSTANCE = new FMLClientHandler();
|
||||
|
||||
/**
|
||||
* A reference to the server itself
|
||||
*/
|
||||
private Minecraft client;
|
||||
|
||||
private DummyModContainer optifineContainer;
|
||||
|
||||
private boolean guiLoaded;
|
||||
|
||||
private boolean serverIsRunning;
|
||||
|
||||
private MissingModsException modsMissing;
|
||||
|
||||
private boolean loading;
|
||||
|
||||
private WrongMinecraftVersionException wrongMC;
|
||||
|
||||
private CustomModLoadingErrorDisplayException customError;
|
||||
|
||||
/**
|
||||
* Called to start the whole game off from
|
||||
* {@link MinecraftServer#startServer}
|
||||
*
|
||||
* @param minecraftServer
|
||||
*/
|
||||
public void beginMinecraftLoading(Minecraft minecraft)
|
||||
{
|
||||
if (minecraft.func_71355_q())
|
||||
{
|
||||
FMLLog.severe("DEMO MODE DETECTED, FML will not work. Finishing now.");
|
||||
haltGame("FML will not run in demo mode", new RuntimeException());
|
||||
return;
|
||||
}
|
||||
|
||||
loading = true;
|
||||
client = minecraft;
|
||||
ObfuscationReflectionHelper.detectObfuscation(World.class);
|
||||
TextureFXManager.instance().setClient(client);
|
||||
FMLCommonHandler.instance().beginLoading(this);
|
||||
new ModLoaderClientHelper(client);
|
||||
try
|
||||
{
|
||||
Class<?> optifineConfig = Class.forName("Config", false, Loader.instance().getModClassLoader());
|
||||
String optifineVersion = (String) optifineConfig.getField("VERSION").get(null);
|
||||
Map<String,Object> dummyOptifineMeta = ImmutableMap.<String,Object>builder().put("name", "Optifine").put("version", optifineVersion).build();
|
||||
ModMetadata optifineMetadata = MetadataCollection.from(getClass().getResourceAsStream("optifinemod.info"),"optifine").getMetadataForId("optifine", dummyOptifineMeta);
|
||||
optifineContainer = new DummyModContainer(optifineMetadata);
|
||||
FMLLog.info("Forge Mod Loader has detected optifine %s, enabling compatibility features",optifineContainer.getVersion());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
optifineContainer = null;
|
||||
}
|
||||
try
|
||||
{
|
||||
Loader.instance().loadMods();
|
||||
}
|
||||
catch (WrongMinecraftVersionException wrong)
|
||||
{
|
||||
wrongMC = wrong;
|
||||
}
|
||||
catch (MissingModsException missing)
|
||||
{
|
||||
modsMissing = missing;
|
||||
}
|
||||
catch (CustomModLoadingErrorDisplayException custom)
|
||||
{
|
||||
FMLLog.log(Level.SEVERE, custom, "A custom exception was thrown by a mod, the game will now halt");
|
||||
customError = custom;
|
||||
}
|
||||
catch (LoaderException le)
|
||||
{
|
||||
haltGame("There was a severe problem during mod loading that has caused the game to fail", le);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void haltGame(String message, Throwable t)
|
||||
{
|
||||
client.func_71377_b(new CrashReport(message, t));
|
||||
throw Throwables.propagate(t);
|
||||
}
|
||||
/**
|
||||
* Called a bit later on during initialization to finish loading mods
|
||||
* Also initializes key bindings
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public void finishMinecraftLoading()
|
||||
{
|
||||
if (modsMissing != null || wrongMC != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
Loader.instance().initializeMods();
|
||||
}
|
||||
catch (CustomModLoadingErrorDisplayException custom)
|
||||
{
|
||||
FMLLog.log(Level.SEVERE, custom, "A custom exception was thrown by a mod, the game will now halt");
|
||||
customError = custom;
|
||||
return;
|
||||
}
|
||||
catch (LoaderException le)
|
||||
{
|
||||
haltGame("There was a severe problem during mod loading that has caused the game to fail", le);
|
||||
return;
|
||||
}
|
||||
LanguageRegistry.reloadLanguageTable();
|
||||
RenderingRegistry.instance().loadEntityRenderers((Map<Class<? extends Entity>, Render>)RenderManager.field_78727_a.field_78729_o);
|
||||
|
||||
loading = false;
|
||||
KeyBindingRegistry.instance().uploadKeyBindingsToGame(client.field_71474_y);
|
||||
}
|
||||
|
||||
public void onInitializationComplete()
|
||||
{
|
||||
if (wrongMC != null)
|
||||
{
|
||||
client.func_71373_a(new GuiWrongMinecraft(wrongMC));
|
||||
}
|
||||
else if (modsMissing != null)
|
||||
{
|
||||
client.func_71373_a(new GuiModsMissing(modsMissing));
|
||||
}
|
||||
else if (customError != null)
|
||||
{
|
||||
client.func_71373_a(new GuiCustomModLoadingErrorScreen(customError));
|
||||
}
|
||||
else
|
||||
{
|
||||
TextureFXManager.instance().loadTextures(client.field_71418_C.func_77292_e());
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Get the server instance
|
||||
*/
|
||||
public Minecraft getClient()
|
||||
{
|
||||
return client;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a handle to the client's logger instance
|
||||
* The client actually doesn't have one- so we return null
|
||||
*/
|
||||
public Logger getMinecraftLogger()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the instance
|
||||
*/
|
||||
public static FMLClientHandler instance()
|
||||
{
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param player
|
||||
* @param gui
|
||||
*/
|
||||
public void displayGuiScreen(EntityPlayer player, GuiScreen gui)
|
||||
{
|
||||
if (client.field_71439_g==player && gui != null) {
|
||||
client.func_71373_a(gui);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mods
|
||||
*/
|
||||
public void addSpecialModEntries(ArrayList<ModContainer> mods)
|
||||
{
|
||||
if (optifineContainer!=null) {
|
||||
mods.add(optifineContainer);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getAdditionalBrandingInformation()
|
||||
{
|
||||
if (optifineContainer!=null)
|
||||
{
|
||||
return Arrays.asList(String.format("Optifine %s",optifineContainer.getVersion()));
|
||||
} else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Side getSide()
|
||||
{
|
||||
return Side.CLIENT;
|
||||
}
|
||||
|
||||
public boolean hasOptifine()
|
||||
{
|
||||
return optifineContainer!=null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showGuiScreen(Object clientGuiElement)
|
||||
{
|
||||
GuiScreen gui = (GuiScreen) clientGuiElement;
|
||||
client.func_71373_a(gui);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Entity spawnEntityIntoClientWorld(EntityRegistration er, EntitySpawnPacket packet)
|
||||
{
|
||||
WorldClient wc = client.field_71441_e;
|
||||
|
||||
Class<? extends Entity> cls = er.getEntityClass();
|
||||
|
||||
try
|
||||
{
|
||||
Entity entity;
|
||||
if (er.hasCustomSpawning())
|
||||
{
|
||||
entity = er.doCustomSpawning(packet);
|
||||
}
|
||||
else
|
||||
{
|
||||
entity = (Entity)(cls.getConstructor(World.class).newInstance(wc));
|
||||
entity.field_70157_k = packet.entityId;
|
||||
entity.func_70012_b(packet.scaledX, packet.scaledY, packet.scaledZ, packet.scaledYaw, packet.scaledPitch);
|
||||
if (entity instanceof EntityLiving)
|
||||
{
|
||||
((EntityLiving)entity).field_70759_as = packet.scaledHeadYaw;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
entity.field_70118_ct = packet.rawX;
|
||||
entity.field_70117_cu = packet.rawY;
|
||||
entity.field_70116_cv = packet.rawZ;
|
||||
|
||||
if (entity instanceof IThrowableEntity)
|
||||
{
|
||||
Entity thrower = client.field_71439_g.field_70157_k == packet.throwerId ? client.field_71439_g : wc.func_73045_a(packet.throwerId);
|
||||
((IThrowableEntity)entity).setThrower(thrower);
|
||||
}
|
||||
|
||||
|
||||
Entity parts[] = entity.func_70021_al();
|
||||
if (parts != null)
|
||||
{
|
||||
int i = packet.entityId - entity.field_70157_k;
|
||||
for (int j = 0; j < parts.length; j++)
|
||||
{
|
||||
parts[j].field_70157_k += i;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (packet.metadata != null)
|
||||
{
|
||||
entity.func_70096_w().func_75687_a((List)packet.metadata);
|
||||
}
|
||||
|
||||
if (packet.throwerId > 0)
|
||||
{
|
||||
entity.func_70016_h(packet.speedScaledX, packet.speedScaledY, packet.speedScaledZ);
|
||||
}
|
||||
|
||||
if (entity instanceof IEntityAdditionalSpawnData)
|
||||
{
|
||||
((IEntityAdditionalSpawnData)entity).readSpawnData(packet.dataStream);
|
||||
}
|
||||
|
||||
wc.func_73027_a(packet.entityId, entity);
|
||||
return entity;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
FMLLog.log(Level.SEVERE, e, "A severe problem occurred during the spawning of an entity");
|
||||
throw Throwables.propagate(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void adjustEntityLocationOnClient(EntitySpawnAdjustmentPacket packet)
|
||||
{
|
||||
Entity ent = client.field_71441_e.func_73045_a(packet.entityId);
|
||||
if (ent != null)
|
||||
{
|
||||
ent.field_70118_ct = packet.serverX;
|
||||
ent.field_70117_cu = packet.serverY;
|
||||
ent.field_70116_cv = packet.serverZ;
|
||||
}
|
||||
else
|
||||
{
|
||||
FMLLog.fine("Attempted to adjust the position of entity %d which is not present on the client", packet.entityId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beginServerLoading(MinecraftServer server)
|
||||
{
|
||||
// NOOP
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finishServerLoading()
|
||||
{
|
||||
// NOOP
|
||||
}
|
||||
|
||||
@Override
|
||||
public MinecraftServer getServer()
|
||||
{
|
||||
return client.func_71401_C();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendPacket(Packet packet)
|
||||
{
|
||||
if(client.field_71439_g != null)
|
||||
{
|
||||
client.field_71439_g.field_71174_a.func_72552_c(packet);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayMissingMods(ModMissingPacket modMissingPacket)
|
||||
{
|
||||
client.func_71373_a(new GuiModsMissingForServer(modMissingPacket));
|
||||
}
|
||||
|
||||
/**
|
||||
* If the client is in the midst of loading, we disable saving so that custom settings aren't wiped out
|
||||
*/
|
||||
public boolean isLoading()
|
||||
{
|
||||
return loading;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleTinyPacket(NetHandler handler, Packet131MapData mapData)
|
||||
{
|
||||
((NetClientHandler)handler).fmlPacket131Callback(mapData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setClientCompatibilityLevel(byte compatibilityLevel)
|
||||
{
|
||||
NetClientHandler.setConnectionCompatibilityLevel(compatibilityLevel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getClientCompatibilityLevel()
|
||||
{
|
||||
return NetClientHandler.getConnectionCompatibilityLevel();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* The FML Forge Mod Loader suite.
|
||||
* Copyright (C) 2012 cpw
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package cpw.mods.fml.client;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import net.minecraft.src.RenderEngine;
|
||||
import net.minecraft.src.TextureFX;
|
||||
import net.minecraft.src.ITexturePack;
|
||||
import cpw.mods.fml.common.FMLCommonHandler;
|
||||
import cpw.mods.fml.common.FMLLog;
|
||||
|
||||
public class FMLTextureFX extends TextureFX implements ITextureFX
|
||||
{
|
||||
public int tileSizeBase = 16;
|
||||
public int tileSizeSquare = 256;
|
||||
public int tileSizeMask = 15;
|
||||
public int tileSizeSquareMask = 255;
|
||||
public boolean errored = false;
|
||||
protected Logger log = FMLLog.getLogger();
|
||||
|
||||
public FMLTextureFX(int icon)
|
||||
{
|
||||
super(icon);
|
||||
}
|
||||
|
||||
@Override public void setErrored(boolean err){ errored = err; }
|
||||
@Override public boolean getErrored(){ return errored; }
|
||||
@Override
|
||||
public void onTexturePackChanged(RenderEngine engine, ITexturePack texturepack, Dimension dimensions)
|
||||
{
|
||||
onTextureDimensionsUpdate(dimensions.width, dimensions.height);
|
||||
}
|
||||
@Override
|
||||
public void onTextureDimensionsUpdate(int width, int height)
|
||||
{
|
||||
tileSizeBase = width >> 4;
|
||||
tileSizeSquare = tileSizeBase * tileSizeBase;
|
||||
tileSizeMask = tileSizeBase - 1;
|
||||
tileSizeSquareMask = tileSizeSquare - 1;
|
||||
setErrored(false);
|
||||
setup();
|
||||
}
|
||||
|
||||
protected void setup()
|
||||
{
|
||||
field_76852_a = new byte[tileSizeSquare << 2];
|
||||
}
|
||||
|
||||
public boolean unregister(RenderEngine engine, List<TextureFX> effects)
|
||||
{
|
||||
effects.remove(this);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package cpw.mods.fml.client;
|
||||
|
||||
import cpw.mods.fml.common.Loader;
|
||||
import cpw.mods.fml.common.WrongMinecraftVersionException;
|
||||
import net.minecraft.src.GuiErrorScreen;
|
||||
|
||||
public class GuiCustomModLoadingErrorScreen extends GuiErrorScreen
|
||||
{
|
||||
private CustomModLoadingErrorDisplayException customException;
|
||||
public GuiCustomModLoadingErrorScreen(CustomModLoadingErrorDisplayException customException)
|
||||
{
|
||||
this.customException = customException;
|
||||
}
|
||||
@Override
|
||||
public void func_73866_w_()
|
||||
{
|
||||
super.func_73866_w_();
|
||||
this.customException.initGui(this, field_73886_k);
|
||||
}
|
||||
@Override
|
||||
public void func_73863_a(int p_73863_1_, int p_73863_2_, float p_73863_3_)
|
||||
{
|
||||
this.func_73873_v_();
|
||||
this.customException.drawScreen(this, field_73886_k, p_73863_1_, p_73863_2_, p_73863_3_);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
* The FML Forge Mod Loader suite.
|
||||
* Copyright (C) 2012 cpw
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package cpw.mods.fml.client;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.src.FontRenderer;
|
||||
import net.minecraft.src.GuiButton;
|
||||
import net.minecraft.src.GuiScreen;
|
||||
import net.minecraft.src.GuiSmallButton;
|
||||
import net.minecraft.src.StringTranslate;
|
||||
import net.minecraft.src.Tessellator;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
|
||||
import cpw.mods.fml.common.Loader;
|
||||
import cpw.mods.fml.common.ModContainer;
|
||||
|
||||
/**
|
||||
* @author cpw
|
||||
*
|
||||
*/
|
||||
public class GuiModList extends GuiScreen
|
||||
{
|
||||
private GuiScreen mainMenu;
|
||||
private GuiSlotModList modList;
|
||||
private int selected = -1;
|
||||
private ModContainer selectedMod;
|
||||
private int listWidth;
|
||||
private ArrayList<ModContainer> mods;
|
||||
|
||||
/**
|
||||
* @param mainMenu
|
||||
*/
|
||||
public GuiModList(GuiScreen mainMenu)
|
||||
{
|
||||
this.mainMenu=mainMenu;
|
||||
this.mods=new ArrayList<ModContainer>();
|
||||
FMLClientHandler.instance().addSpecialModEntries(mods);
|
||||
for (ModContainer mod : Loader.instance().getModList()) {
|
||||
if (mod.getMetadata()!=null && !Strings.isNullOrEmpty(mod.getMetadata().parent)) {
|
||||
String parentMod = mod.getMetadata().parent;
|
||||
ModContainer parentContainer = Loader.instance().getIndexedModList().get(parentMod);
|
||||
if (parentContainer != null)
|
||||
{
|
||||
mod.getMetadata().parentMod = parentContainer;
|
||||
parentContainer.getMetadata().childMods.add(mod);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
mods.add(mod);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void func_73866_w_()
|
||||
{
|
||||
for (ModContainer mod : mods) {
|
||||
listWidth=Math.max(listWidth,getFontRenderer().func_78256_a(mod.getName()) + 10);
|
||||
listWidth=Math.max(listWidth,getFontRenderer().func_78256_a(mod.getVersion()) + 10);
|
||||
}
|
||||
listWidth=Math.min(listWidth, 150);
|
||||
StringTranslate translations = StringTranslate.func_74808_a();
|
||||
this.field_73887_h.add(new GuiSmallButton(6, this.field_73880_f / 2 - 75, this.field_73881_g - 38, translations.func_74805_b("gui.done")));
|
||||
this.modList=new GuiSlotModList(this, mods, listWidth);
|
||||
this.modList.registerScrollButtons(this.field_73887_h, 7, 8);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void func_73875_a(GuiButton button) {
|
||||
if (button.field_73742_g)
|
||||
{
|
||||
switch (button.field_73741_f)
|
||||
{
|
||||
case 6:
|
||||
this.field_73882_e.func_71373_a(this.mainMenu);
|
||||
return;
|
||||
}
|
||||
}
|
||||
super.func_73875_a(button);
|
||||
}
|
||||
|
||||
public int drawLine(String line, int offset, int shifty)
|
||||
{
|
||||
this.field_73886_k.func_78276_b(line, offset, shifty, 0xd7edea);
|
||||
return shifty + 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void func_73863_a(int p_571_1_, int p_571_2_, float p_571_3_)
|
||||
{
|
||||
this.modList.drawScreen(p_571_1_, p_571_2_, p_571_3_);
|
||||
this.func_73732_a(this.field_73886_k, "Mod List", this.field_73880_f / 2, 16, 0xFFFFFF);
|
||||
int offset = this.listWidth + 20;
|
||||
if (selectedMod != null) {
|
||||
GL11.glEnable(GL11.GL_BLEND);
|
||||
if (!selectedMod.getMetadata().autogenerated) {
|
||||
int shifty = 35;
|
||||
if (!selectedMod.getMetadata().logoFile.isEmpty())
|
||||
{
|
||||
int texture = this.field_73882_e.field_71446_o.func_78341_b(selectedMod.getMetadata().logoFile);
|
||||
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
this.field_73882_e.field_71446_o.func_78342_b(texture);
|
||||
Dimension dim = TextureFXManager.instance().getTextureDimensions(texture);
|
||||
int top = 32;
|
||||
Tessellator tess = Tessellator.field_78398_a;
|
||||
tess.func_78382_b();
|
||||
tess.func_78374_a(offset, top + dim.height, field_73735_i, 0, 1);
|
||||
tess.func_78374_a(offset + dim.width, top + dim.height, field_73735_i, 1, 1);
|
||||
tess.func_78374_a(offset + dim.width, top, field_73735_i, 1, 0);
|
||||
tess.func_78374_a(offset, top, field_73735_i, 0, 0);
|
||||
tess.func_78381_a();
|
||||
|
||||
shifty += 65;
|
||||
}
|
||||
this.field_73886_k.func_78261_a(selectedMod.getMetadata().name, offset, shifty, 0xFFFFFF);
|
||||
shifty += 12;
|
||||
|
||||
shifty = drawLine(String.format("Version: %s (%s)", selectedMod.getDisplayVersion(), selectedMod.getVersion()), offset, shifty);
|
||||
shifty = drawLine(String.format("Mod State: %s", Loader.instance().getModState(selectedMod)), offset, shifty);
|
||||
if (!selectedMod.getMetadata().credits.isEmpty()) {
|
||||
shifty = drawLine(String.format("Credits: %s", selectedMod.getMetadata().credits), offset, shifty);
|
||||
}
|
||||
shifty = drawLine(String.format("Authors: %s", selectedMod.getMetadata().getAuthorList()), offset, shifty);
|
||||
shifty = drawLine(String.format("URL: %s", selectedMod.getMetadata().url), offset, shifty);
|
||||
shifty = drawLine(selectedMod.getMetadata().childMods.isEmpty() ? "No child mods for this mod" : String.format("Child mods: %s", selectedMod.getMetadata().getChildModList()), offset, shifty);
|
||||
this.getFontRenderer().func_78279_b(selectedMod.getMetadata().description, offset, shifty + 10, this.field_73880_f - offset - 20, 0xDDDDDD);
|
||||
} else {
|
||||
offset = ( this.listWidth + this.field_73880_f ) / 2;
|
||||
this.func_73732_a(this.field_73886_k, selectedMod.getName(), offset, 35, 0xFFFFFF);
|
||||
this.func_73732_a(this.field_73886_k, String.format("Version: %s",selectedMod.getVersion()), offset, 45, 0xFFFFFF);
|
||||
this.func_73732_a(this.field_73886_k, String.format("Mod State: %s",Loader.instance().getModState(selectedMod)), offset, 55, 0xFFFFFF);
|
||||
this.func_73732_a(this.field_73886_k, "No mod information found", offset, 65, 0xDDDDDD);
|
||||
this.func_73732_a(this.field_73886_k, "Ask your mod author to provide a mod mcmod.info file", offset, 75, 0xDDDDDD);
|
||||
}
|
||||
GL11.glDisable(GL11.GL_BLEND);
|
||||
}
|
||||
super.func_73863_a(p_571_1_, p_571_2_, p_571_3_);
|
||||
}
|
||||
|
||||
Minecraft getMinecraftInstance() {
|
||||
return field_73882_e;
|
||||
}
|
||||
|
||||
FontRenderer getFontRenderer() {
|
||||
return field_73886_k;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param var1
|
||||
*/
|
||||
public void selectModIndex(int var1)
|
||||
{
|
||||
this.selected=var1;
|
||||
if (var1>=0 && var1<=mods.size()) {
|
||||
this.selectedMod=mods.get(selected);
|
||||
} else {
|
||||
this.selectedMod=null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean modIndexSelected(int var1)
|
||||
{
|
||||
return var1==selected;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package cpw.mods.fml.client;
|
||||
|
||||
import cpw.mods.fml.common.MissingModsException;
|
||||
import cpw.mods.fml.common.versioning.ArtifactVersion;
|
||||
import net.minecraft.src.GuiErrorScreen;
|
||||
|
||||
public class GuiModsMissing extends GuiErrorScreen
|
||||
{
|
||||
|
||||
private MissingModsException modsMissing;
|
||||
|
||||
public GuiModsMissing(MissingModsException modsMissing)
|
||||
{
|
||||
this.modsMissing = modsMissing;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void func_73866_w_()
|
||||
{
|
||||
super.func_73866_w_();
|
||||
}
|
||||
@Override
|
||||
public void func_73863_a(int p_73863_1_, int p_73863_2_, float p_73863_3_)
|
||||
{
|
||||
this.func_73873_v_();
|
||||
int offset = Math.max(85 - modsMissing.missingMods.size() * 10, 10);
|
||||
this.func_73732_a(this.field_73886_k, "Forge Mod Loader has found a problem with your minecraft installation", this.field_73880_f / 2, offset, 0xFFFFFF);
|
||||
offset+=10;
|
||||
this.func_73732_a(this.field_73886_k, "The mods and versions listed below could not be found", this.field_73880_f / 2, offset, 0xFFFFFF);
|
||||
offset+=5;
|
||||
for (ArtifactVersion v : modsMissing.missingMods)
|
||||
{
|
||||
offset+=10;
|
||||
this.func_73732_a(this.field_73886_k, String.format("%s : %s", v.getLabel(), v.getRangeString()), this.field_73880_f / 2, offset, 0xEEEEEE);
|
||||
}
|
||||
offset+=20;
|
||||
this.func_73732_a(this.field_73886_k, "The file 'ForgeModLoader-client-0.log' contains more information", this.field_73880_f / 2, offset, 0xFFFFFF);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package cpw.mods.fml.client;
|
||||
|
||||
import net.minecraft.src.GuiButton;
|
||||
import net.minecraft.src.GuiScreen;
|
||||
import net.minecraft.src.GuiSmallButton;
|
||||
import net.minecraft.src.StringTranslate;
|
||||
import cpw.mods.fml.common.network.ModMissingPacket;
|
||||
import cpw.mods.fml.common.versioning.ArtifactVersion;
|
||||
|
||||
public class GuiModsMissingForServer extends GuiScreen
|
||||
{
|
||||
private ModMissingPacket modsMissing;
|
||||
|
||||
public GuiModsMissingForServer(ModMissingPacket modsMissing)
|
||||
{
|
||||
this.modsMissing = modsMissing;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void func_73866_w_()
|
||||
{
|
||||
StringTranslate translations = StringTranslate.func_74808_a();
|
||||
this.field_73887_h.add(new GuiSmallButton(1, this.field_73880_f / 2 - 75, this.field_73881_g - 38, translations.func_74805_b("gui.done")));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void func_73875_a(GuiButton p_73875_1_)
|
||||
{
|
||||
if (p_73875_1_.field_73742_g && p_73875_1_.field_73741_f == 1)
|
||||
{
|
||||
FMLClientHandler.instance().getClient().func_71373_a(null);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void func_73863_a(int p_73863_1_, int p_73863_2_, float p_73863_3_)
|
||||
{
|
||||
this.func_73873_v_();
|
||||
int offset = Math.max(85 - modsMissing.getModList().size() * 10, 10);
|
||||
this.func_73732_a(this.field_73886_k, "Forge Mod Loader could not connect to this server", this.field_73880_f / 2, offset, 0xFFFFFF);
|
||||
offset += 10;
|
||||
this.func_73732_a(this.field_73886_k, "The mods and versions listed below could not be found", this.field_73880_f / 2, offset, 0xFFFFFF);
|
||||
offset += 10;
|
||||
this.func_73732_a(this.field_73886_k, "They are required to play on this server", this.field_73880_f / 2, offset, 0xFFFFFF);
|
||||
offset += 5;
|
||||
for (ArtifactVersion v : modsMissing.getModList())
|
||||
{
|
||||
offset += 10;
|
||||
this.func_73732_a(this.field_73886_k, String.format("%s : %s", v.getLabel(), v.getRangeString()), this.field_73880_f / 2, offset, 0xEEEEEE);
|
||||
}
|
||||
super.func_73863_a(p_73863_1_, p_73863_2_, p_73863_3_);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,400 @@
|
||||
package cpw.mods.fml.client;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.src.GuiButton;
|
||||
import net.minecraft.src.Tessellator;
|
||||
|
||||
import org.lwjgl.input.Mouse;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
public abstract class GuiScrollingList
|
||||
{
|
||||
private final Minecraft client;
|
||||
protected final int listWidth;
|
||||
protected final int listHeight;
|
||||
protected final int top;
|
||||
protected final int bottom;
|
||||
private final int right;
|
||||
protected final int left;
|
||||
protected final int slotHeight;
|
||||
private int scrollUpActionId;
|
||||
private int scrollDownActionId;
|
||||
protected int mouseX;
|
||||
protected int mouseY;
|
||||
private float initialMouseClickY = -2.0F;
|
||||
private float scrollFactor;
|
||||
private float scrollDistance;
|
||||
private int selectedIndex = -1;
|
||||
private long lastClickTime = 0L;
|
||||
private boolean field_25123_p = true;
|
||||
private boolean field_27262_q;
|
||||
private int field_27261_r;
|
||||
|
||||
public GuiScrollingList(Minecraft client, int width, int height, int top, int bottom, int left, int entryHeight)
|
||||
{
|
||||
this.client = client;
|
||||
this.listWidth = width;
|
||||
this.listHeight = height;
|
||||
this.top = top;
|
||||
this.bottom = bottom;
|
||||
this.slotHeight = entryHeight;
|
||||
this.left = left;
|
||||
this.right = width + this.left;
|
||||
}
|
||||
|
||||
public void func_27258_a(boolean p_27258_1_)
|
||||
{
|
||||
this.field_25123_p = p_27258_1_;
|
||||
}
|
||||
|
||||
protected void func_27259_a(boolean p_27259_1_, int p_27259_2_)
|
||||
{
|
||||
this.field_27262_q = p_27259_1_;
|
||||
this.field_27261_r = p_27259_2_;
|
||||
|
||||
if (!p_27259_1_)
|
||||
{
|
||||
this.field_27261_r = 0;
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract int getSize();
|
||||
|
||||
protected abstract void elementClicked(int index, boolean doubleClick);
|
||||
|
||||
protected abstract boolean isSelected(int index);
|
||||
|
||||
protected int getContentHeight()
|
||||
{
|
||||
return this.getSize() * this.slotHeight + this.field_27261_r;
|
||||
}
|
||||
|
||||
protected abstract void drawBackground();
|
||||
|
||||
protected abstract void drawSlot(int var1, int var2, int var3, int var4, Tessellator var5);
|
||||
|
||||
protected void func_27260_a(int p_27260_1_, int p_27260_2_, Tessellator p_27260_3_) {}
|
||||
|
||||
protected void func_27255_a(int p_27255_1_, int p_27255_2_) {}
|
||||
|
||||
protected void func_27257_b(int p_27257_1_, int p_27257_2_) {}
|
||||
|
||||
public int func_27256_c(int p_27256_1_, int p_27256_2_)
|
||||
|
||||
{
|
||||
int var3 = this.left + 1;
|
||||
int var4 = this.left + this.listWidth - 7;
|
||||
int var5 = p_27256_2_ - this.top - this.field_27261_r + (int)this.scrollDistance - 4;
|
||||
int var6 = var5 / this.slotHeight;
|
||||
return p_27256_1_ >= var3 && p_27256_1_ <= var4 && var6 >= 0 && var5 >= 0 && var6 < this.getSize() ? var6 : -1;
|
||||
}
|
||||
|
||||
public void registerScrollButtons(List p_22240_1_, int p_22240_2_, int p_22240_3_)
|
||||
{
|
||||
this.scrollUpActionId = p_22240_2_;
|
||||
this.scrollDownActionId = p_22240_3_;
|
||||
}
|
||||
|
||||
private void applyScrollLimits()
|
||||
{
|
||||
int var1 = this.getContentHeight() - (this.bottom - this.top - 4);
|
||||
|
||||
if (var1 < 0)
|
||||
{
|
||||
var1 /= 2;
|
||||
}
|
||||
|
||||
if (this.scrollDistance < 0.0F)
|
||||
{
|
||||
this.scrollDistance = 0.0F;
|
||||
}
|
||||
|
||||
if (this.scrollDistance > (float)var1)
|
||||
{
|
||||
this.scrollDistance = (float)var1;
|
||||
}
|
||||
}
|
||||
|
||||
public void actionPerformed(GuiButton button)
|
||||
{
|
||||
if (button.field_73742_g)
|
||||
{
|
||||
if (button.field_73741_f == this.scrollUpActionId)
|
||||
{
|
||||
this.scrollDistance -= (float)(this.slotHeight * 2 / 3);
|
||||
this.initialMouseClickY = -2.0F;
|
||||
this.applyScrollLimits();
|
||||
}
|
||||
else if (button.field_73741_f == this.scrollDownActionId)
|
||||
{
|
||||
this.scrollDistance += (float)(this.slotHeight * 2 / 3);
|
||||
this.initialMouseClickY = -2.0F;
|
||||
this.applyScrollLimits();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void drawScreen(int mouseX, int mouseY, float p_22243_3_)
|
||||
{
|
||||
this.mouseX = mouseX;
|
||||
this.mouseY = mouseY;
|
||||
this.drawBackground();
|
||||
int listLength = this.getSize();
|
||||
int scrollBarXStart = this.left + this.listWidth - 6;
|
||||
int scrollBarXEnd = scrollBarXStart + 6;
|
||||
int boxLeft = this.left;
|
||||
int boxRight = scrollBarXStart-1;
|
||||
int var10;
|
||||
int var11;
|
||||
int var13;
|
||||
int var19;
|
||||
|
||||
if (Mouse.isButtonDown(0))
|
||||
{
|
||||
if (this.initialMouseClickY == -1.0F)
|
||||
{
|
||||
boolean var7 = true;
|
||||
|
||||
if (mouseY >= this.top && mouseY <= this.bottom)
|
||||
{
|
||||
var10 = mouseY - this.top - this.field_27261_r + (int)this.scrollDistance - 4;
|
||||
var11 = var10 / this.slotHeight;
|
||||
|
||||
if (mouseX >= boxLeft && mouseX <= boxRight && var11 >= 0 && var10 >= 0 && var11 < listLength)
|
||||
{
|
||||
boolean var12 = var11 == this.selectedIndex && System.currentTimeMillis() - this.lastClickTime < 250L;
|
||||
this.elementClicked(var11, var12);
|
||||
this.selectedIndex = var11;
|
||||
this.lastClickTime = System.currentTimeMillis();
|
||||
}
|
||||
else if (mouseX >= boxLeft && mouseX <= boxRight && var10 < 0)
|
||||
{
|
||||
this.func_27255_a(mouseX - boxLeft, mouseY - this.top + (int)this.scrollDistance - 4);
|
||||
var7 = false;
|
||||
}
|
||||
|
||||
if (mouseX >= scrollBarXStart && mouseX <= scrollBarXEnd)
|
||||
{
|
||||
this.scrollFactor = -1.0F;
|
||||
var19 = this.getContentHeight() - (this.bottom - this.top - 4);
|
||||
|
||||
if (var19 < 1)
|
||||
{
|
||||
var19 = 1;
|
||||
}
|
||||
|
||||
var13 = (int)((float)((this.bottom - this.top) * (this.bottom - this.top)) / (float)this.getContentHeight());
|
||||
|
||||
if (var13 < 32)
|
||||
{
|
||||
var13 = 32;
|
||||
}
|
||||
|
||||
if (var13 > this.bottom - this.top - 8)
|
||||
{
|
||||
var13 = this.bottom - this.top - 8;
|
||||
}
|
||||
|
||||
this.scrollFactor /= (float)(this.bottom - this.top - var13) / (float)var19;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.scrollFactor = 1.0F;
|
||||
}
|
||||
|
||||
if (var7)
|
||||
{
|
||||
this.initialMouseClickY = (float)mouseY;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.initialMouseClickY = -2.0F;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.initialMouseClickY = -2.0F;
|
||||
}
|
||||
}
|
||||
else if (this.initialMouseClickY >= 0.0F)
|
||||
{
|
||||
this.scrollDistance -= ((float)mouseY - this.initialMouseClickY) * this.scrollFactor;
|
||||
this.initialMouseClickY = (float)mouseY;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (Mouse.next())
|
||||
{
|
||||
int var16 = Mouse.getEventDWheel();
|
||||
|
||||
if (var16 != 0)
|
||||
{
|
||||
if (var16 > 0)
|
||||
{
|
||||
var16 = -1;
|
||||
}
|
||||
else if (var16 < 0)
|
||||
{
|
||||
var16 = 1;
|
||||
}
|
||||
|
||||
this.scrollDistance += (float)(var16 * this.slotHeight / 2);
|
||||
}
|
||||
}
|
||||
|
||||
this.initialMouseClickY = -1.0F;
|
||||
}
|
||||
|
||||
this.applyScrollLimits();
|
||||
GL11.glDisable(GL11.GL_LIGHTING);
|
||||
GL11.glDisable(GL11.GL_FOG);
|
||||
Tessellator var18 = Tessellator.field_78398_a;
|
||||
GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.client.field_71446_o.func_78341_b("/gui/background.png"));
|
||||
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
float var17 = 32.0F;
|
||||
var18.func_78382_b();
|
||||
var18.func_78378_d(2105376);
|
||||
var18.func_78374_a((double)this.left, (double)this.bottom, 0.0D, (double)((float)this.left / var17), (double)((float)(this.bottom + (int)this.scrollDistance) / var17));
|
||||
var18.func_78374_a((double)this.right, (double)this.bottom, 0.0D, (double)((float)this.right / var17), (double)((float)(this.bottom + (int)this.scrollDistance) / var17));
|
||||
var18.func_78374_a((double)this.right, (double)this.top, 0.0D, (double)((float)this.right / var17), (double)((float)(this.top + (int)this.scrollDistance) / var17));
|
||||
var18.func_78374_a((double)this.left, (double)this.top, 0.0D, (double)((float)this.left / var17), (double)((float)(this.top + (int)this.scrollDistance) / var17));
|
||||
var18.func_78381_a();
|
||||
// boxRight = this.listWidth / 2 - 92 - 16;
|
||||
var10 = this.top + 4 - (int)this.scrollDistance;
|
||||
|
||||
if (this.field_27262_q)
|
||||
{
|
||||
this.func_27260_a(boxRight, var10, var18);
|
||||
}
|
||||
|
||||
int var14;
|
||||
|
||||
for (var11 = 0; var11 < listLength; ++var11)
|
||||
{
|
||||
var19 = var10 + var11 * this.slotHeight + this.field_27261_r;
|
||||
var13 = this.slotHeight - 4;
|
||||
|
||||
if (var19 <= this.bottom && var19 + var13 >= this.top)
|
||||
{
|
||||
if (this.field_25123_p && this.isSelected(var11))
|
||||
{
|
||||
var14 = boxLeft;
|
||||
int var15 = boxRight;
|
||||
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
GL11.glDisable(GL11.GL_TEXTURE_2D);
|
||||
var18.func_78382_b();
|
||||
var18.func_78378_d(8421504);
|
||||
var18.func_78374_a((double)var14, (double)(var19 + var13 + 2), 0.0D, 0.0D, 1.0D);
|
||||
var18.func_78374_a((double)var15, (double)(var19 + var13 + 2), 0.0D, 1.0D, 1.0D);
|
||||
var18.func_78374_a((double)var15, (double)(var19 - 2), 0.0D, 1.0D, 0.0D);
|
||||
var18.func_78374_a((double)var14, (double)(var19 - 2), 0.0D, 0.0D, 0.0D);
|
||||
var18.func_78378_d(0);
|
||||
var18.func_78374_a((double)(var14 + 1), (double)(var19 + var13 + 1), 0.0D, 0.0D, 1.0D);
|
||||
var18.func_78374_a((double)(var15 - 1), (double)(var19 + var13 + 1), 0.0D, 1.0D, 1.0D);
|
||||
var18.func_78374_a((double)(var15 - 1), (double)(var19 - 1), 0.0D, 1.0D, 0.0D);
|
||||
var18.func_78374_a((double)(var14 + 1), (double)(var19 - 1), 0.0D, 0.0D, 0.0D);
|
||||
var18.func_78381_a();
|
||||
GL11.glEnable(GL11.GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
this.drawSlot(var11, boxRight, var19, var13, var18);
|
||||
}
|
||||
}
|
||||
|
||||
GL11.glDisable(GL11.GL_DEPTH_TEST);
|
||||
byte var20 = 4;
|
||||
this.overlayBackground(0, this.top, 255, 255);
|
||||
this.overlayBackground(this.bottom, this.listHeight, 255, 255);
|
||||
GL11.glEnable(GL11.GL_BLEND);
|
||||
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
GL11.glDisable(GL11.GL_ALPHA_TEST);
|
||||
GL11.glShadeModel(GL11.GL_SMOOTH);
|
||||
GL11.glDisable(GL11.GL_TEXTURE_2D);
|
||||
var18.func_78382_b();
|
||||
var18.func_78384_a(0, 0);
|
||||
var18.func_78374_a((double)this.left, (double)(this.top + var20), 0.0D, 0.0D, 1.0D);
|
||||
var18.func_78374_a((double)this.right, (double)(this.top + var20), 0.0D, 1.0D, 1.0D);
|
||||
var18.func_78384_a(0, 255);
|
||||
var18.func_78374_a((double)this.right, (double)this.top, 0.0D, 1.0D, 0.0D);
|
||||
var18.func_78374_a((double)this.left, (double)this.top, 0.0D, 0.0D, 0.0D);
|
||||
var18.func_78381_a();
|
||||
var18.func_78382_b();
|
||||
var18.func_78384_a(0, 255);
|
||||
var18.func_78374_a((double)this.left, (double)this.bottom, 0.0D, 0.0D, 1.0D);
|
||||
var18.func_78374_a((double)this.right, (double)this.bottom, 0.0D, 1.0D, 1.0D);
|
||||
var18.func_78384_a(0, 0);
|
||||
var18.func_78374_a((double)this.right, (double)(this.bottom - var20), 0.0D, 1.0D, 0.0D);
|
||||
var18.func_78374_a((double)this.left, (double)(this.bottom - var20), 0.0D, 0.0D, 0.0D);
|
||||
var18.func_78381_a();
|
||||
var19 = this.getContentHeight() - (this.bottom - this.top - 4);
|
||||
|
||||
if (var19 > 0)
|
||||
{
|
||||
var13 = (this.bottom - this.top) * (this.bottom - this.top) / this.getContentHeight();
|
||||
|
||||
if (var13 < 32)
|
||||
{
|
||||
var13 = 32;
|
||||
}
|
||||
|
||||
if (var13 > this.bottom - this.top - 8)
|
||||
{
|
||||
var13 = this.bottom - this.top - 8;
|
||||
}
|
||||
|
||||
var14 = (int)this.scrollDistance * (this.bottom - this.top - var13) / var19 + this.top;
|
||||
|
||||
if (var14 < this.top)
|
||||
{
|
||||
var14 = this.top;
|
||||
}
|
||||
|
||||
var18.func_78382_b();
|
||||
var18.func_78384_a(0, 255);
|
||||
var18.func_78374_a((double)scrollBarXStart, (double)this.bottom, 0.0D, 0.0D, 1.0D);
|
||||
var18.func_78374_a((double)scrollBarXEnd, (double)this.bottom, 0.0D, 1.0D, 1.0D);
|
||||
var18.func_78374_a((double)scrollBarXEnd, (double)this.top, 0.0D, 1.0D, 0.0D);
|
||||
var18.func_78374_a((double)scrollBarXStart, (double)this.top, 0.0D, 0.0D, 0.0D);
|
||||
var18.func_78381_a();
|
||||
var18.func_78382_b();
|
||||
var18.func_78384_a(8421504, 255);
|
||||
var18.func_78374_a((double)scrollBarXStart, (double)(var14 + var13), 0.0D, 0.0D, 1.0D);
|
||||
var18.func_78374_a((double)scrollBarXEnd, (double)(var14 + var13), 0.0D, 1.0D, 1.0D);
|
||||
var18.func_78374_a((double)scrollBarXEnd, (double)var14, 0.0D, 1.0D, 0.0D);
|
||||
var18.func_78374_a((double)scrollBarXStart, (double)var14, 0.0D, 0.0D, 0.0D);
|
||||
var18.func_78381_a();
|
||||
var18.func_78382_b();
|
||||
var18.func_78384_a(12632256, 255);
|
||||
var18.func_78374_a((double)scrollBarXStart, (double)(var14 + var13 - 1), 0.0D, 0.0D, 1.0D);
|
||||
var18.func_78374_a((double)(scrollBarXEnd - 1), (double)(var14 + var13 - 1), 0.0D, 1.0D, 1.0D);
|
||||
var18.func_78374_a((double)(scrollBarXEnd - 1), (double)var14, 0.0D, 1.0D, 0.0D);
|
||||
var18.func_78374_a((double)scrollBarXStart, (double)var14, 0.0D, 0.0D, 0.0D);
|
||||
var18.func_78381_a();
|
||||
}
|
||||
|
||||
this.func_27257_b(mouseX, mouseY);
|
||||
GL11.glEnable(GL11.GL_TEXTURE_2D);
|
||||
GL11.glShadeModel(GL11.GL_FLAT);
|
||||
GL11.glEnable(GL11.GL_ALPHA_TEST);
|
||||
GL11.glDisable(GL11.GL_BLEND);
|
||||
}
|
||||
|
||||
private void overlayBackground(int p_22239_1_, int p_22239_2_, int p_22239_3_, int p_22239_4_)
|
||||
{
|
||||
Tessellator var5 = Tessellator.field_78398_a;
|
||||
GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.client.field_71446_o.func_78341_b("/gui/background.png"));
|
||||
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
float var6 = 32.0F;
|
||||
var5.func_78382_b();
|
||||
var5.func_78384_a(4210752, p_22239_4_);
|
||||
var5.func_78374_a(0.0D, (double)p_22239_2_, 0.0D, 0.0D, (double)((float)p_22239_2_ / var6));
|
||||
var5.func_78374_a((double)this.listWidth + 30, (double)p_22239_2_, 0.0D, (double)((float)(this.listWidth + 30) / var6), (double)((float)p_22239_2_ / var6));
|
||||
var5.func_78384_a(4210752, p_22239_3_);
|
||||
var5.func_78374_a((double)this.listWidth + 30, (double)p_22239_1_, 0.0D, (double)((float)(this.listWidth + 30) / var6), (double)((float)p_22239_1_ / var6));
|
||||
var5.func_78374_a(0.0D, (double)p_22239_1_, 0.0D, 0.0D, (double)((float)p_22239_1_ / var6));
|
||||
var5.func_78381_a();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* The FML Forge Mod Loader suite.
|
||||
* Copyright (C) 2012 cpw
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package cpw.mods.fml.client;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import net.minecraft.src.Tessellator;
|
||||
import cpw.mods.fml.common.Loader;
|
||||
import cpw.mods.fml.common.LoaderState.ModState;
|
||||
import cpw.mods.fml.common.ModContainer;
|
||||
|
||||
/**
|
||||
* @author cpw
|
||||
*
|
||||
*/
|
||||
public class GuiSlotModList extends GuiScrollingList
|
||||
{
|
||||
private GuiModList parent;
|
||||
private ArrayList<ModContainer> mods;
|
||||
|
||||
public GuiSlotModList(GuiModList parent, ArrayList<ModContainer> mods, int listWidth)
|
||||
{
|
||||
super(parent.getMinecraftInstance(), listWidth, parent.field_73881_g, 32, parent.field_73881_g - 65 + 4, 10, 35);
|
||||
this.parent=parent;
|
||||
this.mods=mods;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getSize()
|
||||
{
|
||||
return mods.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void elementClicked(int var1, boolean var2)
|
||||
{
|
||||
this.parent.selectModIndex(var1);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isSelected(int var1)
|
||||
{
|
||||
return this.parent.modIndexSelected(var1);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawBackground()
|
||||
{
|
||||
this.parent.func_73873_v_();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getContentHeight()
|
||||
{
|
||||
return (this.getSize()) * 35 + 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawSlot(int listIndex, int var2, int var3, int var4, Tessellator var5)
|
||||
{
|
||||
ModContainer mc=mods.get(listIndex);
|
||||
if (Loader.instance().getModState(mc)==ModState.DISABLED)
|
||||
{
|
||||
this.parent.getFontRenderer().func_78276_b(this.parent.getFontRenderer().func_78269_a(mc.getName(), listWidth - 10), this.left + 3 , var3 + 2, 0xFF2222);
|
||||
this.parent.getFontRenderer().func_78276_b(this.parent.getFontRenderer().func_78269_a(mc.getDisplayVersion(), listWidth - 10), this.left + 3 , var3 + 12, 0xFF2222);
|
||||
this.parent.getFontRenderer().func_78276_b(this.parent.getFontRenderer().func_78269_a("DISABLED", listWidth - 10), this.left + 3 , var3 + 22, 0xFF2222);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.parent.getFontRenderer().func_78276_b(this.parent.getFontRenderer().func_78269_a(mc.getName(), listWidth - 10), this.left + 3 , var3 + 2, 0xFFFFFF);
|
||||
this.parent.getFontRenderer().func_78276_b(this.parent.getFontRenderer().func_78269_a(mc.getDisplayVersion(), listWidth - 10), this.left + 3 , var3 + 12, 0xCCCCCC);
|
||||
this.parent.getFontRenderer().func_78276_b(this.parent.getFontRenderer().func_78269_a(mc.getMetadata() !=null ? mc.getMetadata().getChildModCountString() : "Metadata not found", listWidth - 10), this.left + 3 , var3 + 22, 0xCCCCCC);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package cpw.mods.fml.client;
|
||||
|
||||
import cpw.mods.fml.common.Loader;
|
||||
import cpw.mods.fml.common.WrongMinecraftVersionException;
|
||||
import cpw.mods.fml.common.versioning.ArtifactVersion;
|
||||
import net.minecraft.src.GuiErrorScreen;
|
||||
import net.minecraft.src.GuiScreen;
|
||||
|
||||
public class GuiWrongMinecraft extends GuiErrorScreen
|
||||
{
|
||||
private WrongMinecraftVersionException wrongMC;
|
||||
public GuiWrongMinecraft(WrongMinecraftVersionException wrongMC)
|
||||
{
|
||||
this.wrongMC = wrongMC;
|
||||
}
|
||||
@Override
|
||||
public void func_73866_w_()
|
||||
{
|
||||
super.func_73866_w_();
|
||||
}
|
||||
@Override
|
||||
public void func_73863_a(int p_73863_1_, int p_73863_2_, float p_73863_3_)
|
||||
{
|
||||
this.func_73873_v_();
|
||||
int offset = 75;
|
||||
this.func_73732_a(this.field_73886_k, "Forge Mod Loader has found a problem with your minecraft installation", this.field_73880_f / 2, offset, 0xFFFFFF);
|
||||
offset+=10;
|
||||
this.func_73732_a(this.field_73886_k, String.format("The mod listed below does not want to run in Minecraft version %s", Loader.instance().getMinecraftModContainer().getVersion()), this.field_73880_f / 2, offset, 0xFFFFFF);
|
||||
offset+=5;
|
||||
offset+=10;
|
||||
this.func_73732_a(this.field_73886_k, String.format("%s (%s) wants Minecraft %s", wrongMC.mod.getName(), wrongMC.mod.getModId(), wrongMC.mod.acceptableMinecraftVersionRange()), this.field_73880_f / 2, offset, 0xEEEEEE);
|
||||
offset+=20;
|
||||
this.func_73732_a(this.field_73886_k, "The file 'ForgeModLoader-client-0.log' contains more information", this.field_73880_f / 2, offset, 0xFFFFFF);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* The FML Forge Mod Loader suite.
|
||||
* Copyright (C) 2012 cpw
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package cpw.mods.fml.client;
|
||||
|
||||
import java.awt.Dimension;
|
||||
|
||||
import net.minecraft.src.RenderEngine;
|
||||
import net.minecraft.src.ITexturePack;
|
||||
|
||||
public interface ITextureFX
|
||||
{
|
||||
public void onTexturePackChanged(RenderEngine engine, ITexturePack texturepack, Dimension dimensions);
|
||||
|
||||
public void onTextureDimensionsUpdate(int width, int height);
|
||||
|
||||
public void setErrored(boolean errored);
|
||||
|
||||
public boolean getErrored();
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* The FML Forge Mod Loader suite.
|
||||
* Copyright (C) 2012 cpw
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package cpw.mods.fml.client;
|
||||
|
||||
import net.minecraft.src.TextureFX;
|
||||
|
||||
class OverrideInfo
|
||||
{
|
||||
public String texture;
|
||||
public String override;
|
||||
public int index;
|
||||
public int imageIndex;
|
||||
public TextureFX textureFX;
|
||||
public boolean added;
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
try {
|
||||
OverrideInfo inf=(OverrideInfo) obj;
|
||||
return index==inf.index && imageIndex==inf.imageIndex;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return index+imageIndex;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* The FML Forge Mod Loader suite.
|
||||
* Copyright (C) 2012 cpw
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package cpw.mods.fml.client;
|
||||
|
||||
import java.util.BitSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import cpw.mods.fml.common.FMLCommonHandler;
|
||||
import cpw.mods.fml.common.FMLLog;
|
||||
|
||||
/**
|
||||
* @author cpw
|
||||
*
|
||||
*/
|
||||
public class SpriteHelper
|
||||
{
|
||||
private static HashMap<String, BitSet> spriteInfo = new HashMap<String, BitSet>();
|
||||
|
||||
private static void initMCSpriteMaps() {
|
||||
BitSet slots =
|
||||
SpriteHelper.toBitSet(
|
||||
"0000000000000000" +
|
||||
"0000000000110000" +
|
||||
"0000000000100000" +
|
||||
"0000000001100000" +
|
||||
"0000000000000000" +
|
||||
"0000000000000000" +
|
||||
"0000000000000000" +
|
||||
"0000000000000000" +
|
||||
"0000000000000000" +
|
||||
"0000000000000000" +
|
||||
"0000000000000000" +
|
||||
"0000000000011111" +
|
||||
"0000000000000000" +
|
||||
"0000000001111100" +
|
||||
"0000000001111000" +
|
||||
"0000000000000000");
|
||||
spriteInfo.put("/terrain.png", slots);
|
||||
|
||||
slots = SpriteHelper.toBitSet(
|
||||
"0000000000000000" +
|
||||
"0000000000000000" +
|
||||
"0000000000000000" +
|
||||
"0000000000000000" +
|
||||
"0000000000000000" +
|
||||
"0000000000000000" +
|
||||
"0000000000000000" +
|
||||
"0000000000000000" +
|
||||
"0000000000000000" +
|
||||
"0111100000000000" +
|
||||
"1111100010000000" +
|
||||
"0000101110000000" +
|
||||
"0111000000000000" +
|
||||
"1100001100001111" +
|
||||
"0000000000001111" +
|
||||
"0000000000000000");
|
||||
spriteInfo.put("/gui/items.png", slots);
|
||||
}
|
||||
/**
|
||||
* Register a sprite map for ModTextureStatic, to allow for other mods to override
|
||||
* your sprite page.
|
||||
*
|
||||
*
|
||||
*/
|
||||
public static void registerSpriteMapForFile(String file, String spriteMap) {
|
||||
if (spriteInfo.size() == 0) {
|
||||
initMCSpriteMaps();
|
||||
}
|
||||
if (spriteInfo.containsKey(file)) {
|
||||
FMLCommonHandler.instance().getFMLLogger().finer(String.format("Duplicate attempt to register a sprite file %s for overriding -- ignoring",file));
|
||||
return;
|
||||
}
|
||||
spriteInfo.put(file, toBitSet(spriteMap));
|
||||
}
|
||||
|
||||
public static int getUniqueSpriteIndex(String path)
|
||||
{
|
||||
if (!spriteInfo.containsKey("/terrain.png"))
|
||||
{
|
||||
initMCSpriteMaps();
|
||||
}
|
||||
|
||||
BitSet slots = spriteInfo.get(path);
|
||||
|
||||
if (slots == null)
|
||||
{
|
||||
Exception ex = new Exception(String.format("Invalid getUniqueSpriteIndex call for texture: %s", path));
|
||||
FMLLog.log(Level.SEVERE, ex, "A critical error has been detected with sprite overrides");
|
||||
FMLCommonHandler.instance().raiseException(ex,"Invalid request to getUniqueSpriteIndex",true);
|
||||
}
|
||||
|
||||
int ret = getFreeSlot(slots);
|
||||
|
||||
if (ret == -1)
|
||||
{
|
||||
Exception ex = new Exception(String.format("No more sprite indicies left for: %s", path));
|
||||
FMLLog.log(Level.SEVERE, ex, "There are no sprite indicies left for %s", path);
|
||||
FMLCommonHandler.instance().raiseException(ex,"No more sprite indicies left", true);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static BitSet toBitSet(String data)
|
||||
{
|
||||
BitSet ret = new BitSet(data.length());
|
||||
for (int x = 0; x < data.length(); x++)
|
||||
{
|
||||
ret.set(x, data.charAt(x) == '1');
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static int getFreeSlot(BitSet slots)
|
||||
{
|
||||
int next=slots.nextSetBit(0);
|
||||
slots.clear(next);
|
||||
return next;
|
||||
}
|
||||
|
||||
public static int freeSlotCount(String textureToOverride)
|
||||
{
|
||||
return spriteInfo.get(textureToOverride).cardinality();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,323 @@
|
||||
package cpw.mods.fml.client;
|
||||
|
||||
import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D;
|
||||
import static org.lwjgl.opengl.GL11.GL_TEXTURE_BINDING_2D;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.src.ModTextureStatic;
|
||||
import net.minecraft.src.RenderEngine;
|
||||
import net.minecraft.src.TextureFX;
|
||||
import net.minecraft.src.ITexturePack;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Multimap;
|
||||
|
||||
import cpw.mods.fml.common.FMLCommonHandler;
|
||||
import cpw.mods.fml.common.FMLLog;
|
||||
import cpw.mods.fml.common.ModContainer;
|
||||
|
||||
public class TextureFXManager
|
||||
{
|
||||
private static final TextureFXManager INSTANCE = new TextureFXManager();
|
||||
|
||||
private class TextureProperties
|
||||
{
|
||||
private int textureId;
|
||||
private Dimension dim;
|
||||
}
|
||||
|
||||
private Map<Integer,TextureProperties> textureProperties = Maps.newHashMap();
|
||||
private Multimap<String, OverrideInfo> overrideInfo = ArrayListMultimap.create();
|
||||
private HashSet<OverrideInfo> animationSet = new HashSet<OverrideInfo>();
|
||||
|
||||
private List<TextureFX> addedTextureFX = new ArrayList<TextureFX>();
|
||||
|
||||
private Minecraft client;
|
||||
|
||||
void setClient(Minecraft client)
|
||||
{
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
public boolean onUpdateTextureEffect(TextureFX effect)
|
||||
{
|
||||
ITextureFX ifx = (effect instanceof ITextureFX ? ((ITextureFX)effect) : null);
|
||||
|
||||
if (ifx != null && ifx.getErrored())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
String name = effect.getClass().getSimpleName();
|
||||
client.field_71424_I.func_76320_a(name);
|
||||
try
|
||||
{
|
||||
if (!FMLClientHandler.instance().hasOptifine())
|
||||
{
|
||||
effect.func_76846_a();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
FMLLog.warning("Texture FX %s has failed to animate. Likely caused by a texture pack change that they did not respond correctly to", name);
|
||||
if (ifx != null)
|
||||
{
|
||||
ifx.setErrored(true);
|
||||
}
|
||||
client.field_71424_I.func_76319_b();
|
||||
return false;
|
||||
}
|
||||
client.field_71424_I.func_76319_b();
|
||||
|
||||
if (ifx != null)
|
||||
{
|
||||
Dimension dim = getTextureDimensions(effect);
|
||||
int target = ((dim.width >> 4) * (dim.height >> 4)) << 2;
|
||||
if (effect.field_76852_a.length != target)
|
||||
{
|
||||
FMLLog.warning("Detected a texture FX sizing discrepancy in %s (%d, %d)", name, effect.field_76852_a.length, target);
|
||||
ifx.setErrored(true);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//Quick and dirty image scaling, no smoothing or fanciness, meant for speed as it will be called every tick.
|
||||
public void scaleTextureFXData(byte[] data, ByteBuffer buf, int target, int length)
|
||||
{
|
||||
int sWidth = (int)Math.sqrt(data.length / 4);
|
||||
int factor = target / sWidth;
|
||||
byte[] tmp = new byte[4];
|
||||
|
||||
buf.clear();
|
||||
|
||||
if (factor > 1)
|
||||
{
|
||||
for (int y = 0; y < sWidth; y++)
|
||||
{
|
||||
int sRowOff = sWidth * y;
|
||||
int tRowOff = target * y * factor;
|
||||
for (int x = 0; x < sWidth; x++)
|
||||
{
|
||||
int sPos = (x + sRowOff) * 4;
|
||||
tmp[0] = data[sPos + 0];
|
||||
tmp[1] = data[sPos + 1];
|
||||
tmp[2] = data[sPos + 2];
|
||||
tmp[3] = data[sPos + 3];
|
||||
|
||||
int tPosTop = (x * factor) + tRowOff;
|
||||
for (int y2 = 0; y2 < factor; y2++)
|
||||
{
|
||||
buf.position((tPosTop + (y2 * target)) * 4);
|
||||
for (int x2 = 0; x2 < factor; x2++)
|
||||
{
|
||||
buf.put(tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buf.position(0).limit(length);
|
||||
}
|
||||
|
||||
public void onPreRegisterEffect(TextureFX effect)
|
||||
{
|
||||
Dimension dim = getTextureDimensions(effect);
|
||||
if (effect instanceof ITextureFX)
|
||||
{
|
||||
((ITextureFX)effect).onTextureDimensionsUpdate(dim.width, dim.height);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public int getEffectTexture(TextureFX effect)
|
||||
{
|
||||
Integer id = effectTextures.get(effect);
|
||||
if (id != null)
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
int old = GL11.glGetInteger(GL_TEXTURE_BINDING_2D);
|
||||
|
||||
effect.func_76845_a(client.field_71446_o);
|
||||
|
||||
id = GL11.glGetInteger(GL_TEXTURE_BINDING_2D);
|
||||
|
||||
GL11.glBindTexture(GL_TEXTURE_2D, old);
|
||||
|
||||
effectTextures.put(effect, id);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
public void onTexturePackChange(RenderEngine engine, ITexturePack texturepack, List<TextureFX> effects)
|
||||
{
|
||||
pruneOldTextureFX(texturepack, effects);
|
||||
|
||||
for (TextureFX tex : effects)
|
||||
{
|
||||
if (tex instanceof ITextureFX)
|
||||
{
|
||||
((ITextureFX)tex).onTexturePackChanged(engine, texturepack, getTextureDimensions(tex));
|
||||
}
|
||||
}
|
||||
|
||||
loadTextures(texturepack);
|
||||
}
|
||||
|
||||
private HashMap<Integer, Dimension> textureDims = new HashMap<Integer, Dimension>();
|
||||
private IdentityHashMap<TextureFX, Integer> effectTextures = new IdentityHashMap<TextureFX, Integer>();
|
||||
private ITexturePack earlyTexturePack;
|
||||
public void setTextureDimensions(int id, int width, int height, List<TextureFX> effects)
|
||||
{
|
||||
Dimension dim = new Dimension(width, height);
|
||||
textureDims.put(id, dim);
|
||||
|
||||
for (TextureFX tex : effects)
|
||||
{
|
||||
if (getEffectTexture(tex) == id && tex instanceof ITextureFX)
|
||||
{
|
||||
((ITextureFX)tex).onTextureDimensionsUpdate(width, height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Dimension getTextureDimensions(TextureFX effect)
|
||||
{
|
||||
return getTextureDimensions(getEffectTexture(effect));
|
||||
}
|
||||
|
||||
public Dimension getTextureDimensions(int id)
|
||||
{
|
||||
return textureDims.get(id);
|
||||
}
|
||||
|
||||
public void addAnimation(TextureFX anim)
|
||||
{
|
||||
OverrideInfo info=new OverrideInfo();
|
||||
info.index=anim.field_76850_b;
|
||||
info.imageIndex=anim.field_76847_f;
|
||||
info.textureFX=anim;
|
||||
if (animationSet.contains(info)) {
|
||||
animationSet.remove(info);
|
||||
}
|
||||
animationSet.add(info);
|
||||
}
|
||||
|
||||
|
||||
public void loadTextures(ITexturePack texturePack)
|
||||
{
|
||||
registerTextureOverrides(client.field_71446_o);
|
||||
}
|
||||
|
||||
|
||||
public void registerTextureOverrides(RenderEngine renderer) {
|
||||
for (OverrideInfo animationOverride : animationSet) {
|
||||
renderer.func_78355_a(animationOverride.textureFX);
|
||||
addedTextureFX.add(animationOverride.textureFX);
|
||||
FMLCommonHandler.instance().getFMLLogger().finer(String.format("Registered texture override %d (%d) on %s (%d)", animationOverride.index, animationOverride.textureFX.field_76850_b, animationOverride.textureFX.getClass().getSimpleName(), animationOverride.textureFX.field_76847_f));
|
||||
}
|
||||
|
||||
for (String fileToOverride : overrideInfo.keySet()) {
|
||||
for (OverrideInfo override : overrideInfo.get(fileToOverride)) {
|
||||
try
|
||||
{
|
||||
BufferedImage image=loadImageFromTexturePack(renderer, override.override);
|
||||
ModTextureStatic mts=new ModTextureStatic(override.index, 1, override.texture, image);
|
||||
renderer.func_78355_a(mts);
|
||||
addedTextureFX.add(mts);
|
||||
FMLCommonHandler.instance().getFMLLogger().finer(String.format("Registered texture override %d (%d) on %s (%d)", override.index, mts.field_76850_b, override.texture, mts.field_76847_f));
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
FMLCommonHandler.instance().getFMLLogger().throwing("FMLClientHandler", "registerTextureOverrides", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void registerAnimatedTexturesFor(ModContainer mod)
|
||||
{
|
||||
}
|
||||
|
||||
public void onEarlyTexturePackLoad(ITexturePack fallback)
|
||||
{
|
||||
if (client==null) {
|
||||
// We're far too early- let's wait
|
||||
this.earlyTexturePack = fallback;
|
||||
} else {
|
||||
loadTextures(fallback);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void pruneOldTextureFX(ITexturePack var1, List<TextureFX> effects)
|
||||
{
|
||||
ListIterator<TextureFX> li = addedTextureFX.listIterator();
|
||||
while (li.hasNext())
|
||||
{
|
||||
TextureFX tex = li.next();
|
||||
if (tex instanceof FMLTextureFX)
|
||||
{
|
||||
if (((FMLTextureFX)tex).unregister(client.field_71446_o, effects))
|
||||
{
|
||||
li.remove();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
effects.remove(tex);
|
||||
li.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
public void addNewTextureOverride(String textureToOverride, String overridingTexturePath, int location) {
|
||||
OverrideInfo info = new OverrideInfo();
|
||||
info.index = location;
|
||||
info.override = overridingTexturePath;
|
||||
info.texture = textureToOverride;
|
||||
overrideInfo.put(textureToOverride, info);
|
||||
FMLLog.fine("Overriding %s @ %d with %s. %d slots remaining",textureToOverride, location, overridingTexturePath, SpriteHelper.freeSlotCount(textureToOverride));
|
||||
}
|
||||
|
||||
public BufferedImage loadImageFromTexturePack(RenderEngine renderEngine, String path) throws IOException
|
||||
{
|
||||
InputStream image=client.field_71418_C.func_77292_e().func_77532_a(path);
|
||||
if (image==null) {
|
||||
throw new RuntimeException(String.format("The requested image path %s is not found",path));
|
||||
}
|
||||
BufferedImage result=ImageIO.read(image);
|
||||
if (result==null)
|
||||
{
|
||||
throw new RuntimeException(String.format("The requested image path %s appears to be corrupted",path));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static TextureFXManager instance()
|
||||
{
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* The FML Forge Mod Loader suite.
|
||||
* Copyright (C) 2012 cpw
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package cpw.mods.fml.client.modloader;
|
||||
|
||||
import net.minecraft.src.BaseMod;
|
||||
import net.minecraft.src.Block;
|
||||
import net.minecraft.src.IBlockAccess;
|
||||
import net.minecraft.src.RenderBlocks;
|
||||
import cpw.mods.fml.client.registry.ISimpleBlockRenderingHandler;
|
||||
|
||||
/**
|
||||
* @author cpw
|
||||
*
|
||||
*/
|
||||
public class ModLoaderBlockRendererHandler implements ISimpleBlockRenderingHandler
|
||||
{
|
||||
private int renderId;
|
||||
private boolean render3dInInventory;
|
||||
private BaseMod mod;
|
||||
|
||||
/**
|
||||
* @param mod
|
||||
*
|
||||
*/
|
||||
public ModLoaderBlockRendererHandler(int renderId, boolean render3dInInventory, BaseMod mod)
|
||||
{
|
||||
this.renderId=renderId;
|
||||
this.render3dInInventory=render3dInInventory;
|
||||
this.mod=mod;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRenderId()
|
||||
{
|
||||
return renderId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldRender3DInInventory()
|
||||
{
|
||||
return render3dInInventory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param world
|
||||
* @param x
|
||||
* @param y
|
||||
* @param z
|
||||
* @param block
|
||||
* @param modelId
|
||||
* @param renderer
|
||||
*/
|
||||
@Override
|
||||
public boolean renderWorldBlock(IBlockAccess world, int x, int y, int z, Block block, int modelId, RenderBlocks renderer)
|
||||
{
|
||||
return mod.renderWorldBlock(renderer, world, x, y, z, block, modelId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param block
|
||||
* @param metadata
|
||||
* @param modelID
|
||||
* @param renderer
|
||||
*/
|
||||
@Override
|
||||
public void renderInventoryBlock(Block block, int metadata, int modelID, RenderBlocks renderer)
|
||||
{
|
||||
mod.renderInvBlock(renderer, block, metadata, modelID);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,177 @@
|
||||
package cpw.mods.fml.client.modloader;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.src.BaseMod;
|
||||
import net.minecraft.src.Entity;
|
||||
import net.minecraft.src.EntityClientPlayerMP;
|
||||
import net.minecraft.src.EntityPlayer;
|
||||
import net.minecraft.src.KeyBinding;
|
||||
import net.minecraft.src.NetClientHandler;
|
||||
import net.minecraft.src.NetHandler;
|
||||
import net.minecraft.src.INetworkManager;
|
||||
import net.minecraft.src.Packet250CustomPayload;
|
||||
import net.minecraft.src.Render;
|
||||
import net.minecraft.src.RenderManager;
|
||||
|
||||
import com.google.common.base.Equivalences;
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.base.Suppliers;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Iterators;
|
||||
import com.google.common.collect.MapDifference;
|
||||
import com.google.common.collect.MapDifference.ValueDifference;
|
||||
import com.google.common.collect.MapMaker;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.collect.Multimaps;
|
||||
|
||||
import cpw.mods.fml.client.FMLClientHandler;
|
||||
import cpw.mods.fml.client.registry.KeyBindingRegistry;
|
||||
import cpw.mods.fml.client.registry.RenderingRegistry;
|
||||
import cpw.mods.fml.common.FMLLog;
|
||||
import cpw.mods.fml.common.Loader;
|
||||
import cpw.mods.fml.common.modloader.BaseModProxy;
|
||||
import cpw.mods.fml.common.modloader.IModLoaderSidedHelper;
|
||||
import cpw.mods.fml.common.modloader.ModLoaderHelper;
|
||||
import cpw.mods.fml.common.modloader.ModLoaderModContainer;
|
||||
import cpw.mods.fml.common.network.EntitySpawnPacket;
|
||||
import cpw.mods.fml.common.registry.EntityRegistry.EntityRegistration;
|
||||
|
||||
public class ModLoaderClientHelper implements IModLoaderSidedHelper
|
||||
{
|
||||
public static int obtainBlockModelIdFor(BaseMod mod, boolean inventoryRenderer)
|
||||
{
|
||||
int renderId=RenderingRegistry.getNextAvailableRenderId();
|
||||
ModLoaderBlockRendererHandler bri=new ModLoaderBlockRendererHandler(renderId, inventoryRenderer, mod);
|
||||
RenderingRegistry.registerBlockHandler(bri);
|
||||
return renderId;
|
||||
}
|
||||
|
||||
|
||||
public static void handleFinishLoadingFor(ModLoaderModContainer mc, Minecraft game)
|
||||
{
|
||||
FMLLog.finer("Handling post startup activities for ModLoader mod %s", mc.getModId());
|
||||
BaseMod mod = (BaseMod) mc.getMod();
|
||||
|
||||
Map<Class<? extends Entity>, Render> renderers = Maps.newHashMap(RenderManager.field_78727_a.field_78729_o);
|
||||
|
||||
try
|
||||
{
|
||||
FMLLog.finest("Requesting renderers from basemod %s", mc.getModId());
|
||||
mod.addRenderer(renderers);
|
||||
FMLLog.finest("Received %d renderers from basemod %s", renderers.size(), mc.getModId());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
FMLLog.log(Level.SEVERE, e, "A severe problem was detected with the mod %s during the addRenderer call. Continuing, but expect odd results", mc.getModId());
|
||||
}
|
||||
|
||||
MapDifference<Class<? extends Entity>, Render> difference = Maps.difference(RenderManager.field_78727_a.field_78729_o, renderers, Equivalences.identity());
|
||||
|
||||
for ( Entry<Class<? extends Entity>, Render> e : difference.entriesOnlyOnLeft().entrySet())
|
||||
{
|
||||
FMLLog.warning("The mod %s attempted to remove an entity renderer %s from the entity map. This will be ignored.", mc.getModId(), e.getKey().getName());
|
||||
}
|
||||
|
||||
for (Entry<Class<? extends Entity>, Render> e : difference.entriesOnlyOnRight().entrySet())
|
||||
{
|
||||
FMLLog.finest("Registering ModLoader entity renderer %s as instance of %s", e.getKey().getName(), e.getValue().getClass().getName());
|
||||
RenderingRegistry.registerEntityRenderingHandler(e.getKey(), e.getValue());
|
||||
}
|
||||
|
||||
for (Entry<Class<? extends Entity>, ValueDifference<Render>> e : difference.entriesDiffering().entrySet())
|
||||
{
|
||||
FMLLog.finest("Registering ModLoader entity rendering override for %s as instance of %s", e.getKey().getName(), e.getValue().rightValue().getClass().getName());
|
||||
RenderingRegistry.registerEntityRenderingHandler(e.getKey(), e.getValue().rightValue());
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
mod.registerAnimation(game);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
FMLLog.log(Level.SEVERE, e, "A severe problem was detected with the mod %s during the registerAnimation call. Continuing, but expect odd results", mc.getModId());
|
||||
}
|
||||
}
|
||||
|
||||
public ModLoaderClientHelper(Minecraft client)
|
||||
{
|
||||
this.client = client;
|
||||
ModLoaderHelper.sidedHelper = this;
|
||||
keyBindingContainers = Multimaps.newMultimap(Maps.<ModLoaderModContainer, Collection<ModLoaderKeyBindingHandler>>newHashMap(), new Supplier<Collection<ModLoaderKeyBindingHandler>>()
|
||||
{
|
||||
@Override
|
||||
public Collection<ModLoaderKeyBindingHandler> get()
|
||||
{
|
||||
return Collections.singleton(new ModLoaderKeyBindingHandler());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private Minecraft client;
|
||||
private static Multimap<ModLoaderModContainer, ModLoaderKeyBindingHandler> keyBindingContainers;
|
||||
|
||||
@Override
|
||||
public void finishModLoading(ModLoaderModContainer mc)
|
||||
{
|
||||
handleFinishLoadingFor(mc, client);
|
||||
}
|
||||
|
||||
|
||||
public static void registerKeyBinding(BaseModProxy mod, KeyBinding keyHandler, boolean allowRepeat)
|
||||
{
|
||||
ModLoaderModContainer mlmc = (ModLoaderModContainer) Loader.instance().activeModContainer();
|
||||
ModLoaderKeyBindingHandler handler = Iterables.getOnlyElement(keyBindingContainers.get(mlmc));
|
||||
handler.setModContainer(mlmc);
|
||||
handler.addKeyBinding(keyHandler, allowRepeat);
|
||||
KeyBindingRegistry.registerKeyBinding(handler);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object getClientGui(BaseModProxy mod, EntityPlayer player, int ID, int x, int y, int z)
|
||||
{
|
||||
return ((net.minecraft.src.BaseMod)mod).getContainerGUI((EntityClientPlayerMP) player, ID, x, y, z);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Entity spawnEntity(BaseModProxy mod, EntitySpawnPacket input, EntityRegistration er)
|
||||
{
|
||||
return ((net.minecraft.src.BaseMod)mod).spawnEntity(er.getModEntityId(), client.field_71441_e, input.scaledX, input.scaledY, input.scaledZ);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void sendClientPacket(BaseModProxy mod, Packet250CustomPayload packet)
|
||||
{
|
||||
((net.minecraft.src.BaseMod)mod).clientCustomPayload(client.field_71439_g.field_71174_a, packet);
|
||||
}
|
||||
|
||||
private Map<INetworkManager,NetHandler> managerLookups = new MapMaker().weakKeys().weakValues().makeMap();
|
||||
@Override
|
||||
public void clientConnectionOpened(NetHandler netClientHandler, INetworkManager manager, BaseModProxy mod)
|
||||
{
|
||||
managerLookups.put(manager, netClientHandler);
|
||||
((BaseMod)mod).clientConnect((NetClientHandler)netClientHandler);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean clientConnectionClosed(INetworkManager manager, BaseModProxy mod)
|
||||
{
|
||||
if (managerLookups.containsKey(manager))
|
||||
{
|
||||
((BaseMod)mod).clientDisconnect((NetClientHandler) managerLookups.get(manager));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* The FML Forge Mod Loader suite.
|
||||
* Copyright (C) 2012 cpw
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package cpw.mods.fml.client.modloader;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
|
||||
import org.lwjgl.input.Mouse;
|
||||
|
||||
import com.google.common.collect.ObjectArrays;
|
||||
import com.google.common.primitives.Booleans;
|
||||
|
||||
import net.minecraft.src.KeyBinding;
|
||||
import cpw.mods.fml.client.registry.KeyBindingRegistry;
|
||||
import cpw.mods.fml.common.TickType;
|
||||
import cpw.mods.fml.common.modloader.ModLoaderModContainer;
|
||||
|
||||
/**
|
||||
* @author cpw
|
||||
*
|
||||
*/
|
||||
public class ModLoaderKeyBindingHandler extends KeyBindingRegistry.KeyHandler
|
||||
{
|
||||
private ModLoaderModContainer modContainer;
|
||||
private List<KeyBinding> helper;
|
||||
private boolean[] active = new boolean[0];
|
||||
private boolean[] mlRepeats = new boolean[0];
|
||||
private boolean[] armed = new boolean[0];
|
||||
|
||||
public ModLoaderKeyBindingHandler()
|
||||
{
|
||||
super(new KeyBinding[0], new boolean[0]);
|
||||
}
|
||||
|
||||
void setModContainer(ModLoaderModContainer modContainer)
|
||||
{
|
||||
this.modContainer = modContainer;
|
||||
}
|
||||
|
||||
public void fireKeyEvent(KeyBinding kb)
|
||||
{
|
||||
((net.minecraft.src.BaseMod)modContainer.getMod()).keyboardEvent(kb);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyDown(EnumSet<TickType> type, KeyBinding kb, boolean end, boolean repeats)
|
||||
{
|
||||
if (!end)
|
||||
{
|
||||
return;
|
||||
}
|
||||
int idx = helper.indexOf(kb);
|
||||
if (type.contains(TickType.CLIENT))
|
||||
{
|
||||
armed[idx] = true;
|
||||
}
|
||||
if (armed[idx] && type.contains(TickType.RENDER) && (!active[idx] || mlRepeats[idx]))
|
||||
{
|
||||
fireKeyEvent(kb);
|
||||
active[idx] = true;
|
||||
armed[idx] = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyUp(EnumSet<TickType> type, KeyBinding kb, boolean end)
|
||||
{
|
||||
if (!end)
|
||||
{
|
||||
return;
|
||||
}
|
||||
int idx = helper.indexOf(kb);
|
||||
active[idx] = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnumSet<TickType> ticks()
|
||||
{
|
||||
return EnumSet.of(TickType.CLIENT, TickType.RENDER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLabel()
|
||||
{
|
||||
return modContainer.getModId() +" KB "+keyBindings[0].field_74512_d;
|
||||
}
|
||||
|
||||
void addKeyBinding(KeyBinding binding, boolean repeats)
|
||||
{
|
||||
this.keyBindings = ObjectArrays.concat(this.keyBindings, binding);
|
||||
this.repeatings = new boolean[this.keyBindings.length];
|
||||
Arrays.fill(this.repeatings, true);
|
||||
this.active = new boolean[this.keyBindings.length];
|
||||
this.armed = new boolean[this.keyBindings.length];
|
||||
this.mlRepeats = Booleans.concat(this.mlRepeats, new boolean[] { repeats });
|
||||
this.keyDown = new boolean[this.keyBindings.length];
|
||||
this.helper = Arrays.asList(this.keyBindings);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package cpw.mods.fml.client.registry;
|
||||
|
||||
import net.minecraft.src.TileEntity;
|
||||
import net.minecraft.src.TileEntityRenderer;
|
||||
import net.minecraft.src.TileEntitySpecialRenderer;
|
||||
import cpw.mods.fml.common.registry.GameRegistry;
|
||||
|
||||
public class ClientRegistry
|
||||
{
|
||||
/**
|
||||
*
|
||||
* Utility method for registering a tile entity and it's renderer at once - generally you should register them separately
|
||||
*
|
||||
* @param tileEntityClass
|
||||
* @param id
|
||||
* @param specialRenderer
|
||||
*/
|
||||
public static void registerTileEntity(Class <? extends TileEntity > tileEntityClass, String id, TileEntitySpecialRenderer specialRenderer)
|
||||
{
|
||||
GameRegistry.registerTileEntity(tileEntityClass, id);
|
||||
bindTileEntitySpecialRenderer(tileEntityClass, specialRenderer);
|
||||
}
|
||||
|
||||
public static void bindTileEntitySpecialRenderer(Class <? extends TileEntity> tileEntityClass, TileEntitySpecialRenderer specialRenderer)
|
||||
{
|
||||
TileEntityRenderer.field_76963_a.field_76966_m.put(tileEntityClass, specialRenderer);
|
||||
specialRenderer.func_76893_a(TileEntityRenderer.field_76963_a);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package cpw.mods.fml.client.registry;
|
||||
|
||||
import net.minecraft.src.Block;
|
||||
import net.minecraft.src.IBlockAccess;
|
||||
import net.minecraft.src.RenderBlocks;
|
||||
|
||||
public interface ISimpleBlockRenderingHandler
|
||||
{
|
||||
public abstract void renderInventoryBlock(Block block, int metadata, int modelID, RenderBlocks renderer);
|
||||
|
||||
public abstract boolean renderWorldBlock(IBlockAccess world, int x, int y, int z, Block block, int modelId, RenderBlocks renderer);
|
||||
|
||||
public abstract boolean shouldRender3DInInventory();
|
||||
|
||||
public abstract int getRenderId();
|
||||
}
|
||||
@@ -0,0 +1,187 @@
|
||||
package cpw.mods.fml.client.registry;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Set;
|
||||
|
||||
import net.minecraft.src.GameSettings;
|
||||
import net.minecraft.src.KeyBinding;
|
||||
|
||||
import org.lwjgl.input.Keyboard;
|
||||
import org.lwjgl.input.Mouse;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
import cpw.mods.fml.common.ITickHandler;
|
||||
import cpw.mods.fml.common.Side;
|
||||
import cpw.mods.fml.common.TickType;
|
||||
import cpw.mods.fml.common.registry.TickRegistry;
|
||||
|
||||
public class KeyBindingRegistry
|
||||
{
|
||||
/**
|
||||
* Register a KeyHandler to the game. This handler will be called on certain tick events
|
||||
* if any of its key is inactive or has recently changed state
|
||||
*
|
||||
* @param handler
|
||||
*/
|
||||
public static void registerKeyBinding(KeyHandler handler) {
|
||||
instance().keyHandlers.add(handler);
|
||||
if (!handler.isDummy)
|
||||
{
|
||||
TickRegistry.registerTickHandler(handler, Side.CLIENT);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Extend this class to register a KeyBinding and recieve callback
|
||||
* when the key binding is triggered
|
||||
*
|
||||
* @author cpw
|
||||
*
|
||||
*/
|
||||
public static abstract class KeyHandler implements ITickHandler
|
||||
{
|
||||
protected KeyBinding[] keyBindings;
|
||||
protected boolean[] keyDown;
|
||||
protected boolean[] repeatings;
|
||||
private boolean isDummy;
|
||||
|
||||
/**
|
||||
* Pass an array of keybindings and a repeat flag for each one
|
||||
*
|
||||
* @param keyBindings
|
||||
* @param repeatings
|
||||
*/
|
||||
public KeyHandler(KeyBinding[] keyBindings, boolean[] repeatings)
|
||||
{
|
||||
assert keyBindings.length == repeatings.length : "You need to pass two arrays of identical length";
|
||||
this.keyBindings = keyBindings;
|
||||
this.repeatings = repeatings;
|
||||
this.keyDown = new boolean[keyBindings.length];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Register the keys into the system. You will do your own keyboard management elsewhere. No events will fire
|
||||
* if you use this method
|
||||
*
|
||||
* @param keyBindings
|
||||
*/
|
||||
public KeyHandler(KeyBinding[] keyBindings)
|
||||
{
|
||||
this.keyBindings = keyBindings;
|
||||
this.isDummy = true;
|
||||
}
|
||||
|
||||
public KeyBinding[] getKeyBindings()
|
||||
{
|
||||
return this.keyBindings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Not to be overridden - KeyBindings are tickhandlers under the covers
|
||||
*/
|
||||
@Override
|
||||
public final void tickStart(EnumSet<TickType> type, Object... tickData)
|
||||
{
|
||||
keyTick(type, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Not to be overridden - KeyBindings are tickhandlers under the covers
|
||||
*/
|
||||
@Override
|
||||
public final void tickEnd(EnumSet<TickType> type, Object... tickData)
|
||||
{
|
||||
keyTick(type, true);
|
||||
}
|
||||
|
||||
private void keyTick(EnumSet<TickType> type, boolean tickEnd)
|
||||
{
|
||||
for (int i = 0; i < keyBindings.length; i++)
|
||||
{
|
||||
KeyBinding keyBinding = keyBindings[i];
|
||||
int keyCode = keyBinding.field_74512_d;
|
||||
boolean state = (keyCode < 0 ? Mouse.isButtonDown(keyCode + 100) : Keyboard.isKeyDown(keyCode));
|
||||
if (state != keyDown[i] || (state && repeatings[i]))
|
||||
{
|
||||
if (state)
|
||||
{
|
||||
keyDown(type, keyBinding, tickEnd, state!=keyDown[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
keyUp(type, keyBinding, tickEnd);
|
||||
}
|
||||
if (tickEnd)
|
||||
{
|
||||
keyDown[i] = state;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the key is first in the down position on any tick from the {@link #ticks()}
|
||||
* set. Will be called subsequently with isRepeat set to true
|
||||
*
|
||||
* @see #keyUp(EnumSet, KeyBinding, boolean)
|
||||
*
|
||||
* @param types the type(s) of tick that fired when this key was first down
|
||||
* @param tickEnd was it an end or start tick which fired the key
|
||||
* @param isRepeat is it a repeat key event
|
||||
*/
|
||||
public abstract void keyDown(EnumSet<TickType> types, KeyBinding kb, boolean tickEnd, boolean isRepeat);
|
||||
/**
|
||||
* Fired once when the key changes state from down to up
|
||||
*
|
||||
* @see #keyDown(EnumSet, KeyBinding, boolean, boolean)
|
||||
*
|
||||
* @param types the type(s) of tick that fired when this key was first down
|
||||
* @param tickEnd was it an end or start tick which fired the key
|
||||
*/
|
||||
public abstract void keyUp(EnumSet<TickType> types, KeyBinding kb, boolean tickEnd);
|
||||
|
||||
|
||||
/**
|
||||
* This is the list of ticks for which the key binding should trigger. The only
|
||||
* valid ticks are client side ticks, obviously.
|
||||
*
|
||||
* @see cpw.mods.fml.common.ITickHandler#ticks()
|
||||
*/
|
||||
public abstract EnumSet<TickType> ticks();
|
||||
}
|
||||
|
||||
private static final KeyBindingRegistry INSTANCE = new KeyBindingRegistry();
|
||||
|
||||
private Set<KeyHandler> keyHandlers = Sets.newLinkedHashSet();
|
||||
|
||||
@Deprecated
|
||||
public static KeyBindingRegistry instance()
|
||||
{
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
|
||||
public void uploadKeyBindingsToGame(GameSettings settings)
|
||||
{
|
||||
ArrayList<KeyBinding> harvestedBindings = Lists.newArrayList();
|
||||
for (KeyHandler key : keyHandlers)
|
||||
{
|
||||
for (KeyBinding kb : key.keyBindings)
|
||||
{
|
||||
harvestedBindings.add(kb);
|
||||
}
|
||||
}
|
||||
KeyBinding[] modKeyBindings = harvestedBindings.toArray(new KeyBinding[harvestedBindings.size()]);
|
||||
KeyBinding[] allKeys = new KeyBinding[settings.field_74324_K.length + modKeyBindings.length];
|
||||
System.arraycopy(settings.field_74324_K, 0, allKeys, 0, settings.field_74324_K.length);
|
||||
System.arraycopy(modKeyBindings, 0, allKeys, settings.field_74324_K.length, modKeyBindings.length);
|
||||
settings.field_74324_K = allKeys;
|
||||
settings.func_74300_a();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
package cpw.mods.fml.client.registry;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import net.minecraft.src.Block;
|
||||
import net.minecraft.src.Entity;
|
||||
import net.minecraft.src.IBlockAccess;
|
||||
import net.minecraft.src.Render;
|
||||
import net.minecraft.src.RenderBiped;
|
||||
import net.minecraft.src.RenderBlocks;
|
||||
import net.minecraft.src.RenderManager;
|
||||
import net.minecraft.src.RenderPlayer;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.ObjectArrays;
|
||||
|
||||
import cpw.mods.fml.client.SpriteHelper;
|
||||
import cpw.mods.fml.client.TextureFXManager;
|
||||
|
||||
/**
|
||||
* @author cpw
|
||||
*
|
||||
*/
|
||||
public class RenderingRegistry
|
||||
{
|
||||
private static final RenderingRegistry INSTANCE = new RenderingRegistry();
|
||||
|
||||
private int nextRenderId = 36;
|
||||
|
||||
private Map<Integer, ISimpleBlockRenderingHandler> blockRenderers = Maps.newHashMap();
|
||||
|
||||
private List<EntityRendererInfo> entityRenderers = Lists.newArrayList();
|
||||
|
||||
/**
|
||||
* Add a new armour prefix to the RenderPlayer
|
||||
*
|
||||
* @param armor
|
||||
*/
|
||||
public static int addNewArmourRendererPrefix(String armor)
|
||||
{
|
||||
RenderPlayer.field_77110_j = ObjectArrays.concat(RenderPlayer.field_77110_j, armor);
|
||||
RenderBiped.field_82424_k = RenderPlayer.field_77110_j;
|
||||
return RenderPlayer.field_77110_j.length - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register an entity rendering handler. This will, after mod initialization, be inserted into the main
|
||||
* render map for entities
|
||||
*
|
||||
* @param entityClass
|
||||
* @param renderer
|
||||
*/
|
||||
public static void registerEntityRenderingHandler(Class<? extends Entity> entityClass, Render renderer)
|
||||
{
|
||||
instance().entityRenderers.add(new EntityRendererInfo(entityClass, renderer));
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a simple block rendering handler
|
||||
*
|
||||
* @param handler
|
||||
*/
|
||||
public static void registerBlockHandler(ISimpleBlockRenderingHandler handler)
|
||||
{
|
||||
instance().blockRenderers.put(handler.getRenderId(), handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the simple block rendering handler
|
||||
* This version will not call getRenderId on the passed in handler, instead using the supplied ID, so you
|
||||
* can easily re-use the same rendering handler for multiple IDs
|
||||
*
|
||||
* @param renderId
|
||||
* @param handler
|
||||
*/
|
||||
public static void registerBlockHandler(int renderId, ISimpleBlockRenderingHandler handler)
|
||||
{
|
||||
instance().blockRenderers.put(renderId, handler);
|
||||
}
|
||||
/**
|
||||
* Get the next available renderId from the block render ID list
|
||||
*/
|
||||
public static int getNextAvailableRenderId()
|
||||
{
|
||||
return instance().nextRenderId++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a texture override for the given path and return the used index
|
||||
*
|
||||
* @param fileToOverride
|
||||
* @param fileToAdd
|
||||
*/
|
||||
public static int addTextureOverride(String fileToOverride, String fileToAdd)
|
||||
{
|
||||
int idx = SpriteHelper.getUniqueSpriteIndex(fileToOverride);
|
||||
addTextureOverride(fileToOverride, fileToAdd, idx);
|
||||
return idx;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a texture override for the given path and index
|
||||
*
|
||||
* @param path
|
||||
* @param overlayPath
|
||||
* @param index
|
||||
*/
|
||||
public static void addTextureOverride(String path, String overlayPath, int index)
|
||||
{
|
||||
TextureFXManager.instance().addNewTextureOverride(path, overlayPath, index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get and reserve a unique texture index for the supplied path
|
||||
*
|
||||
* @param path
|
||||
*/
|
||||
public static int getUniqueTextureIndex(String path)
|
||||
{
|
||||
return SpriteHelper.getUniqueSpriteIndex(path);
|
||||
}
|
||||
|
||||
@Deprecated public static RenderingRegistry instance()
|
||||
{
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
private static class EntityRendererInfo
|
||||
{
|
||||
public EntityRendererInfo(Class<? extends Entity> target, Render renderer)
|
||||
{
|
||||
this.target = target;
|
||||
this.renderer = renderer;
|
||||
}
|
||||
private Class<? extends Entity> target;
|
||||
private Render renderer;
|
||||
}
|
||||
|
||||
public boolean renderWorldBlock(RenderBlocks renderer, IBlockAccess world, int x, int y, int z, Block block, int modelId)
|
||||
{
|
||||
if (!blockRenderers.containsKey(modelId)) { return false; }
|
||||
ISimpleBlockRenderingHandler bri = blockRenderers.get(modelId);
|
||||
return bri.renderWorldBlock(world, x, y, z, block, modelId, renderer);
|
||||
}
|
||||
|
||||
public void renderInventoryBlock(RenderBlocks renderer, Block block, int metadata, int modelID)
|
||||
{
|
||||
if (!blockRenderers.containsKey(modelID)) { return; }
|
||||
ISimpleBlockRenderingHandler bri = blockRenderers.get(modelID);
|
||||
bri.renderInventoryBlock(block, metadata, modelID, renderer);
|
||||
}
|
||||
|
||||
public boolean renderItemAsFull3DBlock(int modelId)
|
||||
{
|
||||
ISimpleBlockRenderingHandler bri = blockRenderers.get(modelId);
|
||||
return bri != null && bri.shouldRender3DInInventory();
|
||||
}
|
||||
|
||||
public void loadEntityRenderers(Map<Class<? extends Entity>, Render> rendererMap)
|
||||
{
|
||||
for (EntityRendererInfo info : entityRenderers)
|
||||
{
|
||||
rendererMap.put(info.target, info.renderer);
|
||||
info.renderer.func_76976_a(RenderManager.field_78727_a);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,444 @@
|
||||
/*
|
||||
* The FML Forge Mod Loader suite. Copyright (C) 2012 cpw
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.minecraft.src;
|
||||
|
||||
import static cpw.mods.fml.common.Side.CLIENT;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import cpw.mods.fml.client.FMLClientHandler;
|
||||
import cpw.mods.fml.common.FMLLog;
|
||||
import cpw.mods.fml.common.TickType;
|
||||
import cpw.mods.fml.common.asm.SideOnly;
|
||||
|
||||
public abstract class BaseMod implements cpw.mods.fml.common.modloader.BaseModProxy
|
||||
{
|
||||
// CALLBACK MECHANISMS
|
||||
|
||||
public final boolean doTickInGame(TickType tick, boolean tickEnd, Object... data)
|
||||
{
|
||||
Minecraft mc = FMLClientHandler.instance().getClient();
|
||||
boolean hasWorld = mc.field_71441_e != null;
|
||||
// World and render ticks
|
||||
if (tickEnd && ( tick==TickType.RENDER || tick==TickType.CLIENT ) && hasWorld) {
|
||||
return onTickInGame((Float) data[0], mc);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public final boolean doTickInGUI(TickType tick, boolean tickEnd, Object... data)
|
||||
{
|
||||
Minecraft mc = FMLClientHandler.instance().getClient();
|
||||
|
||||
boolean hasWorld = mc.field_71441_e != null;
|
||||
|
||||
if (tickEnd && ( tick==TickType.RENDER || ( tick==TickType.CLIENT && hasWorld))) {
|
||||
return onTickInGUI((Float) data[0], mc, mc.field_71462_r);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
public final void onRenderHarvest(Map renderers)
|
||||
{
|
||||
addRenderer((Map<Class<? extends Entity>,Render>)renderers);
|
||||
}
|
||||
|
||||
public final void onRegisterAnimations()
|
||||
{
|
||||
registerAnimation(FMLClientHandler.instance().getClient());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onCrafting(Object... craftingParameters)
|
||||
{
|
||||
takenFromCrafting((EntityPlayer)craftingParameters[0], (ItemStack)craftingParameters[1], (IInventory)craftingParameters[2]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onSmelting(Object... smeltingParameters)
|
||||
{
|
||||
takenFromFurnace((EntityPlayer)smeltingParameters[0], (ItemStack)smeltingParameters[1]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean dispense(double x, double y, double z, int xVelocity, int zVelocity, Object... data)
|
||||
{
|
||||
return dispenseEntity((World)data[0], x, y, z, xVelocity, zVelocity, (ItemStack)data[1]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean onChat(Object... data)
|
||||
{
|
||||
receiveChatPacket(((Packet3Chat)data[0]).field_73476_b);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final void onServerLogin(Object handler) {
|
||||
serverConnect((NetClientHandler) handler);
|
||||
}
|
||||
|
||||
public final void onServerLogout() {
|
||||
serverDisconnect();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onPlayerLogin(Object player)
|
||||
{
|
||||
onClientLogin((EntityPlayer) player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onPlayerLogout(Object player)
|
||||
{
|
||||
onClientLogout((EntityPlayer)player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onPlayerChangedDimension(Object player)
|
||||
{
|
||||
onClientDimensionChanged((EntityPlayer)player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onPacket250Packet(Object... data)
|
||||
{
|
||||
receiveCustomPacket((Packet250CustomPayload)data[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void notifyPickup(Object... pickupData)
|
||||
{
|
||||
EntityItem item = (EntityItem) pickupData[0];
|
||||
EntityPlayer player = (EntityPlayer) pickupData[1];
|
||||
onItemPickup(player, item.field_70294_a);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void generate(Random random, int chunkX, int chunkZ, Object... additionalData)
|
||||
{
|
||||
World w = (World) additionalData[0];
|
||||
IChunkProvider cp = (IChunkProvider) additionalData[1];
|
||||
|
||||
if (cp instanceof ChunkProviderGenerate)
|
||||
{
|
||||
generateSurface(w, random, chunkX << 4, chunkZ << 4);
|
||||
}
|
||||
else if (cp instanceof ChunkProviderHell)
|
||||
{
|
||||
generateNether(w, random, chunkX << 4, chunkZ << 4);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean handleCommand(String command, Object... data)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
*/
|
||||
// BASEMOD API
|
||||
/**
|
||||
* Override if you wish to provide a fuel item for the furnace and return the fuel value of the item
|
||||
*
|
||||
* @param id
|
||||
* @param metadata
|
||||
*/
|
||||
public int addFuel(int id, int metadata)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@SideOnly(CLIENT)
|
||||
public void addRenderer(Map<Class<? extends Entity>, Render> renderers)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Override if you wish to perform some action other than just dispensing the item from the dispenser
|
||||
*
|
||||
* @param world
|
||||
* @param x
|
||||
* @param y
|
||||
* @param z
|
||||
* @param xVel
|
||||
* @param zVel
|
||||
* @param item
|
||||
*/
|
||||
@Override
|
||||
public int dispenseEntity(World world, ItemStack item, Random rnd, int x, int y, int z, int xVel, int zVel, double entX, double entY, double entZ)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override if you wish to generate Nether (Hell biome) blocks
|
||||
*
|
||||
* @param world
|
||||
* @param random
|
||||
* @param chunkX
|
||||
* @param chunkZ
|
||||
*/
|
||||
public void generateNether(World world, Random random, int chunkX, int chunkZ)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Override if you wish to generate Overworld (not hell or the end) blocks
|
||||
*
|
||||
* @param world
|
||||
* @param random
|
||||
* @param chunkX
|
||||
* @param chunkZ
|
||||
*/
|
||||
public void generateSurface(World world, Random random, int chunkX, int chunkZ)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback to return a gui screen to display
|
||||
* @param player
|
||||
* @param containerID
|
||||
* @param x
|
||||
* @param y
|
||||
* @param z
|
||||
*/
|
||||
@SideOnly(CLIENT)
|
||||
public GuiContainer getContainerGUI(EntityClientPlayerMP player, int containerID, int x, int y, int z)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of your mod. Defaults to the class name
|
||||
*/
|
||||
public String getName()
|
||||
{
|
||||
return getClass().getSimpleName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get your mod priorities
|
||||
*/
|
||||
public String getPriorities()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the version of your mod
|
||||
*/
|
||||
public abstract String getVersion();
|
||||
|
||||
@SideOnly(CLIENT)
|
||||
public void keyboardEvent(KeyBinding event)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Load your mod
|
||||
*/
|
||||
public abstract void load();
|
||||
|
||||
/**
|
||||
* Finish loading your mod
|
||||
*/
|
||||
public void modsLoaded()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle item pickup
|
||||
*
|
||||
* @param player
|
||||
* @param item
|
||||
*/
|
||||
public void onItemPickup(EntityPlayer player, ItemStack item)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Ticked every game tick if you have subscribed to tick events through {@link ModLoader#setInGameHook(BaseMod, boolean, boolean)}
|
||||
*
|
||||
* @param time the rendering subtick time (0.0-1.0)
|
||||
* @param minecraftInstance the client
|
||||
* @return true to continue receiving ticks
|
||||
*/
|
||||
@SideOnly(CLIENT)
|
||||
public boolean onTickInGame(float time, Minecraft minecraftInstance)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean onTickInGame(MinecraftServer minecraftServer)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@SideOnly(CLIENT)
|
||||
public boolean onTickInGUI(float tick, Minecraft game, GuiScreen gui)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Only implemented on the client side
|
||||
* {@link #serverChat(EntityPlayer, Packet3Chat)}
|
||||
*
|
||||
* @param text
|
||||
*/
|
||||
@Override
|
||||
public void clientChat(String text)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a client connects
|
||||
* @param handler
|
||||
*/
|
||||
@SideOnly(CLIENT)
|
||||
public void clientConnect(NetClientHandler handler)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the client disconnects
|
||||
* @param handler
|
||||
*/
|
||||
@SideOnly(CLIENT)
|
||||
public void clientDisconnect(NetClientHandler handler)
|
||||
{
|
||||
|
||||
}
|
||||
/**
|
||||
* Called client side to receive a custom payload for this mod
|
||||
*
|
||||
* @param packet
|
||||
*/
|
||||
@Override
|
||||
public void receiveCustomPacket(Packet250CustomPayload packet)
|
||||
{
|
||||
}
|
||||
|
||||
@SideOnly(CLIENT)
|
||||
public void registerAnimation(Minecraft game)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@SideOnly(CLIENT)
|
||||
public void renderInvBlock(RenderBlocks renderer, Block block, int metadata, int modelID)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@SideOnly(CLIENT)
|
||||
public boolean renderWorldBlock(RenderBlocks renderer, IBlockAccess world, int x, int y, int z, Block block, int modelID)
|
||||
{
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serverConnect(NetHandler handler) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serverCustomPayload(NetServerHandler handler, Packet250CustomPayload packet)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serverDisconnect() {
|
||||
|
||||
}
|
||||
/**
|
||||
* Called when someone crafts an item from a crafting table
|
||||
*
|
||||
* @param player
|
||||
* @param item
|
||||
* @param matrix
|
||||
*/
|
||||
public void takenFromCrafting(EntityPlayer player, ItemStack item, IInventory matrix)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when someone takes a smelted item from a furnace
|
||||
*
|
||||
* @param player
|
||||
* @param item
|
||||
*/
|
||||
public void takenFromFurnace(EntityPlayer player, ItemStack item)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* The identifier string for the mod- used in client<->server negotiation
|
||||
*/
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return getName() + " " + getVersion();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a chat message is received. Return true to stop further processing
|
||||
*/
|
||||
@Override
|
||||
public void serverChat(NetServerHandler source, String message)
|
||||
{
|
||||
}
|
||||
/**
|
||||
* Called when a new client logs in.
|
||||
*
|
||||
* @param player
|
||||
*/
|
||||
@Override
|
||||
public void onClientLogin(EntityPlayer player)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a client logs out of the server.
|
||||
*/
|
||||
@Override
|
||||
public void onClientLogout(INetworkManager mgr)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Spawn the entity of the supplied type, if it is your mod's
|
||||
*/
|
||||
@SideOnly(CLIENT)
|
||||
public Entity spawnEntity(int entityId, World world, double scaledX, double scaledY, double scaledZ)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public void clientCustomPayload(NetClientHandler handler, Packet250CustomPayload packet)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* The FML Forge Mod Loader suite.
|
||||
* Copyright (C) 2012 cpw
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package net.minecraft.src;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
|
||||
public class EntityRendererProxy extends EntityRenderer
|
||||
{
|
||||
public static final String fmlMarker = "This is an FML marker";
|
||||
private Minecraft game;
|
||||
|
||||
public EntityRendererProxy(Minecraft minecraft)
|
||||
{
|
||||
super(minecraft);
|
||||
game = minecraft;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void func_78480_b(float tick)
|
||||
{
|
||||
super.func_78480_b(tick);
|
||||
//This is where ModLoader does all of it's ticking
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* The FML Forge Mod Loader suite.
|
||||
* Copyright (C) 2012 cpw
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package net.minecraft.src;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import cpw.mods.fml.client.TextureFXManager;
|
||||
import cpw.mods.fml.client.registry.RenderingRegistry;
|
||||
import cpw.mods.fml.common.FMLLog;
|
||||
|
||||
/**
|
||||
*
|
||||
* A static hook library for optifine and other basemod editing code to access FML functions
|
||||
*
|
||||
* @author cpw
|
||||
*
|
||||
*/
|
||||
public class FMLRenderAccessLibrary
|
||||
{
|
||||
public static Logger getLogger()
|
||||
{
|
||||
return FMLLog.getLogger();
|
||||
}
|
||||
|
||||
public static void log(Level level, String message)
|
||||
{
|
||||
FMLLog.log(level, message);
|
||||
}
|
||||
|
||||
public static void log(Level level, String message, Throwable throwable)
|
||||
{
|
||||
FMLLog.log(level, throwable, message);
|
||||
}
|
||||
|
||||
public static void setTextureDimensions(int textureId, int width, int height, List<TextureFX> textureFXList)
|
||||
{
|
||||
TextureFXManager.instance().setTextureDimensions(textureId, width, height, textureFXList);
|
||||
}
|
||||
|
||||
public static void preRegisterEffect(TextureFX textureFX)
|
||||
{
|
||||
TextureFXManager.instance().onPreRegisterEffect(textureFX);
|
||||
}
|
||||
|
||||
public static boolean onUpdateTextureEffect(TextureFX textureFX)
|
||||
{
|
||||
return TextureFXManager.instance().onUpdateTextureEffect(textureFX);
|
||||
}
|
||||
|
||||
public static Dimension getTextureDimensions(TextureFX textureFX)
|
||||
{
|
||||
return TextureFXManager.instance().getTextureDimensions(textureFX);
|
||||
}
|
||||
|
||||
public static void onTexturePackChange(RenderEngine engine, ITexturePack texturePack, List<TextureFX> textureFXList)
|
||||
{
|
||||
TextureFXManager.instance().onTexturePackChange(engine, texturePack, textureFXList);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public static boolean renderWorldBlock(RenderBlocks renderer, IBlockAccess world, int x, int y, int z, Block block, int modelId)
|
||||
{
|
||||
return RenderingRegistry.instance().renderWorldBlock(renderer, world, x, y, z, block, modelId);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public static void renderInventoryBlock(RenderBlocks renderer, Block block, int metadata, int modelID)
|
||||
{
|
||||
RenderingRegistry.instance().renderInventoryBlock(renderer, block, metadata, modelID);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public static boolean renderItemAsFull3DBlock(int modelId)
|
||||
{
|
||||
return RenderingRegistry.instance().renderItemAsFull3DBlock(modelId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* The FML Forge Mod Loader suite. Copyright (C) 2012 cpw
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.minecraft.src;
|
||||
|
||||
import static java.lang.annotation.ElementType.FIELD;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* @author cpw
|
||||
*
|
||||
*/
|
||||
@Retention(value = RUNTIME)
|
||||
@Target(value = FIELD)
|
||||
public @interface MLProp
|
||||
{
|
||||
/**
|
||||
* Adds additional help to top of configuration file.
|
||||
*/
|
||||
String info() default "";
|
||||
|
||||
/**
|
||||
* Maximum value allowed if field is a number.
|
||||
*/
|
||||
double max() default Double.MAX_VALUE;
|
||||
|
||||
/**
|
||||
* Minimum value allowed if field is a number.
|
||||
*/
|
||||
double min() default Double.MIN_VALUE;
|
||||
|
||||
/**
|
||||
* Overrides the field name for property key.
|
||||
*/
|
||||
String name() default "";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,883 @@
|
||||
/*
|
||||
* The FML Forge Mod Loader suite. Copyright (C) 2012 cpw
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package net.minecraft.src;
|
||||
|
||||
import static cpw.mods.fml.common.Side.CLIENT;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import cpw.mods.fml.client.FMLClientHandler;
|
||||
import cpw.mods.fml.client.SpriteHelper;
|
||||
import cpw.mods.fml.client.TextureFXManager;
|
||||
import cpw.mods.fml.client.modloader.ModLoaderClientHelper;
|
||||
import cpw.mods.fml.client.modloader.ModLoaderKeyBindingHandler;
|
||||
import cpw.mods.fml.client.registry.ClientRegistry;
|
||||
import cpw.mods.fml.client.registry.KeyBindingRegistry;
|
||||
import cpw.mods.fml.client.registry.RenderingRegistry;
|
||||
import cpw.mods.fml.common.FMLCommonHandler;
|
||||
import cpw.mods.fml.common.FMLLog;
|
||||
import cpw.mods.fml.common.Loader;
|
||||
import cpw.mods.fml.common.ObfuscationReflectionHelper;
|
||||
import cpw.mods.fml.common.asm.SideOnly;
|
||||
import cpw.mods.fml.common.modloader.ModLoaderHelper;
|
||||
import cpw.mods.fml.common.modloader.ModLoaderModContainer;
|
||||
import cpw.mods.fml.common.network.NetworkRegistry;
|
||||
import cpw.mods.fml.common.network.PacketDispatcher;
|
||||
import cpw.mods.fml.common.network.Player;
|
||||
import cpw.mods.fml.common.registry.EntityRegistry;
|
||||
import cpw.mods.fml.common.registry.GameRegistry;
|
||||
import cpw.mods.fml.common.registry.LanguageRegistry;
|
||||
import cpw.mods.fml.server.FMLServerHandler;
|
||||
|
||||
public class ModLoader
|
||||
{
|
||||
public static final String fmlMarker = "This is an FML marker";
|
||||
// TODO dirty workaround for millinaire
|
||||
@Deprecated
|
||||
public static final Map<String,Map<String,String>> localizedStrings=Collections.emptyMap();
|
||||
|
||||
/**
|
||||
* Adds localization info for an achievement, Not used on the server.
|
||||
*
|
||||
* @param achievement The achievement to name
|
||||
* @param name The name
|
||||
* @param description The description
|
||||
*/
|
||||
public static void addAchievementDesc(Achievement achievement, String name, String description)
|
||||
{
|
||||
String achName=achievement.func_75970_i();
|
||||
addLocalization(achName, name);
|
||||
addLocalization(achName+".desc", description);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is a call in hook from modified external code. Implemented elsewhere.
|
||||
*
|
||||
* {@link GameRegistry#getFuelValue(ItemStack))}
|
||||
*
|
||||
* @param id The Item ID
|
||||
* @param metadata The Item Metadata
|
||||
* @return The fuel strength, in ticks, 0 if unhandled
|
||||
*/
|
||||
@Deprecated
|
||||
public static int addAllFuel(int id, int metadata)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@SideOnly(CLIENT)
|
||||
public static void addAllRenderers(Map<Class<? extends Entity>, Render> renderers)
|
||||
{
|
||||
}
|
||||
|
||||
@SideOnly(CLIENT)
|
||||
public static void addAnimation(TextureFX anim)
|
||||
{
|
||||
TextureFXManager.instance().addAnimation(anim);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new prefix to the armor texture list
|
||||
*
|
||||
* {@link RenderingRegistry#addNewArmourRendererPrefix(String))}
|
||||
*
|
||||
* @param armor The new armor prefix
|
||||
* @return The new armor index
|
||||
*/
|
||||
@SideOnly(CLIENT)
|
||||
public static int addArmor(String armor)
|
||||
{
|
||||
return RenderingRegistry.addNewArmourRendererPrefix(armor);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method adds the supplied biome to the set of candidate biomes for the default world generator type.
|
||||
*
|
||||
* @param biome The biome to add
|
||||
*/
|
||||
public static void addBiome(BiomeGenBase biome)
|
||||
{
|
||||
GameRegistry.addBiome(biome);
|
||||
}
|
||||
|
||||
public static void addEntityTracker(BaseMod mod, Class<? extends Entity> entityClass, int entityTypeId, int updateRange, int updateInterval, boolean sendVelocityInfo)
|
||||
{
|
||||
ModLoaderHelper.buildEntityTracker(mod, entityClass, entityTypeId, updateRange, updateInterval, sendVelocityInfo);
|
||||
}
|
||||
|
||||
public static void addCommand(ICommand command)
|
||||
{
|
||||
ModLoaderHelper.addCommand(command);
|
||||
}
|
||||
/**
|
||||
* Add localization for the specified string
|
||||
*
|
||||
* @param key Key
|
||||
* @param value Value
|
||||
*/
|
||||
public static void addLocalization(String key, String value)
|
||||
{
|
||||
addLocalization(key, "en_US", value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add localization for the specified string
|
||||
*
|
||||
* @param key Key
|
||||
* @param lang Language identifier
|
||||
* @param value Value
|
||||
*/
|
||||
public static void addLocalization(String key, String lang, String value)
|
||||
{
|
||||
LanguageRegistry.instance().addStringLocalization(key, lang, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Name the specified minecraft object with the supplied name
|
||||
*
|
||||
* @param instance Item to name
|
||||
* @param name The name to give it
|
||||
*/
|
||||
public static void addName(Object instance, String name)
|
||||
{
|
||||
addName(instance,"en_US",name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unimplemented on the server as it does not generate names
|
||||
*
|
||||
* @param instance Item to name
|
||||
* @param lang Languge identifier
|
||||
* @param name Name to give it
|
||||
*/
|
||||
public static void addName(Object instance, String lang, String name)
|
||||
{
|
||||
LanguageRegistry.instance().addNameForObject(instance, lang, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to register a small image to be applied to a larger texture image,
|
||||
* typically how old ModLoader mods add custom Item/Block textures.
|
||||
*
|
||||
* Forge mods should use setTextureFile in Item/Block
|
||||
*
|
||||
* Will return the icon index it was applied to.
|
||||
*
|
||||
* Unimplemented on the server as it does not render textures
|
||||
*
|
||||
* @param fileToOverride The texture to apply the new image to
|
||||
* @param fileToAdd The new image
|
||||
* @return The 'icon index' in the main image that the new image will be applied to
|
||||
*/
|
||||
@SideOnly(CLIENT)
|
||||
public static int addOverride(String fileToOverride, String fileToAdd)
|
||||
{
|
||||
return RenderingRegistry.addTextureOverride(fileToOverride, fileToAdd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to register a small image to be applied to a larger texture image,
|
||||
* typically how old ModLoader mods add custom Item/Block textures.
|
||||
*
|
||||
* Forge mods should use setTextureFile in Item/Block
|
||||
*
|
||||
* Unimplemented on the server as it does not render textures
|
||||
*
|
||||
* @param path The texture to apply the new image to
|
||||
* @param overlayPath The new image
|
||||
* @param index Where on the texture to apply it
|
||||
*/
|
||||
@SideOnly(CLIENT)
|
||||
public static void addOverride(String path, String overlayPath, int index)
|
||||
{
|
||||
RenderingRegistry.addTextureOverride(path, overlayPath, index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a Shaped Recipe
|
||||
*
|
||||
* @param output The result
|
||||
* @param params The input
|
||||
*/
|
||||
public static void addRecipe(ItemStack output, Object... params)
|
||||
{
|
||||
GameRegistry.addRecipe(output, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a shapeless recipe
|
||||
*
|
||||
* @param output The result
|
||||
* @param params The input
|
||||
*/
|
||||
public static void addShapelessRecipe(ItemStack output, Object... params)
|
||||
{
|
||||
GameRegistry.addShapelessRecipe(output, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new product to be smelted
|
||||
*
|
||||
* @param input
|
||||
* @param output
|
||||
*/
|
||||
public static void addSmelting(int input, ItemStack output)
|
||||
{
|
||||
GameRegistry.addSmelting(input, output, 1.0f);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new product to be smelted
|
||||
*
|
||||
* @param input
|
||||
* @param output
|
||||
*/
|
||||
public static void addSmelting(int input, ItemStack output, float experience)
|
||||
{
|
||||
GameRegistry.addSmelting(input, output, experience);
|
||||
}
|
||||
/**
|
||||
* Add a mob to the spawn list
|
||||
*
|
||||
* @param entityClass
|
||||
* @param weightedProb
|
||||
* @param min
|
||||
* @param max
|
||||
* @param spawnList
|
||||
*/
|
||||
public static void addSpawn(Class<? extends EntityLiving> entityClass, int weightedProb, int min, int max, EnumCreatureType spawnList)
|
||||
{
|
||||
EntityRegistry.addSpawn(entityClass, weightedProb, min, max, spawnList, WorldType.base12Biomes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a mob to the spawn list
|
||||
*
|
||||
* @param entityClass
|
||||
* @param weightedProb
|
||||
* @param min
|
||||
* @param max
|
||||
* @param spawnList
|
||||
* @param biomes
|
||||
*/
|
||||
public static void addSpawn(Class<? extends EntityLiving> entityClass, int weightedProb, int min, int max, EnumCreatureType spawnList, BiomeGenBase... biomes)
|
||||
{
|
||||
EntityRegistry.addSpawn(entityClass, weightedProb, min, max, spawnList, biomes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a mob to the spawn list
|
||||
*
|
||||
* @param entityName
|
||||
* @param weightedProb
|
||||
* @param min
|
||||
* @param max
|
||||
* @param spawnList
|
||||
*/
|
||||
public static void addSpawn(String entityName, int weightedProb, int min, int max, EnumCreatureType spawnList)
|
||||
{
|
||||
EntityRegistry.addSpawn(entityName, weightedProb, min, max, spawnList, WorldType.base12Biomes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a mob to the spawn list
|
||||
*
|
||||
* @param entityName
|
||||
* @param weightedProb
|
||||
* @param min
|
||||
* @param max
|
||||
* @param spawnList
|
||||
* @param biomes
|
||||
*/
|
||||
public static void addSpawn(String entityName, int weightedProb, int min, int max, EnumCreatureType spawnList, BiomeGenBase... biomes)
|
||||
{
|
||||
EntityRegistry.addSpawn(entityName, weightedProb, min, max, spawnList, biomes);
|
||||
}
|
||||
|
||||
public static void addTrade(int profession, TradeEntry entry)
|
||||
{
|
||||
ModLoaderHelper.registerTrade(profession, entry);
|
||||
}
|
||||
/**
|
||||
* Send a packet from the client
|
||||
* @param packet
|
||||
*/
|
||||
public static void clientSendPacket(Packet packet)
|
||||
{
|
||||
PacketDispatcher.sendPacketToServer(packet);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is a call in hook from modified external code. Implemented elsewhere.
|
||||
*
|
||||
* @param world
|
||||
* @param x
|
||||
* @param y
|
||||
* @param z
|
||||
* @param xVel
|
||||
* @param zVel
|
||||
* @param item
|
||||
* @return Always false, not implemented here
|
||||
*/
|
||||
@Deprecated
|
||||
public static boolean dispenseEntity(World world, double x, double y, double z, int xVel, int zVel, ItemStack item)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a container and drop all the items in it on the ground around
|
||||
*
|
||||
* @param world
|
||||
* @param x
|
||||
* @param y
|
||||
* @param z
|
||||
*/
|
||||
public static void genericContainerRemoval(World world, int x, int y, int z)
|
||||
{
|
||||
/* TileEntity te = world.func_603_b(x, y, z);
|
||||
|
||||
if (!(te instanceof IInventory))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
IInventory inv = (IInventory)te;
|
||||
|
||||
for (int l = 0; l < inv.func_469_c(); l++)
|
||||
{
|
||||
ItemStack itemstack = inv.func_468_c(l);
|
||||
|
||||
if (itemstack == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
float f = world.field_1037_n.nextFloat() * 0.8F + 0.1F;
|
||||
float f1 = world.field_1037_n.nextFloat() * 0.8F + 0.1F;
|
||||
float f2 = world.field_1037_n.nextFloat() * 0.8F + 0.1F;
|
||||
|
||||
while (itemstack.field_1615_a > 0)
|
||||
{
|
||||
int i1 = world.field_1037_n.nextInt(21) + 10;
|
||||
|
||||
if (i1 > itemstack.field_1615_a)
|
||||
{
|
||||
i1 = itemstack.field_1615_a;
|
||||
}
|
||||
|
||||
itemstack.field_1615_a -= i1;
|
||||
EntityItem entityitem = new EntityItem(world, (float)te.field_823_f + f, (float)te.field_822_g + f1, (float)te.field_821_h + f2, new ItemStack(itemstack.field_1617_c, i1, itemstack.func_21181_i()));
|
||||
float f3 = 0.05F;
|
||||
entityitem.field_608_an = (float) world.field_1037_n.nextGaussian() * f3;
|
||||
entityitem.field_607_ao = (float) world.field_1037_n.nextGaussian() * f3 + 0.2F;
|
||||
entityitem.field_606_ap = (float) world.field_1037_n.nextGaussian() * f3;
|
||||
|
||||
if (itemstack.func_40710_n())
|
||||
{
|
||||
entityitem.field_801_a.func_40706_d((NBTTagCompound) itemstack.func_40709_o().func_40195_b());
|
||||
}
|
||||
|
||||
world.func_674_a(entityitem);
|
||||
}
|
||||
}
|
||||
*/ }
|
||||
|
||||
/**
|
||||
* Get a list of all BaseMod loaded into the system
|
||||
* {@link ModLoaderModContainer#findAll}
|
||||
*
|
||||
* @return A list containing all loaded ModLoader mods
|
||||
*/
|
||||
public static List<BaseMod> getLoadedMods()
|
||||
{
|
||||
return ModLoaderModContainer.findAll(BaseMod.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a logger instance {@link FMLCommonHandler#getFMLLogger()}
|
||||
*
|
||||
* @return The current logger
|
||||
*/
|
||||
public static Logger getLogger()
|
||||
{
|
||||
return FMLLog.getLogger();
|
||||
}
|
||||
|
||||
@SideOnly(CLIENT)
|
||||
public static Minecraft getMinecraftInstance()
|
||||
{
|
||||
return FMLClientHandler.instance().getClient();
|
||||
}
|
||||
|
||||
public static MinecraftServer getMinecraftServerInstance()
|
||||
{
|
||||
return FMLCommonHandler.instance().getMinecraftServerInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a value from a field using reflection
|
||||
* {@link ObfuscationReflectionHelper#getPrivateValue(Class, Object, int)}
|
||||
*
|
||||
* @param instanceclass
|
||||
* @param instance
|
||||
* @param fieldindex
|
||||
* @return The value in the specified field.
|
||||
*/
|
||||
public static <T, E> T getPrivateValue(Class<? super E> instanceclass, E instance, int fieldindex)
|
||||
{
|
||||
return ObfuscationReflectionHelper.getPrivateValue(instanceclass, instance, fieldindex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a value from a field using reflection
|
||||
* {@link ObfuscationReflectionHelper#getPrivateValue(Class, Object, String[])}
|
||||
*
|
||||
* @param instanceclass
|
||||
* @param instance
|
||||
* @param field
|
||||
* @return The value in the specified field.
|
||||
*/
|
||||
public static <T, E> T getPrivateValue(Class<? super E> instanceclass, E instance, String field)
|
||||
{
|
||||
return ObfuscationReflectionHelper.getPrivateValue(instanceclass, instance, field);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stubbed method on the server to return a unique model id
|
||||
*
|
||||
*/
|
||||
@SideOnly(CLIENT)
|
||||
public static int getUniqueBlockModelID(BaseMod mod, boolean inventoryRenderer)
|
||||
{
|
||||
return ModLoaderClientHelper.obtainBlockModelIdFor(mod, inventoryRenderer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a new unique entity id
|
||||
* {@link EntityRegistry#findGlobalUniqueEntityId()}
|
||||
*
|
||||
* @return A unique entity ID
|
||||
*/
|
||||
public static int getUniqueEntityId()
|
||||
{
|
||||
return EntityRegistry.findGlobalUniqueEntityId();
|
||||
}
|
||||
|
||||
@SideOnly(CLIENT)
|
||||
public static int getUniqueSpriteIndex(String path)
|
||||
{
|
||||
return SpriteHelper.getUniqueSpriteIndex(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* To properly implement packet 250 protocol you should always check your
|
||||
* channel is active prior to sending the packet
|
||||
*
|
||||
* @param player
|
||||
* @param channel
|
||||
* @return If the channel is registered to the current connection.
|
||||
*/
|
||||
public static boolean isChannelActive(EntityPlayer player, String channel)
|
||||
{
|
||||
return NetworkRegistry.instance().isChannelActive(channel, (Player)player);
|
||||
}
|
||||
|
||||
@SideOnly(CLIENT)
|
||||
public static boolean isGUIOpen(Class<? extends GuiScreen> gui)
|
||||
{
|
||||
return FMLClientHandler.instance().getClient().field_71462_r != null && FMLClientHandler.instance().getClient().field_71462_r.equals(gui);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the named mod loaded?
|
||||
* {@link Loader#isModLoaded(String)}
|
||||
*
|
||||
* @param modname
|
||||
* @return If the specified mod is loaded
|
||||
*/
|
||||
public static boolean isModLoaded(String modname)
|
||||
{
|
||||
return Loader.isModLoaded(modname);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implemented elsewhere
|
||||
*/
|
||||
@Deprecated
|
||||
public static void loadConfig()
|
||||
{
|
||||
}
|
||||
|
||||
@SideOnly(CLIENT)
|
||||
public static BufferedImage loadImage(RenderEngine renderEngine, String path) throws Exception
|
||||
{
|
||||
return TextureFXManager.instance().loadImageFromTexturePack(renderEngine, path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call in from elsewhere. Unimplemented here.
|
||||
* @param player
|
||||
* @param item
|
||||
*/
|
||||
@Deprecated
|
||||
public static void onItemPickup(EntityPlayer player, ItemStack item)
|
||||
{
|
||||
}
|
||||
/**
|
||||
* Call in from elsewhere. Unimplemented here.
|
||||
*/
|
||||
@Deprecated
|
||||
@SideOnly(CLIENT)
|
||||
public static void onTick(float tick, Minecraft game)
|
||||
{
|
||||
}
|
||||
|
||||
@SideOnly(CLIENT)
|
||||
public static void openGUI(EntityPlayer player, GuiScreen gui)
|
||||
{
|
||||
FMLClientHandler.instance().displayGuiScreen(player, gui);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void populateChunk(IChunkProvider generator, int chunkX, int chunkZ, World world)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is a call in hook from modified external code. Implemented elsewhere.
|
||||
* {@link FMLNetworkHandler#handlePacket250(Packet250CustomPayload, NetworkManager, NetHandler)}
|
||||
*
|
||||
* @param packet
|
||||
*/
|
||||
@Deprecated
|
||||
public static void receivePacket(Packet250CustomPayload packet)
|
||||
{
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@SideOnly(CLIENT)
|
||||
public static KeyBinding[] registerAllKeys(KeyBinding[] keys)
|
||||
{
|
||||
return keys;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@SideOnly(CLIENT)
|
||||
public static void registerAllTextureOverrides(RenderEngine cache)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a new block
|
||||
*
|
||||
* @param block
|
||||
*/
|
||||
public static void registerBlock(Block block)
|
||||
{
|
||||
GameRegistry.registerBlock(block);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a new block
|
||||
*
|
||||
* @param block
|
||||
* @param itemclass
|
||||
*/
|
||||
public static void registerBlock(Block block, Class<? extends ItemBlock> itemclass)
|
||||
{
|
||||
GameRegistry.registerBlock(block, itemclass);
|
||||
}
|
||||
|
||||
public static void registerContainerID(BaseMod mod, int id)
|
||||
{
|
||||
ModLoaderHelper.buildGuiHelper(mod, id);
|
||||
}
|
||||
/**
|
||||
* Register a new entity ID
|
||||
*
|
||||
* @param entityClass
|
||||
* @param entityName
|
||||
* @param id
|
||||
*/
|
||||
public static void registerEntityID(Class<? extends Entity> entityClass, String entityName, int id)
|
||||
{
|
||||
EntityRegistry.registerGlobalEntityID(entityClass, entityName, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a new entity ID
|
||||
*
|
||||
* @param entityClass
|
||||
* @param entityName
|
||||
* @param id
|
||||
* @param background
|
||||
* @param foreground
|
||||
*/
|
||||
public static void registerEntityID(Class<? extends Entity> entityClass, String entityName, int id, int background, int foreground)
|
||||
{
|
||||
EntityRegistry.registerGlobalEntityID(entityClass, entityName, id, background, foreground);
|
||||
}
|
||||
|
||||
@SideOnly(CLIENT)
|
||||
public static void registerKey(BaseMod mod, KeyBinding keyHandler, boolean allowRepeat)
|
||||
{
|
||||
ModLoaderClientHelper.registerKeyBinding(mod, keyHandler, allowRepeat);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the mod for packets on this channel.
|
||||
* {@link NetworkRegistry#registerChannel(IPacketHandler, String)}
|
||||
*
|
||||
* @param mod
|
||||
* @param channel
|
||||
*/
|
||||
public static void registerPacketChannel(BaseMod mod, String channel)
|
||||
{
|
||||
NetworkRegistry.instance().registerChannel(ModLoaderHelper.buildPacketHandlerFor(mod), channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a new tile entity class
|
||||
*
|
||||
* @param tileEntityClass
|
||||
* @param id
|
||||
*/
|
||||
public static void registerTileEntity(Class<? extends TileEntity> tileEntityClass, String id)
|
||||
{
|
||||
GameRegistry.registerTileEntity(tileEntityClass, id);
|
||||
}
|
||||
|
||||
@SideOnly(CLIENT)
|
||||
public static void registerTileEntity(Class<? extends TileEntity> tileEntityClass, String id, TileEntitySpecialRenderer renderer)
|
||||
{
|
||||
ClientRegistry.registerTileEntity(tileEntityClass, id, renderer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a biome from the list of generated biomes
|
||||
*
|
||||
* @param biome
|
||||
*/
|
||||
public static void removeBiome(BiomeGenBase biome)
|
||||
{
|
||||
GameRegistry.removeBiome(biome);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a spawn
|
||||
*
|
||||
* @param entityClass
|
||||
* @param spawnList
|
||||
*/
|
||||
public static void removeSpawn(Class<? extends EntityLiving> entityClass, EnumCreatureType spawnList)
|
||||
{
|
||||
EntityRegistry.removeSpawn(entityClass, spawnList, WorldType.base12Biomes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a spawn
|
||||
*
|
||||
* @param entityClass
|
||||
* @param spawnList
|
||||
* @param biomes
|
||||
*/
|
||||
public static void removeSpawn(Class<? extends EntityLiving> entityClass, EnumCreatureType spawnList, BiomeGenBase... biomes)
|
||||
{
|
||||
EntityRegistry.removeSpawn(entityClass, spawnList, biomes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a spawn
|
||||
*
|
||||
* @param entityName
|
||||
* @param spawnList
|
||||
*/
|
||||
public static void removeSpawn(String entityName, EnumCreatureType spawnList)
|
||||
{
|
||||
EntityRegistry.removeSpawn(entityName, spawnList, WorldType.base12Biomes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a spawn
|
||||
*
|
||||
* @param entityName
|
||||
* @param spawnList
|
||||
* @param biomes
|
||||
*/
|
||||
public static void removeSpawn(String entityName, EnumCreatureType spawnList, BiomeGenBase... biomes)
|
||||
{
|
||||
EntityRegistry.removeSpawn(entityName, spawnList, biomes);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@SideOnly(CLIENT)
|
||||
public static boolean renderBlockIsItemFull3D(int modelID)
|
||||
{
|
||||
return RenderingRegistry.instance().renderItemAsFull3DBlock(modelID);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@SideOnly(CLIENT)
|
||||
public static void renderInvBlock(RenderBlocks renderer, Block block, int metadata, int modelID)
|
||||
{
|
||||
RenderingRegistry.instance().renderInventoryBlock(renderer, block, metadata, modelID);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@SideOnly(CLIENT)
|
||||
public static boolean renderWorldBlock(RenderBlocks renderer, IBlockAccess world, int x, int y, int z, Block block, int modelID)
|
||||
{
|
||||
return RenderingRegistry.instance().renderWorldBlock(renderer, world, x, y, z, block, modelID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configuration is handled elsewhere
|
||||
* {@link ModLoaderModContainer}
|
||||
*/
|
||||
@Deprecated
|
||||
public static void saveConfig()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a packet from client to server
|
||||
*
|
||||
* @param packet
|
||||
*/
|
||||
public static void sendPacket(Packet packet) {
|
||||
PacketDispatcher.sendPacketToServer(packet);
|
||||
}
|
||||
/**
|
||||
* Send a chat message to the server
|
||||
* {@link FMLNetworkHandler#handleChatMessage(NetHandler, Packet3Chat)}
|
||||
*
|
||||
* @param text
|
||||
*/
|
||||
@Deprecated
|
||||
public static void serverChat(String text)
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@SideOnly(CLIENT)
|
||||
public static void serverLogin(NetClientHandler handler, Packet1Login loginPacket)
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
|
||||
public static void serverSendPacket(NetServerHandler handler, Packet packet)
|
||||
{
|
||||
if (handler != null)
|
||||
{
|
||||
PacketDispatcher.sendPacketToPlayer(packet, (Player)handler.getPlayer());
|
||||
}
|
||||
}
|
||||
public static void serverOpenWindow(EntityPlayerMP player, Container container, int ID, int x, int y, int z)
|
||||
{
|
||||
ModLoaderHelper.openGui(ID, player, container, x, y, z);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate that you want to receive ticks
|
||||
*
|
||||
* @param mod receiving the events
|
||||
* @param enable indicates whether you want to recieve them or not
|
||||
* @param useClock don't receive render subticks, just world ticks
|
||||
*/
|
||||
public static void setInGameHook(BaseMod mod, boolean enable, boolean useClock)
|
||||
{
|
||||
ModLoaderHelper.updateStandardTicks(mod, enable, useClock);
|
||||
}
|
||||
|
||||
|
||||
public static void setInGUIHook(BaseMod mod, boolean enable, boolean useClock)
|
||||
{
|
||||
ModLoaderHelper.updateGUITicks(mod, enable, useClock);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a private field to a value using reflection
|
||||
* {@link ObfuscationReflectionHelper#setPrivateValue(Class, Object, int, Object)}
|
||||
*
|
||||
* @param instanceclass
|
||||
* @param instance
|
||||
* @param fieldindex
|
||||
* @param value
|
||||
*/
|
||||
public static <T, E> void setPrivateValue(Class<? super T> instanceclass, T instance, int fieldindex, E value)
|
||||
{
|
||||
ObfuscationReflectionHelper.setPrivateValue(instanceclass, instance, value, fieldindex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a private field to a value using reflection
|
||||
* {@link ObfuscationReflectionHelper#setPrivateValue(Class, Object, String, Object)}
|
||||
*
|
||||
* @param instanceclass
|
||||
* @param instance
|
||||
* @param field
|
||||
* @param value
|
||||
*/
|
||||
public static <T, E> void setPrivateValue(Class<? super T> instanceclass, T instance, String field, E value)
|
||||
{
|
||||
ObfuscationReflectionHelper.setPrivateValue(instanceclass, instance, value, field);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is a call in hook from modified external code. Implemented elsewhere.
|
||||
*
|
||||
* @param player
|
||||
* @param item
|
||||
* @param matrix
|
||||
*/
|
||||
@Deprecated
|
||||
public static void takenFromCrafting(EntityPlayer player, ItemStack item, IInventory matrix)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is a call in hook from modified external code. Implemented elsewhere.
|
||||
*
|
||||
* @param player
|
||||
* @param item
|
||||
*/
|
||||
@Deprecated
|
||||
public static void takenFromFurnace(EntityPlayer player, ItemStack item)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw the offered exception. Likely will stop the game.
|
||||
*
|
||||
* @param message
|
||||
* @param e
|
||||
*/
|
||||
public static void throwException(String message, Throwable e)
|
||||
{
|
||||
FMLCommonHandler.instance().raiseException(e, message, true);
|
||||
}
|
||||
|
||||
public static void throwException(Throwable e)
|
||||
{
|
||||
throwException("Exception in ModLoader", e);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* The FML Forge Mod Loader suite.
|
||||
* Copyright (C) 2012 cpw
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package net.minecraft.src;
|
||||
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.ImageObserver;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import cpw.mods.fml.client.FMLClientHandler;
|
||||
import cpw.mods.fml.client.FMLTextureFX;
|
||||
|
||||
/**
|
||||
* A texture override for animations, it takes a vertical image of
|
||||
* texture frames and constantly rotates them in the texture.
|
||||
*/
|
||||
public class ModTextureAnimation extends FMLTextureFX
|
||||
{
|
||||
private final int tickRate;
|
||||
private byte[][] images;
|
||||
private int index = 0;
|
||||
private int ticks = 0;
|
||||
|
||||
private String targetTex = null;
|
||||
private BufferedImage imgData = null;
|
||||
|
||||
public ModTextureAnimation(int icon, int target, BufferedImage image, int tickCount)
|
||||
{
|
||||
this(icon, 1, target, image, tickCount);
|
||||
}
|
||||
|
||||
public ModTextureAnimation(int icon, int size, int target, BufferedImage image, int tickCount)
|
||||
{
|
||||
this(icon, size, (target == 0 ? "/terrain.png" : "/gui/items.png"), image, tickCount);
|
||||
}
|
||||
|
||||
public ModTextureAnimation(int icon, int size, String target, BufferedImage image, int tickCount)
|
||||
{
|
||||
super(icon);
|
||||
RenderEngine re = FMLClientHandler.instance().getClient().field_71446_o;
|
||||
|
||||
targetTex = target;
|
||||
field_76849_e = size;
|
||||
field_76847_f = re.func_78341_b(target);
|
||||
|
||||
tickRate = tickCount;
|
||||
ticks = tickCount;
|
||||
imgData = image;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setup()
|
||||
{
|
||||
super.setup();
|
||||
|
||||
int sWidth = imgData.getWidth();
|
||||
int sHeight = imgData.getHeight();
|
||||
int tWidth = tileSizeBase;
|
||||
int tHeight = tileSizeBase;
|
||||
|
||||
|
||||
int frames = (int)Math.floor((double)(sHeight / sWidth));
|
||||
|
||||
if (frames < 1)
|
||||
{
|
||||
throw new IllegalArgumentException(String.format("Attempted to create a TextureAnimation with no complete frames: %dx%d", sWidth, sHeight));
|
||||
}
|
||||
else
|
||||
{
|
||||
images = new byte[frames][];
|
||||
BufferedImage image = imgData;
|
||||
|
||||
if (sWidth != tWidth)
|
||||
{
|
||||
BufferedImage b = new BufferedImage(tWidth, tHeight * frames, 6);
|
||||
Graphics2D g = b.createGraphics();
|
||||
g.drawImage(imgData, 0, 0, tWidth, tHeight * frames, 0, 0, sWidth, sHeight, (ImageObserver)null);
|
||||
g.dispose();
|
||||
image = b;
|
||||
}
|
||||
|
||||
for (int frame = 0; frame < frames; frame++)
|
||||
{
|
||||
int[] pixels = new int[tileSizeSquare];
|
||||
image.getRGB(0, tHeight * frame, tWidth, tHeight, pixels, 0, tWidth);
|
||||
images[frame] = new byte[tileSizeSquare << 2];
|
||||
|
||||
for (int i = 0; i < pixels.length; i++)
|
||||
{
|
||||
int i4 = i * 4;
|
||||
images[frame][i4 + 0] = (byte)(pixels[i] >> 16 & 255);
|
||||
images[frame][i4 + 1] = (byte)(pixels[i] >> 8 & 255);
|
||||
images[frame][i4 + 2] = (byte)(pixels[i] >> 0 & 255);
|
||||
images[frame][i4 + 3] = (byte)(pixels[i] >> 24 & 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void func_76846_a()
|
||||
{
|
||||
if (++ticks >= tickRate)
|
||||
{
|
||||
if (++index >= images.length)
|
||||
{
|
||||
index = 0;
|
||||
}
|
||||
|
||||
field_76852_a = images[index];
|
||||
ticks = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public void func_76845_a(RenderEngine renderEngine)
|
||||
{
|
||||
GL11.glBindTexture(GL11.GL_TEXTURE_2D, field_76847_f);
|
||||
}
|
||||
|
||||
// TODO: REMOVE THIS - just for you dan200
|
||||
@Deprecated
|
||||
public void func_783_a()
|
||||
{
|
||||
func_76846_a();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* The FML Forge Mod Loader suite.
|
||||
* Copyright (C) 2012 cpw
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package net.minecraft.src;
|
||||
|
||||
import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D;
|
||||
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.ImageObserver;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import cpw.mods.fml.client.FMLClientHandler;
|
||||
import cpw.mods.fml.client.FMLTextureFX;
|
||||
|
||||
public class ModTextureStatic extends FMLTextureFX
|
||||
{
|
||||
private boolean oldanaglyph = false;
|
||||
private int[] pixels = null;
|
||||
private String targetTex = null;
|
||||
private int storedSize;
|
||||
private BufferedImage overrideData = null;
|
||||
private int needApply = 2;
|
||||
|
||||
|
||||
public ModTextureStatic(int icon, int target, BufferedImage image)
|
||||
{
|
||||
this(icon, 1, target, image);
|
||||
}
|
||||
|
||||
public ModTextureStatic(int icon, int size, int target, BufferedImage image)
|
||||
{
|
||||
this(icon, size, (target == 0 ? "/terrain.png" : "/gui/items.png"), image);
|
||||
}
|
||||
|
||||
public ModTextureStatic(int icon, int size, String target, BufferedImage image)
|
||||
{
|
||||
super(icon);
|
||||
RenderEngine re = FMLClientHandler.instance().getClient().field_71446_o;
|
||||
|
||||
targetTex = target;
|
||||
storedSize = size;
|
||||
field_76849_e = size;
|
||||
field_76847_f = re.func_78341_b(target);
|
||||
overrideData = image;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setup()
|
||||
{
|
||||
super.setup();
|
||||
int sWidth = overrideData.getWidth();
|
||||
int sHeight = overrideData.getHeight();
|
||||
|
||||
pixels = new int[tileSizeSquare];
|
||||
if (tileSizeBase == sWidth && tileSizeBase == sHeight)
|
||||
{
|
||||
overrideData.getRGB(0, 0, sWidth, sHeight, pixels, 0, sWidth);
|
||||
}
|
||||
else
|
||||
{
|
||||
BufferedImage tmp = new BufferedImage(tileSizeBase, tileSizeBase, 6);
|
||||
Graphics2D gfx = tmp.createGraphics();
|
||||
gfx.drawImage(overrideData, 0, 0, tileSizeBase, tileSizeBase, 0, 0, sWidth, sHeight, (ImageObserver)null);
|
||||
tmp.getRGB(0, 0, tileSizeBase, tileSizeBase, pixels, 0, tileSizeBase);
|
||||
gfx.dispose();
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void func_76846_a()
|
||||
{
|
||||
if (oldanaglyph != field_76851_c)
|
||||
{
|
||||
update();
|
||||
}
|
||||
// This makes it so we only apply the texture to the target texture when we need to,
|
||||
//due to the fact that update is called when the Effect is first registered, we actually
|
||||
//need to wait for the next one.
|
||||
field_76849_e = (needApply == 0 ? 0 : storedSize);
|
||||
if (needApply > 0)
|
||||
{
|
||||
needApply--;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void func_76845_a(RenderEngine p_76845_1_)
|
||||
{
|
||||
GL11.glBindTexture(GL_TEXTURE_2D, p_76845_1_.func_78341_b(targetTex));
|
||||
}
|
||||
|
||||
public void update()
|
||||
{
|
||||
needApply = 2;
|
||||
for (int idx = 0; idx < pixels.length; idx++)
|
||||
{
|
||||
int i = idx * 4;
|
||||
int a = pixels[idx] >> 24 & 255;
|
||||
int r = pixels[idx] >> 16 & 255;
|
||||
int g = pixels[idx] >> 8 & 255;
|
||||
int b = pixels[idx] >> 0 & 255;
|
||||
|
||||
if (field_76851_c)
|
||||
{
|
||||
r = g = b = (r + g + b) / 3;
|
||||
}
|
||||
|
||||
field_76852_a[i + 0] = (byte)r;
|
||||
field_76852_a[i + 1] = (byte)g;
|
||||
field_76852_a[i + 2] = (byte)b;
|
||||
field_76852_a[i + 3] = (byte)a;
|
||||
}
|
||||
|
||||
oldanaglyph = field_76851_c;
|
||||
}
|
||||
|
||||
//Implementation of http://scale2x.sourceforge.net/algorithm.html
|
||||
public static BufferedImage scale2x(BufferedImage image)
|
||||
{
|
||||
int w = image.getWidth();
|
||||
int h = image.getHeight();
|
||||
BufferedImage tmp = new BufferedImage(w * 2, h * 2, 2);
|
||||
|
||||
for (int x = 0; x < h; ++x)
|
||||
{
|
||||
int x2 = x * 2;
|
||||
for (int y = 0; y < w; ++y)
|
||||
{
|
||||
int y2 = y * 2;
|
||||
int E = image.getRGB(y, x);
|
||||
int D = (x == 0 ? E : image.getRGB(y, x - 1));
|
||||
int B = (y == 0 ? E : image.getRGB(y - 1, x ));
|
||||
int H = (y >= w - 1 ? E : image.getRGB(y + 1, x ));
|
||||
int F = (x >= h - 1 ? E : image.getRGB(y, x + 1));
|
||||
|
||||
int e0, e1, e2, e3;
|
||||
|
||||
if (B != H && D != F)
|
||||
{
|
||||
e0 = D == B ? D : E;
|
||||
e1 = B == F ? F : E;
|
||||
e2 = D == H ? D : E;
|
||||
e3 = H == F ? F : E;
|
||||
}
|
||||
else
|
||||
{
|
||||
e0 = e1 = e2 = e3 = E;
|
||||
}
|
||||
|
||||
tmp.setRGB(y2, x2, e0);
|
||||
tmp.setRGB(y2 + 1, x2, e1);
|
||||
tmp.setRGB(y2, x2 + 1, e2);
|
||||
tmp.setRGB(y2 + 1, x2 + 1, e3);
|
||||
}
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return String.format("ModTextureStatic %s @ %d", targetTex, field_76850_b);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package net.minecraft.src;
|
||||
|
||||
/**
|
||||
* Compatibility class for ModLoader -- do not use
|
||||
*
|
||||
* @author cpw
|
||||
*
|
||||
*/
|
||||
public class TradeEntry
|
||||
{
|
||||
public final int id;
|
||||
public float chance;
|
||||
public boolean buying;
|
||||
public int min = 0;
|
||||
public int max = 0;
|
||||
|
||||
public TradeEntry(int id, float chance, boolean buying, int min, int max)
|
||||
{
|
||||
this.id = id;
|
||||
this.chance = chance;
|
||||
this.buying = buying;
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
}
|
||||
|
||||
public TradeEntry(int id, float chance, boolean buying)
|
||||
{
|
||||
this(id, chance, buying, 0, 0);
|
||||
}
|
||||
}
|
||||
+227
@@ -0,0 +1,227 @@
|
||||
--- commands.py
|
||||
+++ commands.py
|
||||
@@ -58,6 +58,8 @@
|
||||
|
||||
|
||||
def reallyrmtree(path):
|
||||
+ if os.path.isfile(os.path.join(path, 'asm-all-4.0.jar')): #Check if asm exists, indicating the libs folder, if so, don't delete it
|
||||
+ return
|
||||
if not sys.platform.startswith('win'):
|
||||
if os.path.exists(path):
|
||||
shutil.rmtree(path)
|
||||
@@ -584,6 +586,9 @@
|
||||
self.has_astyle_cfg = False
|
||||
if os.path.isfile(self.astyleconf):
|
||||
self.has_astyle_cfg = True
|
||||
+
|
||||
+ #FML Entries
|
||||
+ self.srcshared = os.path.normpath(os.path.join(self.dirsrc, 'common'))
|
||||
|
||||
def creatergcfg(self, reobf=False, keep_lvt=False, keep_generics=False, rg_update=False):
|
||||
"""Create the files necessary for RetroGuard"""
|
||||
@@ -781,7 +786,8 @@
|
||||
testlk = {CLIENT: self.testclient, SERVER: self.testserver}
|
||||
|
||||
if not os.path.exists(os.path.join(srclk[side], os.path.normpath(testlk[side] + '.java'))):
|
||||
- return False
|
||||
+ if not os.path.exists(os.path.join(self.srcshared, os.path.normpath(testlk[side] + '.java'))):
|
||||
+ return False
|
||||
return True
|
||||
|
||||
def checkbins(self, side):
|
||||
@@ -1029,6 +1035,10 @@
|
||||
pathsrclk = {CLIENT: self.srcclient, SERVER: self.srcserver}
|
||||
pathlog = {CLIENT: self.clientrecomplog, SERVER: self.serverrecomplog}
|
||||
|
||||
+ if side == SERVER: #Disable server because FML recombines it into client
|
||||
+ self.logger.info('Server side recompiling skipped, this is normal')
|
||||
+ return
|
||||
+
|
||||
if not os.path.exists(pathbinlk[side]):
|
||||
os.makedirs(pathbinlk[side])
|
||||
|
||||
@@ -1041,6 +1051,7 @@
|
||||
all_files = True
|
||||
append_pattern = False
|
||||
pkglist = filterdirs(pathsrclk[side], '*.java', append_pattern=append_pattern, all_files=all_files)
|
||||
+ pkglist = pkglist + filterdirs(self.srcshared, '*.java', append_pattern=append_pattern, all_files=all_files) #FML, Add Common folder
|
||||
dirs = ' '.join(pkglist)
|
||||
classpath = os.pathsep.join(cplk[side])
|
||||
forkcmd = self.cmdrecomp.format(classpath=classpath, sourcepath=pathsrclk[side], outpath=pathbinlk[side],
|
||||
@@ -1062,7 +1073,7 @@
|
||||
raise
|
||||
|
||||
def startserver(self):
|
||||
- classpath = [self.binserver] + self.cpathserver
|
||||
+ classpath = [self.binserver, self.srcshared] + self.cpathserver
|
||||
classpath = [os.path.join('..', p) for p in classpath]
|
||||
classpath = os.pathsep.join(classpath)
|
||||
os.chdir(self.dirjars)
|
||||
@@ -1070,7 +1081,7 @@
|
||||
self.runmc(forkcmd)
|
||||
|
||||
def startclient(self):
|
||||
- classpath = [self.binclient] + self.cpathclient
|
||||
+ classpath = [self.binclient, self.srcshared] + self.cpathclient
|
||||
classpath = [os.path.join('..', p) for p in classpath]
|
||||
classpath = os.pathsep.join(classpath)
|
||||
natives = os.path.join('..', self.dirnatives)
|
||||
@@ -1197,20 +1208,20 @@
|
||||
with open(self.csvmethods, 'rb') as fh:
|
||||
methodsreader = csv.DictReader(fh)
|
||||
for row in methodsreader:
|
||||
- if int(row['side']) == side:
|
||||
+ if int(row['side']) == side or int(row['side']) == 2:
|
||||
if row['name'] != row['searge']:
|
||||
names['methods'][row['searge']] = row['name']
|
||||
with open(self.csvfields, 'rb') as fh:
|
||||
fieldsreader = csv.DictReader(fh)
|
||||
for row in fieldsreader:
|
||||
- if int(row['side']) == side:
|
||||
+ if int(row['side']) == side or int(row['side']) == 2:
|
||||
if row['name'] != row['searge']:
|
||||
names['fields'][row['searge']] = row['name']
|
||||
if self.has_param_csv:
|
||||
with open(self.csvparams, 'rb') as fh:
|
||||
paramsreader = csv.DictReader(fh)
|
||||
for row in paramsreader:
|
||||
- if int(row['side']) == side:
|
||||
+ if int(row['side']) == side or int(row['side']) == 2:
|
||||
names['params'][row['param']] = row['name']
|
||||
|
||||
regexps = {
|
||||
@@ -1240,6 +1251,11 @@
|
||||
|
||||
# HINT: We pathwalk the sources
|
||||
for path, _, filelist in os.walk(pathsrclk[side], followlinks=True):
|
||||
+ for cur_file in fnmatch.filter(filelist, '*.java'):
|
||||
+ updatefile(os.path.normpath(os.path.join(path, cur_file)))
|
||||
+
|
||||
+ # FML, copy of the above, for the common folder
|
||||
+ for path, _, filelist in os.walk(self.srcshared, followlinks=True):
|
||||
for cur_file in fnmatch.filter(filelist, '*.java'):
|
||||
updatefile(os.path.normpath(os.path.join(path, cur_file)))
|
||||
return True
|
||||
@@ -1322,12 +1338,14 @@
|
||||
pathsrclk = {CLIENT: self.srcclient, SERVER: self.srcserver}
|
||||
|
||||
strip_comments(pathsrclk[side])
|
||||
+ strip_comments(self.srcshared)
|
||||
|
||||
def process_cleanup(self, side):
|
||||
"""Do lots of random cleanups including stripping comments, trailing whitespace and extra blank lines"""
|
||||
pathsrclk = {CLIENT: self.srcclient, SERVER: self.srcserver}
|
||||
|
||||
src_cleanup(pathsrclk[side], fix_imports=True, fix_unicode=True, fix_charval=True, fix_pi=True, fix_round=False)
|
||||
+ src_cleanup(self.srcshared, fix_imports=True, fix_unicode=True, fix_charval=True, fix_pi=True, fix_round=False)
|
||||
|
||||
def process_javadoc(self, side):
|
||||
"""Add CSV descriptions to methods and fields as javadoc"""
|
||||
@@ -1336,6 +1354,21 @@
|
||||
if not self.has_doc_csv:
|
||||
self.logger.warning('!! javadoc disabled due to no csvs !!')
|
||||
return False
|
||||
+
|
||||
+ #FML Recall this function on the common folder
|
||||
+ #Potential bug: If this is called without a subsiquent rename call, will cause double comments
|
||||
+ if pathsrclk[side] != self.srcshared:
|
||||
+ if side == CLIENT:
|
||||
+ tmp = self.srcclient
|
||||
+ self.srcclient = self.srcshared
|
||||
+ self.process_javadoc(side)
|
||||
+ self.srcclient = tmp
|
||||
+ else:
|
||||
+ tmp = self.srcserver
|
||||
+ self.srcserver = self.srcshared
|
||||
+ self.process_javadoc(side)
|
||||
+ self.srcserver = tmp
|
||||
+
|
||||
|
||||
#HINT: We read the relevant CSVs
|
||||
methodsreader = csv.DictReader(open(self.csvmethods, 'r'))
|
||||
@@ -1344,13 +1377,13 @@
|
||||
methods = {}
|
||||
for row in methodsreader:
|
||||
#HINT: Only include methods that have a non-empty description
|
||||
- if int(row['side']) == side and row['desc']:
|
||||
+ if (int(row['side']) == side or int(row['side']) == 2) and row['desc']:
|
||||
methods[row['searge']] = row['desc'].replace('*/', '* /')
|
||||
|
||||
fields = {}
|
||||
for row in fieldsreader:
|
||||
#HINT: Only include fields that have a non-empty description
|
||||
- if int(row['side']) == side and row['desc']:
|
||||
+ if (int(row['side']) == side or int(row['side']) == 2) and row['desc']:
|
||||
fields[row['searge']] = row['desc'].replace('*/', '* /')
|
||||
|
||||
regexps = {
|
||||
@@ -1422,12 +1455,13 @@
|
||||
|
||||
# HINT: We create the list of source directories based on the list of packages
|
||||
pkglist = filterdirs(pathsrclk[side], '*.java', append_pattern=True)
|
||||
+ pkglist = pkglist + filterdirs(self.srcshared, '*.java', append_pattern=True) #FML, Add Common folder
|
||||
dirs = ' '.join(pkglist)
|
||||
forkcmd = self.cmdastyle.format(classes=dirs, conffile=self.astyleconf)
|
||||
self.runcmd(forkcmd)
|
||||
return True
|
||||
|
||||
- def gathermd5s(self, side, reobf=False):
|
||||
+ def gathermd5s(self, side, reobf=False, skip_fml=False):
|
||||
if not reobf:
|
||||
md5lk = {CLIENT: self.md5client, SERVER: self.md5server}
|
||||
else:
|
||||
@@ -1442,6 +1476,9 @@
|
||||
class_path = ''
|
||||
else:
|
||||
class_path += '/'
|
||||
+ if skip_fml:
|
||||
+ if class_path.startswith('cpw/'):
|
||||
+ continue
|
||||
for class_file in fnmatch.filter(filelist, '*.class'):
|
||||
class_name = class_path + os.path.splitext(class_file)[0]
|
||||
bin_file = os.path.normpath(os.path.join(path, class_file))
|
||||
@@ -1594,6 +1631,9 @@
|
||||
sys.exit(1)
|
||||
|
||||
for entry in newfiles:
|
||||
+ if 'commands.py' in entry[0]: #FML, Disable updating of Commands.py
|
||||
+ print 'Update to runtime/commands.py found, but disbled due to using fml'
|
||||
+ continue
|
||||
if entry[3] == 'U':
|
||||
self.logger.info('Retrieving file from server : %s', entry[0])
|
||||
cur_file = os.path.normpath(entry[0])
|
||||
@@ -1614,6 +1654,9 @@
|
||||
md5reoblk = {CLIENT: self.md5reobfclient, SERVER: self.md5reobfserver}
|
||||
outpathlk = {CLIENT: self.srcmodclient, SERVER: self.srcmodserver}
|
||||
src = {CLIENT: self.srcclient, SERVER: self.srcserver}
|
||||
+
|
||||
+ if side == SERVER: #Noop out server side stuff
|
||||
+ return
|
||||
|
||||
# HINT: We need a table for the old md5 and the new ones
|
||||
md5table = {}
|
||||
@@ -1646,6 +1689,7 @@
|
||||
# HINT: We extract the source files for the modified class files
|
||||
for in_class in trgclasses:
|
||||
src_file = os.path.normpath(os.path.join(src[side], in_class + '.java'))
|
||||
+ cmn_file = os.path.normpath(os.path.join(self.srcshared, in_class + '.java'))
|
||||
dest_file = os.path.normpath(os.path.join(outpathlk[side], in_class + '.java'))
|
||||
if os.path.isfile(src_file):
|
||||
if not os.path.exists(os.path.dirname(dest_file)):
|
||||
@@ -1655,4 +1699,15 @@
|
||||
self.logger.info('> Outputted %s to %s', in_class.ljust(35), outpathlk[side])
|
||||
except IOError:
|
||||
self.logger.error('* File %s copy failed', in_class)
|
||||
-
|
||||
+ elif os.path.isfile(cmn_file):
|
||||
+ if not os.path.exists(os.path.dirname(dest_file)):
|
||||
+ os.makedirs(os.path.dirname(dest_file))
|
||||
+ try:
|
||||
+ shutil.copyfile(cmn_file, dest_file)
|
||||
+ self.logger.info('> Outputted %s to %s', in_class.ljust(35), outpathlk[side])
|
||||
+ except IOError:
|
||||
+ self.logger.error('* File %s copy failed', in_class)
|
||||
+
|
||||
+def commands_sanity_check():
|
||||
+ print 'Commands patch applied successfully'
|
||||
+
|
||||
@@ -0,0 +1,29 @@
|
||||
package cpw.mods.fml.common;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Declare a variable to be populated by a Bukkit Plugin proxy instance if the bukkit coremod
|
||||
* is available. It can only be applied to field typed as {@link BukkitProxy}
|
||||
* Generally it should be used in conjunction with {@link Mod#bukkitPlugin()} specifying the
|
||||
* plugin to load.
|
||||
*
|
||||
* @author cpw
|
||||
*
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
public @interface BukkitPluginRef
|
||||
{
|
||||
/**
|
||||
* A reference (possibly version specific) to a Bukkit Plugin by name, using the name@versionbound
|
||||
* specification. If this is a bukkit enabled environment the field annotated by this
|
||||
* will be populated with a {@link BukkitProxy} instance if possible. This proxy will be gotten by
|
||||
* reflectively calling the "getModProxy" method on the bukkit plugin instance.
|
||||
* @return
|
||||
*/
|
||||
String value();
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package cpw.mods.fml.common;
|
||||
|
||||
/**
|
||||
* A marker interface for retrieving a proxy to a bukkit plugin.
|
||||
* Fields associated with {@link BukkitPluginRef} annotations should be should probably
|
||||
* declare this type and cast down if the target is available (not null)
|
||||
* @author cpw
|
||||
*
|
||||
*/
|
||||
public interface BukkitProxy
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
package cpw.mods.fml.common;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.common.eventbus.EventBus;
|
||||
|
||||
import cpw.mods.fml.common.versioning.ArtifactVersion;
|
||||
import cpw.mods.fml.common.versioning.DefaultArtifactVersion;
|
||||
import cpw.mods.fml.common.versioning.VersionRange;
|
||||
|
||||
public class DummyModContainer implements ModContainer
|
||||
{
|
||||
private ModMetadata md;
|
||||
private ArtifactVersion processedVersion;
|
||||
|
||||
public DummyModContainer(ModMetadata md)
|
||||
{
|
||||
this.md = md;
|
||||
}
|
||||
|
||||
public DummyModContainer()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindMetadata(MetadataCollection mc)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ArtifactVersion> getDependants()
|
||||
{
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ArtifactVersion> getDependencies()
|
||||
{
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<ArtifactVersion> getRequirements()
|
||||
{
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModMetadata getMetadata()
|
||||
{
|
||||
return md;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getMod()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getModId()
|
||||
{
|
||||
return md.modId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName()
|
||||
{
|
||||
return md.name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSortingRules()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getSource()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion()
|
||||
{
|
||||
return md.version;
|
||||
}
|
||||
|
||||
public boolean matches(Object mod)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnabledState(boolean enabled)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean registerBus(EventBus bus, LoadController controller)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArtifactVersion getProcessedVersion()
|
||||
{
|
||||
if (processedVersion == null)
|
||||
{
|
||||
processedVersion = new DefaultArtifactVersion(getModId(), getVersion());
|
||||
}
|
||||
return processedVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isImmutable()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNetworkMod()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayVersion()
|
||||
{
|
||||
return md.version;
|
||||
}
|
||||
@Override
|
||||
public VersionRange acceptableMinecraftVersionRange()
|
||||
{
|
||||
return Loader.instance().getMinecraftModContainer().getStaticVersionRange();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,439 @@
|
||||
/*
|
||||
* The FML Forge Mod Loader suite.
|
||||
* Copyright (C) 2012 cpw
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package cpw.mods.fml.common;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.src.CrashReport;
|
||||
import net.minecraft.src.DedicatedServer;
|
||||
import net.minecraft.src.Entity;
|
||||
import net.minecraft.src.EntityPlayer;
|
||||
import net.minecraft.src.EntityPlayerMP;
|
||||
import net.minecraft.src.NBTBase;
|
||||
import net.minecraft.src.NBTTagCompound;
|
||||
import net.minecraft.src.NetHandler;
|
||||
import net.minecraft.src.Packet131MapData;
|
||||
import net.minecraft.src.SaveHandler;
|
||||
import net.minecraft.src.ServerListenThread;
|
||||
import net.minecraft.src.ThreadMinecraftServer;
|
||||
import net.minecraft.src.World;
|
||||
import net.minecraft.src.WorldInfo;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableList.Builder;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.MapMaker;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
import cpw.mods.fml.common.network.EntitySpawnAdjustmentPacket;
|
||||
import cpw.mods.fml.common.network.EntitySpawnPacket;
|
||||
import cpw.mods.fml.common.registry.EntityRegistry.EntityRegistration;
|
||||
import cpw.mods.fml.common.registry.TickRegistry;
|
||||
import cpw.mods.fml.server.FMLServerHandler;
|
||||
|
||||
|
||||
/**
|
||||
* The main class for non-obfuscated hook handling code
|
||||
*
|
||||
* Anything that doesn't require obfuscated or client/server specific code should
|
||||
* go in this handler
|
||||
*
|
||||
* It also contains a reference to the sided handler instance that is valid
|
||||
* allowing for common code to access specific properties from the obfuscated world
|
||||
* without a direct dependency
|
||||
*
|
||||
* @author cpw
|
||||
*
|
||||
*/
|
||||
public class FMLCommonHandler
|
||||
{
|
||||
/**
|
||||
* The singleton
|
||||
*/
|
||||
private static final FMLCommonHandler INSTANCE = new FMLCommonHandler();
|
||||
/**
|
||||
* The delegate for side specific data and functions
|
||||
*/
|
||||
private IFMLSidedHandler sidedDelegate;
|
||||
|
||||
private List<IScheduledTickHandler> scheduledClientTicks = Lists.newArrayList();
|
||||
private List<IScheduledTickHandler> scheduledServerTicks = Lists.newArrayList();
|
||||
private Class<?> forge;
|
||||
private boolean noForge;
|
||||
private List<String> brandings;
|
||||
private List<ICrashCallable> crashCallables = Lists.newArrayList(Loader.instance().getCallableCrashInformation());
|
||||
private Set<SaveHandler> handlerSet = Sets.newSetFromMap(new MapMaker().weakKeys().<SaveHandler,Boolean>makeMap());
|
||||
|
||||
|
||||
|
||||
public void beginLoading(IFMLSidedHandler handler)
|
||||
{
|
||||
sidedDelegate = handler;
|
||||
FMLLog.info("Attempting early MinecraftForge initialization");
|
||||
callForgeMethod("initialize");
|
||||
callForgeMethod("registerCrashCallable");
|
||||
FMLLog.info("Completed early MinecraftForge initialization");
|
||||
}
|
||||
|
||||
public void rescheduleTicks(Side side)
|
||||
{
|
||||
TickRegistry.updateTickQueue(side.isClient() ? scheduledClientTicks : scheduledServerTicks, side);
|
||||
}
|
||||
public void tickStart(EnumSet<TickType> ticks, Side side, Object ... data)
|
||||
{
|
||||
List<IScheduledTickHandler> scheduledTicks = side.isClient() ? scheduledClientTicks : scheduledServerTicks;
|
||||
|
||||
if (scheduledTicks.size()==0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (IScheduledTickHandler ticker : scheduledTicks)
|
||||
{
|
||||
EnumSet<TickType> ticksToRun = EnumSet.copyOf(Objects.firstNonNull(ticker.ticks(), EnumSet.noneOf(TickType.class)));
|
||||
ticksToRun.removeAll(EnumSet.complementOf(ticks));
|
||||
if (!ticksToRun.isEmpty())
|
||||
{
|
||||
ticker.tickStart(ticksToRun, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void tickEnd(EnumSet<TickType> ticks, Side side, Object ... data)
|
||||
{
|
||||
List<IScheduledTickHandler> scheduledTicks = side.isClient() ? scheduledClientTicks : scheduledServerTicks;
|
||||
|
||||
if (scheduledTicks.size()==0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (IScheduledTickHandler ticker : scheduledTicks)
|
||||
{
|
||||
EnumSet<TickType> ticksToRun = EnumSet.copyOf(Objects.firstNonNull(ticker.ticks(), EnumSet.noneOf(TickType.class)));
|
||||
ticksToRun.removeAll(EnumSet.complementOf(ticks));
|
||||
if (!ticksToRun.isEmpty())
|
||||
{
|
||||
ticker.tickEnd(ticksToRun, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the instance
|
||||
*/
|
||||
public static FMLCommonHandler instance()
|
||||
{
|
||||
return INSTANCE;
|
||||
}
|
||||
/**
|
||||
* Find the container that associates with the supplied mod object
|
||||
* @param mod
|
||||
*/
|
||||
public ModContainer findContainerFor(Object mod)
|
||||
{
|
||||
return Loader.instance().getReversedModObjectList().get(mod);
|
||||
}
|
||||
/**
|
||||
* Get the forge mod loader logging instance (goes to the forgemodloader log file)
|
||||
* @return
|
||||
*/
|
||||
public Logger getFMLLogger()
|
||||
{
|
||||
return FMLLog.getLogger();
|
||||
}
|
||||
|
||||
public Side getSide()
|
||||
{
|
||||
return sidedDelegate.getSide();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the effective side for the context in the game. This is dependent
|
||||
* on thread analysis to try and determine whether the code is running in the
|
||||
* server or not. Use at your own risk
|
||||
*/
|
||||
public Side getEffectiveSide()
|
||||
{
|
||||
Thread thr = Thread.currentThread();
|
||||
if ((thr instanceof ThreadMinecraftServer) || (thr instanceof ServerListenThread))
|
||||
{
|
||||
return Side.SERVER;
|
||||
}
|
||||
|
||||
return Side.CLIENT;
|
||||
}
|
||||
/**
|
||||
* Raise an exception
|
||||
*/
|
||||
public void raiseException(Throwable exception, String message, boolean stopGame)
|
||||
{
|
||||
FMLCommonHandler.instance().getFMLLogger().throwing("FMLHandler", "raiseException", exception);
|
||||
if (stopGame)
|
||||
{
|
||||
getSidedDelegate().haltGame(message,exception);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private Class<?> findMinecraftForge()
|
||||
{
|
||||
if (forge==null && !noForge)
|
||||
{
|
||||
try {
|
||||
forge = Class.forName("net.minecraftforge.common.MinecraftForge");
|
||||
} catch (Exception ex) {
|
||||
noForge = true;
|
||||
}
|
||||
}
|
||||
return forge;
|
||||
}
|
||||
|
||||
private Object callForgeMethod(String method)
|
||||
{
|
||||
if (noForge)
|
||||
return null;
|
||||
try
|
||||
{
|
||||
return findMinecraftForge().getMethod(method).invoke(null);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// No Forge installation
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void computeBranding()
|
||||
{
|
||||
if (brandings == null)
|
||||
{
|
||||
Builder brd = ImmutableList.<String>builder();
|
||||
brd.add(Loader.instance().getMCVersionString());
|
||||
brd.add("FML v"+Loader.instance().getFMLVersionString());
|
||||
String forgeBranding = (String) callForgeMethod("getBrandingVersion");
|
||||
if (!Strings.isNullOrEmpty(forgeBranding))
|
||||
{
|
||||
brd.add(forgeBranding);
|
||||
}
|
||||
brd.addAll(sidedDelegate.getAdditionalBrandingInformation());
|
||||
try {
|
||||
Properties props=new Properties();
|
||||
props.load(getClass().getClassLoader().getResourceAsStream("fmlbranding.properties"));
|
||||
brd.add(props.getProperty("fmlbranding"));
|
||||
} catch (Exception ex) {
|
||||
// Ignore - no branding file found
|
||||
}
|
||||
int tModCount = Loader.instance().getModList().size();
|
||||
int aModCount = Loader.instance().getActiveModList().size();
|
||||
brd.add(String.format("%d mod%s loaded, %d mod%s active", tModCount, tModCount!=1 ? "s" :"", aModCount, aModCount!=1 ? "s" :"" ));
|
||||
brandings = brd.build();
|
||||
}
|
||||
}
|
||||
public List<String> getBrandings()
|
||||
{
|
||||
if (brandings == null)
|
||||
{
|
||||
computeBranding();
|
||||
}
|
||||
return ImmutableList.copyOf(brandings);
|
||||
}
|
||||
|
||||
public IFMLSidedHandler getSidedDelegate()
|
||||
{
|
||||
return sidedDelegate;
|
||||
}
|
||||
|
||||
public void onPostServerTick()
|
||||
{
|
||||
tickEnd(EnumSet.of(TickType.SERVER), Side.SERVER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Every tick just after world and other ticks occur
|
||||
*/
|
||||
public void onPostWorldTick(Object world)
|
||||
{
|
||||
tickEnd(EnumSet.of(TickType.WORLD), Side.SERVER, world);
|
||||
}
|
||||
|
||||
public void onPreServerTick()
|
||||
{
|
||||
tickStart(EnumSet.of(TickType.SERVER), Side.SERVER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Every tick just before world and other ticks occur
|
||||
*/
|
||||
public void onPreWorldTick(Object world)
|
||||
{
|
||||
tickStart(EnumSet.of(TickType.WORLD), Side.SERVER, world);
|
||||
}
|
||||
|
||||
public void onWorldLoadTick(World[] worlds)
|
||||
{
|
||||
rescheduleTicks(Side.SERVER);
|
||||
for (World w : worlds)
|
||||
{
|
||||
tickStart(EnumSet.of(TickType.WORLDLOAD), Side.SERVER, w);
|
||||
}
|
||||
}
|
||||
|
||||
public void handleServerStarting(MinecraftServer server)
|
||||
{
|
||||
Loader.instance().serverStarting(server);
|
||||
}
|
||||
|
||||
public void handleServerStarted()
|
||||
{
|
||||
Loader.instance().serverStarted();
|
||||
}
|
||||
|
||||
public void handleServerStopping()
|
||||
{
|
||||
Loader.instance().serverStopping();
|
||||
}
|
||||
|
||||
public MinecraftServer getMinecraftServerInstance()
|
||||
{
|
||||
return sidedDelegate.getServer();
|
||||
}
|
||||
|
||||
public void showGuiScreen(Object clientGuiElement)
|
||||
{
|
||||
sidedDelegate.showGuiScreen(clientGuiElement);
|
||||
}
|
||||
|
||||
public Entity spawnEntityIntoClientWorld(EntityRegistration registration, EntitySpawnPacket entitySpawnPacket)
|
||||
{
|
||||
return sidedDelegate.spawnEntityIntoClientWorld(registration, entitySpawnPacket);
|
||||
}
|
||||
|
||||
public void adjustEntityLocationOnClient(EntitySpawnAdjustmentPacket entitySpawnAdjustmentPacket)
|
||||
{
|
||||
sidedDelegate.adjustEntityLocationOnClient(entitySpawnAdjustmentPacket);
|
||||
}
|
||||
|
||||
public void onServerStart(DedicatedServer dedicatedServer)
|
||||
{
|
||||
FMLServerHandler.instance();
|
||||
sidedDelegate.beginServerLoading(dedicatedServer);
|
||||
}
|
||||
|
||||
public void onServerStarted()
|
||||
{
|
||||
sidedDelegate.finishServerLoading();
|
||||
}
|
||||
|
||||
|
||||
public void onPreClientTick()
|
||||
{
|
||||
tickStart(EnumSet.of(TickType.CLIENT), Side.CLIENT);
|
||||
|
||||
}
|
||||
|
||||
public void onPostClientTick()
|
||||
{
|
||||
tickEnd(EnumSet.of(TickType.CLIENT), Side.CLIENT);
|
||||
}
|
||||
|
||||
public void onRenderTickStart(float timer)
|
||||
{
|
||||
tickStart(EnumSet.of(TickType.RENDER), Side.CLIENT, timer);
|
||||
}
|
||||
|
||||
public void onRenderTickEnd(float timer)
|
||||
{
|
||||
tickEnd(EnumSet.of(TickType.RENDER), Side.CLIENT, timer);
|
||||
}
|
||||
|
||||
public void onPlayerPreTick(EntityPlayer player)
|
||||
{
|
||||
Side side = player instanceof EntityPlayerMP ? Side.SERVER : Side.CLIENT;
|
||||
tickStart(EnumSet.of(TickType.PLAYER), side, player);
|
||||
}
|
||||
|
||||
public void onPlayerPostTick(EntityPlayer player)
|
||||
{
|
||||
Side side = player instanceof EntityPlayerMP ? Side.SERVER : Side.CLIENT;
|
||||
tickEnd(EnumSet.of(TickType.PLAYER), side, player);
|
||||
}
|
||||
|
||||
public void registerCrashCallable(ICrashCallable callable)
|
||||
{
|
||||
crashCallables.add(callable);
|
||||
}
|
||||
|
||||
public void enhanceCrashReport(CrashReport crashReport)
|
||||
{
|
||||
for (ICrashCallable call: crashCallables)
|
||||
{
|
||||
crashReport.func_71500_a(call.getLabel(), call);
|
||||
}
|
||||
}
|
||||
|
||||
public void handleTinyPacket(NetHandler handler, Packet131MapData mapData)
|
||||
{
|
||||
sidedDelegate.handleTinyPacket(handler, mapData);
|
||||
}
|
||||
|
||||
public void handleWorldDataSave(SaveHandler handler, WorldInfo worldInfo, NBTTagCompound tagCompound)
|
||||
{
|
||||
for (ModContainer mc : Loader.instance().getModList())
|
||||
{
|
||||
if (mc instanceof InjectedModContainer)
|
||||
{
|
||||
WorldAccessContainer wac = ((InjectedModContainer)mc).getWrappedWorldAccessContainer();
|
||||
if (wac != null)
|
||||
{
|
||||
NBTTagCompound dataForWriting = wac.getDataForWriting(handler, worldInfo);
|
||||
tagCompound.func_74766_a(mc.getModId(), dataForWriting);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void handleWorldDataLoad(SaveHandler handler, WorldInfo worldInfo, NBTTagCompound tagCompound)
|
||||
{
|
||||
if (getEffectiveSide()!=Side.SERVER)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (handlerSet.contains(handler))
|
||||
{
|
||||
return;
|
||||
}
|
||||
handlerSet.add(handler);
|
||||
Map<String,NBTBase> additionalProperties = Maps.newHashMap();
|
||||
worldInfo.setAdditionalProperties(additionalProperties);
|
||||
for (ModContainer mc : Loader.instance().getModList())
|
||||
{
|
||||
if (mc instanceof InjectedModContainer)
|
||||
{
|
||||
WorldAccessContainer wac = ((InjectedModContainer)mc).getWrappedWorldAccessContainer();
|
||||
if (wac != null)
|
||||
{
|
||||
wac.readData(handler, worldInfo, additionalProperties, tagCompound.func_74775_l(mc.getModId()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* The FML Forge Mod Loader suite.
|
||||
* Copyright (C) 2012 cpw
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package cpw.mods.fml.common;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
import net.minecraft.src.NBTBase;
|
||||
import net.minecraft.src.NBTTagCompound;
|
||||
import net.minecraft.src.NBTTagList;
|
||||
import net.minecraft.src.NBTTagString;
|
||||
import net.minecraft.src.SaveHandler;
|
||||
import net.minecraft.src.WorldInfo;
|
||||
|
||||
import com.google.common.collect.MapMaker;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.eventbus.EventBus;
|
||||
|
||||
/**
|
||||
* @author cpw
|
||||
*
|
||||
*/
|
||||
public class FMLDummyContainer extends DummyModContainer implements WorldAccessContainer
|
||||
{
|
||||
public FMLDummyContainer()
|
||||
{
|
||||
super(new ModMetadata());
|
||||
ModMetadata meta = getMetadata();
|
||||
meta.modId="FML";
|
||||
meta.name="Forge Mod Loader";
|
||||
meta.version=Loader.instance().getFMLVersionString();
|
||||
meta.credits="Made possible with help from many people";
|
||||
meta.authorList=Arrays.asList("cpw, LexManos");
|
||||
meta.description="The Forge Mod Loader provides the ability for systems to load mods " +
|
||||
"from the file system. It also provides key capabilities for mods to be able " +
|
||||
"to cooperate and provide a good modding environment. " +
|
||||
"The mod loading system is compatible with ModLoader, all your ModLoader " +
|
||||
"mods should work.";
|
||||
meta.url="https://github.com/cpw/FML/wiki";
|
||||
meta.updateUrl="https://github.com/cpw/FML/wiki";
|
||||
meta.screenshots=new String[0];
|
||||
meta.logoFile="";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean registerBus(EventBus bus, LoadController controller)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NBTTagCompound getDataForWriting(SaveHandler handler, WorldInfo info)
|
||||
{
|
||||
NBTTagCompound fmlData = new NBTTagCompound();
|
||||
NBTTagList list = new NBTTagList();
|
||||
for (ModContainer mc : Loader.instance().getActiveModList())
|
||||
{
|
||||
NBTTagCompound mod = new NBTTagCompound();
|
||||
mod.func_74778_a("ModId", mc.getModId());
|
||||
mod.func_74778_a("ModVersion", mc.getVersion());
|
||||
list.func_74742_a(mod);
|
||||
}
|
||||
fmlData.func_74782_a("ModList", list);
|
||||
return fmlData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readData(SaveHandler handler, WorldInfo info, Map<String, NBTBase> propertyMap, NBTTagCompound tag)
|
||||
{
|
||||
if (tag.func_74764_b("ModList"))
|
||||
{
|
||||
NBTTagList modList = tag.func_74761_m("ModList");
|
||||
for (int i = 0; i < modList.func_74745_c(); i++)
|
||||
{
|
||||
NBTTagCompound mod = (NBTTagCompound) modList.func_74743_b(i);
|
||||
String modId = mod.func_74779_i("ModId");
|
||||
String modVersion = mod.func_74779_i("ModVersion");
|
||||
ModContainer container = Loader.instance().getIndexedModList().get(modId);
|
||||
if (container == null)
|
||||
{
|
||||
FMLLog.severe("This world was saved with mod %s which appears to be missing, things may not work well", modId);
|
||||
continue;
|
||||
}
|
||||
if (!modVersion.equals(container.getVersion()))
|
||||
{
|
||||
FMLLog.info("This world was saved with mod %s version %s and it is now at version %s, things may not work well", modId, modVersion, container.getVersion());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package cpw.mods.fml.common;
|
||||
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class FMLLog
|
||||
{
|
||||
private static cpw.mods.fml.relauncher.FMLRelaunchLog coreLog = cpw.mods.fml.relauncher.FMLRelaunchLog.log;
|
||||
|
||||
public static void log(Level level, String format, Object... data)
|
||||
{
|
||||
coreLog.log(level, format, data);
|
||||
}
|
||||
|
||||
public static void log(Level level, Throwable ex, String format, Object... data)
|
||||
{
|
||||
coreLog.log(level, ex, format, data);
|
||||
}
|
||||
|
||||
public static void severe(String format, Object... data)
|
||||
{
|
||||
log(Level.SEVERE, format, data);
|
||||
}
|
||||
|
||||
public static void warning(String format, Object... data)
|
||||
{
|
||||
log(Level.WARNING, format, data);
|
||||
}
|
||||
|
||||
public static void info(String format, Object... data)
|
||||
{
|
||||
log(Level.INFO, format, data);
|
||||
}
|
||||
|
||||
public static void fine(String format, Object... data)
|
||||
{
|
||||
log(Level.FINE, format, data);
|
||||
}
|
||||
|
||||
public static void finer(String format, Object... data)
|
||||
{
|
||||
log(Level.FINER, format, data);
|
||||
}
|
||||
|
||||
public static void finest(String format, Object... data)
|
||||
{
|
||||
log(Level.FINEST, format, data);
|
||||
}
|
||||
public static Logger getLogger()
|
||||
{
|
||||
return coreLog.getLogger();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,479 @@
|
||||
/*
|
||||
* The FML Forge Mod Loader suite. Copyright (C) 2012 cpw
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package cpw.mods.fml.common;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
import com.google.common.collect.BiMap;
|
||||
import com.google.common.collect.ImmutableBiMap;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.collect.SetMultimap;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.eventbus.EventBus;
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
|
||||
import cpw.mods.fml.common.Mod.Instance;
|
||||
import cpw.mods.fml.common.Mod.Metadata;
|
||||
import cpw.mods.fml.common.discovery.ASMDataTable;
|
||||
import cpw.mods.fml.common.discovery.ASMDataTable.ASMData;
|
||||
import cpw.mods.fml.common.event.FMLConstructionEvent;
|
||||
import cpw.mods.fml.common.event.FMLInitializationEvent;
|
||||
import cpw.mods.fml.common.event.FMLPostInitializationEvent;
|
||||
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
|
||||
import cpw.mods.fml.common.event.FMLServerStartedEvent;
|
||||
import cpw.mods.fml.common.event.FMLServerStartingEvent;
|
||||
import cpw.mods.fml.common.event.FMLServerStoppingEvent;
|
||||
import cpw.mods.fml.common.event.FMLStateEvent;
|
||||
import cpw.mods.fml.common.network.FMLNetworkHandler;
|
||||
import cpw.mods.fml.common.versioning.ArtifactVersion;
|
||||
import cpw.mods.fml.common.versioning.DefaultArtifactVersion;
|
||||
import cpw.mods.fml.common.versioning.VersionParser;
|
||||
import cpw.mods.fml.common.versioning.VersionRange;
|
||||
|
||||
public class FMLModContainer implements ModContainer
|
||||
{
|
||||
private Mod modDescriptor;
|
||||
private Object modInstance;
|
||||
private File source;
|
||||
private ModMetadata modMetadata;
|
||||
private String className;
|
||||
private Map<String, Object> descriptor;
|
||||
private boolean enabled = true;
|
||||
private String internalVersion;
|
||||
private boolean overridesMetadata;
|
||||
private EventBus eventBus;
|
||||
private LoadController controller;
|
||||
private Multimap<Class<? extends Annotation>, Object> annotations;
|
||||
private DefaultArtifactVersion processedVersion;
|
||||
private boolean isNetworkMod;
|
||||
|
||||
private static final BiMap<Class<? extends FMLStateEvent>, Class<? extends Annotation>> modAnnotationTypes = ImmutableBiMap.<Class<? extends FMLStateEvent>, Class<? extends Annotation>>builder()
|
||||
.put(FMLPreInitializationEvent.class, Mod.PreInit.class)
|
||||
.put(FMLInitializationEvent.class, Mod.Init.class)
|
||||
.put(FMLPostInitializationEvent.class, Mod.PostInit.class)
|
||||
.put(FMLServerStartingEvent.class, Mod.ServerStarting.class)
|
||||
.put(FMLServerStartedEvent.class, Mod.ServerStarted.class)
|
||||
.put(FMLServerStoppingEvent.class, Mod.ServerStopping.class)
|
||||
.build();
|
||||
private static final BiMap<Class<? extends Annotation>, Class<? extends FMLStateEvent>> modTypeAnnotations = modAnnotationTypes.inverse();
|
||||
private String annotationDependencies;
|
||||
private VersionRange minecraftAccepted;
|
||||
|
||||
|
||||
public FMLModContainer(String className, File modSource, Map<String,Object> modDescriptor)
|
||||
{
|
||||
this.className = className;
|
||||
this.source = modSource;
|
||||
this.descriptor = modDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getModId()
|
||||
{
|
||||
return (String) descriptor.get("modid");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName()
|
||||
{
|
||||
return modMetadata.name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion()
|
||||
{
|
||||
return internalVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getSource()
|
||||
{
|
||||
return source;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModMetadata getMetadata()
|
||||
{
|
||||
return modMetadata;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindMetadata(MetadataCollection mc)
|
||||
{
|
||||
modMetadata = mc.getMetadataForId(getModId(), descriptor);
|
||||
|
||||
if (descriptor.containsKey("useMetadata"))
|
||||
{
|
||||
overridesMetadata = !((Boolean)descriptor.get("useMetadata")).booleanValue();
|
||||
}
|
||||
|
||||
if (overridesMetadata || !modMetadata.useDependencyInformation)
|
||||
{
|
||||
Set<ArtifactVersion> requirements = Sets.newHashSet();
|
||||
List<ArtifactVersion> dependencies = Lists.newArrayList();
|
||||
List<ArtifactVersion> dependants = Lists.newArrayList();
|
||||
annotationDependencies = (String) descriptor.get("dependencies");
|
||||
Loader.instance().computeDependencies(annotationDependencies, requirements, dependencies, dependants);
|
||||
modMetadata.requiredMods = requirements;
|
||||
modMetadata.dependencies = dependencies;
|
||||
modMetadata.dependants = dependants;
|
||||
FMLLog.finest("Parsed dependency info : %s %s %s", requirements, dependencies, dependants);
|
||||
}
|
||||
else
|
||||
{
|
||||
FMLLog.finest("Using mcmod dependency info : %s %s %s", modMetadata.requiredMods, modMetadata.dependencies, modMetadata.dependants);
|
||||
}
|
||||
if (Strings.isNullOrEmpty(modMetadata.name))
|
||||
{
|
||||
FMLLog.info("Mod %s is missing the required element 'name'. Substituting %s", getModId(), getModId());
|
||||
modMetadata.name = getModId();
|
||||
}
|
||||
internalVersion = (String) descriptor.get("version");
|
||||
if (Strings.isNullOrEmpty(internalVersion))
|
||||
{
|
||||
Properties versionProps = searchForVersionProperties();
|
||||
if (versionProps != null)
|
||||
{
|
||||
internalVersion = versionProps.getProperty(getModId()+".version");
|
||||
FMLLog.fine("Found version %s for mod %s in version.properties, using", internalVersion, getModId());
|
||||
}
|
||||
|
||||
}
|
||||
if (Strings.isNullOrEmpty(internalVersion) && !Strings.isNullOrEmpty(modMetadata.version))
|
||||
{
|
||||
FMLLog.warning("Mod %s is missing the required element 'version' and a version.properties file could not be found. Falling back to metadata version %s", getModId(), modMetadata.version);
|
||||
internalVersion = modMetadata.version;
|
||||
}
|
||||
if (Strings.isNullOrEmpty(internalVersion))
|
||||
{
|
||||
FMLLog.warning("Mod %s is missing the required element 'version' and no fallback can be found. Substituting '1.0'.", getModId());
|
||||
modMetadata.version = internalVersion = "1.0";
|
||||
}
|
||||
|
||||
String mcVersionString = (String) descriptor.get("acceptedMinecraftVersions");
|
||||
if (!Strings.isNullOrEmpty(mcVersionString))
|
||||
{
|
||||
minecraftAccepted = VersionParser.parseRange(mcVersionString);
|
||||
}
|
||||
else
|
||||
{
|
||||
minecraftAccepted = Loader.instance().getMinecraftModContainer().getStaticVersionRange();
|
||||
}
|
||||
}
|
||||
|
||||
public Properties searchForVersionProperties()
|
||||
{
|
||||
try
|
||||
{
|
||||
FMLLog.fine("Attempting to load the file version.properties from %s to locate a version number for %s", getSource().getName(), getModId());
|
||||
Properties version = null;
|
||||
if (getSource().isFile())
|
||||
{
|
||||
ZipFile source = new ZipFile(getSource());
|
||||
ZipEntry versionFile = source.getEntry("version.properties");
|
||||
if (versionFile!=null)
|
||||
{
|
||||
version = new Properties();
|
||||
version.load(source.getInputStream(versionFile));
|
||||
}
|
||||
source.close();
|
||||
}
|
||||
else if (getSource().isDirectory())
|
||||
{
|
||||
File propsFile = new File(getSource(),"version.properties");
|
||||
if (propsFile.exists() && propsFile.isFile())
|
||||
{
|
||||
version = new Properties();
|
||||
FileInputStream fis = new FileInputStream(propsFile);
|
||||
version.load(fis);
|
||||
fis.close();
|
||||
}
|
||||
}
|
||||
return version;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Throwables.propagateIfPossible(e);
|
||||
FMLLog.fine("Failed to find a usable version.properties file");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnabledState(boolean enabled)
|
||||
{
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<ArtifactVersion> getRequirements()
|
||||
{
|
||||
return modMetadata.requiredMods;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ArtifactVersion> getDependencies()
|
||||
{
|
||||
return modMetadata.dependencies;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ArtifactVersion> getDependants()
|
||||
{
|
||||
return modMetadata.dependants;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSortingRules()
|
||||
{
|
||||
return ((overridesMetadata || !modMetadata.useDependencyInformation) ? Strings.nullToEmpty(annotationDependencies) : modMetadata.printableSortingRules());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Object mod)
|
||||
{
|
||||
return mod == modInstance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getMod()
|
||||
{
|
||||
return modInstance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean registerBus(EventBus bus, LoadController controller)
|
||||
{
|
||||
if (this.enabled)
|
||||
{
|
||||
FMLLog.fine("Enabling mod %s", getModId());
|
||||
this.eventBus = bus;
|
||||
this.controller = controller;
|
||||
eventBus.register(this);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private Multimap<Class<? extends Annotation>, Object> gatherAnnotations(Class<?> clazz) throws Exception
|
||||
{
|
||||
Multimap<Class<? extends Annotation>,Object> anns = ArrayListMultimap.create();
|
||||
|
||||
for (Method m : clazz.getDeclaredMethods())
|
||||
{
|
||||
for (Annotation a : m.getAnnotations())
|
||||
{
|
||||
if (modTypeAnnotations.containsKey(a.annotationType()))
|
||||
{
|
||||
Class<?>[] paramTypes = new Class[] { modTypeAnnotations.get(a.annotationType()) };
|
||||
|
||||
if (Arrays.equals(m.getParameterTypes(), paramTypes))
|
||||
{
|
||||
m.setAccessible(true);
|
||||
anns.put(a.annotationType(), m);
|
||||
}
|
||||
else
|
||||
{
|
||||
FMLLog.severe("The mod %s appears to have an invalid method annotation %s. This annotation can only apply to methods with argument types %s -it will not be called", getModId(), a.annotationType().getSimpleName(), Arrays.toString(paramTypes));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return anns;
|
||||
}
|
||||
|
||||
private void processFieldAnnotations(ASMDataTable asmDataTable) throws Exception
|
||||
{
|
||||
SetMultimap<String, ASMData> annotations = asmDataTable.getAnnotationsFor(this);
|
||||
|
||||
parseSimpleFieldAnnotation(annotations, Instance.class.getName(), new Function<ModContainer, Object>()
|
||||
{
|
||||
public Object apply(ModContainer mc)
|
||||
{
|
||||
return mc.getMod();
|
||||
}
|
||||
});
|
||||
parseSimpleFieldAnnotation(annotations, Metadata.class.getName(), new Function<ModContainer, Object>()
|
||||
{
|
||||
public Object apply(ModContainer mc)
|
||||
{
|
||||
return mc.getMetadata();
|
||||
}
|
||||
});
|
||||
|
||||
//TODO
|
||||
// for (Object o : annotations.get(Block.class))
|
||||
// {
|
||||
// Field f = (Field) o;
|
||||
// f.set(modInstance, GameRegistry.buildBlock(this, f.getType(), f.getAnnotation(Block.class)));
|
||||
// }
|
||||
}
|
||||
|
||||
private void parseSimpleFieldAnnotation(SetMultimap<String, ASMData> annotations, String annotationClassName, Function<ModContainer, Object> retreiver) throws IllegalAccessException
|
||||
{
|
||||
String[] annName = annotationClassName.split("\\.");
|
||||
String annotationName = annName[annName.length - 1];
|
||||
for (ASMData targets : annotations.get(annotationClassName))
|
||||
{
|
||||
String targetMod = (String) targets.getAnnotationInfo().get("value");
|
||||
Field f = null;
|
||||
Object injectedMod = null;
|
||||
ModContainer mc = this;
|
||||
boolean isStatic = false;
|
||||
Class<?> clz = modInstance.getClass();
|
||||
if (!Strings.isNullOrEmpty(targetMod))
|
||||
{
|
||||
if (Loader.isModLoaded(targetMod))
|
||||
{
|
||||
mc = Loader.instance().getIndexedModList().get(targetMod);
|
||||
}
|
||||
else
|
||||
{
|
||||
mc = null;
|
||||
}
|
||||
}
|
||||
if (mc != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
clz = Class.forName(targets.getClassName(), true, Loader.instance().getModClassLoader());
|
||||
f = clz.getDeclaredField(targets.getObjectName());
|
||||
f.setAccessible(true);
|
||||
isStatic = Modifier.isStatic(f.getModifiers());
|
||||
injectedMod = retreiver.apply(mc);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Throwables.propagateIfPossible(e);
|
||||
FMLLog.log(Level.WARNING, e, "Attempting to load @%s in class %s for %s and failing", annotationName, targets.getClassName(), mc.getModId());
|
||||
}
|
||||
}
|
||||
if (f != null)
|
||||
{
|
||||
Object target = null;
|
||||
if (!isStatic)
|
||||
{
|
||||
target = modInstance;
|
||||
if (!modInstance.getClass().equals(clz))
|
||||
{
|
||||
FMLLog.warning("Unable to inject @%s in non-static field %s.%s for %s as it is NOT the primary mod instance", annotationName, targets.getClassName(), targets.getObjectName(), mc.getModId());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
f.set(target, injectedMod);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void constructMod(FMLConstructionEvent event)
|
||||
{
|
||||
try
|
||||
{
|
||||
ModClassLoader modClassLoader = event.getModClassLoader();
|
||||
modClassLoader.addFile(source);
|
||||
Class<?> clazz = Class.forName(className, true, modClassLoader);
|
||||
ASMDataTable asmHarvestedAnnotations = event.getASMHarvestedData();
|
||||
// TODO
|
||||
asmHarvestedAnnotations.getAnnotationsFor(this);
|
||||
annotations = gatherAnnotations(clazz);
|
||||
isNetworkMod = FMLNetworkHandler.instance().registerNetworkMod(this, clazz, event.getASMHarvestedData());
|
||||
modInstance = clazz.newInstance();
|
||||
ProxyInjector.inject(this, event.getASMHarvestedData(), FMLCommonHandler.instance().getSide());
|
||||
processFieldAnnotations(event.getASMHarvestedData());
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
controller.errorOccurred(this, e);
|
||||
Throwables.propagateIfPossible(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void handleModStateEvent(FMLStateEvent event)
|
||||
{
|
||||
Class<? extends Annotation> annotation = modAnnotationTypes.get(event.getClass());
|
||||
if (annotation == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
for (Object o : annotations.get(annotation))
|
||||
{
|
||||
Method m = (Method) o;
|
||||
m.invoke(modInstance, event);
|
||||
}
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
controller.errorOccurred(this, t);
|
||||
Throwables.propagateIfPossible(t);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArtifactVersion getProcessedVersion()
|
||||
{
|
||||
if (processedVersion == null)
|
||||
{
|
||||
processedVersion = new DefaultArtifactVersion(getModId(), getVersion());
|
||||
}
|
||||
return processedVersion;
|
||||
}
|
||||
@Override
|
||||
public boolean isImmutable()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNetworkMod()
|
||||
{
|
||||
return isNetworkMod;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayVersion()
|
||||
{
|
||||
return modMetadata.version;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VersionRange acceptableMinecraftVersionRange()
|
||||
{
|
||||
return minecraftAccepted;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* The FML Forge Mod Loader suite.
|
||||
* Copyright (C) 2012 cpw
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package cpw.mods.fml.common;
|
||||
|
||||
/**
|
||||
* @author cpw
|
||||
*
|
||||
*/
|
||||
public interface IConsoleHandler
|
||||
{
|
||||
public boolean handleCommand(String command, Object... data);
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* The FML Forge Mod Loader suite.
|
||||
* Copyright (C) 2012 cpw
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package cpw.mods.fml.common;
|
||||
|
||||
import net.minecraft.src.EntityPlayer;
|
||||
import net.minecraft.src.IInventory;
|
||||
import net.minecraft.src.ItemStack;
|
||||
|
||||
/**
|
||||
* Return a crafting handler for the mod container to call
|
||||
*
|
||||
* @author cpw
|
||||
*
|
||||
*/
|
||||
public interface ICraftingHandler
|
||||
{
|
||||
/**
|
||||
* The object array contains these three arguments
|
||||
*
|
||||
* @param player
|
||||
* @param item
|
||||
* @param craftMatrix
|
||||
*/
|
||||
void onCrafting(EntityPlayer player, ItemStack item, IInventory craftMatrix);
|
||||
|
||||
/**
|
||||
* The object array contains these two arguments
|
||||
* @param player
|
||||
* @param item
|
||||
*/
|
||||
void onSmelting(EntityPlayer player, ItemStack item);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package cpw.mods.fml.common;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
public interface ICrashCallable extends Callable<String>
|
||||
{
|
||||
String getLabel();
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* The FML Forge Mod Loader suite. Copyright (C) 2012 cpw
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package cpw.mods.fml.common;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import net.minecraft.src.ItemStack;
|
||||
import net.minecraft.src.World;
|
||||
|
||||
|
||||
public interface IDispenseHandler
|
||||
{
|
||||
/**
|
||||
* Return -1 if you don't want to dispense anything. the other values seem to have specific meanings
|
||||
* to blockdispenser.
|
||||
*
|
||||
* @param x
|
||||
* @param y
|
||||
* @param z
|
||||
* @param xVelocity
|
||||
* @param zVelocity
|
||||
* @param world
|
||||
* @param item
|
||||
* @param random
|
||||
* @param entX
|
||||
* @param entY
|
||||
* @param entZ
|
||||
*/
|
||||
@Deprecated
|
||||
int dispense(double x, double y, double z, int xVelocity, int zVelocity, World world, ItemStack item, Random random, double entX, double entY, double entZ);
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package cpw.mods.fml.common;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import net.minecraft.src.ItemStack;
|
||||
import net.minecraft.src.World;
|
||||
|
||||
/**
|
||||
* @author cpw
|
||||
*
|
||||
*/
|
||||
public interface IDispenserHandler
|
||||
{
|
||||
/**
|
||||
* Called to dispense an entity
|
||||
* @param x
|
||||
* @param y
|
||||
* @param z
|
||||
* @param xVelocity
|
||||
* @param zVelocity
|
||||
* @param world
|
||||
* @param item
|
||||
* @param random
|
||||
* @param entX
|
||||
* @param entY
|
||||
* @param entZ
|
||||
*/
|
||||
int dispense(int x, int y, int z, int xVelocity, int zVelocity, World world, ItemStack item, Random random, double entX, double entY, double entZ);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package cpw.mods.fml.common;
|
||||
|
||||
public interface IFMLHandledException
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package cpw.mods.fml.common;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.src.Entity;
|
||||
import net.minecraft.src.NetHandler;
|
||||
import net.minecraft.src.Packet;
|
||||
import net.minecraft.src.Packet131MapData;
|
||||
import cpw.mods.fml.common.network.EntitySpawnAdjustmentPacket;
|
||||
import cpw.mods.fml.common.network.EntitySpawnPacket;
|
||||
import cpw.mods.fml.common.network.ModMissingPacket;
|
||||
import cpw.mods.fml.common.registry.EntityRegistry.EntityRegistration;
|
||||
|
||||
public interface IFMLSidedHandler
|
||||
{
|
||||
List<String> getAdditionalBrandingInformation();
|
||||
|
||||
Side getSide();
|
||||
|
||||
void haltGame(String message, Throwable exception);
|
||||
|
||||
void showGuiScreen(Object clientGuiElement);
|
||||
|
||||
Entity spawnEntityIntoClientWorld(EntityRegistration registration, EntitySpawnPacket packet);
|
||||
|
||||
void adjustEntityLocationOnClient(EntitySpawnAdjustmentPacket entitySpawnAdjustmentPacket);
|
||||
|
||||
void beginServerLoading(MinecraftServer server);
|
||||
|
||||
void finishServerLoading();
|
||||
|
||||
MinecraftServer getServer();
|
||||
|
||||
void sendPacket(Packet packet);
|
||||
|
||||
void displayMissingMods(ModMissingPacket modMissingPacket);
|
||||
|
||||
void handleTinyPacket(NetHandler handler, Packet131MapData mapData);
|
||||
|
||||
void setClientCompatibilityLevel(byte compatibilityLevel);
|
||||
|
||||
byte getClientCompatibilityLevel();
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package cpw.mods.fml.common;
|
||||
|
||||
import net.minecraft.src.ItemStack;
|
||||
|
||||
public interface IFuelHandler
|
||||
{
|
||||
int getBurnTime(ItemStack fuel);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* The FML Forge Mod Loader suite. Copyright (C) 2012 cpw
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package cpw.mods.fml.common;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @author cpw
|
||||
*
|
||||
*/
|
||||
public interface INetworkHandler
|
||||
{
|
||||
boolean onChat(Object... data);
|
||||
void onPacket250Packet(Object... data);
|
||||
void onServerLogin(Object handler);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* The FML Forge Mod Loader suite.
|
||||
* Copyright (C) 2012 cpw
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package cpw.mods.fml.common;
|
||||
|
||||
import net.minecraft.src.EntityItem;
|
||||
import net.minecraft.src.EntityPlayer;
|
||||
|
||||
public interface IPickupNotifier
|
||||
{
|
||||
void notifyPickup(EntityItem item, EntityPlayer player);
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* The FML Forge Mod Loader suite.
|
||||
* Copyright (C) 2012 cpw
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package cpw.mods.fml.common;
|
||||
|
||||
import net.minecraft.src.EntityPlayer;
|
||||
|
||||
/**
|
||||
* @author cpw
|
||||
*
|
||||
*/
|
||||
public interface IPlayerTracker
|
||||
{
|
||||
void onPlayerLogin(EntityPlayer player);
|
||||
|
||||
void onPlayerLogout(EntityPlayer player);
|
||||
|
||||
void onPlayerChangedDimension(EntityPlayer player);
|
||||
|
||||
void onPlayerRespawn(EntityPlayer player);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package cpw.mods.fml.common;
|
||||
|
||||
public interface IScheduledTickHandler extends ITickHandler
|
||||
{
|
||||
/**
|
||||
* Return the number of actual ticks that will pass
|
||||
* before your next tick will fire. This will be called
|
||||
* just after your last tick fired to compute the next delay.
|
||||
* @return Time until next tick
|
||||
*/
|
||||
public int nextTickSpacing();
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* The FML Forge Mod Loader suite.
|
||||
* Copyright (C) 2012 cpw
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package cpw.mods.fml.common;
|
||||
|
||||
import java.util.EnumSet;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Tick handler for mods to implement and register through the TickRegistry
|
||||
*
|
||||
* The data available to each tick is documented in the TickType
|
||||
*
|
||||
* @author cpw
|
||||
*
|
||||
*/
|
||||
public interface ITickHandler
|
||||
{
|
||||
|
||||
/**
|
||||
* Called at the "start" phase of a tick
|
||||
*
|
||||
* Multiple ticks may fire simultaneously- you will only be called once with all the firing ticks
|
||||
*
|
||||
* @param type
|
||||
* @param tickData
|
||||
*/
|
||||
public void tickStart(EnumSet<TickType> type, Object... tickData);
|
||||
|
||||
/**
|
||||
* Called at the "end" phase of a tick
|
||||
*
|
||||
* Multiple ticks may fire simultaneously- you will only be called once with all the firing ticks
|
||||
*
|
||||
* @param type
|
||||
* @param tickData
|
||||
*/
|
||||
public void tickEnd(EnumSet<TickType> type, Object... tickData);
|
||||
|
||||
/**
|
||||
* Returns the list of ticks this tick handler is interested in receiving at the minute
|
||||
*/
|
||||
public EnumSet<TickType> ticks();
|
||||
|
||||
/**
|
||||
* A profiling label for this tick handler
|
||||
*/
|
||||
public String getLabel();
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* The FML Forge Mod Loader suite.
|
||||
* Copyright (C) 2012 cpw
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package cpw.mods.fml.common;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import net.minecraft.src.IChunkProvider;
|
||||
import net.minecraft.src.World;
|
||||
|
||||
/**
|
||||
* This is called back during world generation.
|
||||
*
|
||||
* @author cpw
|
||||
*
|
||||
*/
|
||||
public interface IWorldGenerator
|
||||
{
|
||||
/**
|
||||
* Generate some world
|
||||
*
|
||||
* @param random the chunk specific {@link Random}.
|
||||
* @param chunkX the chunk X coordinate of this chunk.
|
||||
* @param chunkZ the chunk Z coordinate of this chunk.
|
||||
* @param world : additionalData[0] The minecraft {@link World} we're generating for.
|
||||
* @param chunkGenerator : additionalData[1] The {@link IChunkProvider} that is generating.
|
||||
* @param chunkProvider : additionalData[2] {@link IChunkProvider} that is requesting the world generation.
|
||||
*
|
||||
*/
|
||||
public void generate(Random random, int chunkX, int chunkZ, World world, IChunkProvider chunkGenerator, IChunkProvider chunkProvider);
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
package cpw.mods.fml.common;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.common.eventbus.EventBus;
|
||||
|
||||
import cpw.mods.fml.common.versioning.ArtifactVersion;
|
||||
import cpw.mods.fml.common.versioning.VersionRange;
|
||||
|
||||
public class InjectedModContainer implements ModContainer
|
||||
{
|
||||
private File source;
|
||||
private ModContainer wrappedContainer;
|
||||
|
||||
public InjectedModContainer(ModContainer mc, File source)
|
||||
{
|
||||
this.source = source;
|
||||
this.wrappedContainer = mc;
|
||||
}
|
||||
|
||||
public String getModId()
|
||||
{
|
||||
return wrappedContainer.getModId();
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return wrappedContainer.getName();
|
||||
}
|
||||
|
||||
public String getVersion()
|
||||
{
|
||||
return wrappedContainer.getVersion();
|
||||
}
|
||||
|
||||
public File getSource()
|
||||
{
|
||||
return source;
|
||||
}
|
||||
|
||||
public ModMetadata getMetadata()
|
||||
{
|
||||
return wrappedContainer.getMetadata();
|
||||
}
|
||||
|
||||
public void bindMetadata(MetadataCollection mc)
|
||||
{
|
||||
wrappedContainer.bindMetadata(mc);
|
||||
}
|
||||
|
||||
public void setEnabledState(boolean enabled)
|
||||
{
|
||||
wrappedContainer.setEnabledState(enabled);
|
||||
}
|
||||
|
||||
public Set<ArtifactVersion> getRequirements()
|
||||
{
|
||||
return wrappedContainer.getRequirements();
|
||||
}
|
||||
|
||||
public List<ArtifactVersion> getDependencies()
|
||||
{
|
||||
return wrappedContainer.getDependencies();
|
||||
}
|
||||
|
||||
public List<ArtifactVersion> getDependants()
|
||||
{
|
||||
return wrappedContainer.getDependants();
|
||||
}
|
||||
|
||||
public String getSortingRules()
|
||||
{
|
||||
return wrappedContainer.getSortingRules();
|
||||
}
|
||||
|
||||
public boolean registerBus(EventBus bus, LoadController controller)
|
||||
{
|
||||
return wrappedContainer.registerBus(bus, controller);
|
||||
}
|
||||
|
||||
public boolean matches(Object mod)
|
||||
{
|
||||
return wrappedContainer.matches(mod);
|
||||
}
|
||||
|
||||
public Object getMod()
|
||||
{
|
||||
return wrappedContainer.getMod();
|
||||
}
|
||||
|
||||
public ArtifactVersion getProcessedVersion()
|
||||
{
|
||||
return wrappedContainer.getProcessedVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNetworkMod()
|
||||
{
|
||||
return wrappedContainer.isNetworkMod();
|
||||
}
|
||||
@Override
|
||||
public boolean isImmutable()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayVersion()
|
||||
{
|
||||
return wrappedContainer.getDisplayVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public VersionRange acceptableMinecraftVersionRange()
|
||||
{
|
||||
return wrappedContainer.acceptableMinecraftVersionRange();
|
||||
}
|
||||
|
||||
public WorldAccessContainer getWrappedWorldAccessContainer()
|
||||
{
|
||||
if (wrappedContainer instanceof WorldAccessContainer)
|
||||
{
|
||||
return (WorldAccessContainer) wrappedContainer;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,232 @@
|
||||
package cpw.mods.fml.common;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
import com.google.common.collect.BiMap;
|
||||
import com.google.common.collect.ImmutableBiMap;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableMap.Builder;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.eventbus.EventBus;
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
|
||||
import cpw.mods.fml.common.LoaderState.ModState;
|
||||
import cpw.mods.fml.common.event.FMLLoadEvent;
|
||||
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
|
||||
import cpw.mods.fml.common.event.FMLStateEvent;
|
||||
|
||||
public class LoadController
|
||||
{
|
||||
private Loader loader;
|
||||
private EventBus masterChannel;
|
||||
private ImmutableMap<String,EventBus> eventChannels;
|
||||
private LoaderState state;
|
||||
private Multimap<String, ModState> modStates = ArrayListMultimap.create();
|
||||
private Multimap<String, Throwable> errors = ArrayListMultimap.create();
|
||||
private Map<String, ModContainer> modList;
|
||||
private List<ModContainer> activeModList = Lists.newArrayList();
|
||||
private ModContainer activeContainer;
|
||||
private BiMap<ModContainer, Object> modObjectList;
|
||||
|
||||
public LoadController(Loader loader)
|
||||
{
|
||||
this.loader = loader;
|
||||
this.masterChannel = new EventBus("FMLMainChannel");
|
||||
this.masterChannel.register(this);
|
||||
|
||||
state = LoaderState.NOINIT;
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void buildModList(FMLLoadEvent event)
|
||||
{
|
||||
this.modList = loader.getIndexedModList();
|
||||
Builder<String, EventBus> eventBus = ImmutableMap.builder();
|
||||
|
||||
for (ModContainer mod : loader.getModList())
|
||||
{
|
||||
EventBus bus = new EventBus(mod.getModId());
|
||||
boolean isActive = mod.registerBus(bus, this);
|
||||
if (isActive)
|
||||
{
|
||||
FMLLog.fine("Activating mod %s", mod.getModId());
|
||||
activeModList.add(mod);
|
||||
modStates.put(mod.getModId(), ModState.UNLOADED);
|
||||
eventBus.put(mod.getModId(), bus);
|
||||
}
|
||||
else
|
||||
{
|
||||
FMLLog.warning("Mod %s has been disabled through configuration", mod.getModId());
|
||||
modStates.put(mod.getModId(), ModState.UNLOADED);
|
||||
modStates.put(mod.getModId(), ModState.DISABLED);
|
||||
}
|
||||
}
|
||||
|
||||
eventChannels = eventBus.build();
|
||||
}
|
||||
|
||||
public void distributeStateMessage(LoaderState state, Object... eventData)
|
||||
{
|
||||
if (state.hasEvent())
|
||||
{
|
||||
masterChannel.post(state.getEvent(eventData));
|
||||
}
|
||||
}
|
||||
|
||||
public void transition(LoaderState desiredState)
|
||||
{
|
||||
LoaderState oldState = state;
|
||||
state = state.transition(!errors.isEmpty());
|
||||
if (state != desiredState)
|
||||
{
|
||||
Throwable toThrow = null;
|
||||
FMLLog.severe("Fatal errors were detected during the transition from %s to %s. Loading cannot continue", oldState, desiredState);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
printModStates(sb);
|
||||
FMLLog.severe(sb.toString());
|
||||
FMLLog.severe("The following problems were captured during this phase");
|
||||
for (Entry<String, Throwable> error : errors.entries())
|
||||
{
|
||||
FMLLog.log(Level.SEVERE, error.getValue(), "Caught exception from %s", error.getKey());
|
||||
if (error.getValue() instanceof IFMLHandledException)
|
||||
{
|
||||
toThrow = error.getValue();
|
||||
}
|
||||
else if (toThrow == null)
|
||||
{
|
||||
toThrow = error.getValue();
|
||||
}
|
||||
}
|
||||
if (toThrow != null && toThrow instanceof RuntimeException)
|
||||
{
|
||||
throw (RuntimeException)toThrow;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new LoaderException(toThrow);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ModContainer activeContainer()
|
||||
{
|
||||
return activeContainer;
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void propogateStateMessage(FMLStateEvent stateEvent)
|
||||
{
|
||||
if (stateEvent instanceof FMLPreInitializationEvent)
|
||||
{
|
||||
modObjectList = buildModObjectList();
|
||||
}
|
||||
for (ModContainer mc : activeModList)
|
||||
{
|
||||
activeContainer = mc;
|
||||
String modId = mc.getModId();
|
||||
stateEvent.applyModContainer(activeContainer());
|
||||
FMLLog.finer("Posting state event %s to mod %s", stateEvent.getEventType(), modId);
|
||||
eventChannels.get(modId).post(stateEvent);
|
||||
FMLLog.finer("State event %s delivered to mod %s", stateEvent.getEventType(), modId);
|
||||
activeContainer = null;
|
||||
if (!errors.containsKey(modId))
|
||||
{
|
||||
modStates.put(modId, stateEvent.getModState());
|
||||
}
|
||||
else
|
||||
{
|
||||
modStates.put(modId, ModState.ERRORED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ImmutableBiMap<ModContainer, Object> buildModObjectList()
|
||||
{
|
||||
ImmutableBiMap.Builder<ModContainer, Object> builder = ImmutableBiMap.<ModContainer, Object>builder();
|
||||
for (ModContainer mc : activeModList)
|
||||
{
|
||||
if (!mc.isImmutable() && mc.getMod()!=null)
|
||||
{
|
||||
builder.put(mc, mc.getMod());
|
||||
}
|
||||
if (mc.getMod()==null && !mc.isImmutable() && state!=LoaderState.CONSTRUCTING)
|
||||
{
|
||||
FMLLog.severe("There is a severe problem with %s - it appears not to have constructed correctly", mc.getModId());
|
||||
if (state != LoaderState.CONSTRUCTING)
|
||||
{
|
||||
this.errorOccurred(mc, new RuntimeException());
|
||||
}
|
||||
}
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
public void errorOccurred(ModContainer modContainer, Throwable exception)
|
||||
{
|
||||
if (exception instanceof InvocationTargetException)
|
||||
{
|
||||
errors.put(modContainer.getModId(), ((InvocationTargetException)exception).getCause());
|
||||
}
|
||||
else
|
||||
{
|
||||
errors.put(modContainer.getModId(), exception);
|
||||
}
|
||||
}
|
||||
|
||||
public void printModStates(StringBuilder ret)
|
||||
{
|
||||
for (ModContainer mc : loader.getModList())
|
||||
{
|
||||
ret.append("\n\t").append(mc.getModId()).append(" [").append(mc.getName()).append("] (").append(mc.getSource().getName()).append(") ");
|
||||
Joiner.on("->"). appendTo(ret, modStates.get(mc.getModId()));
|
||||
}
|
||||
}
|
||||
|
||||
public List<ModContainer> getActiveModList()
|
||||
{
|
||||
return activeModList;
|
||||
}
|
||||
|
||||
public ModState getModState(ModContainer selectedMod)
|
||||
{
|
||||
return Iterables.getLast(modStates.get(selectedMod.getModId()), ModState.AVAILABLE);
|
||||
}
|
||||
|
||||
public void distributeStateMessage(Class<?> customEvent)
|
||||
{
|
||||
try
|
||||
{
|
||||
masterChannel.post(customEvent.newInstance());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
FMLLog.log(Level.SEVERE, e, "An unexpected exception");
|
||||
throw new LoaderException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public BiMap<ModContainer, Object> getModObjectList()
|
||||
{
|
||||
if (modObjectList == null)
|
||||
{
|
||||
FMLLog.severe("Detected an attempt by a mod %s to perform game activity during mod construction. This is a serious programming error.", activeContainer);
|
||||
return buildModObjectList();
|
||||
}
|
||||
return ImmutableBiMap.copyOf(modObjectList);
|
||||
}
|
||||
|
||||
public boolean isInState(LoaderState state)
|
||||
{
|
||||
return this.state == state;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,723 @@
|
||||
/*
|
||||
* The FML Forge Mod Loader suite.
|
||||
* Copyright (C) 2012 cpw
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
|
||||
* Software Foundation; either version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package cpw.mods.fml.common;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import net.minecraft.src.CallableMinecraftVersion;
|
||||
|
||||
import com.google.common.base.CharMatcher;
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.collect.BiMap;
|
||||
import com.google.common.collect.HashBiMap;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableMultiset;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.collect.Multiset.Entry;
|
||||
import com.google.common.collect.Multisets;
|
||||
import com.google.common.collect.Ordering;
|
||||
import com.google.common.collect.Sets.SetView;
|
||||
import com.google.common.collect.TreeMultimap;
|
||||
|
||||
import cpw.mods.fml.common.LoaderState.ModState;
|
||||
import cpw.mods.fml.common.discovery.ModDiscoverer;
|
||||
import cpw.mods.fml.common.event.FMLLoadEvent;
|
||||
import cpw.mods.fml.common.functions.ModIdFunction;
|
||||
import cpw.mods.fml.common.modloader.BaseModProxy;
|
||||
import cpw.mods.fml.common.toposort.ModSorter;
|
||||
import cpw.mods.fml.common.toposort.ModSortingException;
|
||||
import cpw.mods.fml.common.toposort.TopologicalSort;
|
||||
import cpw.mods.fml.common.versioning.ArtifactVersion;
|
||||
import cpw.mods.fml.common.versioning.VersionParser;
|
||||
|
||||
/**
|
||||
* The loader class performs the actual loading of the mod code from disk.
|
||||
*
|
||||
* <p>
|
||||
* There are several {@link LoaderState}s to mod loading, triggered in two
|
||||
* different stages from the FML handler code's hooks into the minecraft code.
|
||||
* </p>
|
||||
*
|
||||
* <ol>
|
||||
* <li>LOADING. Scanning the filesystem for mod containers to load (zips, jars,
|
||||
* directories), adding them to the {@link #modClassLoader} Scanning, the loaded
|
||||
* containers for mod classes to load and registering them appropriately.</li>
|
||||
* <li>PREINIT. The mod classes are configured, they are sorted into a load
|
||||
* order, and instances of the mods are constructed.</li>
|
||||
* <li>INIT. The mod instances are initialized. For BaseMod mods, this involves
|
||||
* calling the load method.</li>
|
||||
* <li>POSTINIT. The mod instances are post initialized. For BaseMod mods this
|
||||
* involves calling the modsLoaded method.</li>
|
||||
* <li>UP. The Loader is complete</li>
|
||||
* <li>ERRORED. The loader encountered an error during the LOADING phase and
|
||||
* dropped to this state instead. It will not complete loading from this state,
|
||||
* but it attempts to continue loading before abandoning and giving a fatal
|
||||
* error.</li>
|
||||
* </ol>
|
||||
*
|
||||
* Phase 1 code triggers the LOADING and PREINIT states. Phase 2 code triggers
|
||||
* the INIT and POSTINIT states.
|
||||
*
|
||||
* @author cpw
|
||||
*
|
||||
*/
|
||||
public class Loader
|
||||
{
|
||||
private static final Splitter DEPENDENCYPARTSPLITTER = Splitter.on(":").omitEmptyStrings().trimResults();
|
||||
private static final Splitter DEPENDENCYSPLITTER = Splitter.on(";").omitEmptyStrings().trimResults();
|
||||
/**
|
||||
* The singleton instance
|
||||
*/
|
||||
private static Loader instance;
|
||||
/**
|
||||
* Build information for tracking purposes.
|
||||
*/
|
||||
private static String major;
|
||||
private static String minor;
|
||||
private static String rev;
|
||||
private static String build;
|
||||
private static String mccversion;
|
||||
private static String mcsversion;
|
||||
|
||||
/**
|
||||
* The class loader we load the mods into.
|
||||
*/
|
||||
private ModClassLoader modClassLoader;
|
||||
/**
|
||||
* The sorted list of mods.
|
||||
*/
|
||||
private List<ModContainer> mods;
|
||||
/**
|
||||
* A named list of mods
|
||||
*/
|
||||
private Map<String, ModContainer> namedMods;
|
||||
/**
|
||||
* The canonical configuration directory
|
||||
*/
|
||||
private File canonicalConfigDir;
|
||||
/**
|
||||
* The canonical minecraft directory
|
||||
*/
|
||||
private File canonicalMinecraftDir;
|
||||
/**
|
||||
* The captured error
|
||||
*/
|
||||
private Exception capturedError;
|
||||
private File canonicalModsDir;
|
||||
private LoadController modController;
|
||||
private MinecraftDummyContainer minecraft;
|
||||
|
||||
private static File minecraftDir;
|
||||
private static List<String> injectedContainers;
|
||||
|
||||
public static Loader instance()
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = new Loader();
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
public static void injectData(Object... data)
|
||||
{
|
||||
major = (String) data[0];
|
||||
minor = (String) data[1];
|
||||
rev = (String) data[2];
|
||||
build = (String) data[3];
|
||||
mccversion = (String) data[4];
|
||||
mcsversion = (String) data[5];
|
||||
minecraftDir = (File) data[6];
|
||||
injectedContainers = (List<String>)data[7];
|
||||
}
|
||||
|
||||
private Loader()
|
||||
{
|
||||
modClassLoader = new ModClassLoader(getClass().getClassLoader());
|
||||
String actualMCVersion = new CallableMinecraftVersion(null).func_71493_a();
|
||||
if (!mccversion.equals(actualMCVersion))
|
||||
{
|
||||
FMLLog.severe("This version of FML is built for Minecraft %s, we have detected Minecraft %s in your minecraft jar file", mccversion, actualMCVersion);
|
||||
throw new LoaderException();
|
||||
}
|
||||
|
||||
minecraft = new MinecraftDummyContainer(actualMCVersion);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort the mods into a sorted list, using dependency information from the
|
||||
* containers. The sorting is performed using a {@link TopologicalSort}
|
||||
* based on the pre- and post- dependency information provided by the mods.
|
||||
*/
|
||||
private void sortModList()
|
||||
{
|
||||
FMLLog.fine("Verifying mod requirements are satisfied");
|
||||
try
|
||||
{
|
||||
BiMap<String, ArtifactVersion> modVersions = HashBiMap.create();
|
||||
for (ModContainer mod : getActiveModList())
|
||||
{
|
||||
modVersions.put(mod.getModId(), mod.getProcessedVersion());
|
||||
}
|
||||
|
||||
for (ModContainer mod : getActiveModList())
|
||||
{
|
||||
if (!mod.acceptableMinecraftVersionRange().containsVersion(minecraft.getProcessedVersion()))
|
||||
{
|
||||
FMLLog.severe("The mod %s does not wish to run in Minecraft version %s. You will have to remove it to play.", mod.getModId(), getMCVersionString());
|
||||
throw new WrongMinecraftVersionException(mod);
|
||||
}
|
||||
Map<String,ArtifactVersion> names = Maps.uniqueIndex(mod.getRequirements(), new Function<ArtifactVersion, String>()
|
||||
{
|
||||
public String apply(ArtifactVersion v)
|
||||
{
|
||||
return v.getLabel();
|
||||
}
|
||||
});
|
||||
Set<ArtifactVersion> versionMissingMods = Sets.newHashSet();
|
||||
Set<String> missingMods = Sets.difference(names.keySet(), modVersions.keySet());
|
||||
if (!missingMods.isEmpty())
|
||||
{
|
||||
FMLLog.severe("The mod %s (%s) requires mods %s to be available", mod.getModId(), mod.getName(), missingMods);
|
||||
for (String modid : missingMods)
|
||||
{
|
||||
versionMissingMods.add(names.get(modid));
|
||||
}
|
||||
throw new MissingModsException(versionMissingMods);
|
||||
}
|
||||
ImmutableList<ArtifactVersion> allDeps = ImmutableList.<ArtifactVersion>builder().addAll(mod.getDependants()).addAll(mod.getDependencies()).build();
|
||||
for (ArtifactVersion v : allDeps)
|
||||
{
|
||||
if (modVersions.containsKey(v.getLabel()))
|
||||
{
|
||||
if (!v.containsVersion(modVersions.get(v.getLabel())))
|
||||
{
|
||||
versionMissingMods.add(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!versionMissingMods.isEmpty())
|
||||
{
|
||||
FMLLog.severe("The mod %s (%s) requires mod versions %s to be available", mod.getModId(), mod.getName(), versionMissingMods);
|
||||
throw new MissingModsException(versionMissingMods);
|
||||
}
|
||||
}
|
||||
|
||||
FMLLog.fine("All mod requirements are satisfied");
|
||||
|
||||
ModSorter sorter = new ModSorter(getActiveModList(), namedMods);
|
||||
|
||||
try
|
||||
{
|
||||
FMLLog.fine("Sorting mods into an ordered list");
|
||||
List<ModContainer> sortedMods = sorter.sort();
|
||||
// Reset active list to the sorted list
|
||||
modController.getActiveModList().clear();
|
||||
modController.getActiveModList().addAll(sortedMods);
|
||||
// And inject the sorted list into the overall list
|
||||
mods.removeAll(sortedMods);
|
||||
sortedMods.addAll(mods);
|
||||
mods = sortedMods;
|
||||
FMLLog.fine("Mod sorting completed successfully");
|
||||
}
|
||||
catch (ModSortingException sortException)
|
||||
{
|
||||
FMLLog.severe("A dependency cycle was detected in the input mod set so an ordering cannot be determined");
|
||||
FMLLog.severe("The visited mod list is %s", sortException.getExceptionData().getVisitedNodes());
|
||||
FMLLog.severe("The first mod in the cycle is %s", sortException.getExceptionData().getFirstBadNode());
|
||||
FMLLog.log(Level.SEVERE, sortException, "The full error");
|
||||
throw new LoaderException(sortException);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
FMLLog.fine("Mod sorting data:");
|
||||
for (ModContainer mod : getActiveModList())
|
||||
{
|
||||
if (!mod.isImmutable())
|
||||
{
|
||||
FMLLog.fine("\t%s(%s:%s): %s (%s)", mod.getModId(), mod.getName(), mod.getVersion(), mod.getSource().getName(), mod.getSortingRules());
|
||||
}
|
||||
}
|
||||
if (mods.size()==0)
|
||||
{
|
||||
FMLLog.fine("No mods found to sort");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The primary loading code
|
||||
*
|
||||
* This is visited during first initialization by Minecraft to scan and load
|
||||
* the mods from all sources 1. The minecraft jar itself (for loading of in
|
||||
* jar mods- I would like to remove this if possible but forge depends on it
|
||||
* at present) 2. The mods directory with expanded subdirs, searching for
|
||||
* mods named mod_*.class 3. The mods directory for zip and jar files,
|
||||
* searching for mod classes named mod_*.class again
|
||||
*
|
||||
* The found resources are first loaded into the {@link #modClassLoader}
|
||||
* (always) then scanned for class resources matching the specification
|
||||
* above.
|
||||
*
|
||||
* If they provide the {@link Mod} annotation, they will be loaded as
|
||||
* "FML mods", which currently is effectively a NO-OP. If they are
|
||||
* determined to be {@link BaseModProxy} subclasses they are loaded as such.
|
||||
*
|
||||
* Finally, if they are successfully loaded as classes, they are then added
|
||||
* to the available mod list.
|
||||
*/
|
||||
private ModDiscoverer identifyMods()
|
||||
{
|
||||
FMLLog.fine("Building injected Mod Containers %s", injectedContainers);
|
||||
File coremod = new File(minecraftDir,"coremods");
|
||||
for (String cont : injectedContainers)
|
||||
{
|
||||
ModContainer mc;
|
||||
try
|
||||
{
|
||||
mc = (ModContainer) Class.forName(cont,true,modClassLoader).newInstance();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
FMLLog.log(Level.SEVERE, e, "A problem occured instantiating the injected mod container %s", cont);
|
||||
throw new LoaderException(e);
|
||||
}
|
||||
mods.add(new InjectedModContainer(mc,coremod));
|
||||
}
|
||||
ModDiscoverer discoverer = new ModDiscoverer();
|
||||
FMLLog.fine("Attempting to load mods contained in the minecraft jar file and associated classes");
|
||||
discoverer.findClasspathMods(modClassLoader);
|
||||
FMLLog.fine("Minecraft jar mods loaded successfully");
|
||||
|
||||
FMLLog.info("Searching %s for mods", canonicalModsDir.getAbsolutePath());
|
||||
discoverer.findModDirMods(canonicalModsDir);
|
||||
|
||||
mods.addAll(discoverer.identifyMods());
|
||||
identifyDuplicates(mods);
|
||||
namedMods = Maps.uniqueIndex(mods, new ModIdFunction());
|
||||
FMLLog.info("Forge Mod Loader has identified %d mod%s to load", mods.size(), mods.size() != 1 ? "s" : "");
|
||||
return discoverer;
|
||||
}
|
||||
|
||||
private class ModIdComparator implements Comparator<ModContainer>
|
||||
{
|
||||
@Override
|
||||
public int compare(ModContainer o1, ModContainer o2)
|
||||
{
|
||||
return o1.getModId().compareTo(o2.getModId());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void identifyDuplicates(List<ModContainer> mods)
|
||||
{
|
||||
boolean foundDupe = false;
|
||||
TreeMultimap<ModContainer, File> dupsearch = TreeMultimap.create(new ModIdComparator(), Ordering.arbitrary());
|
||||
for (ModContainer mc : mods)
|
||||
{
|
||||
if (mc.getSource() != null)
|
||||
{
|
||||
dupsearch.put(mc, mc.getSource());
|
||||
}
|
||||
}
|
||||
|
||||
ImmutableMultiset<ModContainer> duplist = Multisets.copyHighestCountFirst(dupsearch.keys());
|
||||
for (Entry<ModContainer> e : duplist.entrySet())
|
||||
{
|
||||
if (e.getCount() > 1)
|
||||
{
|
||||
FMLLog.severe("Found a duplicate mod %s at %s", e.getElement().getModId(), dupsearch.get(e.getElement()));
|
||||
foundDupe = true;
|
||||
}
|
||||
}
|
||||
if (foundDupe) { throw new LoaderException(); }
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
private void initializeLoader()
|
||||
{
|
||||
File modsDir = new File(minecraftDir, "mods");
|
||||
File configDir = new File(minecraftDir, "config");
|
||||
String canonicalModsPath;
|
||||
String canonicalConfigPath;
|
||||
|
||||
try
|
||||
{
|
||||
canonicalMinecraftDir = minecraftDir.getCanonicalFile();
|
||||
canonicalModsPath = modsDir.getCanonicalPath();
|
||||
canonicalConfigPath = configDir.getCanonicalPath();
|
||||
canonicalConfigDir = configDir.getCanonicalFile();
|
||||
canonicalModsDir = modsDir.getCanonicalFile();
|
||||
}
|
||||
catch (IOException ioe)
|
||||
{
|
||||
FMLLog.log(Level.SEVERE, ioe, "Failed to resolve loader directories: mods : %s ; config %s", canonicalModsDir.getAbsolutePath(),
|
||||
configDir.getAbsolutePath());
|
||||
throw new LoaderException(ioe);
|
||||
}
|
||||
|
||||
if (!canonicalModsDir.exists())
|
||||
{
|
||||
FMLLog.info("No mod directory found, creating one: %s", canonicalModsPath);
|
||||
boolean dirMade = canonicalModsDir.mkdir();
|
||||
if (!dirMade)
|
||||
{
|
||||
FMLLog.severe("Unable to create the mod directory %s", canonicalModsPath);
|
||||
throw new LoaderException();
|
||||
}
|
||||
FMLLog.info("Mod directory created successfully");
|
||||
}
|
||||
|
||||
if (!canonicalConfigDir.exists())
|
||||
{
|
||||
FMLLog.fine("No config directory found, creating one: %s", canonicalConfigPath);
|
||||
boolean dirMade = canonicalConfigDir.mkdir();
|
||||
if (!dirMade)
|
||||
{
|
||||
FMLLog.severe("Unable to create the config directory %s", canonicalConfigPath);
|
||||
throw new LoaderException();
|
||||
}
|
||||
FMLLog.info("Config directory created successfully");
|
||||
}
|
||||
|
||||
if (!canonicalModsDir.isDirectory())
|
||||
{
|
||||
FMLLog.severe("Attempting to load mods from %s, which is not a directory", canonicalModsPath);
|
||||
throw new LoaderException();
|
||||
}
|
||||
|
||||
if (!configDir.isDirectory())
|
||||
{
|
||||
FMLLog.severe("Attempting to load configuration from %s, which is not a directory", canonicalConfigPath);
|
||||
throw new LoaderException();
|
||||
}
|
||||
}
|
||||
|
||||
public List<ModContainer> getModList()
|
||||
{
|
||||
return instance().mods != null ? ImmutableList.copyOf(instance().mods) : ImmutableList.<ModContainer>of();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called from the hook to start mod loading. We trigger the
|
||||
* {@link #identifyMods()} and Constructing, Preinitalization, and Initalization phases here. Finally,
|
||||
* the mod list is frozen completely and is consider immutable from then on.
|
||||
*/
|
||||
public void loadMods()
|
||||
{
|
||||
initializeLoader();
|
||||
mods = Lists.newArrayList();
|
||||
namedMods = Maps.newHashMap();
|
||||
modController = new LoadController(this);
|
||||
modController.transition(LoaderState.LOADING);
|
||||
ModDiscoverer disc = identifyMods();
|
||||
disableRequestedMods();
|
||||
modController.distributeStateMessage(FMLLoadEvent.class);
|
||||
sortModList();
|
||||
mods = ImmutableList.copyOf(mods);
|
||||
for (File nonMod : disc.getNonModLibs())
|
||||
{
|
||||
if (nonMod.isFile())
|
||||
{
|
||||
FMLLog.severe("FML has found a non-mod file %s in your mods directory. It will now be injected into your classpath. This could severe stability issues, it should be removed if possible.", nonMod.getName());
|
||||
try
|
||||
{
|
||||
modClassLoader.addFile(nonMod);
|
||||
}
|
||||
catch (MalformedURLException e)
|
||||
{
|
||||
FMLLog.log(Level.SEVERE, e, "Encountered a weird problem with non-mod file injection : %s", nonMod.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
modController.transition(LoaderState.CONSTRUCTING);
|
||||
modController.distributeStateMessage(LoaderState.CONSTRUCTING, modClassLoader, disc.getASMTable());
|
||||
modController.transition(LoaderState.PREINITIALIZATION);
|
||||
modController.distributeStateMessage(LoaderState.PREINITIALIZATION, disc.getASMTable(), canonicalConfigDir);
|
||||
modController.transition(LoaderState.INITIALIZATION);
|
||||
}
|
||||
|
||||
private void disableRequestedMods()
|
||||
{
|
||||
String forcedModList = System.getProperty("fml.modStates", "");
|
||||
FMLLog.fine("Received a system property request \'%s\'",forcedModList);
|
||||
Map<String, String> sysPropertyStateList = Splitter.on(CharMatcher.anyOf(";:"))
|
||||
.omitEmptyStrings().trimResults().withKeyValueSeparator("=")
|
||||
.split(forcedModList);
|
||||
FMLLog.fine("System property request managing the state of %d mods", sysPropertyStateList.size());
|
||||
Map<String, String> modStates = Maps.newHashMap();
|
||||
|
||||
File forcedModFile = new File(canonicalConfigDir, "fmlModState.properties");
|
||||
Properties forcedModListProperties = new Properties();
|
||||
if (forcedModFile.exists() && forcedModFile.isFile())
|
||||
{
|
||||
FMLLog.fine("Found a mod state file %s", forcedModFile.getName());
|
||||
try
|
||||
{
|
||||
forcedModListProperties.load(new FileReader(forcedModFile));
|
||||
FMLLog.fine("Loaded states for %d mods from file", forcedModListProperties.size());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
FMLLog.log(Level.INFO, e, "An error occurred reading the fmlModState.properties file");
|
||||
}
|
||||
}
|
||||
modStates.putAll(Maps.fromProperties(forcedModListProperties));
|
||||
modStates.putAll(sysPropertyStateList);
|
||||
FMLLog.fine("After merging, found state information for %d mods", modStates.size());
|
||||
|
||||
Map<String, Boolean> isEnabled = Maps.transformValues(modStates, new Function<String, Boolean>()
|
||||
{
|
||||
public Boolean apply(String input)
|
||||
{
|
||||
return Boolean.parseBoolean(input);
|
||||
}
|
||||
});
|
||||
|
||||
for (Map.Entry<String, Boolean> entry : isEnabled.entrySet())
|
||||
{
|
||||
if (namedMods.containsKey(entry.getKey()))
|
||||
{
|
||||
FMLLog.info("Setting mod %s to enabled state %b", entry.getKey(), entry.getValue());
|
||||
namedMods.get(entry.getKey()).setEnabledState(entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Query if we know of a mod named modname
|
||||
*
|
||||
* @param modname
|
||||
* @return If the mod is loaded
|
||||
*/
|
||||
public static boolean isModLoaded(String modname)
|
||||
{
|
||||
return instance().namedMods.containsKey(modname) && instance().modController.getModState(instance.namedMods.get(modname))!=ModState.DISABLED;
|
||||
}
|
||||
|
||||
public File getConfigDir()
|
||||
{
|
||||
return canonicalConfigDir;
|
||||
}
|
||||
|
||||
public String getCrashInformation()
|
||||
{
|
||||
StringBuilder ret = new StringBuilder();
|
||||
List<String> branding = FMLCommonHandler.instance().getBrandings();
|
||||
|
||||
Joiner.on(' ').skipNulls().appendTo(ret, branding.subList(1, branding.size()));
|
||||
if (modController!=null)
|
||||
{
|
||||
modController.printModStates(ret);
|
||||
}
|
||||
return ret.toString();
|
||||
}
|
||||
|
||||
public String getFMLVersionString()
|
||||
{
|
||||
return String.format("%s.%s.%s.%s", major, minor, rev, build);
|
||||
}
|
||||
|
||||
public ClassLoader getModClassLoader()
|
||||
{
|
||||
return modClassLoader;
|
||||
}
|
||||
|
||||
public void computeDependencies(String dependencyString, Set<ArtifactVersion> requirements, List<ArtifactVersion> dependencies, List<ArtifactVersion> dependants)
|
||||
{
|
||||
if (dependencyString == null || dependencyString.length() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
boolean parseFailure=false;
|
||||
|
||||
for (String dep : DEPENDENCYSPLITTER.split(dependencyString))
|
||||
{
|
||||
List<String> depparts = Lists.newArrayList(DEPENDENCYPARTSPLITTER.split(dep));
|
||||
// Need two parts to the string
|
||||
if (depparts.size() != 2)
|
||||
{
|
||||
parseFailure=true;
|
||||
continue;
|
||||
}
|
||||
String instruction = depparts.get(0);
|
||||
String target = depparts.get(1);
|
||||
boolean targetIsAll = target.startsWith("*");
|
||||
|
||||
// Cannot have an "all" relationship with anything except pure *
|
||||
if (targetIsAll && target.length()>1)
|
||||
{
|
||||
parseFailure = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
// If this is a required element, add it to the required list
|
||||
if ("required-before".equals(instruction) || "required-after".equals(instruction))
|
||||
{
|
||||
// You can't require everything
|
||||
if (!targetIsAll)
|
||||
{
|
||||
requirements.add(VersionParser.parseVersionReference(target));
|
||||
}
|
||||
else
|
||||
{
|
||||
parseFailure=true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// You cannot have a versioned dependency on everything
|
||||
if (targetIsAll && target.indexOf('@')>-1)
|
||||
{
|
||||
parseFailure = true;
|
||||
continue;
|
||||
}
|
||||
// before elements are things we are loaded before (so they are our dependants)
|
||||
if ("required-before".equals(instruction) || "before".equals(instruction))
|
||||
{
|
||||
dependants.add(VersionParser.parseVersionReference(target));
|
||||
}
|
||||
// after elements are things that load before we do (so they are out dependencies)
|
||||
else if ("required-after".equals(instruction) || "after".equals(instruction))
|
||||
{
|
||||
dependencies.add(VersionParser.parseVersionReference(target));
|
||||
}
|
||||
else
|
||||
{
|
||||
parseFailure=true;
|
||||
}
|
||||
}
|
||||
|
||||
if (parseFailure)
|
||||
{
|
||||
FMLLog.log(Level.WARNING, "Unable to parse dependency string %s", dependencyString);
|
||||
throw new LoaderException();
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String,ModContainer> getIndexedModList()
|
||||
{
|
||||
return ImmutableMap.copyOf(namedMods);
|
||||
}
|
||||
|
||||
public void initializeMods()
|
||||
{
|
||||
// Mod controller should be in the initialization state here
|
||||
modController.distributeStateMessage(LoaderState.INITIALIZATION);
|
||||
modController.transition(LoaderState.POSTINITIALIZATION);
|
||||
modController.distributeStateMessage(LoaderState.POSTINITIALIZATION);
|
||||
modController.transition(LoaderState.AVAILABLE);
|
||||
modController.distributeStateMessage(LoaderState.AVAILABLE);
|
||||
FMLLog.info("Forge Mod Loader has successfully loaded %d mod%s", mods.size(), mods.size()==1 ? "" : "s");
|
||||
}
|
||||
|
||||
public ICrashCallable getCallableCrashInformation()
|
||||
{
|
||||
return new ICrashCallable() {
|
||||
@Override
|
||||
public String call() throws Exception
|
||||
{
|
||||
return getCrashInformation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLabel()
|
||||
{
|
||||
return "FML";
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public List<ModContainer> getActiveModList()
|
||||
{
|
||||
return modController != null ? modController.getActiveModList() : ImmutableList.<ModContainer>of();
|
||||
}
|
||||
|
||||
public ModState getModState(ModContainer selectedMod)
|
||||
{
|
||||
return modController.getModState(selectedMod);
|
||||
}
|
||||
|
||||
public String getMCVersionString()
|
||||
{
|
||||
return "Minecraft " + mccversion;
|
||||
}
|
||||
|
||||
public void serverStarting(Object server)
|
||||
{
|
||||
modController.distributeStateMessage(LoaderState.SERVER_STARTING, server);
|
||||
modController.transition(LoaderState.SERVER_STARTING);
|
||||
}
|
||||
|
||||
public void serverStarted()
|
||||
{
|
||||
modController.distributeStateMessage(LoaderState.SERVER_STARTED);
|
||||
modController.transition(LoaderState.SERVER_STARTED);
|
||||
}
|
||||
|
||||
public void serverStopping()
|
||||
{
|
||||
modController.distributeStateMessage(LoaderState.SERVER_STOPPING);
|
||||
modController.transition(LoaderState.SERVER_STOPPING);
|
||||
modController.transition(LoaderState.AVAILABLE);
|
||||
|
||||
}
|
||||
|
||||
public BiMap<ModContainer, Object> getModObjectList()
|
||||
{
|
||||
return modController.getModObjectList();
|
||||
}
|
||||
|
||||
public BiMap<Object, ModContainer> getReversedModObjectList()
|
||||
{
|
||||
return getModObjectList().inverse();
|
||||
}
|
||||
|
||||
public ModContainer activeModContainer()
|
||||
{
|
||||
return modController.activeContainer();
|
||||
}
|
||||
|
||||
public boolean isInState(LoaderState state)
|
||||
{
|
||||
return modController.isInState(state);
|
||||
}
|
||||
|
||||
public MinecraftDummyContainer getMinecraftModContainer()
|
||||
{
|
||||
return minecraft;
|
||||
}
|
||||
}
|
||||
Loaded 100 of 2601 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user