mirror of
https://github.com/MinecraftForge/MinecraftForge.git
synced 2026-11-14 17:14:44 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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
+1
-14
@@ -1,14 +1 @@
|
||||
* text eol=lf
|
||||
*.bat text eol=crlf
|
||||
*.patch text eol=lf
|
||||
*.java text eol=lf
|
||||
*.gradle text eol=crlf
|
||||
*.png binary
|
||||
*.exe binary
|
||||
*.dll binary
|
||||
*.jar binary
|
||||
*.lzma binary
|
||||
*.zip binary
|
||||
*.pyd binary
|
||||
*.cfg text eol=lf
|
||||
*.py text eol=lf
|
||||
* text=auto
|
||||
+11
-22
@@ -1,23 +1,12 @@
|
||||
#eclipse
|
||||
/bin
|
||||
/.settings
|
||||
/.classpath
|
||||
|
||||
#idea
|
||||
/.idea
|
||||
*.iml
|
||||
|
||||
#gradle
|
||||
/build
|
||||
/.gradle
|
||||
|
||||
#occupational hazards
|
||||
/eclipse/
|
||||
/repo/
|
||||
/buildSrc
|
||||
|
||||
#Patch rejects
|
||||
*.rej
|
||||
/patches-/
|
||||
# FML changelog
|
||||
changelog.txt
|
||||
/minecraft_server
|
||||
/mods
|
||||
/fmlbuild.properties
|
||||
/fmlversion.properties
|
||||
/difflist.txt
|
||||
/.metadata/
|
||||
/eclipse/.metadata/
|
||||
/target
|
||||
fmlbranding.properties
|
||||
/fernflower.zip
|
||||
/commands.py.bck
|
||||
@@ -1,10 +0,0 @@
|
||||
Contributing to Forge
|
||||
=====================
|
||||
|
||||
1) Keep patches to Minecraft classes minimal. If you need a lot of things done, you may either add to relevant forge classes or make a new class.
|
||||
|
||||
2) An example mod must be provided for all PRs adding events/hooks to Forge. Whether it's a full mod using your proposed hooks, or just a pastebin containing a simple example, an example mod is required. Please also explain in detail what your new hook does.
|
||||
|
||||
3) Follow Forge coding guidelines (braces on newlines, spaces instead of tabs, etc)
|
||||
|
||||
For more information, refer to [the wiki](https://github.com/MinecraftForge/MinecraftForge/wiki/If-you-want-to-contribute-to-Forge)
|
||||
@@ -1,7 +1,7 @@
|
||||
This minecraft mod, Forge Mod Loader, including all parts herein except as noted below,
|
||||
is licensed under the GNU LGPL v2.1 or later.
|
||||
This minecraft mod, Forge Mod Loader, including all parts herein, is licensed
|
||||
under the GNU LGPL v2.1 or later.
|
||||
|
||||
Homepage: https://github.com/MinecraftForge/FML
|
||||
Homepage: https://github.com/cpw/FML
|
||||
|
||||
This software includes portions from the Apache Maven project at
|
||||
http://maven.apache.org/ specifically the ComparableVersion.java code. It is
|
||||
@@ -9,30 +9,6 @@ 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.
|
||||
|
||||
|
||||
=== 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 (common/cpw/mods/fml/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 (common/cpw/mods/fml/common/asm/ and subdirectories)
|
||||
under any alternative open source license as classified by the OSI (http://opensource.org/licenses)
|
||||
|
||||
========
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
@@ -1,26 +0,0 @@
|
||||
* Eloraam *
|
||||
|
||||
* FlowerChild *
|
||||
|
||||
* Hawkye *
|
||||
|
||||
* MALfunction84 *
|
||||
|
||||
Submitted the sleep handler code for his mod (Somnia) and others to use.
|
||||
|
||||
* Scokeev9 *
|
||||
|
||||
Gave permission for ScotTools API to be integrated into MCF, and also supported the Forge by converting his mods to use it.
|
||||
|
||||
ScotTools Background: ScotTools was an API that enabled modders to add blocks to harvesting levels (and many other ease-of-use features to create new tools), and the first tool API that used block material for block breaking efficiency which allowed blocks from mods that didn't use ScotTools API to break with the correct speed.
|
||||
|
||||
* SpaceToad *
|
||||
|
||||
* LexManos *
|
||||
|
||||
* cpw *
|
||||
|
||||
* 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.
|
||||
@@ -1,70 +0,0 @@
|
||||
Minecraft Forge Public Licence
|
||||
==============================
|
||||
|
||||
Version 1.0
|
||||
|
||||
0. Definitions
|
||||
--------------
|
||||
|
||||
Minecraft: Denotes a copy of the Minecraft game licensed by Mojang AB
|
||||
|
||||
User: Anybody that interract with the software in one of the following ways:
|
||||
- play
|
||||
- decompile
|
||||
- recompile or compile
|
||||
- modify
|
||||
|
||||
Minecraft Forge: The Minecraft Forge code, in source form, class file form, as
|
||||
obtained in a standalone fashion or as part of a wider distribution.
|
||||
|
||||
Dependency: Code required to have Minecraft Forge working properly. That can
|
||||
include dependencies required to compile the code as well as modifications in
|
||||
the Minecraft sources that are required to have Minecraft Forge working.
|
||||
|
||||
1. Scope
|
||||
--------
|
||||
|
||||
The present license is granted to any user of Minecraft Forge, for all files included
|
||||
unless stated otherwise in the file itself. As a prerequisite, a user of Minecraft
|
||||
Forge must own a legally aquired copy of Minecraft.
|
||||
|
||||
2. Play rights
|
||||
--------------
|
||||
|
||||
The user of Minecraft Forge is allowed to install the software on a client or
|
||||
a server and to play it without restriction.
|
||||
|
||||
3. Modification rights
|
||||
----------------------
|
||||
|
||||
The user has the right to decompile the source code, look at either the
|
||||
decompiled version or the original source code, and to modify it.
|
||||
|
||||
4. Derivation rights
|
||||
--------------------
|
||||
|
||||
The user has the rights to derive code from Minecraft Forge, that is to say to
|
||||
write code that either extends Minecraft Forge class and interfaces,
|
||||
instantiate the objects declared or calls the functions. This code is known as
|
||||
"derived" code, and can be licensed with conditions different from Minecraft
|
||||
Forge.
|
||||
|
||||
|
||||
5. Distribution rights
|
||||
----------------------
|
||||
|
||||
The user of Minecraft Forge is allowed to redistribute Minecraft Forge in
|
||||
partially, in totallity, or included in a distribution. When distributing
|
||||
binaries or class files, the user must provide means to obtain the sources of
|
||||
the distributed version of Minecraft Forge at no costs. This includes the
|
||||
files as well as any dependency that the code may rely on, including patches to
|
||||
minecraft original sources.
|
||||
|
||||
Modification of Minecraft Forge as well as dependencies, including patches to
|
||||
minecraft original sources, has to remain under the terms of the present
|
||||
license.
|
||||
|
||||
The right to distribute Minecraft Forge does not extend to the right to distribute
|
||||
MCP data files included within Minecraft Forge. These are the property of the MCP
|
||||
project and should be removed from any customized distribution of Minecraft Forge
|
||||
or permission sought separately from the MCP team.
|
||||
@@ -1,10 +0,0 @@
|
||||
IBXM is copyright (c) 2007, Martin Cameron, and is licensed under the BSD License.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
Neither the name of mumart nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
SoundSystem CodecIBXM Class License:
|
||||
|
||||
You are free to use this class for any purpose, commercial or otherwise.
|
||||
You may modify this class or source code, and distribute it any way you
|
||||
like, provided the following conditions are met:
|
||||
|
||||
1) You may not falsely claim to be the author of this class or any
|
||||
unmodified portion of it.
|
||||
2) You may not copyright this class or a modified version of it and then
|
||||
sue me for copyright infringement.
|
||||
3) If you modify the source code, you must clearly document the changes
|
||||
made before redistributing the modified source code, so other users know
|
||||
it is not the original code.
|
||||
4) You are not required to give me credit for this class in any derived
|
||||
work, but if you do, you must also mention my website:
|
||||
http://www.paulscode.com
|
||||
5) I the author will not be responsible for any damages (physical,
|
||||
financial, or otherwise) caused by the use if this class or any
|
||||
portion of it.
|
||||
6) I the author do not guarantee, warrant, or make any representations,
|
||||
either expressed or implied, regarding the use of this class or any
|
||||
portion of it.
|
||||
|
||||
Author: Paul Lamb
|
||||
http://www.paulscode.com
|
||||
|
||||
|
||||
This software is based on or using the IBXM library available from
|
||||
http://www.geocities.com/sunet2000/
|
||||
|
||||
|
||||
IBXM is copyright (c) 2007, Martin Cameron, and is licensed under the BSD License.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
Neither the name of mumart nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
-36
@@ -1,36 +0,0 @@
|
||||
*** HOW TO INSTALL ***
|
||||
For Mod Users:
|
||||
|
||||
Download the latest installer from http://files.minecraftforge.net and follow instructions given by the installer.
|
||||
|
||||
|
||||
For Mod Devs:
|
||||
|
||||
Download the latest Forge source distribution from http://files.minecraftforge.net and unzip it to a folder.
|
||||
Open a command prompt, navigate to the directory where you unzipped the Forge sources, and run:
|
||||
If you have Gradle: gradle setupDevWorkspace
|
||||
If you DO NOT have Gradle installed:
|
||||
Windows: ./gradlew.bat setupDevWorkspace
|
||||
MacOS/Linux: ./gradlew setupDevWorkspace
|
||||
|
||||
If you wish to use the Eclipse IDE, run gradle eclipse instead of gradle setupDevWorkspace, or install the Gradle plugin for Eclipse and import the Forge source folder as a Gradle project.
|
||||
|
||||
To get the decompiled classes:
|
||||
If you have Gradle: gradle setupDecompWorkspace
|
||||
If you DO NOT have Gradle installed:
|
||||
Windows: ./gradlew.bat setupDecompWorkspace
|
||||
MacOS/Linux: ./gradlew setupDecompWorkspace
|
||||
|
||||
For Contributors: (Note: This assumes you have Gradle installed. If you don't, use ./gradlew(.bat) instead of gradle.
|
||||
|
||||
Clone this repository to a folder.
|
||||
Open a command prompt and navigate to the folder where you cloned this repo.
|
||||
Run gradle setupForge to setup your development environment.
|
||||
|
||||
To use Eclipse, point your Eclipse workspace at the eclipse folder inside the repo.
|
||||
|
||||
|
||||
Requirements (for both mod devs and contributors):
|
||||
You must have a JDK installed and accessible.
|
||||
If you do not wish to use the gradle wrapper, you can install Gradle from http://www.gradle.org/ .
|
||||
|
||||
@@ -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()
|
||||
-127
@@ -1,127 +0,0 @@
|
||||
buildscript {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
mavenLocal()
|
||||
maven {
|
||||
name = "forge"
|
||||
url = "http://files.minecraftforge.net/maven"
|
||||
}
|
||||
maven {
|
||||
name = "sonatype"
|
||||
url = "https://oss.sonatype.org/content/repositories/snapshots/"
|
||||
}
|
||||
}
|
||||
dependencies {
|
||||
classpath 'net.minecraftforge.gradle:ForgeGradle:1.2-SNAPSHOT'
|
||||
}
|
||||
}
|
||||
|
||||
configurations {
|
||||
deployJars
|
||||
}
|
||||
|
||||
import static net.minecraftforge.gradle.dev.ForgeDevPlugin.*
|
||||
|
||||
apply plugin: 'maven'
|
||||
apply plugin: 'forgedev'
|
||||
|
||||
repositories {
|
||||
mavenLocal()
|
||||
flatDir {
|
||||
name "fileRepo"
|
||||
dirs "repo"
|
||||
}
|
||||
}
|
||||
|
||||
minecraft {
|
||||
version = '1.7.10'
|
||||
mcpVersion = '9.05'
|
||||
fmlDir = projectDir.getAbsolutePath() + "/fml";
|
||||
mainClass = 'cpw.mods.fml.relauncher.ServerLaunchWrapper'
|
||||
tweakClass = 'cpw.mods.fml.common.launcher.FMLTweaker'
|
||||
installerVersion = "1.4"
|
||||
}
|
||||
|
||||
group = 'net.minecraftforge'
|
||||
version = getVersionFromJava(getProject(), 'src/main/java/net/minecraftforge/common/ForgeVersion.java')
|
||||
|
||||
jenkins {
|
||||
job = 'minecraftforge'
|
||||
}
|
||||
|
||||
// crowdin stuff
|
||||
if (project.hasProperty("crowdinKey"))
|
||||
tasks.getLocalizations.apiKey = project.crowdinKey
|
||||
|
||||
|
||||
launch4j {
|
||||
jreMinVersion = '1.6.0'
|
||||
}
|
||||
|
||||
uploadArchives {
|
||||
repositories {
|
||||
add getProject().repositories.mavenLocal()
|
||||
}
|
||||
repositories.mavenDeployer {
|
||||
configuration = configurations.deployJars
|
||||
|
||||
if (project.hasProperty("filesmaven")) {
|
||||
logger.info('Publishing to files server')
|
||||
repository(url: project.filesmaven.url) {
|
||||
authentication(userName: project.filesmaven.username, privateKey: project.filesmaven.key)
|
||||
}
|
||||
} else {
|
||||
logger.info('Publishing to repo folder')
|
||||
repository(url: 'file://localhost/' + project.file('repo').getAbsolutePath())
|
||||
}
|
||||
|
||||
pom {
|
||||
groupId = project.group
|
||||
version = project.version
|
||||
artifactId = project.archivesBaseName
|
||||
}
|
||||
pom.project {
|
||||
name project.archivesBaseName
|
||||
packaging 'jar'
|
||||
description 'Minecraft Forge API'
|
||||
url 'https://github.com/MinecraftForge/MinecraftForge'
|
||||
|
||||
scm {
|
||||
url 'https://github.com/MinecraftForge/MinecraftForge'
|
||||
connection 'scm:git:git://github.com/MinecraftForge/MinecraftForge.git'
|
||||
developerConnection 'scm:git:[email protected]:MinecraftForge/MinecraftForge.git'
|
||||
}
|
||||
|
||||
issueManagement {
|
||||
system 'github'
|
||||
url 'https://github.com/MinecraftForge/MinecraftForge/issues'
|
||||
}
|
||||
|
||||
licenses {
|
||||
license {
|
||||
name 'Forge Public License'
|
||||
url 'https://raw.github.com/MinecraftForge/MinecraftForge/master/MinecraftForge-License.txt'
|
||||
distribution 'repo'
|
||||
}
|
||||
}
|
||||
|
||||
developers {
|
||||
developer {
|
||||
id 'cpw'
|
||||
name 'cpw'
|
||||
roles { role 'developer' }
|
||||
}
|
||||
developer {
|
||||
id 'LexManos'
|
||||
name 'Lex Manos'
|
||||
roles { role 'developer' }
|
||||
}
|
||||
developer {
|
||||
id 'AbrarSyed'
|
||||
name 'Abrar Syed'
|
||||
roles { role 'contributor' }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,396 @@
|
||||
<?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="server.mcp.obfoutput" location="${mcp.obfoutput}/minecraft_server" />
|
||||
<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="server.mcp.srcdir" location="${mcp.srcdir}/minecraft_server" />
|
||||
<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="server.src.dir" location="${basedir}/server" />
|
||||
<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="buildandreobfmcp" 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/server.md5"/>
|
||||
<available file="${mcp.home}/temp/server_reobf.md5"/>
|
||||
<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>
|
||||
<and>
|
||||
<available file="${mcp.home}/bin/minecraft/net/minecraft/client/Minecraft.class"/>
|
||||
<available file="${mcp.home}/bin/minecraft_server/net/minecraft/server/MinecraftServer.class"/>
|
||||
</and>
|
||||
</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-server" depends="buildenvsetup">
|
||||
<copy todir="${server.mcp.srcdir}" overwrite="true" verbose="true">
|
||||
<fileset dir="${server.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-server,merge-common" />
|
||||
|
||||
<target name="build-client" depends="buildenvsetup,merge-client,merge-common,buildandreobfmcp,makeversion">
|
||||
<antcall target="extract-built-jar">
|
||||
<param name="side" value="client" />
|
||||
</antcall>
|
||||
</target>
|
||||
|
||||
<target name="build-server" depends="buildenvsetup,merge-server,merge-common,buildandreobfmcp,makeversion">
|
||||
<antcall target="extract-built-jar">
|
||||
<param name="side" value="server" />
|
||||
</antcall>
|
||||
</target>
|
||||
|
||||
<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">
|
||||
<property name="universal.jarname" value="${modname}-universal-${version}" />
|
||||
<mkdir dir="${basedir}/target" />
|
||||
<jar destfile="${basedir}/target/${universal.jarname}.zip">
|
||||
<manifest>
|
||||
<attribute name="Main-Class" value="net.minecraft.server.MinecraftServer"/>
|
||||
</manifest>
|
||||
<fileset dir="${server.mcp.obfoutput}" includes="**/*.class" />
|
||||
<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="${server.src.dir}" includes="**/*.java" prefix="fml/server" />
|
||||
<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-server,merge-client,merge-common,build-server,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>
|
||||
<!--<exec executable="${python.exe}" dir="${basedir}">
|
||||
<arg value="${basedir}/download_fernflower.py" />
|
||||
<arg value="${mcp.home}"/>
|
||||
</exec>-->
|
||||
<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-server,buildandreobfmcp">
|
||||
<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>
|
||||
@@ -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,405 @@
|
||||
/*
|
||||
* 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 static org.lwjgl.opengl.GL11.*;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.Dimension;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Hashtable;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Random;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.src.BaseMod;
|
||||
import net.minecraft.src.BiomeGenBase;
|
||||
import net.minecraft.src.Block;
|
||||
import net.minecraft.src.CrashReport;
|
||||
import net.minecraft.src.Entity;
|
||||
import net.minecraft.src.EntityItem;
|
||||
import net.minecraft.src.EntityLiving;
|
||||
import net.minecraft.src.EntityPlayer;
|
||||
import net.minecraft.src.GameSettings;
|
||||
import net.minecraft.src.GuiScreen;
|
||||
import net.minecraft.src.IBlockAccess;
|
||||
import net.minecraft.src.IChunkProvider;
|
||||
import net.minecraft.src.IInventory;
|
||||
import net.minecraft.src.Item;
|
||||
import net.minecraft.src.ItemStack;
|
||||
import net.minecraft.src.KeyBinding;
|
||||
import net.minecraft.src.MLProp;
|
||||
import net.minecraft.src.ModTextureStatic;
|
||||
import net.minecraft.src.NetClientHandler;
|
||||
import net.minecraft.src.NetworkManager;
|
||||
import net.minecraft.src.Packet;
|
||||
import net.minecraft.src.Packet1Login;
|
||||
import net.minecraft.src.Packet250CustomPayload;
|
||||
import net.minecraft.src.Packet3Chat;
|
||||
import net.minecraft.src.Profiler;
|
||||
import net.minecraft.src.Render;
|
||||
import net.minecraft.src.RenderBlocks;
|
||||
import net.minecraft.src.RenderEngine;
|
||||
import net.minecraft.src.RenderManager;
|
||||
import net.minecraft.src.RenderPlayer;
|
||||
import net.minecraft.src.StringTranslate;
|
||||
import net.minecraft.src.TextureFX;
|
||||
import net.minecraft.src.TexturePackBase;
|
||||
import net.minecraft.src.World;
|
||||
import net.minecraft.src.WorldClient;
|
||||
import net.minecraft.src.WorldType;
|
||||
import argo.jdom.JdomParser;
|
||||
import argo.jdom.JsonNode;
|
||||
import cpw.mods.fml.client.modloader.ModLoaderClientHelper;
|
||||
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.DummyModContainer;
|
||||
import cpw.mods.fml.common.FMLCommonHandler;
|
||||
import cpw.mods.fml.common.FMLDummyContainer;
|
||||
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.LoaderState;
|
||||
import cpw.mods.fml.common.MetadataCollection;
|
||||
import cpw.mods.fml.common.ModContainer;
|
||||
import cpw.mods.fml.common.ModMetadata;
|
||||
import cpw.mods.fml.common.ProxyInjector;
|
||||
import cpw.mods.fml.common.ObfuscationReflectionHelper;
|
||||
import cpw.mods.fml.common.Side;
|
||||
import cpw.mods.fml.common.SidedProxy;
|
||||
import cpw.mods.fml.common.TickType;
|
||||
import cpw.mods.fml.common.modloader.ModLoaderHelper;
|
||||
import cpw.mods.fml.common.modloader.ModLoaderModContainer;
|
||||
import cpw.mods.fml.common.modloader.ModProperty;
|
||||
import cpw.mods.fml.common.network.EntitySpawnAdjustmentPacket;
|
||||
import cpw.mods.fml.common.network.EntitySpawnPacket;
|
||||
import cpw.mods.fml.common.registry.IEntityAdditionalSpawnData;
|
||||
import cpw.mods.fml.common.registry.IThrowableEntity;
|
||||
|
||||
|
||||
/**
|
||||
* Handles primary communication from hooked code into the system
|
||||
*
|
||||
* The FML entry point is {@link #beginMinecraftLoading(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 FMLClientHandler implements IFMLSidedHandler
|
||||
{
|
||||
/**
|
||||
* The singleton
|
||||
*/
|
||||
private static final FMLClientHandler INSTANCE = new FMLClientHandler();
|
||||
|
||||
/**
|
||||
* A reference to the server itself
|
||||
*/
|
||||
private Minecraft client;
|
||||
|
||||
|
||||
private boolean firstTick;
|
||||
/**
|
||||
* Called to start the whole game off from
|
||||
* {@link MinecraftServer#startServer}
|
||||
*
|
||||
* @param minecraftServer
|
||||
*/
|
||||
|
||||
private DummyModContainer optifineContainer;
|
||||
|
||||
private boolean guiLoaded;
|
||||
|
||||
private boolean serverIsRunning;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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")).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 (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
|
||||
*
|
||||
*/
|
||||
public void finishMinecraftLoading()
|
||||
{
|
||||
try
|
||||
{
|
||||
Loader.instance().initializeMods();
|
||||
}
|
||||
catch (LoaderException le)
|
||||
{
|
||||
haltGame("There was a severe problem during mod loading that has caused the game to fail", le);
|
||||
return;
|
||||
}
|
||||
RenderingRegistry.instance().loadEntityRenderers((Map<Class<? extends Entity>, Render>)RenderManager.field_78727_a.field_78729_o);
|
||||
|
||||
KeyBindingRegistry.uploadKeyBindingsToGame(client.field_71474_y);
|
||||
|
||||
// Mark this as a "first tick"
|
||||
firstTick = true;
|
||||
}
|
||||
/**
|
||||
* Get the server instance
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void profileStart(String profileLabel) {
|
||||
client.field_71424_I.func_76320_a(profileLabel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void profileEnd() {
|
||||
client.field_71424_I.func_76319_b();
|
||||
}
|
||||
|
||||
/**
|
||||
* @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(Class<? extends Entity> cls, EntitySpawnPacket packet)
|
||||
{
|
||||
WorldClient wc = client.field_71441_e;
|
||||
|
||||
try
|
||||
{
|
||||
Entity entity = (Entity)(cls.getConstructor(World.class).newInstance(wc));
|
||||
if (entity instanceof IThrowableEntity)
|
||||
{
|
||||
Entity thrower = client.field_71439_g.field_70157_k == packet.throwerId ? client.field_71439_g : wc.func_73024_a(packet.throwerId);
|
||||
((IThrowableEntity)entity).setThrower(thrower);
|
||||
}
|
||||
|
||||
entity.field_70118_ct = packet.rawX;
|
||||
entity.field_70117_cu = packet.rawY;
|
||||
entity.field_70116_cv = packet.rawZ;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
entity.field_70157_k = packet.entityId;
|
||||
entity.func_70056_a(packet.scaledX, packet.scaledY, packet.scaledZ, packet.scaledYaw, packet.scaledPitch, 1);
|
||||
|
||||
if (entity instanceof EntityLiving)
|
||||
{
|
||||
((EntityLiving)entity).field_70759_as = packet.scaledHeadYaw;
|
||||
}
|
||||
|
||||
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_73024_a(packet.entityId);
|
||||
ent.field_70118_ct = packet.serverX;
|
||||
ent.field_70117_cu = packet.serverY;
|
||||
ent.field_70116_cv = packet.serverZ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beginServerLoading(MinecraftServer server)
|
||||
{
|
||||
// NOOP
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finishServerLoading()
|
||||
{
|
||||
// NOOP
|
||||
}
|
||||
|
||||
@Override
|
||||
public MinecraftServer getServer()
|
||||
{
|
||||
return client.func_71401_C();
|
||||
}
|
||||
}
|
||||
@@ -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 cpw.mods.fml.common.FMLCommonHandler;
|
||||
|
||||
import net.minecraft.src.RenderEngine;
|
||||
import net.minecraft.src.TextureFX;
|
||||
import net.minecraft.src.TexturePackBase;
|
||||
|
||||
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 = FMLCommonHandler.instance().getFMLLogger();
|
||||
|
||||
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, TexturePackBase 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,178 @@
|
||||
/*
|
||||
* 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 java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import cpw.mods.fml.common.FMLModContainer;
|
||||
import cpw.mods.fml.common.FMLDummyContainer;
|
||||
import cpw.mods.fml.common.Loader;
|
||||
import cpw.mods.fml.common.ModContainer;
|
||||
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;
|
||||
|
||||
/**
|
||||
* @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 guiMainMenu
|
||||
*/
|
||||
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 && mod.getMetadata().parentMod != null) {
|
||||
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) {
|
||||
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.getMetadata().version, 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);
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param var1
|
||||
* @return
|
||||
*/
|
||||
public boolean modIndexSelected(int var1)
|
||||
{
|
||||
return var1==selected;
|
||||
}
|
||||
}
|
||||
+83
-139
@@ -1,24 +1,9 @@
|
||||
/*
|
||||
* Forge Mod Loader
|
||||
* Copyright (c) 2012-2013 cpw.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the GNU Lesser Public License v2.1
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* Contributors:
|
||||
* cpw - implementation
|
||||
*/
|
||||
|
||||
package cpw.mods.fml.client;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.Gui;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.renderer.OpenGlHelper;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.src.GuiButton;
|
||||
import net.minecraft.src.Tessellator;
|
||||
|
||||
import org.lwjgl.input.Mouse;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
@@ -96,16 +81,15 @@ public abstract class GuiScrollingList
|
||||
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 var3 = this.listWidth / 2 - 110;
|
||||
int var4 = this.listWidth / 2 + 110;
|
||||
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(@SuppressWarnings("rawtypes") List p_22240_1_, int p_22240_2_, int p_22240_3_)
|
||||
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_;
|
||||
@@ -133,15 +117,15 @@ public abstract class GuiScrollingList
|
||||
|
||||
public void actionPerformed(GuiButton button)
|
||||
{
|
||||
if (button.enabled)
|
||||
if (button.field_73742_g)
|
||||
{
|
||||
if (button.id == this.scrollUpActionId)
|
||||
if (button.field_73741_f == this.scrollUpActionId)
|
||||
{
|
||||
this.scrollDistance -= (float)(this.slotHeight * 2 / 3);
|
||||
this.initialMouseClickY = -2.0F;
|
||||
this.applyScrollLimits();
|
||||
}
|
||||
else if (button.id == this.scrollDownActionId)
|
||||
else if (button.field_73741_f == this.scrollDownActionId)
|
||||
{
|
||||
this.scrollDistance += (float)(this.slotHeight * 2 / 3);
|
||||
this.initialMouseClickY = -2.0F;
|
||||
@@ -263,27 +247,20 @@ public abstract class GuiScrollingList
|
||||
}
|
||||
|
||||
this.applyScrollLimits();
|
||||
Tessellator var18 = Tessellator.instance;
|
||||
if (this.client.theWorld != null)
|
||||
{
|
||||
this.drawGradientRect(this.left, this.top, this.right, this.bottom, -1072689136, -804253680);
|
||||
}
|
||||
else
|
||||
{
|
||||
GL11.glDisable(GL11.GL_LIGHTING);
|
||||
GL11.glDisable(GL11.GL_FOG);
|
||||
this.client.renderEngine.bindTexture(Gui.optionsBackground);
|
||||
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
float var17 = 32.0F;
|
||||
var18.startDrawingQuads();
|
||||
var18.setColorOpaque_I(2105376);
|
||||
var18.addVertexWithUV((double)this.left, (double)this.bottom, 0.0D, (double)((float)this.left / var17), (double)((float)(this.bottom + (int)this.scrollDistance) / var17));
|
||||
var18.addVertexWithUV((double)this.right, (double)this.bottom, 0.0D, (double)((float)this.right / var17), (double)((float)(this.bottom + (int)this.scrollDistance) / var17));
|
||||
var18.addVertexWithUV((double)this.right, (double)this.top, 0.0D, (double)((float)this.right / var17), (double)((float)(this.top + (int)this.scrollDistance) / var17));
|
||||
var18.addVertexWithUV((double)this.left, (double)this.top, 0.0D, (double)((float)this.left / var17), (double)((float)(this.top + (int)this.scrollDistance) / var17));
|
||||
var18.draw();
|
||||
}
|
||||
// boxRight = this.listWidth / 2 - 92 - 16;
|
||||
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)
|
||||
@@ -306,18 +283,18 @@ public abstract class GuiScrollingList
|
||||
int var15 = boxRight;
|
||||
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
GL11.glDisable(GL11.GL_TEXTURE_2D);
|
||||
var18.startDrawingQuads();
|
||||
var18.setColorOpaque_I(8421504);
|
||||
var18.addVertexWithUV((double)var14, (double)(var19 + var13 + 2), 0.0D, 0.0D, 1.0D);
|
||||
var18.addVertexWithUV((double)var15, (double)(var19 + var13 + 2), 0.0D, 1.0D, 1.0D);
|
||||
var18.addVertexWithUV((double)var15, (double)(var19 - 2), 0.0D, 1.0D, 0.0D);
|
||||
var18.addVertexWithUV((double)var14, (double)(var19 - 2), 0.0D, 0.0D, 0.0D);
|
||||
var18.setColorOpaque_I(0);
|
||||
var18.addVertexWithUV((double)(var14 + 1), (double)(var19 + var13 + 1), 0.0D, 0.0D, 1.0D);
|
||||
var18.addVertexWithUV((double)(var15 - 1), (double)(var19 + var13 + 1), 0.0D, 1.0D, 1.0D);
|
||||
var18.addVertexWithUV((double)(var15 - 1), (double)(var19 - 1), 0.0D, 1.0D, 0.0D);
|
||||
var18.addVertexWithUV((double)(var14 + 1), (double)(var19 - 1), 0.0D, 0.0D, 0.0D);
|
||||
var18.draw();
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -327,32 +304,29 @@ public abstract class GuiScrollingList
|
||||
|
||||
GL11.glDisable(GL11.GL_DEPTH_TEST);
|
||||
byte var20 = 4;
|
||||
if (this.client.theWorld == null)
|
||||
{
|
||||
this.overlayBackground(0, this.top, 255, 255);
|
||||
this.overlayBackground(this.bottom, this.listHeight, 255, 255);
|
||||
}
|
||||
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.startDrawingQuads();
|
||||
var18.setColorRGBA_I(0, 0);
|
||||
var18.addVertexWithUV((double)this.left, (double)(this.top + var20), 0.0D, 0.0D, 1.0D);
|
||||
var18.addVertexWithUV((double)this.right, (double)(this.top + var20), 0.0D, 1.0D, 1.0D);
|
||||
var18.setColorRGBA_I(0, 255);
|
||||
var18.addVertexWithUV((double)this.right, (double)this.top, 0.0D, 1.0D, 0.0D);
|
||||
var18.addVertexWithUV((double)this.left, (double)this.top, 0.0D, 0.0D, 0.0D);
|
||||
var18.draw();
|
||||
var18.startDrawingQuads();
|
||||
var18.setColorRGBA_I(0, 255);
|
||||
var18.addVertexWithUV((double)this.left, (double)this.bottom, 0.0D, 0.0D, 1.0D);
|
||||
var18.addVertexWithUV((double)this.right, (double)this.bottom, 0.0D, 1.0D, 1.0D);
|
||||
var18.setColorRGBA_I(0, 0);
|
||||
var18.addVertexWithUV((double)this.right, (double)(this.bottom - var20), 0.0D, 1.0D, 0.0D);
|
||||
var18.addVertexWithUV((double)this.left, (double)(this.bottom - var20), 0.0D, 0.0D, 0.0D);
|
||||
var18.draw();
|
||||
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)
|
||||
@@ -376,27 +350,27 @@ public abstract class GuiScrollingList
|
||||
var14 = this.top;
|
||||
}
|
||||
|
||||
var18.startDrawingQuads();
|
||||
var18.setColorRGBA_I(0, 255);
|
||||
var18.addVertexWithUV((double)scrollBarXStart, (double)this.bottom, 0.0D, 0.0D, 1.0D);
|
||||
var18.addVertexWithUV((double)scrollBarXEnd, (double)this.bottom, 0.0D, 1.0D, 1.0D);
|
||||
var18.addVertexWithUV((double)scrollBarXEnd, (double)this.top, 0.0D, 1.0D, 0.0D);
|
||||
var18.addVertexWithUV((double)scrollBarXStart, (double)this.top, 0.0D, 0.0D, 0.0D);
|
||||
var18.draw();
|
||||
var18.startDrawingQuads();
|
||||
var18.setColorRGBA_I(8421504, 255);
|
||||
var18.addVertexWithUV((double)scrollBarXStart, (double)(var14 + var13), 0.0D, 0.0D, 1.0D);
|
||||
var18.addVertexWithUV((double)scrollBarXEnd, (double)(var14 + var13), 0.0D, 1.0D, 1.0D);
|
||||
var18.addVertexWithUV((double)scrollBarXEnd, (double)var14, 0.0D, 1.0D, 0.0D);
|
||||
var18.addVertexWithUV((double)scrollBarXStart, (double)var14, 0.0D, 0.0D, 0.0D);
|
||||
var18.draw();
|
||||
var18.startDrawingQuads();
|
||||
var18.setColorRGBA_I(12632256, 255);
|
||||
var18.addVertexWithUV((double)scrollBarXStart, (double)(var14 + var13 - 1), 0.0D, 0.0D, 1.0D);
|
||||
var18.addVertexWithUV((double)(scrollBarXEnd - 1), (double)(var14 + var13 - 1), 0.0D, 1.0D, 1.0D);
|
||||
var18.addVertexWithUV((double)(scrollBarXEnd - 1), (double)var14, 0.0D, 1.0D, 0.0D);
|
||||
var18.addVertexWithUV((double)scrollBarXStart, (double)var14, 0.0D, 0.0D, 0.0D);
|
||||
var18.draw();
|
||||
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);
|
||||
@@ -408,47 +382,17 @@ public abstract class GuiScrollingList
|
||||
|
||||
private void overlayBackground(int p_22239_1_, int p_22239_2_, int p_22239_3_, int p_22239_4_)
|
||||
{
|
||||
Tessellator var5 = Tessellator.instance;
|
||||
this.client.renderEngine.bindTexture(Gui.optionsBackground);
|
||||
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.startDrawingQuads();
|
||||
var5.setColorRGBA_I(4210752, p_22239_4_);
|
||||
var5.addVertexWithUV(0.0D, (double)p_22239_2_, 0.0D, 0.0D, (double)((float)p_22239_2_ / var6));
|
||||
var5.addVertexWithUV((double)this.listWidth + 30, (double)p_22239_2_, 0.0D, (double)((float)(this.listWidth + 30) / var6), (double)((float)p_22239_2_ / var6));
|
||||
var5.setColorRGBA_I(4210752, p_22239_3_);
|
||||
var5.addVertexWithUV((double)this.listWidth + 30, (double)p_22239_1_, 0.0D, (double)((float)(this.listWidth + 30) / var6), (double)((float)p_22239_1_ / var6));
|
||||
var5.addVertexWithUV(0.0D, (double)p_22239_1_, 0.0D, 0.0D, (double)((float)p_22239_1_ / var6));
|
||||
var5.draw();
|
||||
}
|
||||
|
||||
protected void drawGradientRect(int par1, int par2, int par3, int par4, int par5, int par6)
|
||||
{
|
||||
float f = (float)(par5 >> 24 & 255) / 255.0F;
|
||||
float f1 = (float)(par5 >> 16 & 255) / 255.0F;
|
||||
float f2 = (float)(par5 >> 8 & 255) / 255.0F;
|
||||
float f3 = (float)(par5 & 255) / 255.0F;
|
||||
float f4 = (float)(par6 >> 24 & 255) / 255.0F;
|
||||
float f5 = (float)(par6 >> 16 & 255) / 255.0F;
|
||||
float f6 = (float)(par6 >> 8 & 255) / 255.0F;
|
||||
float f7 = (float)(par6 & 255) / 255.0F;
|
||||
GL11.glDisable(GL11.GL_TEXTURE_2D);
|
||||
GL11.glEnable(GL11.GL_BLEND);
|
||||
GL11.glDisable(GL11.GL_ALPHA_TEST);
|
||||
OpenGlHelper.glBlendFunc(770, 771, 1, 0);
|
||||
GL11.glShadeModel(GL11.GL_SMOOTH);
|
||||
Tessellator tessellator = Tessellator.instance;
|
||||
tessellator.startDrawingQuads();
|
||||
tessellator.setColorRGBA_F(f1, f2, f3, f);
|
||||
tessellator.addVertex((double)par3, (double)par2, 0.0D);
|
||||
tessellator.addVertex((double)par1, (double)par2, 0.0D);
|
||||
tessellator.setColorRGBA_F(f5, f6, f7, f4);
|
||||
tessellator.addVertex((double)par1, (double)par4, 0.0D);
|
||||
tessellator.addVertex((double)par3, (double)par4, 0.0D);
|
||||
tessellator.draw();
|
||||
GL11.glShadeModel(GL11.GL_FLAT);
|
||||
GL11.glDisable(GL11.GL_BLEND);
|
||||
GL11.glEnable(GL11.GL_ALPHA_TEST);
|
||||
GL11.glEnable(GL11.GL_TEXTURE_2D);
|
||||
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,93 @@
|
||||
/*
|
||||
* 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 cpw.mods.fml.common.Loader;
|
||||
import cpw.mods.fml.common.LoaderState.ModState;
|
||||
import cpw.mods.fml.common.ModContainer;
|
||||
import cpw.mods.fml.common.ModMetadata;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.src.GuiLanguage;
|
||||
import net.minecraft.src.GuiSlot;
|
||||
import net.minecraft.src.StringTranslate;
|
||||
import net.minecraft.src.Tessellator;
|
||||
|
||||
/**
|
||||
* @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 - 11), this.left + 3 , var3 + 2, 0xFF2222);
|
||||
this.parent.getFontRenderer().func_78276_b(this.parent.getFontRenderer().func_78269_a(mc.getVersion(), listWidth - 11), this.left + 3 , var3 + 12, 0xFF2222);
|
||||
this.parent.getFontRenderer().func_78276_b(this.parent.getFontRenderer().func_78269_a("DISABLED", listWidth - 11), this.left + 3 , var3 + 22, 0xFF2222);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.parent.getFontRenderer().func_78276_b(this.parent.getFontRenderer().func_78269_a(mc.getName(), listWidth - 11), this.left + 3 , var3 + 2, 0xFFFFFF);
|
||||
this.parent.getFontRenderer().func_78276_b(this.parent.getFontRenderer().func_78269_a(mc.getVersion(), listWidth - 11), 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 - 9), this.left + 3 , var3 + 22, 0xCCCCCC);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* 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.*;
|
||||
|
||||
public interface ITextureFX
|
||||
{
|
||||
public void onTexturePackChanged(RenderEngine engine, TexturePackBase 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,144 @@
|
||||
/*
|
||||
* 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 net.minecraft.src.ModLoader;
|
||||
import cpw.mods.fml.common.FMLCommonHandler;
|
||||
import cpw.mods.fml.common.FMLLog;
|
||||
import cpw.mods.fml.common.LoaderException;
|
||||
|
||||
/**
|
||||
* @author cpw
|
||||
*
|
||||
*/
|
||||
public class SpriteHelper
|
||||
{
|
||||
private static HashMap<String, BitSet> spriteInfo = new HashMap<String, BitSet>();
|
||||
|
||||
private static void initMCSpriteMaps() {
|
||||
BitSet slots =
|
||||
SpriteHelper.toBitSet(
|
||||
"0000000000000000" +
|
||||
"0000000000000000" +
|
||||
"0000000000000000" +
|
||||
"0000000000000000" +
|
||||
"0000000000000000" +
|
||||
"0000000000000000" +
|
||||
"0000000000000000" +
|
||||
"0000000000000000" +
|
||||
"0000000000000000" +
|
||||
"0000000000000000" +
|
||||
"0000000011111100" +
|
||||
"0000000011111111" +
|
||||
"0000000011111000" +
|
||||
"0000000111111100" +
|
||||
"0000000111111000" +
|
||||
"0000000000000000");
|
||||
spriteInfo.put("/terrain.png", slots);
|
||||
|
||||
slots = SpriteHelper.toBitSet(
|
||||
"0000000000000000" +
|
||||
"0000000000000000" +
|
||||
"0000000000000000" +
|
||||
"0000000000000000" +
|
||||
"0000000000000000" +
|
||||
"0000000000000000" +
|
||||
"0000001000000000" +
|
||||
"0000001110000000" +
|
||||
"0000001000000000" +
|
||||
"1111111010000000" +
|
||||
"1111111010100000" +
|
||||
"1111111111111100" +
|
||||
"1111111111111111" +
|
||||
"1111111111111111" +
|
||||
"1111111111111111" +
|
||||
"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;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param textureToOverride
|
||||
* @return
|
||||
*/
|
||||
public static int freeSlotCount(String textureToOverride)
|
||||
{
|
||||
return spriteInfo.get(textureToOverride).cardinality();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,347 @@
|
||||
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 org.lwjgl.opengl.GL11;
|
||||
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Multimap;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.src.KeyBinding;
|
||||
import net.minecraft.src.ModTextureStatic;
|
||||
import net.minecraft.src.Profiler;
|
||||
import net.minecraft.src.RenderEngine;
|
||||
import net.minecraft.src.TextureFX;
|
||||
import net.minecraft.src.TexturePackBase;
|
||||
import cpw.mods.fml.common.FMLCommonHandler;
|
||||
import cpw.mods.fml.common.FMLLog;
|
||||
import cpw.mods.fml.common.Loader;
|
||||
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();
|
||||
FMLClientHandler.instance().profileStart(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);
|
||||
}
|
||||
FMLClientHandler.instance().profileEnd();
|
||||
return false;
|
||||
}
|
||||
FMLClientHandler.instance().profileEnd();
|
||||
|
||||
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, TexturePackBase 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 TexturePackBase 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param anim
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param p_6531_1_
|
||||
*/
|
||||
public void loadTextures(TexturePackBase texturePack)
|
||||
{
|
||||
registerTextureOverrides(client.field_71446_o);
|
||||
}
|
||||
|
||||
|
||||
public void registerTextureOverrides(RenderEngine renderer) {
|
||||
for (ModContainer mod : Loader.instance().getActiveModList()) {
|
||||
registerAnimatedTexturesFor(mod);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mod
|
||||
*/
|
||||
private void registerAnimatedTexturesFor(ModContainer mod)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param field_6539_c
|
||||
*/
|
||||
public void onEarlyTexturePackLoad(TexturePackBase fallback)
|
||||
{
|
||||
if (client==null) {
|
||||
// We're far too early- let's wait
|
||||
this.earlyTexturePack = fallback;
|
||||
} else {
|
||||
loadTextures(fallback);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void pruneOldTextureFX(TexturePackBase 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));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param renderEngine
|
||||
* @param path
|
||||
* @return
|
||||
*/
|
||||
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,85 @@
|
||||
/*
|
||||
* 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;
|
||||
import cpw.mods.fml.common.ModContainer;
|
||||
import cpw.mods.fml.common.modloader.ModLoaderModContainer;
|
||||
|
||||
/**
|
||||
* @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,63 @@
|
||||
package cpw.mods.fml.client.modloader;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.src.BaseMod;
|
||||
import net.minecraft.src.Entity;
|
||||
import net.minecraft.src.Render;
|
||||
import cpw.mods.fml.client.registry.RenderingRegistry;
|
||||
import cpw.mods.fml.common.modloader.IModLoaderSidedHelper;
|
||||
import cpw.mods.fml.common.modloader.ModLoaderHelper;
|
||||
import cpw.mods.fml.common.modloader.ModLoaderModContainer;
|
||||
|
||||
public class ModLoaderClientHelper implements IModLoaderSidedHelper
|
||||
{
|
||||
|
||||
/**
|
||||
* @param mod
|
||||
* @param inventoryRenderer
|
||||
* @return
|
||||
*/
|
||||
public static int obtainBlockModelIdFor(BaseMod mod, boolean inventoryRenderer)
|
||||
{
|
||||
int renderId=RenderingRegistry.instance().getNextAvailableRenderId();
|
||||
ModLoaderBlockRendererHandler bri=new ModLoaderBlockRendererHandler(renderId, inventoryRenderer, mod);
|
||||
RenderingRegistry.instance().registerBlockHandler(bri);
|
||||
return renderId;
|
||||
}
|
||||
|
||||
|
||||
public static void handleFinishLoadingFor(ModLoaderModContainer mc, Minecraft game)
|
||||
{
|
||||
BaseMod mod = (BaseMod) mc.getMod();
|
||||
|
||||
Map<Class<? extends Entity>, Render> renderers = Maps.newHashMap();
|
||||
|
||||
mod.addRenderer(renderers);
|
||||
|
||||
for (Entry<Class<? extends Entity>, Render> e : renderers.entrySet())
|
||||
{
|
||||
RenderingRegistry.instance().registerEntityRenderingHandler(e.getKey(), e.getValue());
|
||||
}
|
||||
|
||||
mod.registerAnimation(game);
|
||||
}
|
||||
|
||||
public ModLoaderClientHelper(Minecraft client)
|
||||
{
|
||||
this.client = client;
|
||||
ModLoaderHelper.sidedHelper = this;
|
||||
}
|
||||
|
||||
private Minecraft client;
|
||||
|
||||
@Override
|
||||
public void finishModLoading(ModLoaderModContainer mc)
|
||||
{
|
||||
handleFinishLoadingFor(mc, client);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* 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.EnumSet;
|
||||
|
||||
import net.minecraft.src.KeyBinding;
|
||||
|
||||
import org.lwjgl.input.Keyboard;
|
||||
import org.lwjgl.input.Mouse;
|
||||
|
||||
import cpw.mods.fml.client.registry.KeyBindingRegistry;
|
||||
import cpw.mods.fml.common.TickType;
|
||||
import cpw.mods.fml.common.modloader.ModLoaderModContainer;
|
||||
import cpw.mods.fml.common.registry.TickRegistry;
|
||||
|
||||
/**
|
||||
* @author cpw
|
||||
*
|
||||
*/
|
||||
public class ModLoaderKeyBindingHandler extends KeyBindingRegistry.KeyHandler
|
||||
{
|
||||
private ModLoaderModContainer modContainer;
|
||||
private boolean downArmed;
|
||||
private boolean upArmed;
|
||||
|
||||
/**
|
||||
* @param keyHandler
|
||||
* @param allowRepeat
|
||||
* @param modContainer
|
||||
*/
|
||||
public ModLoaderKeyBindingHandler(KeyBinding keyBinding, boolean allowRepeat, ModLoaderModContainer modContainer)
|
||||
{
|
||||
super(keyBinding, allowRepeat);
|
||||
this.modContainer=modContainer;
|
||||
}
|
||||
|
||||
public void onRenderEndTick()
|
||||
{
|
||||
((net.minecraft.src.BaseMod)modContainer.getMod()).keyboardEvent(keyBinding);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyDown(EnumSet<TickType> type, boolean end, boolean repeats)
|
||||
{
|
||||
if (!end)
|
||||
{
|
||||
return;
|
||||
}
|
||||
upArmed = false;
|
||||
if (type.contains(TickType.CLIENT))
|
||||
{
|
||||
downArmed = true;
|
||||
}
|
||||
if (type.contains(TickType.RENDER) && downArmed)
|
||||
{
|
||||
onRenderEndTick();
|
||||
downArmed = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyUp(EnumSet<TickType> type, boolean end)
|
||||
{
|
||||
if (!end)
|
||||
{
|
||||
return;
|
||||
}
|
||||
downArmed = false;
|
||||
if (type.contains(TickType.CLIENT))
|
||||
{
|
||||
upArmed = true;
|
||||
}
|
||||
if (type.contains(TickType.RENDER) && upArmed)
|
||||
{
|
||||
onRenderEndTick();
|
||||
upArmed = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnumSet<TickType> ticks()
|
||||
{
|
||||
return EnumSet.of(TickType.CLIENT, TickType.RENDER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLabel()
|
||||
{
|
||||
return modContainer.getModId() +" KB "+keyBinding.field_74512_d;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package cpw.mods.fml.client.registry;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import net.minecraft.src.BiomeGenBase;
|
||||
import net.minecraft.src.TileEntity;
|
||||
import net.minecraft.src.TileEntityRenderer;
|
||||
import net.minecraft.src.TileEntitySpecialRenderer;
|
||||
|
||||
import cpw.mods.fml.client.FMLClientHandler;
|
||||
import cpw.mods.fml.common.ObfuscationReflectionHelper;
|
||||
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,94 @@
|
||||
package cpw.mods.fml.client.registry;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
|
||||
import org.lwjgl.input.Keyboard;
|
||||
import org.lwjgl.input.Mouse;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import net.minecraft.src.GameSettings;
|
||||
import net.minecraft.src.KeyBinding;
|
||||
|
||||
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
|
||||
{
|
||||
public static abstract class KeyHandler implements ITickHandler
|
||||
{
|
||||
protected KeyBinding keyBinding;
|
||||
protected boolean keyDown;
|
||||
protected boolean repeating;
|
||||
|
||||
public KeyHandler(KeyBinding keyBinding, boolean repeating)
|
||||
{
|
||||
this.keyBinding = keyBinding;
|
||||
this.repeating = repeating;
|
||||
}
|
||||
|
||||
public KeyBinding getKeyBinding()
|
||||
{
|
||||
return this.keyBinding;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void tickStart(EnumSet<TickType> type, Object... tickData)
|
||||
{
|
||||
keyTick(type, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void tickEnd(EnumSet<TickType> type, Object... tickData)
|
||||
{
|
||||
keyTick(type, true);
|
||||
}
|
||||
|
||||
private void keyTick(EnumSet<TickType> type, boolean tickEnd)
|
||||
{
|
||||
int keyCode = keyBinding.field_74512_d;
|
||||
boolean state = (keyCode < 0 ? Mouse.isButtonDown(keyCode + 100) : Keyboard.isKeyDown(keyCode));
|
||||
if (state != keyDown || (state && repeating))
|
||||
{
|
||||
if (state)
|
||||
{
|
||||
keyDown(type, tickEnd, state!=keyDown);
|
||||
}
|
||||
else
|
||||
{
|
||||
keyUp(type, tickEnd);
|
||||
}
|
||||
keyDown = state;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void keyDown(EnumSet<TickType> types, boolean tickEnd, boolean isRepeat);
|
||||
public abstract void keyUp(EnumSet<TickType> types, boolean tickEnd);
|
||||
}
|
||||
|
||||
private static List<KeyHandler> keyHandlers = Lists.newArrayList();
|
||||
|
||||
public static void registerKeyBinding(KeyHandler handler) {
|
||||
keyHandlers.add(handler);
|
||||
TickRegistry.registerTickHandler(handler, Side.CLIENT);
|
||||
}
|
||||
|
||||
public static void uploadKeyBindingsToGame(GameSettings settings)
|
||||
{
|
||||
ArrayList<KeyBinding> harvestedBindings = Lists.newArrayList();
|
||||
for (KeyHandler key : keyHandlers)
|
||||
{
|
||||
harvestedBindings.add(key.keyBinding);
|
||||
}
|
||||
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,113 @@
|
||||
package cpw.mods.fml.client.registry;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.ObjectArrays;
|
||||
|
||||
import net.minecraft.src.Block;
|
||||
import net.minecraft.src.Entity;
|
||||
import net.minecraft.src.IBlockAccess;
|
||||
import net.minecraft.src.Render;
|
||||
import net.minecraft.src.RenderBlocks;
|
||||
import net.minecraft.src.RenderPlayer;
|
||||
import cpw.mods.fml.client.modloader.ModLoaderBlockRendererHandler;
|
||||
import cpw.mods.fml.common.ObfuscationReflectionHelper;
|
||||
|
||||
public class RenderingRegistry
|
||||
{
|
||||
private static final RenderingRegistry INSTANCE = new RenderingRegistry();
|
||||
|
||||
private int nextRenderId = 30;
|
||||
|
||||
private Map<Integer, ISimpleBlockRenderingHandler> blockRenderers = Maps.newHashMap();
|
||||
|
||||
private List<EntityRendererInfo> entityRenderers = Lists.newArrayList();
|
||||
|
||||
public int addNewArmourRendererPrefix(String armor)
|
||||
{
|
||||
RenderPlayer.field_77110_j = ObjectArrays.concat(RenderPlayer.field_77110_j, armor);
|
||||
return RenderPlayer.field_77110_j.length - 1;
|
||||
}
|
||||
|
||||
public static RenderingRegistry instance()
|
||||
{
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
private 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 void registerEntityRenderingHandler(Class<? extends Entity> entityClass, Render renderer)
|
||||
{
|
||||
entityRenderers.add(new EntityRendererInfo(entityClass, renderer));
|
||||
}
|
||||
|
||||
public void registerBlockHandler(ISimpleBlockRenderingHandler handler)
|
||||
{
|
||||
blockRenderers.put(handler.getRenderId(), handler);
|
||||
}
|
||||
|
||||
public int getNextAvailableRenderId()
|
||||
{
|
||||
return nextRenderId++;
|
||||
}
|
||||
/**
|
||||
* @param renderer
|
||||
* @param world
|
||||
* @param x
|
||||
* @param y
|
||||
* @param z
|
||||
* @param block
|
||||
* @param modelId
|
||||
* @return
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param renderer
|
||||
* @param block
|
||||
* @param metadata
|
||||
* @param modelID
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param p_1219_0_
|
||||
* @return
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,440 @@
|
||||
/*
|
||||
* 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.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import cpw.mods.fml.client.FMLClientHandler;
|
||||
import cpw.mods.fml.common.IConsoleHandler;
|
||||
import cpw.mods.fml.common.ICraftingHandler;
|
||||
import cpw.mods.fml.common.IDispenseHandler;
|
||||
import cpw.mods.fml.common.INetworkHandler;
|
||||
import cpw.mods.fml.common.IPickupNotifier;
|
||||
import cpw.mods.fml.common.IPlayerTracker;
|
||||
import cpw.mods.fml.common.IWorldGenerator;
|
||||
import cpw.mods.fml.common.TickType;
|
||||
|
||||
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 = true;
|
||||
// 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();
|
||||
if (tickEnd && ( tick==TickType.RENDER || tick==TickType.CLIENT)) {
|
||||
return onTickInGUI((Float) data[0], mc, mc.field_71462_r);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param minecraftInstance
|
||||
* @return
|
||||
*//*
|
||||
|
||||
*//**
|
||||
* @param renderers
|
||||
*//*
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
*//**
|
||||
* NO-OP on client side
|
||||
*//*
|
||||
@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
|
||||
* @return
|
||||
*/
|
||||
public int addFuel(int id, int metadata)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
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
|
||||
* @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(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
|
||||
*/
|
||||
public boolean onTickInGame(float time, Minecraft minecraftInstance)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean onTickInGUI(float tick, Minecraft game, GuiScreen gui)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Only implemented on the client side
|
||||
* {@link #onChatMessageReceived(EntityPlayer, Packet3Chat)}
|
||||
*
|
||||
* @param text
|
||||
*/
|
||||
@Override
|
||||
public void receiveChatPacket(String text)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
/**
|
||||
* Only called on the client side
|
||||
* {@link #onPacket250Received(EntityPlayer, Packet250CustomPayload)}
|
||||
*
|
||||
* @param packet
|
||||
*/
|
||||
@Override
|
||||
public void receiveCustomPacket(Packet250CustomPayload packet)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
public void registerAnimation(Minecraft game)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void renderInvBlock(RenderBlocks renderer, Block block, int metadata, int modelID)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
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 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 250 packet is received on a channel registered to this mod
|
||||
*
|
||||
* @param source
|
||||
* @param payload
|
||||
*/
|
||||
@Override
|
||||
public void onPacket250Received(EntityPlayer 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(EntityPlayer 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, Object listener)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a new client logs in.
|
||||
*
|
||||
* @param player
|
||||
*/
|
||||
@Override
|
||||
public void onClientLogin(EntityPlayer player)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a client logs out of the server.
|
||||
*
|
||||
* @param player
|
||||
*/
|
||||
@Override
|
||||
public void onClientLogout(NetworkManager mgr)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Called when a client changes dimensions on the server.
|
||||
*
|
||||
* @param player
|
||||
*/
|
||||
public void onClientDimensionChanged(EntityPlayer player)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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,91 @@
|
||||
/*
|
||||
* 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.FMLClientHandler;
|
||||
import cpw.mods.fml.client.TextureFXManager;
|
||||
import cpw.mods.fml.client.registry.RenderingRegistry;
|
||||
import cpw.mods.fml.common.FMLCommonHandler;
|
||||
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, TexturePackBase texturePack, List<TextureFX> textureFXList)
|
||||
{
|
||||
TextureFXManager.instance().onTexturePackChange(engine, texturePack, textureFXList);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
public static void renderInventoryBlock(RenderBlocks renderer, Block block, int metadata, int modelID)
|
||||
{
|
||||
RenderingRegistry.instance().renderInventoryBlock(renderer, block, metadata, modelID);
|
||||
}
|
||||
|
||||
public static boolean renderItemAsFull3DBlock(int modelId)
|
||||
{
|
||||
return RenderingRegistry.instance().renderItemAsFull3DBlock(modelId);
|
||||
}
|
||||
}
|
||||
@@ -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.src;
|
||||
|
||||
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,807 @@
|
||||
/*
|
||||
* 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.image.BufferedImage;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
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.modloader.ModLoaderHelper;
|
||||
import cpw.mods.fml.common.modloader.ModLoaderModContainer;
|
||||
import cpw.mods.fml.common.network.NetworkRegistry;
|
||||
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.common.ObfuscationReflectionHelper;
|
||||
|
||||
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();
|
||||
/**
|
||||
* Not used on the server.
|
||||
*
|
||||
* @param achievement
|
||||
* @param name
|
||||
* @param 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 FMLCommonHandler#fuelLookup(int, int)}
|
||||
*
|
||||
* @param id
|
||||
* @param metadata
|
||||
* @return
|
||||
*/
|
||||
@Deprecated
|
||||
public static int addAllFuel(int id, int metadata)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void addAllRenderers(Map<Class<? extends Entity>, Render> renderers)
|
||||
{
|
||||
}
|
||||
|
||||
public static void addAnimation(TextureFX anim)
|
||||
{
|
||||
TextureFXManager.instance().addAnimation(anim);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is unimplemented in server versions to date.
|
||||
*
|
||||
* @param armor
|
||||
* @return
|
||||
*/
|
||||
public static int addArmor(String armor)
|
||||
{
|
||||
return RenderingRegistry.instance().addNewArmourRendererPrefix(armor);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method adds the supplied biome to the set of candidate biomes for the default world generator type.
|
||||
*
|
||||
* @param biome
|
||||
*/
|
||||
public static void addBiome(BiomeGenBase biome)
|
||||
{
|
||||
GameRegistry.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)
|
||||
{
|
||||
LanguageRegistry.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)
|
||||
{
|
||||
LanguageRegistry.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)
|
||||
{
|
||||
int idx = SpriteHelper.getUniqueSpriteIndex(fileToOverride);
|
||||
addOverride(fileToOverride, fileToAdd, idx);
|
||||
return idx;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
TextureFXManager.instance().addNewTextureOverride(path, overlayPath, index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a Shaped Recipe
|
||||
*
|
||||
* @param output
|
||||
* @param params
|
||||
*/
|
||||
public static void addRecipe(ItemStack output, Object... params)
|
||||
{
|
||||
GameRegistry.addRecipe(output, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a shapeless recipe
|
||||
*
|
||||
* @param output
|
||||
* @param params
|
||||
*/
|
||||
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 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is a call in hook from modified external code. Implemented elsewhere.
|
||||
* {@link FMLClientHandler#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.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
|
||||
*/
|
||||
public static List<BaseMod> getLoadedMods()
|
||||
{
|
||||
return ModLoaderModContainer.findAll(BaseMod.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a logger instance {@link FMLCommonHandler#getFMLLogger()}
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static Logger getLogger()
|
||||
{
|
||||
return FMLLog.getLogger();
|
||||
}
|
||||
|
||||
public static Minecraft getMinecraftInstance()
|
||||
{
|
||||
return FMLClientHandler.instance().getClient();
|
||||
}
|
||||
|
||||
/**
|
||||
* This is not the server
|
||||
* {@link FMLClientHandler#getServer()}
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
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
|
||||
*
|
||||
*/
|
||||
public static int getUniqueBlockModelID(BaseMod mod, boolean inventoryRenderer)
|
||||
{
|
||||
return ModLoaderClientHelper.obtainBlockModelIdFor(mod, inventoryRenderer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a new unique entity id
|
||||
* {@link Entity#getNextId()}
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static int getUniqueEntityId()
|
||||
{
|
||||
return EntityRegistry.findGlobalUniqueEntityId();
|
||||
}
|
||||
|
||||
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
|
||||
*/
|
||||
public static boolean isChannelActive(EntityPlayer player, String channel)
|
||||
{
|
||||
return NetworkRegistry.instance().isChannelActive(channel, (Player)player);
|
||||
}
|
||||
|
||||
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
|
||||
*/
|
||||
public static boolean isModLoaded(String modname)
|
||||
{
|
||||
return Loader.isModLoaded(modname);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implemented elsewhere
|
||||
*/
|
||||
@Deprecated
|
||||
public static void loadConfig()
|
||||
{
|
||||
}
|
||||
|
||||
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
|
||||
public static void onTick(float tick, Minecraft game)
|
||||
{
|
||||
}
|
||||
|
||||
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 FMLServerHandler#handlePacket250(Packet250CustomPayload, EntityPlayer)}
|
||||
*
|
||||
* @param packet
|
||||
*/
|
||||
@Deprecated
|
||||
public static void receivePacket(Packet250CustomPayload packet)
|
||||
{
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static KeyBinding[] registerAllKeys(KeyBinding[] keys)
|
||||
{
|
||||
return keys;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
public static void registerKey(BaseMod mod, KeyBinding keyHandler, boolean allowRepeat)
|
||||
{
|
||||
ModLoaderModContainer mlmc=ModLoaderHelper.registerKeyHelper(mod);
|
||||
KeyBindingRegistry.registerKeyBinding(new ModLoaderKeyBindingHandler(keyHandler, allowRepeat, mlmc));
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the mod for packets on this channel.
|
||||
* {@link FMLCommonHandler#registerChannel(cpw.mods.fml.common.ModContainer, 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);
|
||||
}
|
||||
|
||||
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
|
||||
public static boolean renderBlockIsItemFull3D(int modelID)
|
||||
{
|
||||
return RenderingRegistry.instance().renderItemAsFull3DBlock(modelID);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void renderInvBlock(RenderBlocks renderer, Block block, int metadata, int modelID)
|
||||
{
|
||||
RenderingRegistry.instance().renderInventoryBlock(renderer, block, metadata, modelID);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
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()
|
||||
{
|
||||
}
|
||||
|
||||
public static void sendPacket(Packet packet) {
|
||||
// TODO
|
||||
// FMLClientHandler.instance().sendPacket(packet);
|
||||
}
|
||||
/**
|
||||
* Send a chat message to the server
|
||||
* {@link FMLClientHandler#handleChatPacket(Packet3Chat, EntityPlayer)}
|
||||
*
|
||||
* @param text
|
||||
*/
|
||||
@Deprecated
|
||||
public static void serverChat(String text)
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void serverLogin(NetClientHandler 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 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.
|
||||
* {@link FMLClientHandler#onItemCrafted(EntityPlayer, ItemStack, IInventory)}
|
||||
*
|
||||
* @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.
|
||||
* {@link FMLClientHandler#onItemSmelted(EntityPlayer, ItemStack)}
|
||||
*
|
||||
* @param player
|
||||
* @param item
|
||||
*/
|
||||
@Deprecated
|
||||
public static void takenFromFurnace(EntityPlayer player, ItemStack item)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw the offered exception. Likely will stop the game.
|
||||
* {@link FMLClientHandler#raiseException(Throwable, String, boolean)}
|
||||
*
|
||||
* @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,128 @@
|
||||
/*
|
||||
* 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;
|
||||
import cpw.mods.fml.common.FMLCommonHandler;
|
||||
import static org.lwjgl.opengl.GL11.*;
|
||||
|
||||
/**
|
||||
* 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_783_a()
|
||||
{
|
||||
if (++ticks >= tickRate)
|
||||
{
|
||||
if (++index >= images.length)
|
||||
{
|
||||
index = 0;
|
||||
}
|
||||
|
||||
field_76852_a = images[index];
|
||||
ticks = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* 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;
|
||||
import cpw.mods.fml.common.FMLCommonHandler;
|
||||
import static org.lwjgl.opengl.GL11.*;
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
public void func_783_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--;
|
||||
}
|
||||
}
|
||||
|
||||
public void func_782_a(RenderEngine p_782_1_)
|
||||
{
|
||||
GL11.glBindTexture(GL_TEXTURE_2D, p_782_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);
|
||||
}
|
||||
}
|
||||
+164
@@ -0,0 +1,164 @@
|
||||
--- 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)
|
||||
@@ -582,6 +584,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"""
|
||||
@@ -779,7 +784,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):
|
||||
@@ -1039,6 +1045,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],
|
||||
@@ -1060,7 +1067,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)
|
||||
@@ -1068,7 +1075,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)
|
||||
@@ -1195,20 +1202,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 = {
|
||||
@@ -1238,6 +1245,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
|
||||
@@ -1320,12 +1332,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"""
|
||||
@@ -1334,6 +1348,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'))
|
||||
@@ -1342,13 +1371,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 = {
|
||||
@@ -1420,6 +1449,7 @@
|
||||
|
||||
# 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)
|
||||
@@ -1592,6 +1622,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])
|
||||
@@ -0,0 +1,125 @@
|
||||
package cpw.mods.fml.common;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.eventbus.EventBus;
|
||||
|
||||
import cpw.mods.fml.common.LoaderState.ModState;
|
||||
import cpw.mods.fml.common.discovery.ContainerType;
|
||||
import cpw.mods.fml.common.versioning.ArtifactVersion;
|
||||
|
||||
public class DummyModContainer implements ModContainer
|
||||
{
|
||||
private ModMetadata md;
|
||||
|
||||
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 List<ArtifactVersion> getRequirements()
|
||||
{
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@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()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isImmutable()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNetworkMod()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,394 @@
|
||||
/*
|
||||
* 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.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Random;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipException;
|
||||
import java.util.zip.ZipFile;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.src.DedicatedServer;
|
||||
import net.minecraft.src.Entity;
|
||||
import net.minecraft.src.EntityPlayer;
|
||||
import net.minecraft.src.World;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableList.Builder;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import cpw.mods.fml.common.discovery.ContainerType;
|
||||
import cpw.mods.fml.common.network.EntitySpawnAdjustmentPacket;
|
||||
import cpw.mods.fml.common.network.EntitySpawnPacket;
|
||||
import cpw.mods.fml.common.registry.TickRegistry;
|
||||
import cpw.mods.fml.common.registry.GameRegistry;
|
||||
|
||||
|
||||
/**
|
||||
* 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();
|
||||
|
||||
public void beginLoading(IFMLSidedHandler handler)
|
||||
{
|
||||
sidedDelegate = handler;
|
||||
FMLLog.info("Attempting early MinecraftForge initialization");
|
||||
callForgeMethod("initialize");
|
||||
FMLLog.info("Completed early MinecraftForge initialization");
|
||||
}
|
||||
|
||||
public void rescheduleTicks(Side side)
|
||||
{
|
||||
sidedDelegate.profileStart("modTickScheduling");
|
||||
TickRegistry.updateTickQueue(side.isClient() ? scheduledClientTicks : scheduledServerTicks, side);
|
||||
sidedDelegate.profileEnd();
|
||||
}
|
||||
public void tickStart(EnumSet<TickType> ticks, Side side, Object ... data)
|
||||
{
|
||||
List<IScheduledTickHandler> scheduledTicks = side.isClient() ? scheduledClientTicks : scheduledServerTicks;
|
||||
|
||||
if (scheduledTicks.size()==0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
sidedDelegate.profileStart("modTickStart$"+ticks);
|
||||
for (IScheduledTickHandler ticker : scheduledTicks)
|
||||
{
|
||||
EnumSet<TickType> ticksToRun = EnumSet.copyOf(ticker.ticks());
|
||||
ticksToRun.removeAll(EnumSet.complementOf(ticks));
|
||||
if (!ticksToRun.isEmpty())
|
||||
{
|
||||
sidedDelegate.profileStart(ticker.getLabel());
|
||||
ticker.tickStart(ticksToRun, data);
|
||||
sidedDelegate.profileEnd();
|
||||
}
|
||||
}
|
||||
sidedDelegate.profileEnd();
|
||||
}
|
||||
|
||||
public void tickEnd(EnumSet<TickType> ticks, Side side, Object ... data)
|
||||
{
|
||||
List<IScheduledTickHandler> scheduledTicks = side.isClient() ? scheduledClientTicks : scheduledServerTicks;
|
||||
|
||||
if (scheduledTicks.size()==0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
sidedDelegate.profileStart("modTickEnd$"+ticks);
|
||||
for (IScheduledTickHandler ticker : scheduledTicks)
|
||||
{
|
||||
EnumSet<TickType> ticksToRun = EnumSet.copyOf(ticker.ticks());
|
||||
ticksToRun.removeAll(EnumSet.complementOf(ticks));
|
||||
if (!ticksToRun.isEmpty())
|
||||
{
|
||||
sidedDelegate.profileStart(ticker.getLabel());
|
||||
ticker.tickEnd(ticksToRun, data);
|
||||
sidedDelegate.profileEnd();
|
||||
}
|
||||
}
|
||||
sidedDelegate.profileEnd();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the instance
|
||||
*/
|
||||
public static FMLCommonHandler instance()
|
||||
{
|
||||
return INSTANCE;
|
||||
}
|
||||
/**
|
||||
* Find the container that associates with the supplied mod object
|
||||
* @param mod
|
||||
* @return
|
||||
*/
|
||||
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();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key
|
||||
* @param lang
|
||||
* @param value
|
||||
*/
|
||||
/**
|
||||
* @param languagePack
|
||||
* @param lang
|
||||
*/
|
||||
|
||||
public Side getSide()
|
||||
{
|
||||
return sidedDelegate.getSide();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
if (stopGame)
|
||||
{
|
||||
getSidedDelegate().haltGame(message,exception);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private Class<?> forge;
|
||||
private boolean noForge;
|
||||
private List<String> brandings;
|
||||
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;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @param string
|
||||
* @return
|
||||
*/
|
||||
public void computeBranding()
|
||||
{
|
||||
if (brandings == null)
|
||||
{
|
||||
Builder brd = ImmutableList.<String>builder();
|
||||
brd.add(Loader.instance().getMCVersionString());
|
||||
brd.add(Loader.instance().getFMLVersionString());
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
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(Class<? extends Entity> cls, EntitySpawnPacket entitySpawnPacket)
|
||||
{
|
||||
return sidedDelegate.spawnEntityIntoClientWorld(cls, entitySpawnPacket);
|
||||
}
|
||||
|
||||
public void adjustEntityLocationOnClient(EntitySpawnAdjustmentPacket entitySpawnAdjustmentPacket)
|
||||
{
|
||||
sidedDelegate.adjustEntityLocationOnClient(entitySpawnAdjustmentPacket);
|
||||
}
|
||||
|
||||
public void onServerStart(DedicatedServer dedicatedServer)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Done this way so that the client doesn't depend on server side handler
|
||||
Class<?> cls = Class.forName("cpw.mods.fml.server.FMLServerHandler", true, getClass().getClassLoader());
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
{
|
||||
FMLLog.log(Level.SEVERE, e, "Unable to load the FML server handler");
|
||||
throw Throwables.propagate(e);
|
||||
}
|
||||
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)
|
||||
{
|
||||
tickStart(EnumSet.of(TickType.PLAYER), Side.SERVER, player);
|
||||
}
|
||||
|
||||
public void onPlayerPostTick(EntityPlayer player)
|
||||
{
|
||||
tickEnd(EnumSet.of(TickType.PLAYER), Side.SERVER, player);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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 com.google.common.eventbus.EventBus;
|
||||
|
||||
/**
|
||||
* @author cpw
|
||||
*
|
||||
*/
|
||||
public class FMLDummyContainer extends DummyModContainer
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -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, String.format(format, data));
|
||||
}
|
||||
|
||||
public static void log(Level level, Throwable ex, String format, Object... data)
|
||||
{
|
||||
coreLog.log(level, String.format(format, data), ex);
|
||||
}
|
||||
|
||||
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,328 @@
|
||||
/*
|
||||
* 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.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
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.ImmutableList;
|
||||
import com.google.common.collect.Iterators;
|
||||
import com.google.common.collect.ImmutableBiMap.Builder;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.collect.Table;
|
||||
import com.google.common.eventbus.EventBus;
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
|
||||
import cpw.mods.fml.common.LoaderState.ModState;
|
||||
import cpw.mods.fml.common.Mod.Block;
|
||||
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.discovery.ContainerType;
|
||||
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.registry.GameRegistry;
|
||||
import cpw.mods.fml.common.versioning.ArtifactVersion;
|
||||
import cpw.mods.fml.common.versioning.DefaultArtifactVersion;
|
||||
|
||||
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 List<ArtifactVersion> requirements;
|
||||
private List<ArtifactVersion> dependencies;
|
||||
private List<ArtifactVersion> dependants;
|
||||
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();
|
||||
|
||||
|
||||
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 modMetadata.version;
|
||||
}
|
||||
|
||||
@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("usesMetadata"))
|
||||
{
|
||||
overridesMetadata = !((Boolean)descriptor.get("usesMetadata")).booleanValue();
|
||||
}
|
||||
|
||||
if (overridesMetadata || !modMetadata.useDependencyInformation)
|
||||
{
|
||||
List<ArtifactVersion> requirements = Lists.newArrayList();
|
||||
List<ArtifactVersion> dependencies = Lists.newArrayList();
|
||||
List<ArtifactVersion> dependants = Lists.newArrayList();
|
||||
Loader.instance().computeDependencies((String) descriptor.get("dependencies"), requirements, dependencies, dependants);
|
||||
modMetadata.requiredMods = requirements;
|
||||
modMetadata.dependencies = dependencies;
|
||||
modMetadata.dependants = dependants;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnabledState(boolean enabled)
|
||||
{
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<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 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 (Field f : clazz.getDeclaredFields())
|
||||
{
|
||||
for (Annotation a : f.getAnnotations())
|
||||
{
|
||||
f.setAccessible(true);
|
||||
anns.put(a.annotationType(), f);
|
||||
}
|
||||
}
|
||||
|
||||
for (Method m : clazz.getDeclaredMethods())
|
||||
{
|
||||
for (Annotation a : m.getAnnotations())
|
||||
{
|
||||
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() throws Exception
|
||||
{
|
||||
// Instance annotation
|
||||
for (Object o : annotations.get(Instance.class))
|
||||
{
|
||||
Field f = (Field) o;
|
||||
f.set(modInstance, modInstance);
|
||||
}
|
||||
|
||||
for (Object o : annotations.get(Metadata.class))
|
||||
{
|
||||
Field f = (Field) o;
|
||||
f.set(modInstance, modMetadata);
|
||||
}
|
||||
//TODO
|
||||
// for (Object o : annotations.get(Block.class))
|
||||
// {
|
||||
// Field f = (Field) o;
|
||||
// f.set(modInstance, GameRegistry.buildBlock(this, f.getType(), f.getAnnotation(Block.class)));
|
||||
// }
|
||||
}
|
||||
|
||||
@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();
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -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 craftedItem
|
||||
* @param craftingGrid
|
||||
*/
|
||||
void onCrafting(EntityPlayer player, ItemStack item, IInventory craftMatrix);
|
||||
|
||||
/**
|
||||
* The object array contains these two arguments
|
||||
* @param player
|
||||
* @param smeltedItem
|
||||
*/
|
||||
void onSmelting(EntityPlayer player, ItemStack item);
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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.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 data
|
||||
* @return
|
||||
*/
|
||||
int dispense(double x, double y, double z, int xVelocity, int zVelocity, World world, ItemStack item);
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package cpw.mods.fml.common;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.src.DedicatedServer;
|
||||
import net.minecraft.src.Entity;
|
||||
import net.minecraft.src.World;
|
||||
|
||||
import cpw.mods.fml.common.modloader.ModProperty;
|
||||
import cpw.mods.fml.common.network.EntitySpawnAdjustmentPacket;
|
||||
import cpw.mods.fml.common.network.EntitySpawnPacket;
|
||||
|
||||
public interface IFMLSidedHandler
|
||||
{
|
||||
void profileStart(String profileLabel);
|
||||
|
||||
void profileEnd();
|
||||
|
||||
List<String> getAdditionalBrandingInformation();
|
||||
|
||||
Side getSide();
|
||||
|
||||
void haltGame(String message, Throwable exception);
|
||||
|
||||
void showGuiScreen(Object clientGuiElement);
|
||||
|
||||
Entity spawnEntityIntoClientWorld(Class<? extends Entity> entityClass, EntitySpawnPacket packet);
|
||||
|
||||
void adjustEntityLocationOnClient(EntitySpawnAdjustmentPacket entitySpawnAdjustmentPacket);
|
||||
|
||||
void beginServerLoading(MinecraftServer server);
|
||||
|
||||
void finishServerLoading();
|
||||
|
||||
MinecraftServer getServer();
|
||||
}
|
||||
@@ -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,19 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
public interface IPickupNotifier
|
||||
{
|
||||
void notifyPickup(Object... pickupData);
|
||||
}
|
||||
@@ -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 IPlayerTracker
|
||||
{
|
||||
void onPlayerLogin(Object player);
|
||||
void onPlayerLogout(Object player);
|
||||
void onPlayerChangedDimension(Object player);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
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.
|
||||
* @param tick
|
||||
* @return
|
||||
*/
|
||||
public int nextTickSpacing();
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public EnumSet<TickType> ticks();
|
||||
|
||||
/**
|
||||
* A profiling label for this tick handler
|
||||
* @return
|
||||
*/
|
||||
public String getLabel();
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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. The {@link #generate(Random, int, int, Object...)} method passes in some additional data that
|
||||
* can be cast into minecraft objects.
|
||||
*
|
||||
* @author cpw
|
||||
*
|
||||
*/
|
||||
public interface IWorldGenerator
|
||||
{
|
||||
/**
|
||||
* Generate some world
|
||||
*
|
||||
* @param random the chunk specific {@link Random}.
|
||||
* @param chunkX the block X coordinate of this chunk.
|
||||
* @param chunkZ the block Z coordinate of this chunk.
|
||||
* @param world : additionalData[0] The minecraft {@link World} we're generating for.
|
||||
* @param generator : 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,106 @@
|
||||
package cpw.mods.fml.common;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.eventbus.EventBus;
|
||||
|
||||
import cpw.mods.fml.common.versioning.ArtifactVersion;
|
||||
|
||||
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 List<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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,193 @@
|
||||
package cpw.mods.fml.common;
|
||||
|
||||
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.HashBiMap;
|
||||
import com.google.common.collect.ImmutableBiMap;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.ImmutableMap.Builder;
|
||||
import com.google.common.collect.Iterators;
|
||||
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.FMLConstructionEvent;
|
||||
import cpw.mods.fml.common.event.FMLLoadEvent;
|
||||
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
|
||||
import cpw.mods.fml.common.event.FMLStateEvent;
|
||||
import cpw.mods.fml.common.network.FMLNetworkHandler;
|
||||
|
||||
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 String 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)
|
||||
{
|
||||
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());
|
||||
}
|
||||
|
||||
// Throw embedding the first error (usually the only one)
|
||||
throw new LoaderException(errors.values().iterator().next());
|
||||
}
|
||||
}
|
||||
|
||||
public ModContainer activeContainer()
|
||||
{
|
||||
return activeContainer!=null ? modList.get(activeContainer) : null;
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void propogateStateMessage(FMLStateEvent stateEvent)
|
||||
{
|
||||
for (Map.Entry<String,EventBus> entry : eventChannels.entrySet())
|
||||
{
|
||||
activeContainer = entry.getKey();
|
||||
stateEvent.applyModContainer(activeContainer());
|
||||
FMLLog.finer("Posting state event %s to mod %s", stateEvent, entry.getKey());
|
||||
entry.getValue().post(stateEvent);
|
||||
FMLLog.finer("State event %s delivered to mod %s", stateEvent, entry.getKey());
|
||||
activeContainer = null;
|
||||
if (!errors.containsKey(entry.getKey()))
|
||||
{
|
||||
modStates.put(entry.getKey(), stateEvent.getModState());
|
||||
}
|
||||
else
|
||||
{
|
||||
modStates.put(entry.getKey(), ModState.ERRORED);
|
||||
}
|
||||
}
|
||||
if (stateEvent instanceof FMLConstructionEvent)
|
||||
{
|
||||
buildModObjectList();
|
||||
}
|
||||
}
|
||||
|
||||
public void buildModObjectList()
|
||||
{
|
||||
ImmutableBiMap.Builder<ModContainer, Object> builder = ImmutableBiMap.<ModContainer, Object>builder();
|
||||
for (ModContainer mc : activeModList)
|
||||
{
|
||||
builder.put(mc, mc.getMod());
|
||||
}
|
||||
modObjectList = builder.build();
|
||||
}
|
||||
|
||||
public void errorOccurred(ModContainer modContainer, Throwable exception)
|
||||
{
|
||||
errors.put(modContainer.getModId(), exception);
|
||||
}
|
||||
|
||||
public void printModStates(StringBuilder ret)
|
||||
{
|
||||
for (String modId : modStates.keySet())
|
||||
{
|
||||
ModContainer mod = modList.get(modId);
|
||||
ret.append("\n\t").append(mod.getName()).append(" (").append(mod.getSource().getName()).append(") ");
|
||||
Joiner.on("->"). appendTo(ret, modStates.get(modId));
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
return ImmutableBiMap.copyOf(modObjectList);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,617 @@
|
||||
/*
|
||||
* 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.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.MalformedURLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Hashtable;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.logging.Level;
|
||||
import java.util.regex.Matcher;
|
||||
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
|
||||
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.base.Splitter.MapSplitter;
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.collect.BiMap;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
import cpw.mods.fml.common.LoaderState.ModState;
|
||||
import cpw.mods.fml.common.discovery.ContainerType;
|
||||
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.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 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());
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
{
|
||||
Map<String, ArtifactVersion> modVersions = Maps.newHashMap();
|
||||
for (ModContainer mod : mods)
|
||||
{
|
||||
modVersions.put(mod.getModId(), mod.getProcessedVersion());
|
||||
}
|
||||
|
||||
for (ModContainer mod : mods)
|
||||
{
|
||||
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())))
|
||||
{
|
||||
FMLLog.log(Level.SEVERE, "The mod %s (%s) requires mods %s to be available, one or more are not", mod.getModId(), mod.getName(), allDeps);
|
||||
throw new LoaderException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FMLLog.fine("All mod requirements are satisfied");
|
||||
|
||||
ModSorter sorter = new ModSorter(mods, namedMods);
|
||||
|
||||
try
|
||||
{
|
||||
FMLLog.fine("Sorting mods into an ordered list");
|
||||
mods = sorter.sort();
|
||||
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 : mods)
|
||||
{
|
||||
if (!mod.isImmutable())
|
||||
{
|
||||
FMLLog.fine("\t%s(%s): %s (%s)", mod.getModId(), mod.getName(), 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());
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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 ImmutableList.copyOf(instance().mods);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called from the hook to start mod loading. We trigger the
|
||||
* {@link #identifyMods()} and {@link #preModInit()} 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();
|
||||
sortModList();
|
||||
mods = ImmutableList.copyOf(mods);
|
||||
modController.distributeStateMessage(FMLLoadEvent.class);
|
||||
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 disabledModList = System.getProperty("fml.modStates", "");
|
||||
FMLLog.fine("Received a system property request \'%s\'",disabledModList);
|
||||
Map<String, String> sysPropertyStateList = Splitter.on(CharMatcher.anyOf(";:"))
|
||||
.omitEmptyStrings().trimResults().withKeyValueSeparator("=")
|
||||
.split(disabledModList);
|
||||
FMLLog.fine("System property request managing the state of %d mods", sysPropertyStateList.size());
|
||||
Map<String, String> modStates = Maps.newHashMap();
|
||||
|
||||
File disabledModFile = new File(canonicalConfigDir, "fmlModState.properties");
|
||||
Properties disabledModListProperties = new Properties();
|
||||
if (disabledModFile.exists() && disabledModFile.isFile())
|
||||
{
|
||||
FMLLog.fine("Found a mod state file %s", disabledModFile.getName());
|
||||
try
|
||||
{
|
||||
disabledModListProperties.load(new FileReader(disabledModFile));
|
||||
FMLLog.fine("Loaded states for %d mods from file", disabledModListProperties.size());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
FMLLog.log(Level.INFO, e, "An error occurred reading the fmlModState.properties file");
|
||||
}
|
||||
}
|
||||
modStates.putAll(Maps.fromProperties(disabledModListProperties));
|
||||
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
|
||||
*/
|
||||
public static boolean isModLoaded(String modname)
|
||||
{
|
||||
return instance().namedMods.containsKey(modname);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
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();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public String getFMLVersionString()
|
||||
{
|
||||
return String.format("FML v%s.%s.%s.%s", major, minor, rev, build);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public ClassLoader getModClassLoader()
|
||||
{
|
||||
return modClassLoader;
|
||||
}
|
||||
|
||||
public void computeDependencies(String dependencyString, List<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 Callable getCallableCrashInformation()
|
||||
{
|
||||
return new Callable<String>() {
|
||||
@Override
|
||||
public String call() throws Exception
|
||||
{
|
||||
return getCrashInformation();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public List<ModContainer> getActiveModList()
|
||||
{
|
||||
return modController.getActiveModList();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -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.common;
|
||||
|
||||
public class LoaderException extends RuntimeException
|
||||
{
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = -5675297950958861378L;
|
||||
|
||||
public LoaderException(Throwable wrapped)
|
||||
{
|
||||
super(wrapped);
|
||||
}
|
||||
|
||||
public LoaderException()
|
||||
{
|
||||
}
|
||||
}
|
||||
+4
-22
@@ -1,15 +1,3 @@
|
||||
/*
|
||||
* Forge Mod Loader
|
||||
* Copyright (c) 2012-2013 cpw.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the GNU Lesser Public License v2.1
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* Contributors:
|
||||
* cpw - implementation
|
||||
*/
|
||||
|
||||
package cpw.mods.fml.common;
|
||||
|
||||
import com.google.common.base.Throwables;
|
||||
@@ -19,10 +7,8 @@ import cpw.mods.fml.common.event.FMLInitializationEvent;
|
||||
import cpw.mods.fml.common.event.FMLLoadCompleteEvent;
|
||||
import cpw.mods.fml.common.event.FMLPostInitializationEvent;
|
||||
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
|
||||
import cpw.mods.fml.common.event.FMLServerAboutToStartEvent;
|
||||
import cpw.mods.fml.common.event.FMLServerStartedEvent;
|
||||
import cpw.mods.fml.common.event.FMLServerStartingEvent;
|
||||
import cpw.mods.fml.common.event.FMLServerStoppedEvent;
|
||||
import cpw.mods.fml.common.event.FMLServerStoppingEvent;
|
||||
import cpw.mods.fml.common.event.FMLStateEvent;
|
||||
|
||||
@@ -40,16 +26,13 @@ public enum LoaderState
|
||||
INITIALIZATION("Initializing mods", FMLInitializationEvent.class),
|
||||
POSTINITIALIZATION("Post-initializing mods", FMLPostInitializationEvent.class),
|
||||
AVAILABLE("Mod loading complete", FMLLoadCompleteEvent.class),
|
||||
SERVER_ABOUT_TO_START("Server about to start", FMLServerAboutToStartEvent.class),
|
||||
SERVER_STARTING("Server starting", FMLServerStartingEvent.class),
|
||||
SERVER_STARTED("Server started", FMLServerStartedEvent.class),
|
||||
SERVER_STOPPING("Server stopping", FMLServerStoppingEvent.class),
|
||||
SERVER_STOPPED("Server stopped", FMLServerStoppedEvent.class),
|
||||
ERRORED("Mod Loading errored",null);
|
||||
|
||||
|
||||
private Class<? extends FMLStateEvent> eventClass;
|
||||
@SuppressWarnings("unused")
|
||||
private String name;
|
||||
|
||||
private LoaderState(String name, Class<? extends FMLStateEvent> event)
|
||||
@@ -65,7 +48,7 @@ public enum LoaderState
|
||||
return ERRORED;
|
||||
}
|
||||
// stopping -> available
|
||||
if (this == SERVER_STOPPED)
|
||||
if (this == SERVER_STOPPING)
|
||||
{
|
||||
return AVAILABLE;
|
||||
}
|
||||
@@ -76,7 +59,7 @@ public enum LoaderState
|
||||
{
|
||||
return eventClass != null;
|
||||
}
|
||||
|
||||
|
||||
public FMLStateEvent getEvent(Object... eventData)
|
||||
{
|
||||
try
|
||||
@@ -104,7 +87,7 @@ public enum LoaderState
|
||||
AVAILABLE("Available"),
|
||||
DISABLED("Disabled"),
|
||||
ERRORED("Errored");
|
||||
|
||||
|
||||
private String label;
|
||||
|
||||
private ModState(String label)
|
||||
@@ -112,10 +95,9 @@ public enum LoaderState
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return this.label;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
package cpw.mods.fml.common;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import argo.jdom.JdomParser;
|
||||
import argo.jdom.JsonNode;
|
||||
import argo.jdom.JsonRootNode;
|
||||
import argo.saj.InvalidSyntaxException;
|
||||
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
public class MetadataCollection
|
||||
{
|
||||
private static JdomParser parser = new JdomParser();
|
||||
private Map<String, ModMetadata> metadatas = Maps.newHashMap();
|
||||
private int metadataVersion = 1;
|
||||
|
||||
public static MetadataCollection from(InputStream inputStream)
|
||||
{
|
||||
if (inputStream == null)
|
||||
{
|
||||
return new MetadataCollection();
|
||||
}
|
||||
|
||||
InputStreamReader reader = new InputStreamReader(inputStream);
|
||||
try
|
||||
{
|
||||
JsonRootNode root = parser.parse(reader);
|
||||
if (root.hasElements())
|
||||
{
|
||||
return parse10ModInfo(root);
|
||||
}
|
||||
else
|
||||
{
|
||||
return parseModInfo(root);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw Throwables.propagate(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static MetadataCollection parseModInfo(JsonRootNode root)
|
||||
{
|
||||
MetadataCollection mc = new MetadataCollection();
|
||||
mc.metadataVersion = Integer.parseInt(root.getNumberValue("modinfoversion"));
|
||||
mc.parseModMetadataList(root.getNode("modlist"));
|
||||
return mc;
|
||||
}
|
||||
|
||||
private static MetadataCollection parse10ModInfo(JsonRootNode root)
|
||||
{
|
||||
MetadataCollection mc = new MetadataCollection();
|
||||
mc.parseModMetadataList(root);
|
||||
return mc;
|
||||
}
|
||||
|
||||
private void parseModMetadataList(JsonNode metadataList)
|
||||
{
|
||||
for (JsonNode node : metadataList.getElements())
|
||||
{
|
||||
ModMetadata mmd = new ModMetadata(node);
|
||||
metadatas.put(mmd.modId, mmd);
|
||||
}
|
||||
}
|
||||
|
||||
public ModMetadata getMetadataForId(String modId, Map<String, Object> extraData)
|
||||
{
|
||||
if (!metadatas.containsKey(modId))
|
||||
{
|
||||
ModMetadata dummy = new ModMetadata();
|
||||
dummy.modId = modId;
|
||||
dummy.name = (String) extraData.get("name");
|
||||
dummy.version = (String) extraData.get("version");
|
||||
dummy.autogenerated = true;
|
||||
metadatas.put(modId, dummy);
|
||||
}
|
||||
return metadatas.get(modId);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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 cpw.mods.fml.common;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
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 net.minecraft.src.ItemBlock;
|
||||
|
||||
/**
|
||||
* The new mod style in FML 1.3
|
||||
*
|
||||
* @author cpw
|
||||
*
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface Mod
|
||||
{
|
||||
/**
|
||||
* The unique mod identifier for this mod
|
||||
* @return
|
||||
*/
|
||||
String modid();
|
||||
/**
|
||||
* A user friendly name for the mod
|
||||
* @return
|
||||
*/
|
||||
String name() default "";
|
||||
/**
|
||||
* A version string for this mod
|
||||
* @return
|
||||
*/
|
||||
String version() default "";
|
||||
/**
|
||||
* A simple dependency string for this mod (see modloader's "priorities" string specification)
|
||||
* @return
|
||||
*/
|
||||
String dependencies() default "";
|
||||
/**
|
||||
* Whether to use the mcmod.info metadata by default for this mod.
|
||||
* If true, settings in the mcmod.info file will override settings in these annotations.
|
||||
* @return
|
||||
*/
|
||||
boolean useMetadata() default false;
|
||||
|
||||
/**
|
||||
* Mark the designated method as being called at the "pre-initialization" phase
|
||||
* @author cpw
|
||||
*
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
public @interface PreInit {}
|
||||
/**
|
||||
* Mark the designated method as being called at the "initialization" phase
|
||||
* @author cpw
|
||||
*
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
public @interface Init {}
|
||||
/**
|
||||
* Mark the designated method as being called at the "post-initialization" phase
|
||||
* @author cpw
|
||||
*
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
public @interface PostInit {}
|
||||
/**
|
||||
* Mark the designated method as being called at the "server-starting" phase
|
||||
* @author cpw
|
||||
*
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
public @interface ServerStarting {}
|
||||
/**
|
||||
* Mark the designated method as being called at the "post-initialization" phase
|
||||
* @author cpw
|
||||
*
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
public @interface ServerStarted {}
|
||||
/**
|
||||
* Mark the designated method as being called at the "post-initialization" phase
|
||||
* @author cpw
|
||||
*
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
public @interface ServerStopping {}
|
||||
/**
|
||||
* Populate the annotated field with the mod instance.
|
||||
* @author cpw
|
||||
*
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
public @interface Instance {
|
||||
/**
|
||||
* The mod object to inject into this field
|
||||
* @return
|
||||
*/
|
||||
String value() default "";
|
||||
}
|
||||
/**
|
||||
* Populate the annotated field with the mod's metadata.
|
||||
* @author cpw
|
||||
*
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
public @interface Metadata {
|
||||
/**
|
||||
* The mod id specifying the metadata to load here
|
||||
* @return
|
||||
*/
|
||||
String value() default "";
|
||||
}
|
||||
/**
|
||||
* Populate the annotated field with an instance of the Block as specified
|
||||
* @author cpw
|
||||
*
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
public @interface Block {
|
||||
/**
|
||||
* The block's name
|
||||
* @return
|
||||
*/
|
||||
String name();
|
||||
/**
|
||||
* The associated ItemBlock subtype for the item (can be null for an ItemBlock)
|
||||
* @return
|
||||
*/
|
||||
Class<?> itemTypeClass() default ItemBlock.class;
|
||||
}
|
||||
/**
|
||||
* Populate the annotated field with an Item
|
||||
* @author cpw
|
||||
*
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
public @interface Item {
|
||||
/**
|
||||
* The name of the item
|
||||
* @return
|
||||
*/
|
||||
String name();
|
||||
/**
|
||||
* The type of the item
|
||||
* @return
|
||||
*/
|
||||
String typeClass();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* 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.lang.reflect.Method;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import cpw.mods.fml.common.discovery.ModCandidate;
|
||||
import cpw.mods.fml.relauncher.FMLRelauncher;
|
||||
import cpw.mods.fml.relauncher.RelaunchClassLoader;
|
||||
|
||||
/**
|
||||
* A simple delegating class loader used to load mods into the system
|
||||
*
|
||||
*
|
||||
* @author cpw
|
||||
*
|
||||
*/
|
||||
public class ModClassLoader extends URLClassLoader
|
||||
{
|
||||
private static final List<String> STANDARD_LIBRARIES = ImmutableList.of("jinput.jar", "lwjgl.jar", "lwjgl_util.jar");
|
||||
private RelaunchClassLoader mainClassLoader;
|
||||
|
||||
public ModClassLoader(ClassLoader parent) {
|
||||
super(new URL[0], null);
|
||||
this.mainClassLoader = (RelaunchClassLoader)parent;
|
||||
}
|
||||
|
||||
public void addFile(File modFile) throws MalformedURLException
|
||||
{
|
||||
URL url = modFile.toURI().toURL();
|
||||
mainClassLoader.addURL(url);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> loadClass(String name) throws ClassNotFoundException
|
||||
{
|
||||
return mainClassLoader.loadClass(name);
|
||||
}
|
||||
|
||||
public File[] getParentSources() {
|
||||
List<URL> urls=mainClassLoader.getSources();
|
||||
File[] sources=new File[urls.size()];
|
||||
try
|
||||
{
|
||||
for (int i = 0; i<urls.size(); i++)
|
||||
{
|
||||
sources[i]=new File(urls.get(i).toURI());
|
||||
}
|
||||
return sources;
|
||||
}
|
||||
catch (URISyntaxException e)
|
||||
{
|
||||
FMLLog.log(Level.SEVERE, "Unable to process our input to locate the minecraft code", e);
|
||||
throw new LoaderException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public List<String> getDefaultLibraries()
|
||||
{
|
||||
return STANDARD_LIBRARIES;
|
||||
}
|
||||
}
|
||||
+41
-38
@@ -1,28 +1,25 @@
|
||||
/*
|
||||
* Forge Mod Loader
|
||||
* Copyright (c) 2012-2013 cpw.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the GNU Lesser Public License v2.1
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* The FML Forge Mod Loader suite.
|
||||
* Copyright (C) 2012 cpw
|
||||
*
|
||||
* Contributors:
|
||||
* cpw - implementation
|
||||
* 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.security.cert.Certificate;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.eventbus.EventBus;
|
||||
|
||||
import cpw.mods.fml.common.LoaderState.ModState;
|
||||
import cpw.mods.fml.common.versioning.ArtifactVersion;
|
||||
import cpw.mods.fml.common.versioning.VersionRange;
|
||||
|
||||
/**
|
||||
* The container that wraps around mods in the system.
|
||||
@@ -39,66 +36,85 @@ import cpw.mods.fml.common.versioning.VersionRange;
|
||||
|
||||
public interface ModContainer
|
||||
{
|
||||
public static enum Disableable {
|
||||
YES, RESTART, NEVER, DEPENDENCIES;
|
||||
}
|
||||
/**
|
||||
* The globally unique modid for this mod
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
String getModId();
|
||||
|
||||
/**
|
||||
* A human readable name
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* A human readable version identifier
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
String getVersion();
|
||||
|
||||
/**
|
||||
* The location on the file system which this mod came from
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
File getSource();
|
||||
|
||||
/**
|
||||
* The metadata for this mod
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
ModMetadata getMetadata();
|
||||
|
||||
/**
|
||||
* Attach this mod to it's metadata from the supplied metadata collection
|
||||
*
|
||||
* @param mc
|
||||
*/
|
||||
void bindMetadata(MetadataCollection mc);
|
||||
|
||||
/**
|
||||
* Set the enabled/disabled state of this mod
|
||||
*
|
||||
* @param enabled
|
||||
*/
|
||||
void setEnabledState(boolean enabled);
|
||||
|
||||
/**
|
||||
* A list of the modids that this mod requires loaded prior to loading
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Set<ArtifactVersion> getRequirements();
|
||||
List<ArtifactVersion> getRequirements();
|
||||
|
||||
/**
|
||||
* A list of modids that should be loaded prior to this one. The special
|
||||
* value <strong>*</strong> indicates to load <em>after</em> any other mod.
|
||||
* value <strong>*</strong> indicates to load <em>before</em> any other mod.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
List<ArtifactVersion> getDependencies();
|
||||
|
||||
/**
|
||||
* A list of modids that should be loaded <em>after</em> this one. The
|
||||
* special value <strong>*</strong> indicates to load <em>before</em> any
|
||||
* special value <strong>*</strong> indicates to load <em>after</em> any
|
||||
* other mod.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
List<ArtifactVersion> getDependants();
|
||||
|
||||
/**
|
||||
* A representative string encapsulating the sorting preferences for this
|
||||
* mod
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
String getSortingRules();
|
||||
|
||||
@@ -110,6 +126,7 @@ public interface ModContainer
|
||||
*
|
||||
* @param bus
|
||||
* @param controller
|
||||
* @return
|
||||
*/
|
||||
boolean registerBus(EventBus bus, LoadController controller);
|
||||
|
||||
@@ -117,11 +134,14 @@ public interface ModContainer
|
||||
* Does this mod match the supplied mod
|
||||
*
|
||||
* @param mod
|
||||
* @return
|
||||
*/
|
||||
boolean matches(Object mod);
|
||||
|
||||
/**
|
||||
* Get the actual mod object
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Object getMod();
|
||||
|
||||
@@ -129,22 +149,5 @@ public interface ModContainer
|
||||
|
||||
boolean isImmutable();
|
||||
|
||||
String getDisplayVersion();
|
||||
|
||||
VersionRange acceptableMinecraftVersionRange();
|
||||
|
||||
Certificate getSigningCertificate();
|
||||
|
||||
public static final Map<String,String> EMPTY_PROPERTIES = ImmutableMap.of();
|
||||
Map<String,String> getCustomModProperties();
|
||||
|
||||
public Class<?> getCustomResourcePackClass();
|
||||
|
||||
Map<String, String> getSharedModDescriptor();
|
||||
|
||||
Disableable canBeDisabled();
|
||||
|
||||
String getGuiClassName();
|
||||
|
||||
List<String> getOwnedPackages();
|
||||
boolean isNetworkMod();
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package cpw.mods.fml.common;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.objectweb.asm.Type;
|
||||
|
||||
import cpw.mods.fml.common.discovery.asm.ASMModParser;
|
||||
import cpw.mods.fml.common.discovery.asm.ModAnnotation;
|
||||
import cpw.mods.fml.common.modloader.ModLoaderModContainer;
|
||||
|
||||
public class ModContainerFactory
|
||||
{
|
||||
private static Pattern modClass = Pattern.compile(".*(\\.|)(mod\\_[^\\s$]+)$");
|
||||
private static ModContainerFactory INSTANCE = new ModContainerFactory();
|
||||
public static ModContainerFactory instance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
public ModContainer build(ASMModParser modParser, File modSource)
|
||||
{
|
||||
String className = modParser.getASMType().getClassName();
|
||||
if (modParser.isBaseMod() && modClass.matcher(className).find())
|
||||
{
|
||||
FMLLog.fine("Identified a BaseMod type mod %s", className);
|
||||
return new ModLoaderModContainer(className, modSource, modParser.getBaseModProperties());
|
||||
}
|
||||
|
||||
for (ModAnnotation ann : modParser.getAnnotations())
|
||||
{
|
||||
if (ann.getASMType().equals(Type.getType(Mod.class)))
|
||||
{
|
||||
FMLLog.fine("Identified a FMLMod type mod %s", className);
|
||||
return new FMLModContainer(className, modSource, ann.getValues());
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* 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.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
import argo.jdom.JsonNode;
|
||||
import argo.jdom.JsonStringNode;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.base.Optional;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
import cpw.mods.fml.common.functions.ModNameFunction;
|
||||
import cpw.mods.fml.common.modloader.ModLoaderModContainer;
|
||||
import cpw.mods.fml.common.versioning.ArtifactVersion;
|
||||
import cpw.mods.fml.common.versioning.VersionParser;
|
||||
|
||||
import static argo.jdom.JsonNodeBuilders.*;
|
||||
|
||||
/**
|
||||
* @author cpw
|
||||
*
|
||||
*/
|
||||
public class ModMetadata
|
||||
{
|
||||
private static final class JsonStringConverter implements Function<JsonNode, Object>
|
||||
{
|
||||
public Object apply(JsonNode arg0)
|
||||
{
|
||||
if (arg0.hasElements())
|
||||
{
|
||||
return Lists.transform(arg0.getElements(), new JsonArrayConverter());
|
||||
}
|
||||
else
|
||||
{
|
||||
return arg0.getText();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final class JsonArrayConverter implements Function<JsonNode, String>
|
||||
{
|
||||
public String apply(JsonNode arg0)
|
||||
{
|
||||
return arg0.getText();
|
||||
}
|
||||
}
|
||||
|
||||
public String modId;
|
||||
public String name;
|
||||
public String description;
|
||||
|
||||
public String url = "";
|
||||
public String updateUrl = "";
|
||||
|
||||
public String logoFile = "";
|
||||
public String version = "";
|
||||
public List<String> authorList = Lists.newArrayList();
|
||||
public String credits = "";
|
||||
public String parent = "";
|
||||
public String[] screenshots;
|
||||
|
||||
public ModContainer parentMod;
|
||||
public List<ModContainer> childMods = Lists.newArrayList();
|
||||
|
||||
public boolean useDependencyInformation;
|
||||
public List<ArtifactVersion> requiredMods;
|
||||
public List<ArtifactVersion> dependencies;
|
||||
public List<ArtifactVersion> dependants;
|
||||
public boolean autogenerated;
|
||||
|
||||
/**
|
||||
* @param mod2
|
||||
* @param type2
|
||||
*/
|
||||
public ModMetadata(JsonNode node)
|
||||
{
|
||||
Map<JsonStringNode, Object> processedFields = Maps.transformValues(node.getFields(), new JsonStringConverter());
|
||||
modId = (String)processedFields.get(aStringBuilder("modid"));
|
||||
name = Strings.nullToEmpty((String)processedFields.get(aStringBuilder("name")));
|
||||
description = Strings.nullToEmpty((String)processedFields.get(aStringBuilder("description")));
|
||||
url = Strings.nullToEmpty((String)processedFields.get(aStringBuilder("url")));
|
||||
updateUrl = Strings.nullToEmpty((String)processedFields.get(aStringBuilder("updateUrl")));
|
||||
logoFile = Strings.nullToEmpty((String)processedFields.get(aStringBuilder("logoFile")));
|
||||
version = Strings.nullToEmpty((String)processedFields.get(aStringBuilder("version")));
|
||||
credits = Strings.nullToEmpty((String)processedFields.get(aStringBuilder("credits")));
|
||||
parent = Strings.nullToEmpty((String)processedFields.get(aStringBuilder("parent")));
|
||||
authorList = Optional.fromNullable((List<String>)processedFields.get(aStringBuilder("authorList"))).or(authorList);
|
||||
requiredMods = processReferences((List<String>)processedFields.get(aStringBuilder("requiredMods")));
|
||||
dependencies = processReferences((List<String>)processedFields.get(aStringBuilder("dependencies")));
|
||||
dependants = processReferences((List<String>)processedFields.get(aStringBuilder("dependants")));
|
||||
useDependencyInformation = Boolean.parseBoolean(Strings.nullToEmpty((String)processedFields.get(aStringBuilder("useDependencyInformation"))));
|
||||
}
|
||||
|
||||
public ModMetadata()
|
||||
{
|
||||
}
|
||||
|
||||
private List<ArtifactVersion> processReferences(List<String> refs)
|
||||
{
|
||||
List<ArtifactVersion> res = Lists.newArrayList();
|
||||
if (refs == null)
|
||||
{
|
||||
return res;
|
||||
}
|
||||
for (String ref : refs)
|
||||
{
|
||||
res.add(VersionParser.parseVersionReference(ref));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public String getChildModCountString()
|
||||
{
|
||||
return String.format("%d child mod%s", childMods.size(), childMods.size() != 1 ? "s" : "");
|
||||
}
|
||||
|
||||
public String getAuthorList()
|
||||
{
|
||||
return Joiner.on(", ").join(authorList);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public String getChildModList()
|
||||
{
|
||||
return Joiner.on(", ").join(Lists.transform(childMods, new ModNameFunction()));
|
||||
}
|
||||
|
||||
public String printableSortingRules()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+34
-22
@@ -13,9 +13,8 @@
|
||||
package cpw.mods.fml.common;
|
||||
|
||||
import java.util.Arrays;
|
||||
import org.apache.logging.log4j.Level;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import cpw.mods.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper;
|
||||
import cpw.mods.fml.relauncher.ReflectionHelper;
|
||||
import cpw.mods.fml.relauncher.ReflectionHelper.UnableToAccessFieldException;
|
||||
import cpw.mods.fml.relauncher.ReflectionHelper.UnableToFindFieldException;
|
||||
@@ -28,6 +27,9 @@ import cpw.mods.fml.relauncher.ReflectionHelper.UnableToFindFieldException;
|
||||
*/
|
||||
public class ObfuscationReflectionHelper
|
||||
{
|
||||
public static boolean obfuscation;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T, E> T getPrivateValue(Class<? super E> classToAccess, E instance, int fieldIndex)
|
||||
{
|
||||
try
|
||||
@@ -36,41 +38,36 @@ public class ObfuscationReflectionHelper
|
||||
}
|
||||
catch (UnableToAccessFieldException e)
|
||||
{
|
||||
FMLLog.log(Level.ERROR, e, "There was a problem getting field index %d from %s", fieldIndex, classToAccess.getName());
|
||||
FMLLog.log(Level.SEVERE, e, "There was a problem getting field index %d from %s", fieldIndex, classToAccess.getName());
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
public static String[] remapFieldNames(String className, String... fieldNames)
|
||||
{
|
||||
String internalClassName = FMLDeobfuscatingRemapper.INSTANCE.unmap(className.replace('.', '/'));
|
||||
String[] mappedNames = new String[fieldNames.length];
|
||||
int i = 0;
|
||||
for (String fName : fieldNames)
|
||||
{
|
||||
mappedNames[i++] = FMLDeobfuscatingRemapper.INSTANCE.mapFieldName(internalClassName, fName, null);
|
||||
}
|
||||
return mappedNames;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T, E> T getPrivateValue(Class<? super E> classToAccess, E instance, String... fieldNames)
|
||||
{
|
||||
try
|
||||
{
|
||||
return ReflectionHelper.getPrivateValue(classToAccess, instance, remapFieldNames(classToAccess.getName(),fieldNames));
|
||||
return ReflectionHelper.getPrivateValue(classToAccess, instance, fieldNames);
|
||||
}
|
||||
catch (UnableToFindFieldException e)
|
||||
{
|
||||
FMLLog.log(Level.ERROR,e,"Unable to locate any field %s on type %s", Arrays.toString(fieldNames), classToAccess.getName());
|
||||
FMLLog.log(Level.SEVERE,e,"Unable to locate any field %s on type %s", Arrays.toString(fieldNames), classToAccess.getName());
|
||||
throw e;
|
||||
}
|
||||
catch (UnableToAccessFieldException e)
|
||||
{
|
||||
FMLLog.log(Level.ERROR, e, "Unable to access any field %s on type %s", Arrays.toString(fieldNames), classToAccess.getName());
|
||||
FMLLog.log(Level.SEVERE, e, "Unable to access any field %s on type %s", Arrays.toString(fieldNames), classToAccess.getName());
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static <T, E> void setPrivateValue(Class<? super T> classToAccess, T instance, int fieldIndex, E value)
|
||||
{
|
||||
setPrivateValue(classToAccess, instance, value, fieldIndex);
|
||||
}
|
||||
|
||||
public static <T, E> void setPrivateValue(Class<? super T> classToAccess, T instance, E value, int fieldIndex)
|
||||
{
|
||||
try
|
||||
@@ -79,26 +76,41 @@ public class ObfuscationReflectionHelper
|
||||
}
|
||||
catch (UnableToAccessFieldException e)
|
||||
{
|
||||
FMLLog.log(Level.ERROR, e, "There was a problem setting field index %d on type %s", fieldIndex, classToAccess.getName());
|
||||
FMLLog.log(Level.SEVERE, e, "There was a problem setting field index %d on type %s", fieldIndex, classToAccess.getName());
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static <T, E> void setPrivateValue(Class<? super T> classToAccess, T instance, String fieldName, E value)
|
||||
{
|
||||
setPrivateValue(classToAccess, instance, value, fieldName);
|
||||
}
|
||||
|
||||
public static <T, E> void setPrivateValue(Class<? super T> classToAccess, T instance, E value, String... fieldNames)
|
||||
{
|
||||
try
|
||||
{
|
||||
ReflectionHelper.setPrivateValue(classToAccess, instance, value, remapFieldNames(classToAccess.getName(), fieldNames));
|
||||
ReflectionHelper.setPrivateValue(classToAccess, instance, value, fieldNames);
|
||||
}
|
||||
catch (UnableToFindFieldException e)
|
||||
{
|
||||
FMLLog.log(Level.ERROR, e, "Unable to locate any field %s on type %s", Arrays.toString(fieldNames), classToAccess.getName());
|
||||
FMLLog.log(Level.SEVERE, e, "Unable to locate any field %s on type %s", Arrays.toString(fieldNames), classToAccess.getName());
|
||||
throw e;
|
||||
}
|
||||
catch (UnableToAccessFieldException e)
|
||||
{
|
||||
FMLLog.log(Level.ERROR, e, "Unable to set any field %s on type %s", Arrays.toString(fieldNames), classToAccess.getName());
|
||||
FMLLog.log(Level.SEVERE, e, "Unable to set any field %s on type %s", Arrays.toString(fieldNames), classToAccess.getName());
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public static void detectObfuscation(Class<?> clazz)
|
||||
{
|
||||
obfuscation = !clazz.getSimpleName().equals("World");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* 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.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.objectweb.asm.Type;
|
||||
|
||||
import cpw.mods.fml.common.discovery.ASMDataTable;
|
||||
import cpw.mods.fml.common.discovery.ASMDataTable.ASMData;
|
||||
|
||||
/**
|
||||
* @author cpw
|
||||
*
|
||||
*/
|
||||
public class ProxyInjector
|
||||
{
|
||||
public static void inject(ModContainer mod, ASMDataTable data, Side side)
|
||||
{
|
||||
FMLLog.fine("Attempting to inject @SidedProxy classes into %s", mod.getModId());
|
||||
Set<ASMData> targets = data.getAnnotationsFor(mod).get(SidedProxy.class.getName());
|
||||
ClassLoader mcl = Loader.instance().getModClassLoader();
|
||||
|
||||
for (ASMData targ : targets)
|
||||
{
|
||||
try
|
||||
{
|
||||
Class<?> proxyTarget = Class.forName(targ.getClassName(), true, mcl);
|
||||
Field target = proxyTarget.getDeclaredField(targ.getObjectName());
|
||||
if (target == null)
|
||||
{
|
||||
// Impossible?
|
||||
FMLLog.severe("Attempted to load a proxy type into %s.%s but the field was not found", targ.getClassName(), targ.getObjectName());
|
||||
throw new LoaderException();
|
||||
}
|
||||
|
||||
String targetType = side.isClient() ? target.getAnnotation(SidedProxy.class).clientSide() : target.getAnnotation(SidedProxy.class).serverSide();
|
||||
Object proxy=Class.forName(targetType, true, mcl).newInstance();
|
||||
|
||||
if ((target.getModifiers() & Modifier.STATIC) == 0 )
|
||||
{
|
||||
FMLLog.severe("Attempted to load a proxy type %s into %s.%s, but the field is not static", targetType, targ.getClassName(), targ.getObjectName());
|
||||
throw new LoaderException();
|
||||
}
|
||||
if (!target.getType().isAssignableFrom(proxy.getClass()))
|
||||
{
|
||||
FMLLog.severe("Attempted to load a proxy type %s into %s.%s, but the types don't match", targetType, targ.getClassName(), targ.getObjectName());
|
||||
throw new LoaderException();
|
||||
}
|
||||
target.set(null, proxy);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
FMLLog.log(Level.SEVERE, e, "An error occured trying to load a proxy into %s.%s", targ.getAnnotationInfo(), targ.getClassName(), targ.getObjectName());
|
||||
throw new LoaderException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
public enum Side {
|
||||
CLIENT, SERVER, BUKKIT;
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public boolean isServer()
|
||||
{
|
||||
return !isClient();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public boolean isClient()
|
||||
{
|
||||
return this == CLIENT;
|
||||
}
|
||||
}
|
||||
@@ -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 cpw.mods.fml.common;
|
||||
|
||||
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 a special bukkit plugin class to load and populate
|
||||
*/
|
||||
String bukkitSide() default "";
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package cpw.mods.fml.common;
|
||||
|
||||
import java.util.EnumSet;
|
||||
|
||||
public class SingleIntervalHandler implements IScheduledTickHandler
|
||||
{
|
||||
private ITickHandler wrapped;
|
||||
public SingleIntervalHandler(ITickHandler handler)
|
||||
{
|
||||
this.wrapped=handler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tickStart(EnumSet<TickType> type, Object... tickData)
|
||||
{
|
||||
wrapped.tickStart(type, tickData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tickEnd(EnumSet<TickType> type, Object... tickData)
|
||||
{
|
||||
wrapped.tickEnd(type, tickData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnumSet<TickType> ticks()
|
||||
{
|
||||
return wrapped.ticks();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLabel()
|
||||
{
|
||||
return wrapped.getLabel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int nextTickSpacing()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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.common;
|
||||
|
||||
import java.util.EnumSet;
|
||||
|
||||
public enum TickType {
|
||||
/**
|
||||
* Fired during the world evaluation loop
|
||||
* server and client side
|
||||
*
|
||||
* arg 0 : The world that is ticking
|
||||
*/
|
||||
WORLD,
|
||||
/**
|
||||
* client side
|
||||
* Fired during the render processing phase
|
||||
* arg 0 : float "partial render time"
|
||||
*/
|
||||
RENDER,
|
||||
/**
|
||||
* client side
|
||||
* Fired during the render processing phase if a GUI is open
|
||||
* arg 0 : float "partial render time"
|
||||
* arg 1 : the open gui or null if no gui is open
|
||||
*/
|
||||
GUI,
|
||||
/**
|
||||
* client side
|
||||
* Fired during the client evaluation loop
|
||||
* arg 0 : The open gui or null if no gui is open
|
||||
*/
|
||||
CLIENTGUI,
|
||||
/**
|
||||
* server side
|
||||
* Fired once as the world loads from disk
|
||||
*/
|
||||
WORLDLOAD,
|
||||
/**
|
||||
* client side only
|
||||
* Fired once per client tick loop.
|
||||
*/
|
||||
CLIENT,
|
||||
/**
|
||||
* client and server side.
|
||||
* Fired whenever the players update loop runs.
|
||||
* arg 0 : the player
|
||||
* arg 1 : the world the player is in
|
||||
*/
|
||||
PLAYER,
|
||||
/**
|
||||
* server side only.
|
||||
* This is the server game tick.
|
||||
* Fired once per tick loop on the server.
|
||||
*/
|
||||
SERVER;
|
||||
|
||||
/**
|
||||
* Partner ticks that are also cancelled by returning false from onTickInGame
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public EnumSet<TickType> partnerTicks()
|
||||
{
|
||||
if (this==CLIENT) return EnumSet.of(RENDER);
|
||||
if (this==RENDER) return EnumSet.of(CLIENT);
|
||||
if (this==GUI) return EnumSet.of(CLIENTGUI);
|
||||
if (this==CLIENTGUI) return EnumSet.of(GUI);
|
||||
return EnumSet.noneOf(TickType.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package cpw.mods.fml.common.asm;
|
||||
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.Type;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
|
||||
import cpw.mods.fml.common.registry.BlockProxy;
|
||||
import cpw.mods.fml.relauncher.IClassTransformer;
|
||||
|
||||
public class ASMTransformer implements IClassTransformer
|
||||
{
|
||||
@Override
|
||||
public byte[] transform(String name, byte[] bytes)
|
||||
{
|
||||
if ("net.minecraft.src.Block".equals(name))
|
||||
{
|
||||
ClassReader cr = new ClassReader(bytes);
|
||||
ClassNode cn = new ClassNode(Opcodes.ASM4);
|
||||
cr.accept(cn, ClassReader.EXPAND_FRAMES);
|
||||
cn.interfaces.add(Type.getInternalName(BlockProxy.class));
|
||||
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
|
||||
cn.accept(cw);
|
||||
return cw.toByteArray();
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package cpw.mods.fml.common.asm;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.swing.JOptionPane;
|
||||
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.ClassVisitor;
|
||||
import org.objectweb.asm.FieldVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import cpw.mods.fml.relauncher.FMLRelauncher;
|
||||
import cpw.mods.fml.relauncher.IFMLCallHook;
|
||||
import cpw.mods.fml.relauncher.RelaunchClassLoader;
|
||||
|
||||
public class FMLSanityChecker implements IFMLCallHook
|
||||
{
|
||||
static class MLDetectorClassVisitor extends ClassVisitor
|
||||
{
|
||||
private boolean foundMarker = false;
|
||||
private MLDetectorClassVisitor()
|
||||
{
|
||||
super(Opcodes.ASM4);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FieldVisitor visitField(int arg0, String arg1, String arg2, String arg3, Object arg4)
|
||||
{
|
||||
if ("fmlMarker".equals(arg1))
|
||||
{
|
||||
foundMarker = true;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private RelaunchClassLoader cl;
|
||||
|
||||
@Override
|
||||
public Void call() throws Exception
|
||||
{
|
||||
byte[] mlClass = cl.getClassBytes("ModLoader");
|
||||
// Only care in obfuscated env
|
||||
if (mlClass == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
MLDetectorClassVisitor mlTester = new MLDetectorClassVisitor();
|
||||
ClassReader cr = new ClassReader(mlClass);
|
||||
cr.accept(mlTester, ClassReader.SKIP_CODE);
|
||||
if (!mlTester.foundMarker)
|
||||
{
|
||||
JOptionPane.showMessageDialog(null, "<html>CRITICAL ERROR<br/>" +
|
||||
"ModLoader was detected in this environment<br/>" +
|
||||
"ForgeModLoader cannot be installed alongside ModLoader<br/>" +
|
||||
"All mods should work without ModLoader being installed<br/>" +
|
||||
"Because ForgeModLoader is 100% compatible with ModLoader<br/>" +
|
||||
"Re-install Minecraft Forge or Forge ModLoader into a clean<br/>" +
|
||||
"jar and try again.",
|
||||
"ForgeModLoader critical error",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
throw new RuntimeException("Invalid ModLoader class detected");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectData(Map<String, Object> data)
|
||||
{
|
||||
cl = (RelaunchClassLoader) data.get("classLoader");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package cpw.mods.fml.common.asm;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import cpw.mods.fml.common.Side;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.CONSTRUCTOR})
|
||||
public @interface SideOnly
|
||||
{
|
||||
public Side value();
|
||||
}
|
||||
+47
-155
@@ -1,66 +1,55 @@
|
||||
/*
|
||||
* Forge Mod Loader
|
||||
* Copyright (c) 2012-2013 cpw.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the GNU Lesser Public License v2.1
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* Contributors:
|
||||
* cpw - implementation
|
||||
*/
|
||||
|
||||
package cpw.mods.fml.common.asm.transformers;
|
||||
|
||||
import static org.objectweb.asm.Opcodes.ACC_FINAL;
|
||||
import static org.objectweb.asm.Opcodes.ACC_PRIVATE;
|
||||
import static org.objectweb.asm.Opcodes.ACC_PROTECTED;
|
||||
import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
|
||||
import static org.objectweb.asm.Opcodes.INVOKESPECIAL;
|
||||
import static org.objectweb.asm.Opcodes.INVOKEVIRTUAL;
|
||||
import static org.objectweb.asm.Opcodes.ACC_FINAL;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.URL;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import net.minecraft.launchwrapper.IClassTransformer;
|
||||
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.tree.AbstractInsnNode;
|
||||
import org.objectweb.asm.Type;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import org.objectweb.asm.tree.FieldNode;
|
||||
import org.objectweb.asm.tree.MethodInsnNode;
|
||||
import org.objectweb.asm.tree.MethodNode;
|
||||
|
||||
import com.google.common.base.CharMatcher;
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.io.CharSource;
|
||||
import com.google.common.io.LineProcessor;
|
||||
import com.google.common.io.Resources;
|
||||
|
||||
import cpw.mods.fml.relauncher.FMLRelaunchLog;
|
||||
import cpw.mods.fml.relauncher.IClassTransformer;
|
||||
|
||||
public class AccessTransformer implements IClassTransformer
|
||||
{
|
||||
private static final boolean DEBUG = Boolean.parseBoolean(System.getProperty("fml.debugAccessTransformer", "false"));
|
||||
class Modifier
|
||||
private class Modifier
|
||||
{
|
||||
public String name = "";
|
||||
public String desc = "";
|
||||
@@ -69,14 +58,13 @@ public class AccessTransformer implements IClassTransformer
|
||||
public int targetAccess = 0;
|
||||
public boolean changeFinal = false;
|
||||
public boolean markFinal = false;
|
||||
protected boolean modifyClassVisibility;
|
||||
|
||||
private void setTargetAccess(String name)
|
||||
{
|
||||
if (name.startsWith("public")) targetAccess = ACC_PUBLIC;
|
||||
else if (name.startsWith("private")) targetAccess = ACC_PRIVATE;
|
||||
else if (name.startsWith("protected")) targetAccess = ACC_PROTECTED;
|
||||
|
||||
|
||||
if (name.endsWith("-f"))
|
||||
{
|
||||
changeFinal = true;
|
||||
@@ -101,11 +89,7 @@ public class AccessTransformer implements IClassTransformer
|
||||
readMapFile(rulesFile);
|
||||
}
|
||||
|
||||
AccessTransformer(Class<? extends AccessTransformer> dummyClazz)
|
||||
{
|
||||
// This is a noop
|
||||
}
|
||||
void readMapFile(String rulesFile) throws IOException
|
||||
private void readMapFile(String rulesFile) throws IOException
|
||||
{
|
||||
File file = new File(rulesFile);
|
||||
URL rulesResource;
|
||||
@@ -117,12 +101,7 @@ public class AccessTransformer implements IClassTransformer
|
||||
{
|
||||
rulesResource = Resources.getResource(rulesFile);
|
||||
}
|
||||
processATFile(Resources.asCharSource(rulesResource, Charsets.UTF_8));
|
||||
FMLRelaunchLog.fine("Loaded %d rules from AccessTransformer config file %s\n", modifiers.size(), rulesFile);
|
||||
}
|
||||
protected void processATFile(CharSource rulesResource) throws IOException
|
||||
{
|
||||
rulesResource.readLines(new LineProcessor<Void>()
|
||||
Resources.readLines(rulesResource, Charsets.UTF_8, new LineProcessor<Void>()
|
||||
{
|
||||
@Override
|
||||
public Void getResult()
|
||||
@@ -139,122 +118,67 @@ public class AccessTransformer implements IClassTransformer
|
||||
return true;
|
||||
}
|
||||
List<String> parts = Lists.newArrayList(Splitter.on(" ").trimResults().split(line));
|
||||
if (parts.size()>3)
|
||||
if (parts.size()>2 || parts.get(1).indexOf('.') == -1)
|
||||
{
|
||||
throw new RuntimeException("Invalid config file line "+ input);
|
||||
}
|
||||
Modifier m = new Modifier();
|
||||
m.setTargetAccess(parts.get(0));
|
||||
|
||||
if (parts.size() == 2)
|
||||
List<String> descriptor = Lists.newArrayList(Splitter.on(".").trimResults().split(parts.get(1)));
|
||||
String nameReference = descriptor.get(1);
|
||||
int parenIdx = nameReference.indexOf('(');
|
||||
if (parenIdx>0)
|
||||
{
|
||||
m.modifyClassVisibility = true;
|
||||
m.desc = nameReference.substring(parenIdx);
|
||||
m.name = nameReference.substring(0,parenIdx);
|
||||
}
|
||||
else
|
||||
{
|
||||
String nameReference = parts.get(2);
|
||||
int parenIdx = nameReference.indexOf('(');
|
||||
if (parenIdx>0)
|
||||
{
|
||||
m.desc = nameReference.substring(parenIdx);
|
||||
m.name = nameReference.substring(0,parenIdx);
|
||||
}
|
||||
else
|
||||
{
|
||||
m.name = nameReference;
|
||||
}
|
||||
m.name = nameReference;
|
||||
}
|
||||
String className = parts.get(1).replace('/', '.');
|
||||
modifiers.put(className, m);
|
||||
if (DEBUG) System.out.printf("AT RULE: %s %s %s (type %s)\n", toBinary(m.targetAccess), m.name, m.desc, className);
|
||||
modifiers.put(descriptor.get(0), m);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public byte[] transform(String name, String transformedName, byte[] bytes)
|
||||
public byte[] transform(String name, byte[] bytes)
|
||||
{
|
||||
if (bytes == null) { return null; }
|
||||
|
||||
if (DEBUG)
|
||||
{
|
||||
FMLRelaunchLog.fine("Considering all methods and fields on %s (%s)\n", transformedName, name);
|
||||
}
|
||||
if (!modifiers.containsKey(transformedName)) { return bytes; }
|
||||
if (!modifiers.containsKey(name)) { return bytes; }
|
||||
|
||||
ClassNode classNode = new ClassNode();
|
||||
ClassReader classReader = new ClassReader(bytes);
|
||||
classReader.accept(classNode, 0);
|
||||
|
||||
Collection<Modifier> mods = modifiers.get(transformedName);
|
||||
Collection<Modifier> mods = modifiers.get(name);
|
||||
for (Modifier m : mods)
|
||||
{
|
||||
if (m.modifyClassVisibility)
|
||||
{
|
||||
classNode.access = getFixedAccess(classNode.access, m);
|
||||
if (DEBUG)
|
||||
{
|
||||
System.out.println(String.format("Class: %s %s -> %s", name, toBinary(m.oldAccess), toBinary(m.newAccess)));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (m.desc.isEmpty())
|
||||
{
|
||||
for (FieldNode n : classNode.fields)
|
||||
for (FieldNode n : (List<FieldNode>) classNode.fields)
|
||||
{
|
||||
if (n.name.equals(m.name) || m.name.equals("*"))
|
||||
if (n.name.equals(m.name))
|
||||
{
|
||||
n.access = getFixedAccess(n.access, m);
|
||||
if (DEBUG)
|
||||
{
|
||||
System.out.println(String.format("Field: %s.%s %s -> %s", name, n.name, toBinary(m.oldAccess), toBinary(m.newAccess)));
|
||||
}
|
||||
|
||||
if (!m.name.equals("*"))
|
||||
{
|
||||
break;
|
||||
}
|
||||
System.out.println(String.format("Field: %s.%s %s -> %s", name, m.name, Integer.toBinaryString(m.oldAccess),
|
||||
Integer.toBinaryString(m.newAccess)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
List<MethodNode> nowOverridable = Lists.newArrayList();
|
||||
for (MethodNode n : classNode.methods)
|
||||
for (MethodNode n : (List<MethodNode>) classNode.methods)
|
||||
{
|
||||
if ((n.name.equals(m.name) && n.desc.equals(m.desc)) || m.name.equals("*"))
|
||||
if (n.name.equals(m.name) && n.desc.equals(m.desc))
|
||||
{
|
||||
n.access = getFixedAccess(n.access, m);
|
||||
|
||||
// constructors always use INVOKESPECIAL
|
||||
if (!n.name.equals("<init>"))
|
||||
{
|
||||
// if we changed from private to something else we need to replace all INVOKESPECIAL calls to this method with INVOKEVIRTUAL
|
||||
// so that overridden methods will be called. Only need to scan this class, because obviously the method was private.
|
||||
boolean wasPrivate = (m.oldAccess & ACC_PRIVATE) == ACC_PRIVATE;
|
||||
boolean isNowPrivate = (m.newAccess & ACC_PRIVATE) == ACC_PRIVATE;
|
||||
|
||||
if (wasPrivate && !isNowPrivate)
|
||||
{
|
||||
nowOverridable.add(n);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (DEBUG)
|
||||
{
|
||||
System.out.println(String.format("Method: %s.%s%s %s -> %s", name, n.name, n.desc, toBinary(m.oldAccess), toBinary(m.newAccess)));
|
||||
}
|
||||
|
||||
if (!m.name.equals("*"))
|
||||
{
|
||||
break;
|
||||
}
|
||||
System.out.println(String.format("Method: %s.%s%s %s -> %s", name, m.name, m.desc, toBinary(m.oldAccess), toBinary(m.newAccess)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
replaceInvokeSpecial(classNode, nowOverridable);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -263,29 +187,6 @@ public class AccessTransformer implements IClassTransformer
|
||||
return writer.toByteArray();
|
||||
}
|
||||
|
||||
private void replaceInvokeSpecial(ClassNode clazz, List<MethodNode> toReplace)
|
||||
{
|
||||
for (MethodNode method : clazz.methods)
|
||||
{
|
||||
for (Iterator<AbstractInsnNode> it = method.instructions.iterator(); it.hasNext();)
|
||||
{
|
||||
AbstractInsnNode insn = it.next();
|
||||
if (insn.getOpcode() == INVOKESPECIAL)
|
||||
{
|
||||
MethodInsnNode mInsn = (MethodInsnNode) insn;
|
||||
for (MethodNode n : toReplace)
|
||||
{
|
||||
if (n.name.equals(mInsn.name) && n.desc.equals(mInsn.desc))
|
||||
{
|
||||
mInsn.setOpcode(INVOKEVIRTUAL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String toBinary(int num)
|
||||
{
|
||||
return String.format("%16s", Integer.toBinaryString(num)).replace(' ', '0');
|
||||
@@ -314,9 +215,9 @@ public class AccessTransformer implements IClassTransformer
|
||||
default:
|
||||
throw new RuntimeException("The fuck?");
|
||||
}
|
||||
|
||||
|
||||
// Clear the "final" marker on fields only if specified in control field
|
||||
if (target.changeFinal)
|
||||
if (target.changeFinal && target.desc == "")
|
||||
{
|
||||
if (target.markFinal)
|
||||
{
|
||||
@@ -336,7 +237,7 @@ public class AccessTransformer implements IClassTransformer
|
||||
if (args.length < 2)
|
||||
{
|
||||
System.out.println("Usage: AccessTransformer <JarPath> <MapFile> [MapFile2]... ");
|
||||
System.exit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
boolean hasTransformer = false;
|
||||
@@ -358,7 +259,7 @@ public class AccessTransformer implements IClassTransformer
|
||||
if (!hasTransformer)
|
||||
{
|
||||
System.out.println("Culd not find a valid transformer to perform");
|
||||
System.exit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
File orig = new File(args[0]);
|
||||
@@ -366,13 +267,13 @@ public class AccessTransformer implements IClassTransformer
|
||||
if (!orig.exists() && !temp.exists())
|
||||
{
|
||||
System.out.println("Could not find target jar: " + orig);
|
||||
System.exit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!orig.renameTo(temp))
|
||||
{
|
||||
System.out.println("Could not rename file: " + orig + " -> " + temp);
|
||||
System.exit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
@@ -382,9 +283,8 @@ public class AccessTransformer implements IClassTransformer
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
|
||||
if (!temp.delete())
|
||||
{
|
||||
System.out.println("Could not delete temp file: " + temp);
|
||||
@@ -452,7 +352,7 @@ public class AccessTransformer implements IClassTransformer
|
||||
|
||||
for (AccessTransformer trans : transformers)
|
||||
{
|
||||
entryData = trans.transform(name, name, entryData);
|
||||
entryData = trans.transform(name, entryData);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -486,12 +386,4 @@ public class AccessTransformer implements IClassTransformer
|
||||
}
|
||||
}
|
||||
}
|
||||
Multimap<String, Modifier> getModifiers()
|
||||
{
|
||||
return modifiers;
|
||||
}
|
||||
boolean isEmpty()
|
||||
{
|
||||
return modifiers.isEmpty();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,570 @@
|
||||
package cpw.mods.fml.common.asm.transformers;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.URL;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.zip.*;
|
||||
|
||||
import org.objectweb.asm.*;
|
||||
import org.objectweb.asm.tree.*;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.base.Optional;
|
||||
import com.google.common.collect.Iterators;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
import cpw.mods.fml.common.Side;
|
||||
import cpw.mods.fml.common.asm.SideOnly;
|
||||
|
||||
public class MCPMerger
|
||||
{
|
||||
private static Hashtable<String, ClassInfo> clients = new Hashtable<String, ClassInfo>();
|
||||
private static Hashtable<String, ClassInfo> shared = new Hashtable<String, ClassInfo>();
|
||||
private static Hashtable<String, ClassInfo> servers = new Hashtable<String, ClassInfo>();
|
||||
private static HashSet<String> copyToServer = new HashSet<String>();
|
||||
private static HashSet<String> copyToClient = new HashSet<String>();
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
if (args.length != 3)
|
||||
{
|
||||
System.out.println("Usage: AccessTransformer <MapFile> <minecraft.jar> <minecraft_server.jar>");
|
||||
return;
|
||||
}
|
||||
|
||||
File map_file = new File(args[0]);
|
||||
File client_jar = new File(args[1]);
|
||||
File server_jar = new File(args[2]);
|
||||
File client_jar_tmp = new File(args[1] + ".MergeBack");
|
||||
File server_jar_tmp = new File(args[2] + ".MergeBack");
|
||||
|
||||
|
||||
if (client_jar_tmp.exists() && !client_jar_tmp.delete())
|
||||
{
|
||||
System.out.println("Could not delete temp file: " + client_jar_tmp);
|
||||
}
|
||||
|
||||
if (server_jar_tmp.exists() && !server_jar_tmp.delete())
|
||||
{
|
||||
System.out.println("Could not delete temp file: " + server_jar_tmp);
|
||||
}
|
||||
|
||||
if (!client_jar.exists())
|
||||
{
|
||||
System.out.println("Could not find minecraft.jar: " + client_jar);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!server_jar.exists())
|
||||
{
|
||||
System.out.println("Could not find minecraft_server.jar: " + server_jar);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!client_jar.renameTo(client_jar_tmp))
|
||||
{
|
||||
System.out.println("Could not rename file: " + client_jar + " -> " + client_jar_tmp);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!server_jar.renameTo(server_jar_tmp))
|
||||
{
|
||||
System.out.println("Could not rename file: " + server_jar + " -> " + server_jar_tmp);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!readMapFile(map_file))
|
||||
{
|
||||
System.out.println("Could not read map file: " + map_file);
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
processJar(client_jar_tmp, server_jar_tmp, client_jar, server_jar);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
if (!client_jar_tmp.delete())
|
||||
{
|
||||
System.out.println("Could not delete temp file: " + client_jar_tmp);
|
||||
}
|
||||
|
||||
if (!server_jar_tmp.delete())
|
||||
{
|
||||
System.out.println("Could not delete temp file: " + server_jar_tmp);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean readMapFile(File mapFile)
|
||||
{
|
||||
try
|
||||
{
|
||||
FileInputStream fstream = new FileInputStream(mapFile);
|
||||
DataInputStream in = new DataInputStream(fstream);
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(in));
|
||||
|
||||
String line;
|
||||
while ((line = br.readLine()) != null)
|
||||
{
|
||||
boolean toClient = line.charAt(0) == '<';
|
||||
line = line.substring(1);
|
||||
if (toClient) copyToClient.add(line);
|
||||
else copyToServer.add(line);
|
||||
}
|
||||
|
||||
in.close();
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
System.err.println("Error: " + e.getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static void processJar(File clientInFile, File serverInFile, File clientOutFile, File serverOutFile) throws IOException
|
||||
{
|
||||
ZipFile cInJar = null;
|
||||
ZipFile sInJar = null;
|
||||
ZipOutputStream cOutJar = null;
|
||||
ZipOutputStream sOutJar = null;
|
||||
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
cInJar = new ZipFile(clientInFile);
|
||||
sInJar = new ZipFile(serverInFile);
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
throw new FileNotFoundException("Could not open input file: " + e.getMessage());
|
||||
}
|
||||
try
|
||||
{
|
||||
cOutJar = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(clientOutFile)));
|
||||
sOutJar = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(serverOutFile)));
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
throw new FileNotFoundException("Could not open output file: " + e.getMessage());
|
||||
}
|
||||
Hashtable<String, ZipEntry> cClasses = getClassEntries(cInJar, cOutJar);
|
||||
Hashtable<String, ZipEntry> sClasses = getClassEntries(sInJar, sOutJar);
|
||||
|
||||
for (Entry<String, ZipEntry> entry : cClasses.entrySet())
|
||||
{
|
||||
String name = entry.getKey();
|
||||
ZipEntry cEntry = entry.getValue();
|
||||
ZipEntry sEntry = sClasses.get(name);
|
||||
|
||||
if (sEntry == null)
|
||||
{
|
||||
if (!copyToServer.contains(name))
|
||||
{
|
||||
copyEntry(cInJar, cEntry, cOutJar);
|
||||
}
|
||||
else
|
||||
{
|
||||
System.out.println("Copy class c->s : " + name);
|
||||
copyClass(cInJar, cEntry, cOutJar, sOutJar, true);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
sClasses.remove(name);
|
||||
ClassInfo info = new ClassInfo(name);
|
||||
shared.put(name, info);
|
||||
|
||||
byte[] cData = readEntry(cInJar, entry.getValue());
|
||||
byte[] sData = readEntry(sInJar, sEntry);
|
||||
byte[] data = processClass(cData, sData, info);
|
||||
|
||||
ZipEntry newEntry = new ZipEntry(cEntry.getName());
|
||||
cOutJar.putNextEntry(newEntry);
|
||||
cOutJar.write(data);
|
||||
sOutJar.putNextEntry(newEntry);
|
||||
sOutJar.write(data);
|
||||
}
|
||||
for (Entry<String, ZipEntry> entry : sClasses.entrySet())
|
||||
{
|
||||
if (!copyToClient.contains(entry.getKey()))
|
||||
{
|
||||
copyEntry(sInJar, entry.getValue(), sOutJar);
|
||||
}
|
||||
else
|
||||
{
|
||||
System.out.println("Copy class s->c : " + entry.getKey());
|
||||
copyClass(sInJar, entry.getValue(), cOutJar, sOutJar, false);
|
||||
}
|
||||
}
|
||||
|
||||
for (String name : new String[]{SideOnly.class.getName(), Side.class.getName()})
|
||||
{
|
||||
byte[] data = getClassBytes(name);
|
||||
ZipEntry newEntry = new ZipEntry(name.replace(".", "/").concat(".class"));
|
||||
cOutJar.putNextEntry(newEntry);
|
||||
cOutJar.write(data);
|
||||
sOutJar.putNextEntry(newEntry);
|
||||
sOutJar.write(data);
|
||||
}
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (cInJar != null)
|
||||
{
|
||||
try { cInJar.close(); } catch (IOException e){}
|
||||
}
|
||||
|
||||
if (sInJar != null)
|
||||
{
|
||||
try { sInJar.close(); } catch (IOException e) {}
|
||||
}
|
||||
if (cOutJar != null)
|
||||
{
|
||||
try { cOutJar.close(); } catch (IOException e){}
|
||||
}
|
||||
|
||||
if (sOutJar != null)
|
||||
{
|
||||
try { sOutJar.close(); } catch (IOException e) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void copyClass(ZipFile inJar, ZipEntry entry, ZipOutputStream outJar, ZipOutputStream outJar2, boolean isClientOnly) throws IOException
|
||||
{
|
||||
ClassReader reader = new ClassReader(readEntry(inJar, entry));
|
||||
ClassNode classNode = new ClassNode();
|
||||
|
||||
reader.accept(classNode, 0);
|
||||
if (classNode.visibleAnnotations == null) classNode.visibleAnnotations = new ArrayList<AnnotationNode>();
|
||||
classNode.visibleAnnotations.add(getSideAnn(isClientOnly));
|
||||
|
||||
ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
|
||||
classNode.accept(writer);
|
||||
byte[] data = writer.toByteArray();
|
||||
|
||||
ZipEntry newEntry = new ZipEntry(entry.getName());
|
||||
outJar.putNextEntry(newEntry);
|
||||
outJar.write(data);
|
||||
outJar2.putNextEntry(newEntry);
|
||||
outJar2.write(data);
|
||||
}
|
||||
|
||||
private static AnnotationNode getSideAnn(boolean isClientOnly)
|
||||
{
|
||||
AnnotationNode ann = new AnnotationNode(Type.getDescriptor(SideOnly.class));
|
||||
ann.values = new ArrayList<Object>();
|
||||
ann.values.add("value");
|
||||
ann.values.add(new String[]{ Type.getDescriptor(Side.class), (isClientOnly ? "CLIENT" : "SERVER")});
|
||||
return ann;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static Hashtable<String, ZipEntry> getClassEntries(ZipFile inFile, ZipOutputStream outFile) throws IOException
|
||||
{
|
||||
Hashtable<String, ZipEntry> ret = new Hashtable<String, ZipEntry>();
|
||||
for (ZipEntry entry : Collections.list((Enumeration<ZipEntry>)inFile.entries()))
|
||||
{
|
||||
if (entry.isDirectory())
|
||||
{
|
||||
outFile.putNextEntry(entry);
|
||||
continue;
|
||||
}
|
||||
String entryName = entry.getName();
|
||||
if (!entryName.endsWith(".class") || entryName.startsWith("."))
|
||||
{
|
||||
copyEntry(inFile, entry, outFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret.put(entryName.replace(".class", ""), entry);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
private static void copyEntry(ZipFile inFile, ZipEntry entry, ZipOutputStream outFile) throws IOException
|
||||
{
|
||||
ZipEntry newEntry = new ZipEntry(entry.getName());
|
||||
outFile.putNextEntry(newEntry);
|
||||
outFile.write(readEntry(inFile, entry));
|
||||
}
|
||||
private static byte[] readEntry(ZipFile inFile, ZipEntry entry) throws IOException
|
||||
{
|
||||
return readFully(inFile.getInputStream(entry));
|
||||
}
|
||||
private static byte[] readFully(InputStream stream) throws IOException
|
||||
{
|
||||
byte[] data = new byte[4096];
|
||||
ByteArrayOutputStream entryBuffer = new ByteArrayOutputStream();
|
||||
int len;
|
||||
do
|
||||
{
|
||||
len = stream.read(data);
|
||||
if (len > 0)
|
||||
{
|
||||
entryBuffer.write(data, 0, len);
|
||||
}
|
||||
} while (len != -1);
|
||||
|
||||
return entryBuffer.toByteArray();
|
||||
}
|
||||
private static class ClassInfo
|
||||
{
|
||||
public String name;
|
||||
public ArrayList<FieldNode> cField = new ArrayList<FieldNode>();
|
||||
public ArrayList<FieldNode> sField = new ArrayList<FieldNode>();
|
||||
public ArrayList<MethodNode> cMethods = new ArrayList<MethodNode>();
|
||||
public ArrayList<MethodNode> sMethods = new ArrayList<MethodNode>();
|
||||
public ClassInfo(String name){ this.name = name; }
|
||||
public boolean isSame() { return (cField.size() == 0 && sField.size() == 0 && cMethods.size() == 0 && sMethods.size() == 0); }
|
||||
}
|
||||
|
||||
public static byte[] processClass(byte[] cIn, byte[] sIn, ClassInfo info)
|
||||
{
|
||||
ClassNode cClassNode = getClassNode(cIn);
|
||||
ClassNode sClassNode = getClassNode(sIn);
|
||||
|
||||
processFields(cClassNode, sClassNode, info);
|
||||
processMethods(cClassNode, sClassNode, info);
|
||||
|
||||
ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
|
||||
cClassNode.accept(writer);
|
||||
return writer.toByteArray();
|
||||
}
|
||||
|
||||
private static ClassNode getClassNode(byte[] data)
|
||||
{
|
||||
ClassReader reader = new ClassReader(data);
|
||||
ClassNode classNode = new ClassNode();
|
||||
reader.accept(classNode, 0);
|
||||
return classNode;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static void processFields(ClassNode cClass, ClassNode sClass, ClassInfo info)
|
||||
{
|
||||
List<FieldNode> cFields = cClass.fields;
|
||||
List<FieldNode> sFields = sClass.fields;
|
||||
|
||||
int sI = 0;
|
||||
for (int x = 0; x < cFields.size(); x++)
|
||||
{
|
||||
FieldNode cF = cFields.get(x);
|
||||
if (sI < sFields.size())
|
||||
{
|
||||
if (!cF.name.equals(sFields.get(sI).name))
|
||||
{
|
||||
boolean serverHas = false;
|
||||
for (int y = sI + 1; y < sFields.size(); y++)
|
||||
{
|
||||
if (cF.name.equals(sFields.get(y).name))
|
||||
{
|
||||
serverHas = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (serverHas)
|
||||
{
|
||||
boolean clientHas = false;
|
||||
FieldNode sF = sFields.get(sI);
|
||||
for (int y = x + 1; y < cFields.size(); y++)
|
||||
{
|
||||
if (sF.name.equals(cFields.get(y).name))
|
||||
{
|
||||
clientHas = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!clientHas)
|
||||
{
|
||||
if (sF.visibleAnnotations == null) sF.visibleAnnotations = new ArrayList<AnnotationNode>();
|
||||
sF.visibleAnnotations.add(getSideAnn(false));
|
||||
cFields.add(x++, sF);
|
||||
info.sField.add(sF);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cF.visibleAnnotations == null) cF.visibleAnnotations = new ArrayList<AnnotationNode>();
|
||||
cF.visibleAnnotations.add(getSideAnn(true));
|
||||
sFields.add(sI, cF);
|
||||
info.cField.add(cF);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cF.visibleAnnotations == null) cF.visibleAnnotations = new ArrayList<AnnotationNode>();
|
||||
cF.visibleAnnotations.add(getSideAnn(true));
|
||||
sFields.add(sI, cF);
|
||||
info.cField.add(cF);
|
||||
}
|
||||
sI++;
|
||||
}
|
||||
if (sFields.size() != cFields.size())
|
||||
{
|
||||
for (int x = cFields.size(); x < sFields.size(); x++)
|
||||
{
|
||||
FieldNode sF = sFields.get(x);
|
||||
if (sF.visibleAnnotations == null) sF.visibleAnnotations = new ArrayList<AnnotationNode>();
|
||||
sF.visibleAnnotations.add(getSideAnn(true));
|
||||
cFields.add(x++, sF);
|
||||
info.sField.add(sF);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class MethodWrapper
|
||||
{
|
||||
private MethodNode node;
|
||||
public boolean client;
|
||||
public boolean server;
|
||||
public MethodWrapper(MethodNode node)
|
||||
{
|
||||
this.node = node;
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (obj == null || !(obj instanceof MethodWrapper)) return false;
|
||||
MethodWrapper mw = (MethodWrapper) obj;
|
||||
boolean eq = Objects.equal(node.name, mw.node.name) && Objects.equal(node.desc, mw.node.desc);
|
||||
if (eq)
|
||||
{
|
||||
mw.client = this.client | mw.client;
|
||||
mw.server = this.server | mw.server;
|
||||
this.client = this.client | mw.client;
|
||||
this.server = this.server | mw.server;
|
||||
System.out.printf(" eq: %s %s\n", this, mw);
|
||||
}
|
||||
return eq;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return Objects.hashCode(node.name, node.desc);
|
||||
}
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return Objects.toStringHelper(this).add("name", node.name).add("desc",node.desc).add("server",server).add("client",client).toString();
|
||||
}
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
private static void processMethods(ClassNode cClass, ClassNode sClass, ClassInfo info)
|
||||
{
|
||||
List<MethodNode> cMethods = (List<MethodNode>)cClass.methods;
|
||||
List<MethodNode> sMethods = (List<MethodNode>)sClass.methods;
|
||||
LinkedHashSet<MethodWrapper> allMethods = Sets.newLinkedHashSet();
|
||||
|
||||
int cPos = 0;
|
||||
int sPos = 0;
|
||||
int cLen = cMethods.size();
|
||||
int sLen = sMethods.size();
|
||||
String clientName = "";
|
||||
String lastName = clientName;
|
||||
String serverName = "";
|
||||
while (cPos < cLen || sPos < sLen)
|
||||
{
|
||||
do
|
||||
{
|
||||
if (sPos>=sLen)
|
||||
{
|
||||
break;
|
||||
}
|
||||
MethodNode sM = sMethods.get(sPos);
|
||||
serverName = sM.name;
|
||||
if (!serverName.equals(lastName) && cPos != cLen)
|
||||
{
|
||||
System.out.printf("Server -skip : %s %s %d (%s %d) %d [%s]\n", sClass.name, clientName, cLen - cPos, serverName, sLen - sPos, allMethods.size(), lastName);
|
||||
break;
|
||||
}
|
||||
MethodWrapper mw = new MethodWrapper(sM);
|
||||
mw.server = true;
|
||||
allMethods.add(mw);
|
||||
System.out.printf("Server *add* : %s %s %d (%s %d) %d [%s]\n", sClass.name, clientName, cLen - cPos, serverName, sLen - sPos, allMethods.size(), lastName);
|
||||
sPos++;
|
||||
}
|
||||
while (sPos < sLen);
|
||||
do
|
||||
{
|
||||
if (cPos>=cLen)
|
||||
{
|
||||
break;
|
||||
}
|
||||
MethodNode cM = cMethods.get(cPos);
|
||||
lastName = clientName;
|
||||
clientName = cM.name;
|
||||
if (!clientName.equals(lastName) && sPos != sLen)
|
||||
{
|
||||
System.out.printf("Client -skip : %s %s %d (%s %d) %d [%s]\n", cClass.name, clientName, cLen - cPos, serverName, sLen - sPos, allMethods.size(), lastName);
|
||||
break;
|
||||
}
|
||||
MethodWrapper mw = new MethodWrapper(cM);
|
||||
mw.client = true;
|
||||
allMethods.add(mw);
|
||||
System.out.printf("Client *add* : %s %s %d (%s %d) %d [%s]\n", cClass.name, clientName, cLen - cPos, serverName, sLen - sPos, allMethods.size(), lastName);
|
||||
cPos++;
|
||||
}
|
||||
while (cPos < cLen);
|
||||
}
|
||||
|
||||
cMethods.clear();
|
||||
sMethods.clear();
|
||||
|
||||
for (MethodWrapper mw : allMethods)
|
||||
{
|
||||
System.out.println(mw);
|
||||
cMethods.add(mw.node);
|
||||
sMethods.add(mw.node);
|
||||
if (mw.server && mw.client)
|
||||
{
|
||||
// no op
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mw.node.visibleAnnotations == null) mw.node.visibleAnnotations = Lists.newArrayListWithExpectedSize(1);
|
||||
mw.node.visibleAnnotations.add(getSideAnn(mw.client));
|
||||
if (mw.client)
|
||||
{
|
||||
info.sMethods.add(mw.node);
|
||||
}
|
||||
else
|
||||
{
|
||||
info.cMethods.add(mw.node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] getClassBytes(String name) throws IOException
|
||||
{
|
||||
InputStream classStream = null;
|
||||
try
|
||||
{
|
||||
classStream = MCPMerger.class.getResourceAsStream("/" + name.replace('.', '/').concat(".class"));
|
||||
return readFully(classStream);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (classStream != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
classStream.close();
|
||||
}
|
||||
catch (IOException e){}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+25
-18
@@ -1,46 +1,53 @@
|
||||
/*
|
||||
* Forge Mod Loader
|
||||
* Copyright (c) 2012-2013 cpw.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the GNU Lesser Public License v2.1
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* Contributors:
|
||||
* cpw - implementation
|
||||
*/
|
||||
|
||||
package cpw.mods.fml.common.asm.transformers;
|
||||
|
||||
import static org.objectweb.asm.Opcodes.ACC_PRIVATE;
|
||||
import static org.objectweb.asm.Opcodes.ACC_PROTECTED;
|
||||
import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
|
||||
import static org.objectweb.asm.Opcodes.ACC_FINAL;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.URL;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import net.minecraft.launchwrapper.IClassTransformer;
|
||||
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.Type;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import org.objectweb.asm.tree.FieldNode;
|
||||
import org.objectweb.asm.tree.MethodNode;
|
||||
|
||||
import com.google.common.base.CharMatcher;
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.ListMultimap;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.io.LineProcessor;
|
||||
import com.google.common.io.Resources;
|
||||
|
||||
import cpw.mods.fml.relauncher.IClassTransformer;
|
||||
|
||||
public class MarkerTransformer implements IClassTransformer
|
||||
{
|
||||
private ListMultimap<String, String> markers = ArrayListMultimap.create();
|
||||
@@ -97,10 +104,10 @@ public class MarkerTransformer implements IClassTransformer
|
||||
});
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public byte[] transform(String name, String transformedName, byte[] bytes)
|
||||
public byte[] transform(String name, byte[] bytes)
|
||||
{
|
||||
if (bytes == null) { return null; }
|
||||
if (!markers.containsKey(name)) { return bytes; }
|
||||
|
||||
ClassNode classNode = new ClassNode();
|
||||
@@ -251,7 +258,7 @@ public class MarkerTransformer implements IClassTransformer
|
||||
|
||||
for (MarkerTransformer trans : transformers)
|
||||
{
|
||||
entryData = trans.transform(name, name, entryData);
|
||||
entryData = trans.transform(name, entryData);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -285,4 +292,4 @@ public class MarkerTransformer implements IClassTransformer
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+10
-39
@@ -1,22 +1,8 @@
|
||||
/*
|
||||
* Forge Mod Loader
|
||||
* Copyright (c) 2012-2013 cpw.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the GNU Lesser Public License v2.1
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* Contributors:
|
||||
* cpw - implementation
|
||||
*/
|
||||
|
||||
package cpw.mods.fml.common.asm.transformers;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.launchwrapper.IClassTransformer;
|
||||
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.Type;
|
||||
@@ -25,41 +11,29 @@ import org.objectweb.asm.tree.ClassNode;
|
||||
import org.objectweb.asm.tree.FieldNode;
|
||||
import org.objectweb.asm.tree.MethodNode;
|
||||
|
||||
import cpw.mods.fml.relauncher.FMLLaunchHandler;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
import cpw.mods.fml.common.Side;
|
||||
import cpw.mods.fml.common.asm.SideOnly;
|
||||
import cpw.mods.fml.relauncher.FMLRelauncher;
|
||||
import cpw.mods.fml.relauncher.IClassTransformer;
|
||||
|
||||
public class SideTransformer implements IClassTransformer
|
||||
{
|
||||
private static String SIDE = FMLLaunchHandler.side().name();
|
||||
private static final boolean DEBUG = false;
|
||||
private static String SIDE = FMLRelauncher.side();
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public byte[] transform(String name, String transformedName, byte[] bytes)
|
||||
public byte[] transform(String name, byte[] bytes)
|
||||
{
|
||||
if (bytes == null) { return null; }
|
||||
|
||||
ClassNode classNode = new ClassNode();
|
||||
ClassReader classReader = new ClassReader(bytes);
|
||||
classReader.accept(classNode, 0);
|
||||
|
||||
if (remove((List<AnnotationNode>)classNode.visibleAnnotations, SIDE))
|
||||
{
|
||||
if (DEBUG)
|
||||
{
|
||||
System.out.println(String.format("Attempted to load class %s for invalid side %s", classNode.name, SIDE));
|
||||
}
|
||||
throw new RuntimeException(String.format("Attempted to load class %s for invalid side %s", classNode.name, SIDE));
|
||||
}
|
||||
|
||||
Iterator<FieldNode> fields = classNode.fields.iterator();
|
||||
while(fields.hasNext())
|
||||
{
|
||||
FieldNode field = fields.next();
|
||||
if (remove((List<AnnotationNode>)field.visibleAnnotations, SIDE))
|
||||
{
|
||||
if (DEBUG)
|
||||
{
|
||||
System.out.println(String.format("Removing Field: %s.%s", classNode.name, field.name));
|
||||
}
|
||||
System.out.println("Removing Field: " + field.name);
|
||||
fields.remove();
|
||||
}
|
||||
}
|
||||
@@ -69,10 +43,7 @@ public class SideTransformer implements IClassTransformer
|
||||
MethodNode method = methods.next();
|
||||
if (remove((List<AnnotationNode>)method.visibleAnnotations, SIDE))
|
||||
{
|
||||
if (DEBUG)
|
||||
{
|
||||
System.out.println(String.format("Removing Method: %s.%s%s", classNode.name, method.name, method.desc));
|
||||
}
|
||||
System.out.println("Removing Method: " + method.name + " " + method.desc);
|
||||
methods.remove();
|
||||
}
|
||||
}
|
||||
@@ -81,7 +52,7 @@ public class SideTransformer implements IClassTransformer
|
||||
classNode.accept(writer);
|
||||
return writer.toByteArray();
|
||||
}
|
||||
|
||||
|
||||
private boolean remove(List<AnnotationNode> anns, String side)
|
||||
{
|
||||
if (anns == null)
|
||||
+5
-39
@@ -1,17 +1,7 @@
|
||||
/*
|
||||
* Forge Mod Loader
|
||||
* Copyright (c) 2012-2013 cpw.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the GNU Lesser Public License v2.1
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* Contributors:
|
||||
* cpw - implementation
|
||||
*/
|
||||
|
||||
package cpw.mods.fml.common.discovery;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@@ -20,16 +10,18 @@ import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.HashMultimap;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSetMultimap;
|
||||
import com.google.common.collect.ListMultimap;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.collect.Multimaps;
|
||||
import com.google.common.collect.SetMultimap;
|
||||
import com.google.common.collect.ImmutableBiMap.Builder;
|
||||
|
||||
import cpw.mods.fml.common.ModContainer;
|
||||
|
||||
public class ASMDataTable
|
||||
{
|
||||
public final static class ASMData implements Cloneable
|
||||
public static class ASMData
|
||||
{
|
||||
private ModCandidate candidate;
|
||||
private String annotationName;
|
||||
@@ -64,20 +56,6 @@ public class ASMDataTable
|
||||
{
|
||||
return annotationInfo;
|
||||
}
|
||||
|
||||
public ASMData copy(Map<String,Object> newAnnotationInfo)
|
||||
{
|
||||
try
|
||||
{
|
||||
ASMData clone = (ASMData) this.clone();
|
||||
clone.annotationInfo = newAnnotationInfo;
|
||||
return clone;
|
||||
}
|
||||
catch (CloneNotSupportedException e)
|
||||
{
|
||||
throw new RuntimeException("Unpossible", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class ModContainerPredicate implements Predicate<ASMData>
|
||||
@@ -87,7 +65,6 @@ public class ASMDataTable
|
||||
{
|
||||
this.container = container;
|
||||
}
|
||||
@Override
|
||||
public boolean apply(ASMData data)
|
||||
{
|
||||
return container.getSource().equals(data.candidate.getModContainer());
|
||||
@@ -97,7 +74,6 @@ public class ASMDataTable
|
||||
private Map<ModContainer, SetMultimap<String,ASMData>> containerAnnotationData;
|
||||
|
||||
private List<ModContainer> containers = Lists.newArrayList();
|
||||
private SetMultimap<String,ModCandidate> packageMap = HashMultimap.create();
|
||||
|
||||
public SetMultimap<String,ASMData> getAnnotationsFor(ModContainer container)
|
||||
{
|
||||
@@ -128,14 +104,4 @@ public class ASMDataTable
|
||||
{
|
||||
this.containers.add(container);
|
||||
}
|
||||
|
||||
public void registerPackage(ModCandidate modCandidate, String pkg)
|
||||
{
|
||||
this.packageMap.put(pkg,modCandidate);
|
||||
}
|
||||
|
||||
public Set<ModCandidate> getCandidatesFor(String pkg)
|
||||
{
|
||||
return this.packageMap.get(pkg);
|
||||
}
|
||||
}
|
||||
+1
-13
@@ -1,15 +1,3 @@
|
||||
/*
|
||||
* Forge Mod Loader
|
||||
* Copyright (c) 2012-2013 cpw.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the GNU Lesser Public License v2.1
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* Contributors:
|
||||
* cpw - implementation
|
||||
*/
|
||||
|
||||
package cpw.mods.fml.common.discovery;
|
||||
|
||||
import java.util.List;
|
||||
@@ -41,4 +29,4 @@ public enum ContainerType
|
||||
{
|
||||
return discoverer.discover(candidate, table);
|
||||
}
|
||||
}
|
||||
}
|
||||
+7
-27
@@ -1,31 +1,19 @@
|
||||
/*
|
||||
* Forge Mod Loader
|
||||
* Copyright (c) 2012-2013 cpw.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the GNU Lesser Public License v2.1
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* Contributors:
|
||||
* cpw - implementation
|
||||
*/
|
||||
|
||||
package cpw.mods.fml.common.discovery;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Matcher;
|
||||
|
||||
import org.apache.logging.log4j.Level;
|
||||
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import cpw.mods.fml.common.FMLLog;
|
||||
import cpw.mods.fml.common.LoaderException;
|
||||
import cpw.mods.fml.common.MetadataCollection;
|
||||
import cpw.mods.fml.common.ModContainer;
|
||||
import cpw.mods.fml.common.ModContainerFactory;
|
||||
@@ -66,14 +54,12 @@ public class DirectoryDiscoverer implements ITypeDiscoverer
|
||||
try
|
||||
{
|
||||
FileInputStream fis = new FileInputStream(metadata);
|
||||
mc = MetadataCollection.from(fis,modDir.getName());
|
||||
mc = MetadataCollection.from(fis);
|
||||
fis.close();
|
||||
FMLLog.fine("Found an mcmod.info file in directory %s", modDir.getName());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
mc = MetadataCollection.from(null,"");
|
||||
FMLLog.fine("No mcmod.info file found in directory %s", modDir.getName());
|
||||
mc = MetadataCollection.from(null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,7 +71,7 @@ public class DirectoryDiscoverer implements ITypeDiscoverer
|
||||
{
|
||||
if (file.isDirectory())
|
||||
{
|
||||
FMLLog.finer("Recursing into package %s", path + file.getName());
|
||||
FMLLog.finest("Recursing into package %s", path + file.getName());
|
||||
exploreFileSystem(path + file.getName() + ".", file, harvestedMods, candidate, mc);
|
||||
continue;
|
||||
}
|
||||
@@ -99,12 +85,6 @@ public class DirectoryDiscoverer implements ITypeDiscoverer
|
||||
FileInputStream fis = new FileInputStream(file);
|
||||
modParser = new ASMModParser(fis);
|
||||
fis.close();
|
||||
candidate.addClassEntry(path+file.getName());
|
||||
}
|
||||
catch (LoaderException e)
|
||||
{
|
||||
FMLLog.log(Level.ERROR, e, "There was a problem reading the file %s - probably this is a corrupt file", file.getPath());
|
||||
throw e;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -113,7 +93,7 @@ public class DirectoryDiscoverer implements ITypeDiscoverer
|
||||
|
||||
modParser.validate();
|
||||
modParser.sendToTable(table, candidate);
|
||||
ModContainer container = ModContainerFactory.instance().build(modParser, candidate.getModContainer(), candidate);
|
||||
ModContainer container = ModContainerFactory.instance().build(modParser, candidate.getModContainer());
|
||||
if (container!=null)
|
||||
{
|
||||
harvestedMods.add(container);
|
||||
@@ -0,0 +1,13 @@
|
||||
package cpw.mods.fml.common.discovery;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import cpw.mods.fml.common.ModContainer;
|
||||
|
||||
public interface ITypeDiscoverer
|
||||
{
|
||||
public static Pattern classFile = Pattern.compile("([^\\s$]+).class$");
|
||||
|
||||
public List<ModContainer> discover(ModCandidate candidate, ASMDataTable table);
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package cpw.mods.fml.common.discovery;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import cpw.mods.fml.common.FMLLog;
|
||||
import cpw.mods.fml.common.MetadataCollection;
|
||||
import cpw.mods.fml.common.ModContainer;
|
||||
import cpw.mods.fml.common.ModContainerFactory;
|
||||
import cpw.mods.fml.common.discovery.asm.ASMModParser;
|
||||
|
||||
public class JarDiscoverer implements ITypeDiscoverer
|
||||
{
|
||||
@Override
|
||||
public List<ModContainer> discover(ModCandidate candidate, ASMDataTable table)
|
||||
{
|
||||
List<ModContainer> foundMods = Lists.newArrayList();
|
||||
FMLLog.fine("Examining file %s for potential mods", candidate.getModContainer().getName());
|
||||
ZipFile jar = null;
|
||||
try
|
||||
{
|
||||
jar = new ZipFile(candidate.getModContainer());
|
||||
|
||||
ZipEntry modInfo = jar.getEntry("mcmod.info");
|
||||
MetadataCollection mc = null;
|
||||
if (modInfo != null)
|
||||
{
|
||||
FMLLog.finer("Located mcmod.info file in file %s", candidate.getModContainer().getName());
|
||||
mc = MetadataCollection.from(jar.getInputStream(modInfo));
|
||||
}
|
||||
for (ZipEntry ze : Collections.list(jar.entries()))
|
||||
{
|
||||
Matcher match = classFile.matcher(ze.getName());
|
||||
if (match.matches())
|
||||
{
|
||||
ASMModParser modParser = new ASMModParser(jar.getInputStream(ze));
|
||||
modParser.validate();
|
||||
modParser.sendToTable(table, candidate);
|
||||
ModContainer container = ModContainerFactory.instance().build(modParser, candidate.getModContainer());
|
||||
if (container!=null)
|
||||
{
|
||||
table.addContainer(container);
|
||||
foundMods.add(container);
|
||||
container.bindMetadata(mc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
FMLLog.warning("Zip file %s failed to read properly, it will be ignored", candidate.getModContainer().getName());
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (jar != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
jar.close();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
return foundMods;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package cpw.mods.fml.common.discovery;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
import cpw.mods.fml.common.ModContainer;
|
||||
|
||||
|
||||
public class ModCandidate
|
||||
{
|
||||
private File classPathRoot;
|
||||
private File modContainer;
|
||||
private ContainerType sourceType;
|
||||
private boolean classpath;
|
||||
|
||||
public ModCandidate(File classPathRoot, File modContainer, ContainerType sourceType)
|
||||
{
|
||||
this(classPathRoot, modContainer, sourceType, false);
|
||||
}
|
||||
public ModCandidate(File classPathRoot, File modContainer, ContainerType sourceType, boolean classpath)
|
||||
{
|
||||
this.classPathRoot = classPathRoot;
|
||||
this.modContainer = modContainer;
|
||||
this.sourceType = sourceType;
|
||||
this.classpath = classpath;
|
||||
}
|
||||
|
||||
public File getClassPathRoot()
|
||||
{
|
||||
return classPathRoot;
|
||||
}
|
||||
|
||||
public File getModContainer()
|
||||
{
|
||||
return modContainer;
|
||||
}
|
||||
|
||||
public ContainerType getSourceType()
|
||||
{
|
||||
return sourceType;
|
||||
}
|
||||
public List<ModContainer> explore(ASMDataTable table)
|
||||
{
|
||||
return sourceType.findMods(this, table);
|
||||
}
|
||||
}
|
||||
+44
-56
@@ -1,34 +1,50 @@
|
||||
/*
|
||||
* Forge Mod Loader
|
||||
* Copyright (c) 2012-2013 cpw.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the GNU Lesser Public License v2.1
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* Contributors:
|
||||
* cpw - implementation
|
||||
*/
|
||||
|
||||
package cpw.mods.fml.common.discovery;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import org.apache.logging.log4j.Level;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
import org.objectweb.asm.AnnotationVisitor;
|
||||
import org.objectweb.asm.Attribute;
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.ClassVisitor;
|
||||
import org.objectweb.asm.FieldVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.collect.HashBasedTable;
|
||||
import com.google.common.collect.HashMultimap;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableTable;
|
||||
import com.google.common.collect.Tables;
|
||||
import com.google.common.collect.ImmutableTable.Builder;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.ObjectArrays;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.collect.Table;
|
||||
import com.google.common.collect.Table.Cell;
|
||||
|
||||
import cpw.mods.fml.common.FMLLog;
|
||||
import cpw.mods.fml.common.LoaderException;
|
||||
import cpw.mods.fml.common.ModClassLoader;
|
||||
import cpw.mods.fml.common.ModContainer;
|
||||
import cpw.mods.fml.relauncher.CoreModManager;
|
||||
import cpw.mods.fml.relauncher.FileListHelper;
|
||||
import cpw.mods.fml.relauncher.ModListHelper;
|
||||
import cpw.mods.fml.relauncher.RelaunchLibraryManager;
|
||||
|
||||
public class ModDiscoverer
|
||||
{
|
||||
@@ -38,23 +54,14 @@ public class ModDiscoverer
|
||||
|
||||
private ASMDataTable dataTable = new ASMDataTable();
|
||||
|
||||
private List<File> nonModLibs = Lists.newArrayList();
|
||||
|
||||
public void findClasspathMods(ModClassLoader modClassLoader)
|
||||
{
|
||||
List<String> knownLibraries = ImmutableList.<String>builder()
|
||||
// skip default libs
|
||||
.addAll(modClassLoader.getDefaultLibraries())
|
||||
// skip loaded coremods
|
||||
.addAll(CoreModManager.getLoadedCoremods())
|
||||
// skip reparse coremods here
|
||||
.addAll(CoreModManager.getReparseableCoremods())
|
||||
.build();
|
||||
List<String> knownLibraries = ImmutableList.<String>builder().addAll(modClassLoader.getDefaultLibraries()).addAll(RelaunchLibraryManager.getLibraries()).build();
|
||||
File[] minecraftSources = modClassLoader.getParentSources();
|
||||
if (minecraftSources.length == 1 && minecraftSources[0].isFile())
|
||||
{
|
||||
FMLLog.fine("Minecraft is a file at %s, loading", minecraftSources[0].getAbsolutePath());
|
||||
candidates.add(new ModCandidate(minecraftSources[0], minecraftSources[0], ContainerType.JAR, true, true));
|
||||
candidates.add(new ModCandidate(minecraftSources[0], minecraftSources[0], ContainerType.JAR));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -64,18 +71,18 @@ public class ModDiscoverer
|
||||
{
|
||||
if (knownLibraries.contains(minecraftSources[i].getName()))
|
||||
{
|
||||
FMLLog.finer("Skipping known library file %s", minecraftSources[i].getAbsolutePath());
|
||||
FMLLog.fine("Skipping known library file %s", minecraftSources[i].getAbsolutePath());
|
||||
}
|
||||
else
|
||||
{
|
||||
FMLLog.fine("Found a minecraft related file at %s, examining for mod candidates", minecraftSources[i].getAbsolutePath());
|
||||
candidates.add(new ModCandidate(minecraftSources[i], minecraftSources[i], ContainerType.JAR, i==0, true));
|
||||
candidates.add(new ModCandidate(minecraftSources[i], minecraftSources[i], ContainerType.JAR, true));
|
||||
}
|
||||
}
|
||||
else if (minecraftSources[i].isDirectory())
|
||||
{
|
||||
FMLLog.fine("Found a minecraft related directory at %s, examining for mod candidates", minecraftSources[i].getAbsolutePath());
|
||||
candidates.add(new ModCandidate(minecraftSources[i], minecraftSources[i], ContainerType.DIR, i==0, true));
|
||||
candidates.add(new ModCandidate(minecraftSources[i], minecraftSources[i], ContainerType.DIR, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -84,21 +91,13 @@ public class ModDiscoverer
|
||||
|
||||
public void findModDirMods(File modsDir)
|
||||
{
|
||||
findModDirMods(modsDir, new File[0]);
|
||||
}
|
||||
File[] modList = modsDir.listFiles();
|
||||
// Sort the files into alphabetical order first
|
||||
Arrays.sort(modList);
|
||||
|
||||
public void findModDirMods(File modsDir, File[] supplementalModFileCandidates)
|
||||
{
|
||||
File[] modList = FileListHelper.sortFileList(modsDir, null);
|
||||
modList = FileListHelper.sortFileList(ObjectArrays.concat(modList, supplementalModFileCandidates, File.class));
|
||||
for (File modFile : modList)
|
||||
{
|
||||
// skip loaded coremods
|
||||
if (CoreModManager.getLoadedCoremods().contains(modFile.getName()))
|
||||
{
|
||||
FMLLog.finer("Skipping already parsed coremod or tweaker %s", modFile.getName());
|
||||
}
|
||||
else if (modFile.isDirectory())
|
||||
if (modFile.isDirectory())
|
||||
{
|
||||
FMLLog.fine("Found a candidate mod directory %s", modFile.getName());
|
||||
candidates.add(new ModCandidate(modFile, modFile, ContainerType.DIR));
|
||||
@@ -129,18 +128,11 @@ public class ModDiscoverer
|
||||
try
|
||||
{
|
||||
List<ModContainer> mods = candidate.explore(dataTable);
|
||||
if (mods.isEmpty() && !candidate.isClasspath())
|
||||
{
|
||||
nonModLibs.add(candidate.getModContainer());
|
||||
}
|
||||
else
|
||||
{
|
||||
modList.addAll(mods);
|
||||
}
|
||||
modList.addAll(mods);
|
||||
}
|
||||
catch (LoaderException le)
|
||||
{
|
||||
FMLLog.log(Level.WARN, le, "Identified a problem with the mod candidate %s, ignoring this source", candidate.getModContainer());
|
||||
FMLLog.log(Level.WARNING, le, "Identified a problem with the mod candidate %s, ignoring this source", candidate.getModContainer());
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
@@ -156,8 +148,4 @@ public class ModDiscoverer
|
||||
return dataTable;
|
||||
}
|
||||
|
||||
public List<File> getNonModLibs()
|
||||
{
|
||||
return nonModLibs;
|
||||
}
|
||||
}
|
||||
Loaded 100 of 1120 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user