Compare commits

..
640 Commits
Author SHA1 Message Date
Christian 70f55c59c0 Add in exclusion list for IFMLLoadingPlugin. 2012-09-08 12:19:03 -04:00
Christian 1c1716d833 Remove debug cruft 2012-09-07 23:14:54 -04:00
Christian d567f79652 To properly align with packet9respawn, make packet1login's dimension an int as well 2012-09-07 22:57:01 -04:00
Christian ecd4e46a45 Attempt to build some protocol negotiation, and fix packet1login so that the dimension is a short, matching packet9respawn 2012-09-07 22:46:31 -04:00
Christian 16fe495d18 Compatibility level is now passed from server to client - and
the client tracks it. This means certain packet changes can be made
without breaking comms, hopefully
2012-09-07 19:32:36 -04:00
Christian 4f70d23d0e Fix dependency checking: you can depend on specific versions of FML 2012-09-07 19:08:28 -04:00
cpw 290a3c94b7 Merge pull request #94 from iChun/patch-1
Fix handleTinyPacket using short instead of int.
2012-09-07 05:43:39 -07:00
iChun 9485dc5a96 Fix handleTinyPacket using short instead of int.
Silly cpw :P
2012-09-07 18:35:26 +08:00
Christian e6abb69b0e Fix up tiny packet handler to actually work 2012-09-06 22:59:38 -04:00
Christian e862052bb4 Allow javax to be shipped by mods. Should allow some more modloader mods to work
unaltered
2012-09-06 22:03:02 -04:00
Christian 4071ad1278 Add in a little bit of protocol cleanup. Start work on allowing multiple
protocol versions
2012-09-06 21:54:43 -04:00
Christian 60619643e6 Give a way to build the packet131mapdata packet correctly populated 2012-09-06 10:12:37 -04:00
Christian b818769c1f Capture and leverage Packet131MapData 2012-09-06 10:03:30 -04:00
Christian 12bc4bab0c Make console logging pass through a single logging thread to avoid concurrency problems with launchers and stuff 2012-09-04 19:11:45 -04:00
Christian 8fccfa21df Overlooked chat message support *sigh*. Fixes wierd mods that communicate through custom
chat messages rather than anything else. Hi Superior enchanting!
2012-09-04 12:37:59 -04:00
Christian a697d043fc Rescan mod packages where there was a possible mod identified to try and make sure we load it. Fixes Matmos r16 2012-09-04 11:39:51 -04:00
Christian 9d812f12cc And handle the other way to globally register an entity 2012-09-03 21:37:20 -04:00
Christian 869cf78e98 Fix up mods trying to register entities outside of modloading. Now you'll get a big fat warning for doing such a derpy thing. 2012-09-03 21:32:21 -04:00
Christian 186680cd8c Fix CJB mod compatibilty for real. Gui container registration can now happen in the constructor. YUK! 2012-09-03 21:14:11 -04:00
Christian 5aed6d995d Fix compatibility with ModLoader dispenser hook. Fixes a bug with
IDispenseHandler too - though it means that interface is now
deprecated
2012-09-03 11:37:17 -04:00
Christian 3d7a665987 Fix headless operation, hopefully 2012-09-02 13:29:46 -04:00
Christian 10a716969b Fix up trying to re-add stuff to the classpath when it's already there 2012-09-02 12:56:08 -04:00
Christian 0eb7180fc1 Fix out of range entity id handling for ModLoader mods a bit more. Thanks Herobrine mod! 2012-09-02 12:39:06 -04:00
Christian b1b4c61b80 Expose GuiMerchantButton 2012-09-02 12:15:13 -04:00
Christian 359cfb5c98 Log a big fat warning for the developer in the case the network version
is not acceptable to the mod itself. (This can happen because of a bad range
specifier for example)
2012-08-31 23:41:29 -04:00
Christian 8656fd50ce Also, make missing entity not blow things up 2012-08-31 16:49:35 -04:00
Christian 25a4dcb653 Fix entity tracker "update" packet not computing correctly. Should work now.. 2012-08-31 16:41:05 -04:00
Christian c90a853377 Fix up addRenderer to catch exceptions from the basemod, also, addrenderer now supplies a list of the
default renderers from MC for editing and will note the changes made.
2012-08-31 11:18:17 -04:00
Christian 18069d8fd2 Change download location for FML libraries to files.minecraftforge.net, add an encoding param to the javac command line to force utf 8 2012-08-31 11:18:17 -04:00
Christian a40f4a75a9 Add in random jar/zip files to the classpath. UGH this is so fucking ugly it's not funny. 2012-08-30 20:10:53 -04:00
Christian 5b6460b68c Use a null socket and try to prefer the result of getLocalHost in the broadcast data. 2012-08-29 16:12:40 -04:00
Christian c0d1348e65 Add in an ItemRenderer null check so FML can run render adding mods 2012-08-29 13:58:56 -04:00
Christian 482c163344 Inverted boolean logic. Grrr. 2012-08-29 13:44:40 -04:00
Christian 221d1131b4 ModLoader mob spawns use packet 24- build a bypass system so that
they can still use it
2012-08-29 12:58:16 -04:00
Christian f19f426449 Remove debug statements 2012-08-28 23:07:37 -04:00
Christian 9dd9b6eb71 Fix keybindings not loading properly from gamesettings file after restart 2012-08-28 22:15:18 -04:00
Christian acb0b21d6d Fix so we always send received packets to handlers.
Renders 250 filtering useless unless i can figure a way to intercept *outbound* packets that isn't as messy as I'm
contemplating
2012-08-27 17:46:08 -04:00
Christian b17dd3c695 Some tests 2012-08-26 22:23:05 -04:00
Christian fa66ffaf3f Fix trying to load the client side packet handler, when on the server, hopefully? 2012-08-26 22:18:57 -04:00
Christian b106420774 Fix up network negotiation - now it will disconnect with a nice
error screen if there are missing mods on the client vs server
2012-08-26 22:13:43 -04:00
Christian c971adb59b Fix missing addCommand call: thanks "spawnwolf test command" 2012-08-26 13:07:35 -04:00
Christian d6326deeb0 Fix a couple of modloader mods. Thanks! 2012-08-26 12:52:50 -04:00
Christian 483667c919 Some functionality fixes for @Instance injection. 2012-08-26 10:55:55 -04:00
Christian 8bef512803 Versions now have two flavours: the @Mod(version) which is the "programmatic version" and
is used for all version relationship calculation. The "display version" as sourced from
mcmod.info is used for display purposes only and can be literally anything. Note: they fall back
to one another when they're missing, and to "1.0" if both are absent.

Also, changed @Instance. Now, you can inject *other* mods using @Instance as long as you depend
on them as a "before" or "dependency" relationship. Classes containing @Instance will only be
loaded if the Mod the @Instance refers is present. So you don't have to worry about runtime class
resolution.
2012-08-26 10:45:00 -04:00
Christian 501009c11f Always for ML mods into "public" class accessibility - we don't call from the default package like ML does. 2012-08-25 21:57:25 -04:00
Christian d3d430827f Add in a convenience method for getting a class instance based on
existence of another Mod. Useful for soft dependencies.
2012-08-25 21:26:41 -04:00
Christian 2d9b88bd52 And more mod sorting fixes. 2012-08-24 12:10:43 -04:00
Christian 93d5934ea7 Actually *use* the sorted mod list 2012-08-24 11:58:18 -04:00
cpw 180a279558 Merge pull request #82 from Chicken-Bones/master
The access transformer will now handle classes in packages.
2012-08-23 16:47:13 -07:00
Chicken Bones cf38461911 The access transformer will now handle classes in packages.
Eg.

public net/minecraft/client/Minecraft.T #timer
2012-08-24 08:09:10 +10:00
Christian 2c85539517 Reverse the meaning of state in fml.modStates system property and fmlModState.properties - it was very
derpy before. Now: true is enabled, false is disabled, as you would expect
2012-08-23 17:37:44 -04:00
Christian d651189581 Actually fix the corrupt JSON problem 2012-08-23 17:27:53 -04:00
Christian f6a8cd556e Fix isModLoaded for "disabled" mods, and the toposort as well 2012-08-23 17:08:18 -04:00
Christian 3bde961dc7 A bit more information for dependency handling 2012-08-23 16:46:23 -04:00
Christian 6396beaef7 Fix up handing corrupt mcmod.info 2012-08-23 16:43:28 -04:00
Christian 6bc6defb07 Fix a problem with network ids 2012-08-23 16:38:34 -04:00
Christian 732861092f Fix up version handling properly. Hopefully, and the error screen. 2012-08-23 15:29:17 -04:00
Christian 9fcc452ed3 Only active mods should have dependencies checked, and be sorted 2012-08-23 14:33:54 -04:00
Christian 26302a6ff2 Fix oddity with Screen, print a version out in the sorted list! 2012-08-23 14:28:49 -04:00
Christian 62dbfb3837 Fix metadata 2012-08-23 14:05:17 -04:00
Christian b91cbe9794 Fix up versioned dependencies so they work a lot better, also add in a missing mods screen 2012-08-23 13:43:25 -04:00
Christian 93b8ba9576 Fix missing serverSendPacket 2012-08-23 09:02:12 -04:00
Christian 23fdbbd03d Trading support for ModLoader - thanks Herblore! 2012-08-23 01:40:03 -04:00
Christian d7a74d84ea Close the jar, for cleanliness sake 2012-08-23 01:39:35 -04:00
Christian 58e6dd9794 Fix authors - it'll read both "authors" and "authorList" from the json now 2012-08-23 01:17:47 -04:00
Christian 907cf2d925 More ML compatibility - fix up dragon mounts, thanks! 2012-08-23 00:37:45 -04:00
Christian ee48a3673d Fix up loading mods that are grandchildren of BaseMod 2012-08-23 00:04:34 -04:00
Christian c6f362b77f Fix entity handling for ModLoader mods, thanks parachute mod! 2012-08-22 23:46:16 -04:00
Christian 6e01c59635 Merge ChickenBones pull into FML - adds player trackers 2012-08-22 18:00:55 -04:00
Christian d411f66903 Fix formatting 2012-08-22 18:00:38 -04:00
Christian 0768dc1610 Tweak patches and hooks slightly 2012-08-22 17:58:46 -04:00
Christian 4c3db16842 More precise error handling when an invalid class is present 2012-08-22 17:50:07 -04:00
Christian 805fd1dd90 Fix textures not applying properly 2012-08-22 17:50:07 -04:00
Christian c59996b24b Fix up entity spawning - hopefully they won't warp anymore. 2012-08-22 17:50:07 -04:00
Christian e0a1e8293b Add in a helper on the server start event for adding commands to
the server.
2012-08-22 17:50:07 -04:00
Christian e8af9c0233 Move villager trading hook up a bit. thanks sengir. 2012-08-22 17:50:07 -04:00
Christian a955d30d64 Fix LAN to try hard to find a real network interface, not just localhost
most of the time
2012-08-22 17:50:07 -04:00
Christian dbab3bb259 Update build to not bother building client jar. Universal is everything
now.
2012-08-22 17:50:07 -04:00
Christian bd9c4ee99a Null protection for ticks() -- probably should uses EnumSet.noneOf() but
you can also use null now to stop ticking. closes #77
2012-08-22 17:50:07 -04:00
Christian a0cbd3755d More precise error handling when an invalid class is present 2012-08-22 17:36:26 -04:00
Christian 12323e233f Fix textures not applying properly 2012-08-22 17:27:06 -04:00
Chicken Bones 8a308db3d4 FML will now search '<mcpdir>/forge/accesstransformers' for user defined access transformer config files to be applied during forge setup 2012-08-23 06:31:00 +10:00
Chicken Bones 0583dc8b74 Added IPlayerTracker hooks 2012-08-23 06:28:53 +10:00
Christian 789a4a3659 Fix up entity spawning - hopefully they won't warp anymore. 2012-08-22 15:11:59 -04:00
Christian a87d0451c8 Add in a helper on the server start event for adding commands to
the server.
2012-08-22 15:11:43 -04:00
Christian 82e9309d27 Move villager trading hook up a bit. thanks sengir. 2012-08-22 11:50:03 -04:00
Christian 8deaa378c9 Fix LAN to try hard to find a real network interface, not just localhost
most of the time
2012-08-22 11:48:30 -04:00
Christian b5363e3552 Update build to not bother building client jar. Universal is everything
now.
2012-08-22 11:12:26 -04:00
Christian 28a10ac340 Null protection for ticks() -- probably should uses EnumSet.noneOf() but
you can also use null now to stop ticking. closes #77
2012-08-22 09:43:32 -04:00
Christian c349d51923 Automatic mod entity registration into the global entity list. This might break
entity code out there, sorry, but this way for most entities you no longer
need to manage the global mod entity stuff at all. just remove it. FML will
take care of the rest (note, worlds won't load the old entities)
2012-08-21 19:34:33 -04:00
Christian ef01745e09 Add in a utility function that *might* tell you the context
you're running in on either client or server: FMLCommonHandler.getEffectiveSide
2012-08-21 19:15:07 -04:00
Christian c97d6a65d0 Try and stop sendPacketToAllAround from being crashy 2012-08-21 18:50:26 -04:00
Christian 2062273504 Mods can add mod specific crash information to the crash report now
Forge needs to implement MinecraftForge.getCrashCallable
2012-08-21 18:48:12 -04:00
Christian 6e6436ee41 Fix up dispenser handling, add in new params for the dispenser: breaks IDispenseHandler, sorry 2012-08-20 21:44:54 -04:00
Christian 38f4a22bc4 Fix up MLProp handling for null info 2012-08-20 21:44:47 -04:00
Christian 3a8b047e3c GUIs working in FML for ML mods 2012-08-20 21:44:28 -04:00
Christian 52483ee6bd Support gui opening for Shelf mod 2012-08-20 21:43:59 -04:00
LexManos dce1cbc096 Updated MCPMerger to annotate unique classes with there sides, and SideTransformer to null out any class that is loaded on the wrong side. 2012-08-19 22:26:52 -07:00
Christian 46c563a9a8 Expose more of the village construction parts for building village
pieces
2012-08-19 11:23:29 -04:00
Christian 1380c2ecce Allow access to the type "ComponentVillage" 2012-08-19 10:35:06 -04:00
Christian 71a3818bdd Documentation and registration for villager stuff 2012-08-19 10:30:24 -04:00
Christian e3a343c797 Fix javadoc derp 2012-08-19 10:21:19 -04:00
Christian 195b1a043e Villager trading, manipulation and village enhancement. Still WIP but should be functional 2012-08-19 10:13:15 -04:00
Christian 69e66c327f Fix exception based logging to actually log the exception! 2012-08-19 09:31:26 -04:00
Christian 885637cc7d Fix up keyboard events for modloader 2012-08-19 01:44:33 -04:00
Christian 90a7c8f787 Pickup notification 2012-08-19 00:26:55 -04:00
Christian 2171c0caa4 Update fml_at with new transforms 2012-08-18 20:08:27 -04:00
Christian 924a6f9254 Fix derp where client sided packet handler would be created on a dedi server env 2012-08-18 19:50:46 -04:00
Christian ad4cffb0c6 Add in support for "dummy" keybindings- ones that are added to the list but never do anything
so the mod can handle it all themselves.
2012-08-18 10:24:29 -04:00
Christian cf77ffb89d Don't complain about minecraft source code being in "net.minecraft.src". Derp. 2012-08-18 10:09:53 -04:00
Christian b2fdcd7f1c Fix ModLoader add XP Smelting 2012-08-18 10:09:25 -04:00
Christian 094ce2ae18 Actually register client/server packetspecs as their correct sides! fixes #71 2012-08-18 09:28:36 -04:00
Christian e8cb2c1bfe Error if channel name is invalid - either too short, or too long 2012-08-17 16:59:48 -04:00
Christian 9c6c56c49d Add a connect and read timeout for downloading libraries. This should really stop the "waiting forever" at startup screen. 2012-08-17 16:21:18 -04:00
Christian 0d5affede3 GIANT FAT WARNINGS if you use any code in net.minecraft.src or any subpackage thereof. Get it out of there, now! 2012-08-17 16:13:05 -04:00
Christian 13f210f403 Fix up ML GUI ticking. Thanks sharose! 2012-08-17 16:09:46 -04:00
Christian c61ad51883 Organize ALL the imports 2012-08-17 09:25:04 -04:00
Christian c0842b0797 Expose the server in serverstart event 2012-08-17 09:25:04 -04:00
Christian 2851079ff0 Fix up directory injection of log file locations 2012-08-17 09:25:04 -04:00
Christian 5197524d1c Refer to FMLLog, not FMLRelaunchLog 2012-08-17 09:25:04 -04:00
Christian 78efd1acc6 Tidy up server launch - reflection not required anymore 2012-08-17 09:25:04 -04:00
Christian eee0a99b88 Also, log what the directory discoverer finds for mcmod.info 2012-08-17 09:25:04 -04:00
Christian 10c96c394d And log the exception if it has a problem reading the jar file 2012-08-17 09:25:04 -04:00
Christian 07cc3fb2d9 Fix jar loader failing to inject any metadata at all if mcmod.info is not found. 2012-08-17 09:25:04 -04:00
LexManos e31f1433bf Change install.cmd to install.bat, why, cuz people are .... Updated readme to mention needing server and client. 2012-08-16 22:57:11 -07:00
Christian af06c97efd Some compatibility fixes for Rei's minimap, and tidy up a couple of things 2012-08-16 13:55:42 -04:00
Christian 400de1d66e Fix Forge branding string call 2012-08-16 13:01:48 -04:00
Christian 2a9285eee8 Update FML for mcp 72 final, change download location for FML files, and make the stop button work.
Hello is NOT going to go away :)
2012-08-16 12:22:56 -04:00
Christian 785bdde6bd Fix critical bug in FML load controller that complains about injected mod containers 2012-08-16 08:34:12 -04:00
Christian 071e2dc524 Handle the case where a mod tries to do something stateful during constructor phase, and log a big
fat message about it. Don't do it!
2012-08-15 20:05:12 -04:00
Christian fc08d072a4 Small fixes, including showing the FULL name of Forge Mod Loader 2012-08-15 19:54:56 -04:00
Christian 0019485aba Fix up null array in keybinding handler 2012-08-15 19:17:21 -04:00
Christian e76f145b65 Actually add in the system property for the minecraft home, should fix multimc too 2012-08-15 19:16:36 -04:00
Christian 27d5937f4c Add in support for setting the home dir via the applet launch, also a system property for forcing the home dir 2012-08-15 17:18:11 -04:00
LexManos 868c4c5977 Cleanup fml.py a little, should fix double printing of 'patching file' 2012-08-15 03:10:45 -07:00
LexManos 5a37929ceb Wrap mod description rendering in BLEND calls https://github.com/MinecraftForge/MinecraftForge/issues/96 2012-08-15 02:52:29 -07:00
LexManos b1dc2dbf8a Made getmodifiedsrc noop for server. 2012-08-15 00:50:40 -07:00
LexManos ecfbef95c7 Fix new eclipse workspace to load the project properly from start. 2012-08-15 00:50:16 -07:00
Christian bfd8fbefee Merge branch 'minecraft132'
Yes, we are already on 1.3.2
2012-08-14 22:33:28 -04:00
Christian f8c36104ad KeyBinding handler change: a handler now takes an array of keys and calls back with the
activated key. Sorry for the inconvenience but this improves the usability of this
API a lot
2012-08-14 22:32:19 -04:00
Christian e26230fb2d Fix renderer's not getting the rendermanager set on them at registration time 2012-08-14 22:32:19 -04:00
LexManos 6417ad0a3c Finished update to MCP 7.2, MC 1.3.2 pre. 2012-08-14 19:24:49 -07:00
Christian 0f988d087c KeyBinding handler change: a handler now takes an array of keys and calls back with the
activated key. Sorry for the inconvenience but this improves the usability of this
API a lot
2012-08-14 22:06:49 -04:00
Christian 7c01b64aed Fix renderer's not getting the rendermanager set on them at registration time 2012-08-14 21:59:47 -04:00
LexManos 03130c78a7 Fixup included workspace to have single project with client/server launches. 2012-08-14 17:42:40 -07:00
Christian 30ab326d2b Start working on MC 1.3.2 2012-08-14 20:09:24 -04:00
Christian 8d1cba57f8 Add in a helper for code migrating from ML renderer stuff 2012-08-14 19:09:22 -04:00
Christian cbfd6c1a66 Merge pull request #62 from calclavia/patch-1
Shortcut function for addNameForObject()
2012-08-14 13:52:58 -07:00
calclavia 81cb3c82f4 Shortcut function for addNameForObject()
Having that long line of code makes the code a bit ugly... Please make this shortcut function like ModLoader.addName() so I don't need to use ModLoader.addName(). :)
2012-08-15 04:45:32 +08:00
Christian e64296e109 Handle mod duplicate detection much better. Default the name of a mod to it's id.
Fix up the block registry problem. Fix the packetsend from c->s actually being
"disconnect" :)
2012-08-14 13:36:29 -04:00
Christian 5872b31781 Fix entity spawn packets 2012-08-14 08:20:28 -04:00
LexManos 51b801b1c6 Force a Jenkins build 2012-08-14 01:21:56 -07:00
LexManos 9ef153c0b6 Merge pull request #60 from remuladgryta/master
fixed 'derp' error on @NetworkMod
2012-08-14 01:16:29 -07:00
remuladgryta 2e236faec7 fixed java.lang.NoSuchMethodException
getServerHandlerSpecDefaultValue() and
getClientHandlerSpecDefaultValue() should no longer give derp exeption
2012-08-14 09:50:22 +03:00
LexManos 129c356ecf FML will skip gathering MD5s for classes in the cpw package during the the inital recompile {Make Side/SideOnly reobf properly} 2012-08-13 21:53:52 -07:00
LexManos d8316b0bdc Merge remote-tracking branch 'origin/master' 2012-08-13 21:05:14 -07:00
LexManos 1d3a92f3f1 Updated FML install to provide better error output, Updated commands.py patch to disable recompile of server project. 2012-08-13 21:02:55 -07:00
Christian 81c858c719 Hopefully let build continue if server reobf fails, and fix derp in FMLNetworkHandler for entities 2012-08-13 23:25:08 -04:00
Christian 341041aedb Fix up concurrent modification exception - ticks for players now occur on both sides 2012-08-13 22:55:23 -04:00
Christian 25256b2295 Merge the last bits of the server code into the common directory, and annotate ModLoader/BaseMod for sided use
This means the FML-Server project is now defunct as all code is either common, client or bukkit.
2012-08-13 22:51:53 -04:00
Christian 13874ba547 Actually fix the applet launch - it now launches properly *and* closes the window 2012-08-13 22:12:36 -04:00
Christian bde58add62 Fix up relaunch of the applet 2012-08-13 21:44:43 -04:00
Christian 9112c63347 Change language loading a bit 2012-08-13 20:28:53 -04:00
Christian 78fa2b8d78 Update spritehelper bitmaps for items and terrain 2012-08-13 20:08:03 -04:00
Christian 6922c369f3 Tidy up some APIs, expose the addOverride mechanism. This should be pluggable by forge
but may need work to allow for each mod to have it's own override set
2012-08-13 19:57:40 -04:00
Christian b0fd438a1d Fix derp in LanguageRegistry 2012-08-13 16:45:47 -04:00
Christian 99f4f0c7d3 FMLModcontainer should not complain about annotations it has no idea about. so stfu fmlmodcontainer 2012-08-13 16:15:11 -04:00
Christian b09c1cd242 Fix derp with EntityRegistry- bimap is not the right type for the name->container list 2012-08-13 15:55:24 -04:00
Christian 5ca3bf9362 Add in a sided variant of the packethandlers in the annotation - also, a bit more
explicit warning on when to register blocks - if you do it after pre-init, you'll
reset the achievements
2012-08-13 15:26:29 -04:00
Christian c6a9884bde Generate channel registration for client, also, do it before the login events so you can send packets 2012-08-13 11:58:44 -04:00
Christian 43825ca78e Capture server packet handling errors into the FML log file for diagnostics 2012-08-13 11:52:30 -04:00
Christian 44eeadb211 one more change for the road :) 2012-08-13 01:24:02 -04:00
Christian 7011da5fa9 Don't spit debug all over the floor 2012-08-13 00:24:15 -04:00
Christian c61ddfa9d1 updated conf, commands patch (missing newline?) and capturing the actual running
MC version and validating it at relaunch time is the correct MC version.
2012-08-13 00:17:34 -04:00
Christian e64b6dcb13 Add in callableminecraftversion 2012-08-12 23:54:41 -04:00
Christian 183dc236e4 Entity AI accessibility, also AccessTransformer can make certain classes public now 2012-08-12 23:50:27 -04:00
Christian ef5349dec2 Add in a simple packet dispatcher for sending packets around 2012-08-12 22:45:18 -04:00
Christian b39afc0711 Add in a sided packet registry so that client vs server can vary 2012-08-12 22:23:03 -04:00
Christian a8579b43ac Fix double forge init on server 2012-08-12 20:34:23 -04:00
Christian fa92eca328 Merge pull request #50 from Krapht/master
Fix for getNextAvailableRenderId() returning ids in use by vanilla - thanks krapht!
2012-08-12 06:55:23 -07:00
Krapht 42165df29f Fixed getNextAvailableRenderId() returning ids in use by vanilla 2012-08-12 14:45:03 +02:00
LexManos 9860569536 Fix MCPMerger injecting Side/SideOnly when it already exists. 2012-08-12 04:27:36 -07:00
LexManos 7aa48a167f Added patch verification to commands.py patch, and made it so MCP will check the original jars for the server, to prevent it from saying modified when it started out clean. 2012-08-12 02:49:39 -07:00
LexManos 6e3764da48 Add DEBUG constant to Access/Side Transformers to remove spam when not needed. Also AccessTransformer and MCPMerger should return a error code when it can not process causing MCP to stop decompile. 2012-08-12 01:23:10 -07:00
Christian 4d503d6925 Fix EntityRegistry - mods can specify update frequency, range and velocity data, and also
patch EntityTracker to actually track FML entities
2012-08-12 00:18:04 -04:00
Christian 8e04d40034 Fix NPE with no channels - always register FML 2012-08-12 00:17:07 -04:00
LexManos cb57cd02e0 Added missing quotes around compile command. 2012-08-11 16:03:33 -07:00
Christian 22fe48e477 Fix up the network mod issue properly. Maintain a real cache of mod objects 2012-08-11 16:21:03 -04:00
Christian 204f73cb05 Remove profiler stuff - it's been deeply reorged. I'll look at re-adding it later 2012-08-11 14:12:39 -04:00
Christian 28096abea5 Fix up command patch to actually work 2012-08-11 14:12:23 -04:00
Christian 2d7eb5cb7f Fix commands.py to always include the two side classes so the fml jars are valid. 2012-08-11 14:01:27 -04:00
Christian e6d6932e21 Fix build script- put client in first 2012-08-11 13:05:37 -04:00
Christian 406e5d64c0 Put the marker on the server ML file too 2012-08-11 13:04:59 -04:00
Christian 13756aad9f Fix universal not to dupe entries in the jar, also add in the fml mod as "untransformable" 2012-08-11 12:34:25 -04:00
Christian c1a8b16f30 Fix up launch when obfuscated *sigh* 2012-08-11 12:24:43 -04:00
Christian e3671285c3 Update netclienthandler patch. 2012-08-11 12:10:22 -04:00
Christian b33cff3613 Fix NPE for server relaunch 2012-08-11 12:05:13 -04:00
Christian afc2a4a75c Fix up Package.getPackage(), also fix up loadcontroller construction 2012-08-11 11:44:55 -04:00
Christian 7c4583c87a Add in Package.getPackage() support for sengir 2012-08-11 11:12:16 -04:00
Christian f563815961 Lost of work to try and complete ML support - probably still bits missing, but mostly there 2012-08-11 11:02:09 -04:00
LexManos 0ce38f747c Newlines in diff file 2012-08-11 02:27:19 -07:00
LexManos efce8e916b Add special case to add Side/SideOnly to difflist 2012-08-11 02:25:40 -07:00
Christian 44728c9f93 Fix up some network related stuff and optimize mod lookup a bit 2012-08-11 02:43:04 -04:00
Christian d96a81e4f2 Fix up proxy injector to inject properly 2012-08-11 02:24:29 -04:00
LexManos f11844374e Fix decompile 2012-08-10 20:41:59 -07:00
Christian 8c63203bb4 Fix NPE on missing mods - still need to actually handle missing mods properly on client 2012-08-10 23:27:11 -04:00
Christian 751299d5f1 New downloader UI and new downloader backend - should be more robust now 2012-08-10 23:18:52 -04:00
LexManos 7d479bf854 Added -no_gen_conf to jenkins build 2012-08-10 20:09:47 -07:00
LexManos c812a4ede5 Added some extra error prints, hopeully get something useful when installed in the client. 2012-08-10 18:54:06 -07:00
LexManos a826283111 Updated conf merger script to just merge everything, and normalize the line endings so git doesn't complain. 2012-08-10 18:25:11 -07:00
Christian f61f30c1e6 SidedProxy should work again - anywhere. Make sure it's on a static field though 2012-08-10 17:42:43 -04:00
Christian 8f76e8ba8b More ticking hooks, and some other bits of clean up. Very close to "done" now. 2012-08-10 17:11:01 -04:00
Christian 537d89b9e0 Fix up modloader and clean up junk method 2012-08-10 16:42:21 -04:00
Christian 0927aaa0f1 A lot of missing patches to code re-added. Almost all functionality should now
be restored.

ModLoader compatibility is not yet assured, there are some wrapper classes that
need re-writing first
2012-08-10 16:39:03 -04:00
LexManos d17aad797d Readded common folder to startclient/server. 2012-08-10 12:38:59 -07:00
Christian 53e611a03a Add in a registration method for gui handlers 2012-08-10 11:12:57 -04:00
Christian 7ac1be8a9a Overwrote lex's command patch 2012-08-10 10:57:18 -04:00
Christian dd7d70d619 Fix up MCP merger - it definitely works now - the game runs and runs well.
Fix up a couple of small network related issues.
Fix up the server launching fml properly.
2012-08-10 10:03:33 -04:00
LexManos b9d1d1e2f4 Added common folder support to startclient/startserver 2012-08-09 20:34:16 -07:00
LexManos 2dc00adec8 Added some missing quotes that caused issues if your workspace had a space in it. 2012-08-09 20:01:51 -07:00
LexManos b97e937f28 Add lib folder to installed eclipse 2012-08-09 19:02:28 -07:00
Christian c54c4e73e6 Add in missing patch - also, launch FML properly from the server 2012-08-09 09:21:16 -04:00
Christian 93528597f4 Entity spawn adjustment - tracker 2012-08-09 08:40:32 -04:00
LexManos a85bb7bfdb Fix ModLoader compilation, and MCPmerger invocation for Forge. 2012-08-09 03:04:25 -07:00
LexManos 0f2d00abf3 Include conf folder and merge config in source zip 2012-08-08 23:44:32 -07:00
Christian 0e4c716177 Entity spawning - done 2012-08-09 01:58:14 -04:00
Christian 85b77c3d12 Generate a universal binary package since we can now :) 2012-08-09 01:57:42 -04:00
Christian 03884b1aaa Merge branch 'MergingClientServer' 2012-08-08 22:58:33 -04:00
Christian dbdc76e6ea Reorganized all the current patches 2012-08-08 22:57:37 -04:00
Christian b8aaed368b Fix up annotation parser to parse arrays and enums 2012-08-08 22:10:56 -04:00
LexManos 6ec3379153 Added SideTransformer to strip side only functions/fields out. 2012-08-08 18:53:41 -07:00
LexManos b177aad1ee Stage 1 of merging the client and server for MCP.
Results:
Client: 362
Server: 3 (Only due to issues of FF decompilation inconsistancies)
Common: 910

Stage 2: Write runtime transformer to remove annotated fields/methods with invalid side annotation.
2012-08-08 05:48:06 -07:00
Christian e050c7807d Gui Handler ported from MC forge 2012-08-08 00:31:24 -04:00
Christian f3f7398a8b Revert dumb stuff with commands patch - lots of gfx patching 2012-08-07 23:11:37 -04:00
Christian da4311dc74 Almost finished basic network stuff now 2012-08-07 20:41:37 -04:00
Christian 59471f6cac Update some patches- more network work 2012-08-07 20:10:36 -04:00
Christian d8b92064d7 Bunch of hooks re-added : network is more complete now, lot of basemod cleanup, moving stuff into
the registry area
2012-08-06 22:30:13 -04:00
Christian 8e96e60179 Fix location of forge in common handler - also some tweaks to modloader and other stuff 2012-08-06 17:27:21 -04:00
Christian 54877176a6 Network support - there's still some work to do and full id sync isn't done yet, but it has proper registration
semantics and hooks for 250 handling
2012-08-06 16:12:50 -04:00
Christian a3ad32a3e5 Add in a lot of network handler stuff - also, expose the asm harvested data 2012-08-06 09:52:42 -04:00
Christian 602a4f219c Remove some unneeded fields from the annotations 2012-08-05 02:24:02 -04:00
LexManos f24977dc3d Made empty constructor for ModMetadata public 2012-08-04 22:51:57 -07:00
LexManos 4607f9ebb0 Fix path trimming for copytree 2012-08-04 20:36:27 -07:00
Christian 672f4a03f2 Change property name to fml.modStates not fml.disabledMods- it makes more sense that way 2012-08-04 12:35:46 -04:00
Christian f0736ade3d Add in a bit of logging when events get sent to mod containers 2012-08-04 11:45:40 -04:00
Christian 4da48cea7a Allow coremods to inject a modcontainer and run code
this will mean that FML is deliberately and very obviously incompatible with a modloader installation.

Fix up worldtype so that the server can run.
2012-08-04 11:31:06 -04:00
LexManos 1b02ea0677 Patch commands.py to support side '2' as common, as well as fix a few small errors in the update_patches and fml scripts. 2012-08-04 03:34:34 -07:00
LexManos 0d1bd4c5d0 Merged transformers/ to /common and renamed the asm source download to align better with the asm bin file name. 2012-08-03 23:51:49 -07:00
LexManos 3f08f1a94c Change place commands.py backup is stored. 2012-08-03 23:24:58 -07:00
LexManos 1069366219 FML finish won't updatemcp automatically, easier integration with forge. 2012-08-03 17:36:16 -07:00
LexManos 0002bd2875 Fix packaging and install to not have the src/ folder, making it align better with the dev env. 2012-08-03 17:32:23 -07:00
LexManos 823077dd7d Moved setting up eclipse to setup_mcp 2012-08-03 16:56:00 -07:00
LexManos 34971ff3e0 Fixed ant script to support common folder building and add the new files to the dist archives. 2012-08-03 03:37:45 -07:00
LexManos 965069ba3a setup_fml's decompile will result in proper md5 files now {if there is no compiler issues} 2012-08-03 03:35:38 -07:00
LexManos 43766751a4 Removed FMLRegistry, and IMinecraftRegistry.
Updated server side to use the seperated registry classes like the client does.
Updated searge name references on server
Made StatBase.statName public using AccessTransformer
Server should compile now
2012-08-03 01:50:48 -07:00
LexManos a92da71c6b Fix MockBlock compile 2012-08-03 01:47:09 -07:00
LexManos da47985361 Download argo/guava source references in install, and updated eclipse workspaces to reference them. 2012-08-02 23:36:00 -07:00
LexManos 68ae32c48c Cleaned up commands.patch, removed debug print in fml.py 2012-08-02 21:14:06 -07:00
LexManos 3373e33d4b Remove clientdrop, old reference files. 2012-08-02 20:32:51 -07:00
LexManos 2839e79ab0 Delete some dead files 2012-08-02 19:42:12 -07:00
Christian 5bffbfbe0d Fix commands patch, WorldType patch and some ML compat stuff 2012-08-02 20:09:18 -02:30
Christian 4080338c1b More fixes 2012-08-02 16:50:30 -02:30
Christian e06e9393c1 More build fixes for jenkins 2012-08-02 10:33:29 -02:30
Christian 4bb9fd7226 Try and fix the jenkins build 2012-08-02 10:30:52 -02:30
Christian 7edc7d74d4 Change some event names, hook up the event code for server events for FML 2012-08-02 09:31:03 -02:30
Christian 9a5dac605c Merge branch 'newfmlmod' 2012-08-02 08:52:11 -02:30
LexManos c0a781c0bd Introduced patching of runtime/commands.py to allow for usage of the src/common folder. 2012-08-02 00:51:51 -07:00
Christian 719bea515e Change some stuff around - begin launching the server through the wrapper too.
A lot of patches went in - the client and server both launch and start up mods.
2012-08-02 02:08:30 -02:30
Christian 153eafdcb0 More stuff 2012-08-01 21:19:11 -02:30
Christian 2f588cf6ef Fix classpath for Client, maybe? 2012-08-01 21:19:11 -02:30
Christian 3ad3c474b5 Line endings for this branch 2012-08-01 21:18:55 -02:30
Christian 73ba4b68be A load of transformer accesses- also a few tweaks to the transformer, and linux support in the fml python 2012-08-01 18:59:45 -02:30
LexManos b786d8909a Rewrote patch generation and application to no longer need diff, and attempt to apply common patches on decompiles that don't have one side or the other. 2012-08-01 06:54:57 -07:00
LexManos ab45ec9fa4 Updated eclipse projects to have src-common linked resources 2012-08-01 03:52:03 -07:00
LexManos fcbe56b504 Modified the decompiler stage to:
Compile and run AccessTransformer during the pre-RG stage of decompilation.
Merge resulting sources that are identical to src/common

ToDo:
Finish the common intergration:
-update_patches - Add common folder support
-apply_patches:
--patch each side, also patch all common patches to each side incase they are not merged, only if file exists.
2012-08-01 03:25:45 -07:00
LexManos 693ec7ddf6 Add temp AccessTransformer config for FML 2012-08-01 03:18:31 -07:00
LexManos 61b83ab992 Discard old setup script 2012-08-01 03:18:02 -07:00
LexManos 6ce9b1ab05 Fixed AccessTransformer issue with trying to load files, instead of resources. 2012-08-01 03:17:36 -07:00
Christian a5d58d79fc Commit the start of some pluggable transformers 2012-07-31 09:46:45 -04:00
Christian dac3249dc4 XP for smelting 2012-07-30 23:07:53 -04:00
Christian 99eddbfa13 Beginning the 1.3.1 update 2012-07-30 22:31:07 -04:00
Christian ea1fc8f358 Add in the ability to create versioned dependencies for mod relationships
BaseMod versions are loaded too late so will never work as a versioned
dependency requirement, but can have versioned deps of others
2012-07-30 17:01:27 -04:00
Christian bbb5a0e891 Fix up coremods with relaunch, add in a sample "coremod" 2012-07-30 11:34:30 -04:00
Christian 3f491fa7cb Add in events for the method pre/init/post annotations so we can add in extra data during the event phase 2012-07-30 00:33:21 -04:00
Christian ae007fcebc Fix whitespace issue 2012-07-29 23:54:07 -04:00
Christian 8580a99728 Fix window sticking around - it doesn't anymore 2012-07-29 23:46:52 -04:00
Christian 3257d2595d Add in "transform excluded" classes that we still need to take loading responsibility for 2012-07-29 23:30:37 -04:00
Christian 5434b3ca24 Added in some dialogs when things don't go so well 2012-07-29 22:55:53 -04:00
Christian 1ea6ba273b New logging stuff, also the early plugin api for forge 2012-07-29 22:54:59 -04:00
Christian 039d9252c6 Merge branch 'minecraft1.3' into newfmlmod 2012-07-23 23:02:25 -02:30
Christian ca67d6eb6d Fix up mod classloading delegation 2012-07-23 22:54:36 -02:30
Christian 7179edfba7 Some patches to go along with the other changes 2012-07-23 22:51:16 -02:30
Christian baec9785a2 More stuff as I roll out the changes 2012-07-23 22:50:37 -02:30
Christian ae2039c65d A bunch more fixes for FML mods 2012-07-23 16:33:17 -02:30
Christian 3f803653c4 Merge remote-tracking branch 'mainlap/newkeys' into newfmlmod
Conflicts:
	client/cpw/mods/fml/client/FMLClientHandler.java
2012-07-22 20:30:42 -02:30
Christian 6ff67693b9 New key handling 2012-07-22 20:25:18 -02:30
Christian 5501d644b9 Check in a lot of recent work 2012-07-22 11:56:38 -02:30
Christian 276fccb170 Check in new fml mod work so far. Lots still to do. 2012-07-14 13:58:46 -04:00
LexManos e2fac06f64 Cleaned up the install script for the source distrabution to setup the workspace properly, delete argo, and download all required dependancies. 2012-07-12 18:07:58 -07:00
LexManos 25def1ceaf Added call to clean_source to build script to fix patch fuzz on windows. 2012-07-12 18:06:39 -07:00
LexManos c0f70309dd Fix Client-Clean project to use relative path to argo. 2012-07-12 18:06:01 -07:00
Christian 899c1f519c Another bloody ticking fix. This should fix mods that use ML.setInGameHook(true,false) on the
server side to recieve ticks.
2012-07-08 22:06:11 -04:00
Christian 5c1363150e Fix up mod classloading delegation 2012-07-06 15:59:16 -04:00
Christian 4153584392 Fixes 2012-07-06 10:42:49 -04:00
Christian 2858731063 Incorporate server patches into client 2012-07-06 10:29:17 -04:00
Christian 874a0c32e0 Remove two places that are unpatchable now 2012-07-06 09:52:21 -04:00
Christian 4f845befaa Server repatching 2012-07-06 09:44:00 -04:00
Christian 95194f1c5b Add a "checkpatches" target and check if your patches are up to date before running a repatch operation 2012-07-06 09:19:58 -04:00
Christian df6bbaa7c5 Launch through the applet launcher too 2012-07-06 01:04:33 -04:00
Christian b1ca21a161 Some patches for the server 2012-07-05 22:31:46 -04:00
Christian bc42a54a51 Lots of client patch fixup 2012-07-05 18:13:47 -04:00
Christian 1555bd8c53 Update git ignore to ignore a fernflowerzip that's lying around 2012-07-05 15:38:37 -04:00
Christian 649e3e7bc5 And we have a brand, "fml". We're definitely modded :) 2012-07-05 15:36:31 -04:00
Christian ead4e5255e UnexpectedThrowable is now the much more awesome CrashReport! 2012-07-05 15:35:38 -04:00
Christian 5eafb71083 Merge branch 'master' into minecraft1.3
Bring some of the ticking fixes in

Conflicts:
	client/cpw/mods/fml/client/FMLClientHandler.java
	patches/minecraft_server/net/minecraft/server/MinecraftServer.java.patch
2012-07-05 15:30:21 -04:00
Christian 8ed36f583d Got the relauncher downloading and injecting library files 2012-07-05 15:23:37 -04:00
Christian 3e311fd4c1 Tweak ticking YET AGAIN. Should fire a solitary GUILOAD tick right as the game screen loads.
Hopefully fixes worldload tick issue too
2012-07-04 00:16:30 -04:00
Christian a4ce90a918 FFS let this fix that bloody ticking mess that is ML compatibility. 2012-07-03 23:03:51 -04:00
Christian ba46389a87 Separate gui ticking completely. send it as if it's a world tick. ML gui ticks are epically dumb.
Fix Worldload being filtered from the trigger arming.
Also, improve errors going to an error screen. There should be more information now.
2012-07-03 22:39:35 -04:00
Christian f7e07ca7d8 Change gui ticking and world load tick. Should close issue #40 and kill it deader
than a very very dead thing. *$^*(#% Modloader ticking b#%$hit
2012-07-03 21:37:54 -04:00
Christian 3e80a9ee7d Merge branch 'master' into minecraft1.3 2012-07-03 08:15:58 -04:00
Christian dfc6f7b1c1 Tweak build xml for more cleanliness 2012-07-03 08:14:35 -04:00
Christian 753f5f7bc8 Merge branch 'antscriptupdates' 2012-07-02 23:50:49 -04:00
Christian 982271e8ec Update some stuff 2012-07-02 23:49:40 -04:00
Christian 802ec3d86a Merge branch 'antscriptupdates' into minecraft1.3 2012-07-02 23:49:06 -04:00
Christian f1b0e33694 Add in more options for ant script and clean up needing to clean every time. 2012-07-02 23:43:29 -04:00
Christian 1d64fb01bd Merge branch 'testrecover' 2012-07-02 20:19:23 -04:00
Christian 086f575a41 Merge branch 'antscriptupdates' into minecraft1.3 2012-07-02 15:56:33 -04:00
Christian 3cda115cd5 Merge branch 'antscriptupdates' 2012-07-02 15:55:24 -04:00
Christian d491502750 Some more fixes to the ant stuff: apply patches now happens at the right time, I grab fernflower as part of
setup and added an updatepatches call too
2012-07-02 15:54:25 -04:00
Christian 1d4c33d161 Merge branch 'antscriptupdates' into minecraft1.3
Conflicts:
	build.xml
2012-07-02 15:21:15 -04:00
Christian 47a879a961 Merge branch 'antscriptupdates' 2012-07-02 15:17:32 -04:00
Christian b59184424b Add in a setupenvironment ant target specifically for setting up an FML environment from scratch 2012-07-02 15:16:40 -04:00
Christian a7803d1785 Harvest MC version from MCP 2012-07-02 13:31:45 -04:00
Christian 5415bf87ce fix sided proxy bukkit test (not used so not a biggie) 2012-07-02 12:32:41 -04:00
Christian a33f2dde77 Harvest MC version from MCP 2012-07-02 12:24:37 -04:00
Christian bb7ef791de Initial checkin. Some patches are probably missing, but client compiles. 2012-06-29 20:18:04 -04:00
Christian aa1a5d3c19 Working simple scheduled ticking, Player ticks 2012-06-28 23:37:30 -04:00
Christian a53d8c926e Support tick spacing through new IScheduledTickHandler 2012-06-28 17:10:35 -04:00
Christian 714cd8d8df Change TickType.WORLD to send the world as arg[0] to match the server. 2012-06-28 14:24:34 -04:00
Christian c9f7444d06 And there are not 1000 seconds in a second 2012-06-28 08:31:32 -04:00
Christian ea05777032 Seconds are 1000 milliseconds long. Not 1 millisecond long. 2012-06-28 08:27:21 -04:00
Christian 14fea4a3a3 Tweak profiler command on bukkit 2012-06-28 08:21:24 -04:00
Christian 0613858855 Fix up a derp in the timing command 2012-06-27 22:13:55 -04:00
Christian 6687ed360b Fix code to use guava 10 only. Stupid bukkit plugins and daft dependencies on guava 10! 2012-06-27 08:23:53 -04:00
Christian 409506d2b2 Tweak for end profiling 2012-06-26 23:37:54 -04:00
Christian b96d6e00c3 Add in simple profiler for bukkit 2012-06-26 23:16:23 -04:00
Christian b6ae926fd3 Add in a mechanism to get the modcontainer for a mod - so things can be programmatically changed 2012-06-26 16:24:50 -04:00
Christian 508c986166 Add in bukkit support for recipe change 2012-06-26 15:40:30 -04:00
Christian 725201040e Add in a new recipe handler registry method for ease of adding recipes to MC 2012-06-26 15:29:34 -04:00
Christian 70d7c8fc68 Update tester mod 2012-06-22 09:30:47 -04:00
Christian 05f9861da4 Fix ticking for GUI ticks too! 2012-06-22 09:30:27 -04:00
Christian c588750c96 Fix dependency string processing error 2012-06-22 06:21:04 -04:00
Christian d00e229198 ModSorting test case 2012-06-21 21:56:16 -04:00
Christian be1a80ebbd Fix ticking properly - ML world ticks now fire once, properly 2012-06-21 18:11:40 -04:00
LexManos 44706ae343 Added stupididty exception for common issue with getMinecraftLogger. 2012-06-21 03:17:33 -07:00
Christian 2af41e7c8c Rename unused ML prop config files if they exist (to .bak) and
skip generating if not needed
2012-06-20 21:17:32 -04:00
Christian e5c29a75de Update bukkit with changes 2012-06-20 12:36:48 -04:00
Christian 2a36dc64bd Revert "Test failing build"
This reverts commit 744febc38e915a12c388fe01ba6715d31b6b6ee2.
2012-06-20 08:44:49 -04:00
Christian dd128c8502 Revert "Revert "Fail the build when recompilation fails""
This reverts commit c2d920d738a294462338fbe955c62a0f4034304c.
2012-06-20 08:44:08 -04:00
Christian 3812dc4464 Revert "Fail the build when recompilation fails"
This reverts commit 482e3be3c9a96df8cefad81d78c7a4e83ad898b4.
2012-06-20 08:39:11 -04:00
Christian 851038679a Test failing build 2012-06-20 08:35:47 -04:00
Christian 146ee9b3c7 Fail the build when recompilation fails 2012-06-20 08:35:14 -04:00
Christian 6c42a77411 Fix huge bug/typo in basemodticker that stopped ticks getting sent 2012-06-20 08:03:57 -04:00
LexManos 7e24034fcc Fix compilation error, Protip: Don't use java7 things when compiling for java6, and Don't report successful build on compilation errors cpw. 2012-06-20 02:14:07 -07:00
LexManos e6eb550bfd Remove cr's from modinfo descriptions, they print oddly in Minecraft. 2012-06-19 19:58:48 -07:00
LexManos 2dbb374869 Print mod metadata info errors if we are in MCP. 2012-06-19 19:55:28 -07:00
LexManos e5efbea2ab Should fix concurent modification exceptions when using removeSpawns 2012-06-19 19:44:52 -07:00
LexManos bc74a16149 Remove some eclipse preference files 2012-06-19 19:44:07 -07:00
LexManos 4cd6c58159 Update gitignore to ignore some eclipse preference files. 2012-06-19 19:43:46 -07:00
LexManos 9e6fbea698 Merge pull request #29 from ScottKillen/master
Fixed WorldType to allow custom WorldTypes
2012-06-19 19:22:06 -07:00
LexManos e796630120 Added EntityRendererProxy class for compatibility with ModLoader mods that rely on it's existance. 2012-06-17 19:30:10 -07:00
Christian cad5ce54dc More ticking cleanup 2012-06-17 18:53:49 -04:00
Christian 3c3e4ca2ff Remove WorldLoad tick from modloader mods- too early. *sigh* 2012-06-17 18:49:19 -04:00
Christian b9b90c6eef Make sure to reset the clock trigger 2012-06-17 18:41:54 -04:00
Christian 747c6131bf Force all client modloader ticks to occur at render end 2012-06-17 18:41:05 -04:00
Scott Killen 5c65939330 Client
======
Added hook in GuiCreateWorld to allow WorldType to present GUI on world creation.
2012-06-17 15:05:16 -04:00
Scott Killen cddcd9ffb3 **Client**
* Delegated World.func_46068_G() (getHorizon), which depends on WorldType, to the WorldType class per LexManos' suggestion
2012-06-17 00:04:50 -04:00
Scott Killen 1295c3863e Client
======
- Fixed WorldType to allow custom WorldTypes in world creation GUI.
- Deprecated client WorldType.getSeaLevel() and renamed it with the more accurate name of getMinimumSpawnHeight.
- Changed related reference WorldProvider.

Server
======
- Fixed WorldType to allow custom WorldTypes
- Added methods to WorldType giving it the exact abilities of client WorldType
- Adjusted WorldProvider so that it relies on WorldType the same way it does on client.
2012-06-16 23:31:17 -04:00
Christian 99ce6e2dee Merge pull request #27 from TheNoid/master
Make FML logs use system line endings …
2012-06-14 12:06:19 -07:00
Dion Williams a9d4a15a4f Make FML logs use system line endings for consistency with Java stack traces in the logs. 2012-06-14 18:01:35 +01:00
LexManos 2fbf60a846 Server side fix for invalid parameter to onCrafting 2012-06-13 20:02:35 -07:00
LexManos 1838344b07 Proper fix for scroll list not covering all of the hidden scroll items. 2012-06-13 19:59:54 -07:00
Christian fd6aacd0fe Merge pull request #26 from GenuineSounds/patch-2
Incorrectly passing the IInventory of the extraction slot instead of the...
2012-06-13 18:52:46 -07:00
Christian 4b142cbdcc Merge pull request #25 from GenuineSounds/patch-1
Having the string trimmed to 9 made most long strings show a couple of p...
2012-06-13 18:50:26 -07:00
Brian Wiegand 802425b4d5 Incorrectly passing the IInventory of the extraction slot instead of the crafting matrix, get back to me on why it's doing this instead of the default behavior of ModLoader and Forge. 2012-06-13 15:17:33 -07:00
Brian Wiegand 745d388cb0 Having the string trimmed to 9 made most long strings show a couple of pixels at the very top and very bottom. ie
https://dl.dropbox.com/u/79514/2012-06-13_13.25.35.png
2012-06-13 14:09:07 -07:00
LexManos 1f52ee1dea Fixed KeyBinding issue with ModLoader container, if you register a KeyBinding twice it will discard the old one. And fixed issue where getVersion() could return null causing NPE. 2012-06-10 17:19:05 -07:00
LexManos 1af7d7970a Made it so it will attempt to scale any Texture Effects that return data for smaller texture resolutions. Made the size descrepancy only a error for ITextureFX texture effects. 2012-06-10 05:56:52 -07:00
Christian 201edc0249 Fix up "errored" mod states so they actually read as errors 2012-06-09 11:07:07 -04:00
Christian 2f4a572a23 Fix up bukkit for biome code 2012-06-09 10:47:43 -04:00
Christian 0cf8cca248 Fix up biome handling for client and server 2012-06-09 10:27:24 -04:00
Scott Killen af4a2589a6 - Fixed client crash bug in add/remove Biome functionality. Arrays.asList() returns a fixed-sized list per java spec. Adding and removing biomes throws UnsupportedOperationException.
- Fixed same on server and added disabled removeBiome functionality. This touched a lot of classes as the nonWorking removeBiome seemed to be lots of places inconsistent with addBiome.
2012-06-09 07:59:35 -04:00
Christian 2d55491692 Tweak error handling - report the exception that caused the bailout 2012-06-08 15:31:30 -04:00
Christian 1007720589 Fix parameter ordering in ticks 2012-06-08 15:22:40 -04:00
Christian b2f470464a Update bukkit for world gen tweaks 2012-06-07 19:47:11 -04:00
Christian 683c99c8b6 Change world generation to expose a mod interface 2012-06-07 19:44:03 -04:00
Christian 428cf691f1 Update bukkit for early load change 2012-06-07 19:28:07 -04:00
Christian bfe54ef7e7 Attempt early initialization of Minecraft Forge 2012-06-07 19:25:49 -04:00
Christian 40dff18025 Update bukkit handler 2012-06-07 17:57:07 -04:00
Christian 4d620d91e4 Add in a server side WORLDLOAD tick 2012-06-07 17:54:43 -04:00
Christian a502e1fc56 Fix ticking- need to register the basemod tickhandler *sigh* 2012-06-07 16:31:23 -04:00
Christian 4f0c220d99 Fix ticking for new name "GAME" vs "WORLD" 2012-06-07 16:21:01 -04:00
Christian Weeks 08a4b21460 Update bukkit handlers 2012-06-07 14:03:42 -04:00
Christian Weeks 9fd6f89fc3 Reorganize basemod ticking to use ITickHandler. Introduce "GAME" tick vs "WORLD" tick for
mods that want to tick per world and "globally"
2012-06-07 13:53:16 -04:00
Christian Weeks 11652d597f Expose a "clean" ticking interface and fix server tick loop for world ticks 2012-06-07 11:12:51 -04:00
Christian Weeks f943cd9b4b Tweak width of description 2012-06-07 08:39:22 -04:00
LexManos 1e392e0bb3 Fix for in game tick running when it shouldn't. Fixed some tabbing issue in crazy's PR. 2012-06-06 08:01:54 -07:00
LexManos e536c58f81 Interm implementation of keyboardEvent for ModLoader. 2012-06-06 01:43:49 -07:00
LexManos 63c02cbe35 Add static log() functions to the RenderAccessLibrary, and fixed up the logo rendering to better display the images. 2012-06-05 18:49:07 -07:00
Christian d9a8392723 Merge pull request #14 from crazyputje/master
onTickInGUI fix. Thanks crazyputje!
2012-06-04 14:41:59 -07:00
crazyputje ae52b91d13 removed 'if (client.theWorld != null)' so it also ticks in the main menu 2012-06-04 20:36:57 +03:00
Christian Weeks 370062cc55 Helps to have a retention policy 2012-06-02 22:41:50 -04:00
Christian Weeks 43eae28f55 Helps to have a retention policy for runtime annotations 2012-06-02 22:40:45 -04:00
Christian Weeks c2c27044b5 Add in bukkit proxy handler 2012-06-02 22:14:25 -04:00
Christian Weeks 09722f3ffc More proxy code 2012-06-02 22:12:15 -04:00
Christian Weeks 2cf960b64d Introduce a proxy side loader for mod use 2012-06-02 22:12:15 -04:00
LexManos 05b31bdd6e Fixed GuiModList Logo rendering to allow for logos of different sizes to be rendered properly. Logos will render themselves full underneath the text, It is the modder's job to make it look good. 2012-06-02 18:05:57 -07:00
Christian Weeks e115807351 Update credits information 2012-06-02 11:45:47 -04:00
Christian Weeks f5b29d2726 Update readme for the client side 2012-06-02 11:44:26 -04:00
Christian Weeks dfac296402 Update bukkit handler to inject names at startup 2012-06-02 11:03:20 -04:00
Christian Weeks 9e2117c955 Merge remote-tracking branch 'origin/master' 2012-06-01 23:25:18 -04:00
Christian Weeks 4fdf2ea290 Fix up optifine detection properly 2012-06-01 23:23:50 -04:00
Christian Weeks 10fb465525 Update bukkit handler 2012-06-01 23:10:38 -04:00
Christian Weeks d44822b7d0 Slight reorganization of texture ticking - accomodate optifine 2012-06-01 23:07:32 -04:00
Christian Weeks 18a35c1ab7 Add in optifine visibility for the mod list. Will search for an "optifine_mod.info" file on the
class path if sp614x wants to add one to optifine.
2012-06-01 14:55:49 -04:00
Christian Weeks 26cf077cfa Fix ticking on bukkit server 2012-06-01 11:08:32 -04:00
Christian Weeks c3379b44dd Fix ticking on the server 2012-06-01 11:07:14 -04:00
Christian Weeks 3ad305aa06 Implement missing language load hook for server 2012-06-01 10:22:08 -04:00
Christian Weeks 89d74da576 Tweaks to basemod setup 2012-06-01 00:33:51 -04:00
Christian Weeks 9ad4177bfa Bukkitside fixup 2012-06-01 00:27:46 -04:00
Christian Weeks 20c830c848 Merge branch 'bukkitreorg' 2012-05-31 23:07:16 -04:00
Christian Weeks 877bb029f9 Merge branch 'bukkit'
Conflicts:
	common/cpw/mods/fml/common/IWorldGenerator.java
	common/cpw/mods/fml/common/registry/FMLRegistry.java
	common/cpw/mods/fml/common/registry/IMinecraftRegistry.java
	common/net/minecraft/server/CommonRegistry.java
	common/net/minecraft/server/IMinecraftRegistry.java
	common/net/minecraft/src/CommonRegistry.java
	common/net/minecraft/src/IMinecraftRegistry.java
2012-05-31 23:00:06 -04:00
Christian Weeks cfb5cb1a2f Fix copied code. Derpbag. 2012-05-31 22:48:44 -04:00
Christian Weeks 245f562e1c Update FML with recent mainline changes 2012-05-31 22:48:44 -04:00
Christian Weeks 68dc92f0e1 Update bukkit with new mod fixes 2012-05-31 22:48:44 -04:00
Christian Weeks ee4089304a Damn you bukkit with your same names for different classes!!!! EntityPlayer->EntityHuman 2012-05-31 22:48:44 -04:00
Christian Weeks f3dfa1a955 Fix chunk generators for bukkit 2012-05-31 22:48:44 -04:00
Christian Weeks 2320e42163 Bukkit version 2012-05-31 22:48:44 -04:00
Christian Weeks bcc35775f4 Merge branch 'bukkit' - massive code reorganization for fml 2.0
Conflicts:
	common/cpw/mods/fml/common/IWorldGenerator.java
	common/cpw/mods/fml/common/registry/FMLRegistry.java
	common/cpw/mods/fml/common/registry/IMinecraftRegistry.java
	common/net/minecraft/server/CommonRegistry.java
	common/net/minecraft/server/IMinecraftRegistry.java
	common/net/minecraft/src/CommonRegistry.java
	common/net/minecraft/src/IMinecraftRegistry.java
2012-05-31 22:45:19 -04:00
Christian Weeks 3239536832 More tweaks for proper API 2012-05-31 22:42:23 -04:00
Christian Weeks 9c1c414ca7 Reorganize for bukkit integration 2012-05-31 22:09:45 -04:00
Christian Weeks 20e5963059 Fix project, new gui layout with screenshot, thanks Sengir! 2012-05-30 09:25:04 -04:00
Christian Weeks 70c57e2ad6 Add in missing hooks, add branding information to the crash report 2012-05-27 07:14:35 -04:00
LexManos 4639786521 Fixed regex issue in last push. 2012-05-27 01:40:22 -07:00
LexManos 71e873ed1f Fixed up for newline before case bodies. 2012-05-27 01:24:45 -07:00
LexManos c416a82e64 Should fix windows {me} generating different patches then linux {cpw} 2012-05-27 00:22:27 -07:00
Christian Weeks 539252053f Move first tick to the real first tick 2012-05-26 02:30:21 -04:00
Christian Weeks da791ef721 Merge in the mod texture changes from Lex 2012-05-26 02:29:35 -04:00
LexManos 49bca8998a Fixed location refs to fmlversion.properties 2012-05-25 23:25:05 -07:00
Christian Weeks 6e14c67e82 Add in a static render access class for optifine and other render editing mods to use 2012-05-25 22:13:51 -04:00
Christian Weeks 7fddb9d59e Add in a "world load" tick fired just as the world completes loading. This SHOULD fix millinaire. 2012-05-25 17:21:30 -04:00
Christian Weeks 006112f3d3 Changing up the mod list data 2012-05-25 15:25:35 -04:00
LexManos e075a430e2 Fixed up ModTexture* classes to use the ITextureFX events to resize the image as needed. Also fixed ModTextureStatic's not being applied properly. 2012-05-24 22:48:15 -07:00
Christian Weeks 134299b413 Fix up two stupid overwrites in my mergeup from lex 2012-05-24 23:18:04 -04:00
Christian Weeks 03059c5cd2 Fix derp in MTS 2012-05-24 22:13:33 -04:00
Christian Weeks 918d9d8687 Patch fixing 2012-05-24 21:40:34 -04:00
Christian Weeks 5017f8b038 Update some stuff for updated tweaks 2012-05-24 21:39:16 -04:00
Christian Weeks 78052d2ce2 Update FMLClient with my changes 2012-05-24 21:33:43 -04:00
Christian Weeks 8a6b10607d my tweaks 2012-05-24 21:06:27 -04:00
LexManos 034117e253 difflist should include server and client now. 2012-05-24 03:48:59 -07:00
LexManos a3ddd6140b Some patch cleanup. 2012-05-24 02:18:20 -07:00
LexManos ac292296fe Rewrote how HD Texture support worked, to make it easier for Optifine to integrate.
Fixed TextureFlamesFX for extramly large texture sizes.
Fixed the texture size sceme to allow for different sizes of textures in the same pack.
2012-05-24 01:35:37 -07:00
LexManos d50a66c8ba Line number changed.. 2012-05-24 01:33:50 -07:00
Christian Weeks fb4d3b2ca9 Fix up the watch 2012-05-18 20:42:12 -04:00
Christian Weeks fcdd2a9176 And some tweaks to the texture handling 2012-05-18 20:17:07 -04:00
Christian Weeks fa921f0aa9 Fix up some fubars in MTS and MTA 2012-05-18 20:16:41 -04:00
Christian Weeks ac221275d9 Lots of error handling. 2012-05-18 10:38:40 -04:00
Christian Weeks 33f8b158a9 Missed a patch *sigh* 2012-05-17 21:57:24 -04:00
Christian Weeks b9b33ebe79 Add simple API to allow mods to let their textures be overriden by other mods 2012-05-17 21:47:12 -04:00
Christian Weeks a23816134b Because, of course, I broke the first build... 2012-05-17 20:27:24 -04:00
Christian Weeks 4e8e84244b Some logging of texture overrides- also, only unregister if it's an actual ModTextureStatic, not if it's a subclass. 2012-05-17 15:39:04 -04:00
Christian Weeks a94316cc9e Derpy exceptions derpy exception handling 2012-05-17 15:19:25 -04:00
Christian Weeks 01a1bc9e6a Remove the dependency in RenderEngine, decided on the simple API for texture FX 2012-05-17 15:11:21 -04:00
Christian Weeks d2b69b2b08 Tweak the render patch- we won't fail if the updateTexture call fails 2012-05-16 00:34:50 -04:00
Christian Weeks 91fbba3873 Update patches: add in a setup for most of the texturefx classes 2012-05-16 00:01:12 -04:00
Christian Weeks a4f3bc853a Tweaking texture loading 2012-05-16 00:00:52 -04:00
Christian Weeks b7ece58caa Fix tileSize -> iconTileSize. Stupid MCP 2012-05-15 22:34:17 -04:00
Christian Weeks fe354c867d Catch throwable (NoClassDefFoundError) and don't abort loading- it's probably a badly named class file. 2012-05-15 22:23:00 -04:00
Christian Weeks 326d52f534 Fix some derpy 2012-05-15 22:18:41 -04:00
Christian Weeks fbd9ac7d95 Update patches for hd textures 2012-05-15 22:10:38 -04:00
Christian Weeks 96018996fc Change hd texture handling 2012-05-15 22:05:24 -04:00
Christian Weeks 9b205b1355 Refresh the renderengine patch- catch and log some texture pack reload errors 2012-05-15 16:21:40 -04:00
Christian Weeks 56f915eb66 More mod list fixes 2012-05-15 16:19:46 -04:00
Christian Weeks 46f8868961 Lots of cleanup on the mod list, pretend we're the mcpatcher for mod HD detection. 2012-05-15 15:52:19 -04:00
Christian Weeks 15089f9d87 Fix up fubar in worldprovider. Add in obfuscation detection. Capture the exception that crashes minecraft in the log file. 2012-05-14 18:21:35 -04:00
Christian Weeks 4783bfe01d ModLoader worldtype hackery compatibility 2012-05-14 16:21:05 -04:00
Christian Weeks 7b894946bf Fix derp 2012-05-14 14:16:50 -04:00
Christian Weeks a01e513822 Only log the warning once per texture 2012-05-14 13:20:50 -04:00
Christian Weeks 3061fd3d8f push patches 2012-05-14 12:22:46 -04:00
Christian Weeks 9b281f0a3c Fix millinaire support. Fix Portal eating rendering time. add in profile visibility for mod stuff. 2012-05-14 11:38:54 -04:00
Christian Weeks e433708056 Fix the serverside. FUUUUUUUU! 2012-05-14 01:45:56 -04:00
Christian Weeks 43eae51bb3 HD patching complete? Clean up mod info data, Dummy field for dummy mods 2012-05-14 01:39:21 -04:00
Christian Weeks 72edbe596e Improving the scroll list, HD texture patches 2012-05-13 02:46:39 -04:00
Christian Weeks 53b5533936 Actually pass in the mod name 2012-05-12 02:25:15 -04:00
Christian Weeks 84c86fd475 Fix up incorrect dependency handling 2012-05-12 02:10:50 -04:00
Christian Weeks a9d644e1e8 Fix stupid problem with braces 2012-05-12 01:06:58 -04:00
Christian Weeks 7ed6c7bd7f Tick only when there's a world 2012-05-12 01:03:36 -04:00
Christian Weeks 3fd23cee0f Fix nulls in the mod list, start building the gui screen 2012-05-12 00:47:04 -04:00
Christian Weeks 0665c93c2b Gui related ticking 2012-05-12 00:00:33 -04:00
Christian Weeks cd741d961e Try always loading the language data 2012-05-11 23:37:58 -04:00
Christian Weeks ea855f82b4 Always load the "en_US" langpack into the translation table first, then the actual language. 2012-05-11 22:20:09 -04:00
Christian Weeks d775f42703 Derpy derp- fix stupid pointless cast 2012-05-11 17:41:33 -04:00
Christian Weeks 0981d3106d Fix missing ml.sendpacket, call in renderers 2012-05-11 17:31:28 -04:00
Christian Weeks a20c7f6f76 Actually mark the sprite as used when you allocate it! 2012-05-11 16:49:21 -04:00
Christian Weeks cf9b57d9fa Helps to add the new hook! 2012-05-11 16:30:23 -04:00
Christian Weeks 7deedb26f5 Hook texture pack changes and loads so we can register override textures 2012-05-11 16:23:26 -04:00
Christian Weeks 4c2c7cb2f3 Fix problem with nulls in getModList
Work on the meta information file
2012-05-11 15:18:26 -04:00
Christian Weeks 7ec180ee7c More tweaks to stuff: mod list, branding, more hooks 2012-05-11 01:45:36 -04:00
Christian Weeks b1ee6c3c95 Tidying up and more hooks 2012-05-10 21:30:06 -04:00
Christian Weeks a36fccc9b0 Tweak block rendering organization. Add in worldgen for client. 2012-05-10 19:51:15 -04:00
Christian Weeks 36b05d9378 Tidy up a lot of code- ModLoader and BaseMod are now almost identical client and server side 2012-05-10 18:54:25 -04:00
Christian Weeks 2b8ac71253 Tweak ordering for sorting- should be a stable sort now 2012-05-10 15:48:26 -04:00
Christian Weeks 1ffb096508 Update git version capture 2012-05-10 13:01:39 -04:00
Christian Weeks 7a66d88e9f Ignore jenkins tags 2012-05-10 12:53:27 -04:00
Christian Weeks 42c5b9534a Tweak some build stuff for versioning 2012-05-10 12:24:17 -04:00
Christian Weeks 0b1f3b51e3 Update build to actually put Loader in... 2012-05-10 11:16:58 -04:00
Christian Weeks 6646b573e8 tweak location of build properties in src jar 2012-05-10 10:09:56 -04:00
Christian Weeks 201762ee50 Lots of tweaks to mod output pretty printing. new versioning scheme. 2012-05-10 09:42:31 -04:00
LexManos 99ee905038 Inventroy rendering 2012-05-10 01:25:56 -07:00
LexManos d2afbd9216 Fixed up the ModLoader render block hook, RP's blocks now render. 2012-05-10 01:00:07 -07:00
LexManos 5f49c5f646 Should fix colliding model ids with MC's internal IDs 2012-05-09 23:38:01 -07:00
Christian Weeks d91c22ea24 Fixes 2012-05-10 02:01:23 -04:00
Christian Weeks 4c9745f73c Fix up build script a bit, all modloader is public, and fix tile entity renderer 2012-05-10 00:07:46 -04:00
Christian Weeks edb0ba811f Add in some more stuff for handling key bindings, rendering 2012-05-07 17:44:49 -04:00
Christian Weeks a1ca27b997 Reorganize ticking a bit 2012-05-07 01:39:55 -04:00
Christian Weeks 285d187884 Separate sprite handling, fix worldtype 2012-05-07 01:26:21 -04:00
Christian Weeks 351c193b98 Working on the ticking stuff 2012-05-07 00:54:18 -04:00
LexManos 8586d8ae85 more client side hooks and Texture overrides/animations. 2012-05-06 16:32:59 -07:00
Christian Weeks 1a40f433a5 Halfway through ticking- won't compile 2012-05-06 00:58:40 -04:00
Christian Weeks 6c6f792c6b ModLoader moves forwards 2012-05-05 20:33:40 -04:00
Christian Weeks 149fa8a577 Let's get hooking! 2012-05-05 19:52:53 -04:00
Christian Weeks f279476684 API is restored for client side. Implementation starting. 2012-05-05 14:42:46 -04:00
Christian Weeks 0ca8ace988 And some patches for that 2012-05-04 17:04:18 -04:00
Christian Weeks 80f87ef569 The beginning 2012-05-04 17:02:12 -04:00
Christian Weeks 904efdd4d8 Introduce the client side FML 2012-05-03 19:40:55 -04:00
Christian Weeks 874d3f0b17 Implement addBiome, hopefully. Pushes biome list to the WorldType field. Sorry Bioxx. 2012-05-03 14:05:13 -04:00
Christian Weeks 603005ba18 Check in some eclipse crapola. 2012-05-03 14:04:16 -04:00
Christian Weeks 6b286543d4 Fix copied code. Derpbag. 2012-04-28 16:47:04 -04:00
Christian Weeks 28992c6f13 Update FML with recent mainline changes 2012-04-28 16:40:25 -04:00
Christian Weeks 174e208369 Merge branch 'master' into bukkit 2012-04-28 16:35:15 -04:00
Christian Weeks c632d5145e Fix a small issue with the build output script
Fix a significant issue with MLProp handling and primitives- they work now
2012-04-26 17:38:31 -04:00
Christian Weeks f3bee8c070 More text fixup 2012-04-19 23:07:07 -04:00
Christian Weeks 8bfeb5ac21 Typos 2012-04-19 22:54:10 -04:00
Christian Weeks 05dc6f8e4b Add in detection for MLMP and try to fail with a graceful message. 2012-04-19 22:40:59 -04:00
Christian Weeks 2eb77acf73 Update bukkit with new mod fixes 2012-04-18 14:06:54 -04:00
Christian Weeks f7cec9be38 Merge branch 'master', remote-tracking branch 'origin' into bukkit 2012-04-18 14:04:39 -04:00
Christian Weeks 8f8ee60eb1 Tweak the loader a little bit to just use file names, not fully qualified directories when referring
to mods.
2012-04-18 14:03:30 -04:00
Christian Weeks 8f14c7321b Damn you bukkit with your same names for different classes!!!! EntityPlayer->EntityHuman 2012-04-16 01:00:06 -04:00
Christian Weeks aedb80c251 Fix chunk generators for bukkit 2012-04-15 22:42:06 -04:00
Christian Weeks e7224c7bda Merge branch 'master' into bukkit 2012-04-15 21:58:18 -04:00
Christian Weeks cceeb88c6d Bukkit version 2012-04-14 23:01:03 -04:00
Christian Weeks 65f39a50c1 Fix "soft" dependencies so they can exist properly 2012-04-14 10:01:55 -04:00
Christian 0a52ed381d Fix server patch 2012-04-10 23:05:22 -04:00
Christian 78f2e8f38a Merge in fixes from chickenbones for tick related problem
and straighten out variable naming in ModLoaderModContainer
2012-04-10 22:22:13 -04:00
Christian Weeks 9fdc403396 Push the patched file, as well 2012-04-09 10:24:58 -04:00
Christian Weeks 9c3a2f052d Add in more "Player" related events. Fix up some MLProp stuff 2012-04-09 10:18:24 -04:00
Christian Weeks 5f26a86bf7 Fix regular expressions, thanks ChickenBones! 2012-04-09 09:19:20 -04:00
Christian Weeks b1d9f3d833 Tweak Console handler patch so we're more friendly to forge 2012-04-08 10:04:28 -04:00
Christian Weeks 05ff62d85f A proper console command handler, also fix ordering of loaded mods 2012-04-08 09:55:56 -04:00
Christian Weeks b0774b89c7 Add in a console command handler so you can access the command console 2012-04-08 02:00:57 -04:00
Christian Weeks 1ec797cddb Don't send a register unless I have channels. Add the channel to the mod channels list. 2012-04-08 01:11:32 -04:00
Christian Weeks 2ff2a78694 Split the packet salutation in two so we can work with or without forge 2012-04-08 00:18:37 -04:00
Christian Weeks 93664d10e6 Add the player object to the onLogin event so you don't need to dive internals for it during login 2012-04-07 22:38:29 -04:00
Christian Weeks 10e5d42522 Call my handleLogin hook from NetLoginHandler, tweak output in server gui and log file. 2012-04-07 22:11:01 -04:00
Christian Weeks d531d70f1f Fix subdirectory loading properly: mods will load inside eclipse.. 2012-04-06 16:14:01 -04:00
Christian Weeks 95596bc198 Actually figure out the path for directory class loading 2012-04-06 15:24:28 -04:00
Christian Weeks b32a92df5b regular expressions in java==fail 2012-04-06 15:03:41 -04:00
Christian Weeks ac6c35d7c4 Recurse into subdirectories found 2012-04-06 14:43:12 -04:00
Christian Weeks 2ed8a8b807 Try multiple "jar" sources- for eclipse testing 2012-04-06 14:23:14 -04:00
Christian Weeks 759e92cc2a it's addURL not addUrl dumbo 2012-04-06 13:57:40 -04:00
Christian Weeks feede96d6d it's getdeclaredmethod, dipstick 2012-04-06 13:47:01 -04:00
Christian Weeks fc33249d32 Fix package private resolution of fields/methods from base minecraft by loading into minecraft's class loader not our own 2012-04-06 13:27:50 -04:00
Christian Weeks ff48f13746 Add in a missing client side method to modloader stubbed for the server 2012-04-06 12:24:52 -04:00
Christian Weeks 47e61610ca Add the hooks for crafting and smelting 2012-04-06 10:34:44 -04:00
Christian Weeks 4f97aedbb2 Should load from whatever minecraft comes from now... 2012-04-06 09:59:58 -04:00
Christian Weeks 51203e49f9 Build should work now. Fix a stupid javadoc import. 2012-04-05 21:44:06 -04:00
Christian Weeks 1906a085ad New build script- version the src dist as well 2012-04-05 21:40:16 -04:00
Christian Weeks 5a3ac6b96e Documentation: lots
Some eclipse workspace settings that might help?
2012-04-05 16:22:47 -04:00
Christian Weeks 1146660fc6 Handle the minecraft object registry better- now the client compiles too
Also a quickie astyle run over the code..
2012-04-05 12:36:54 -04:00
Christian Weeks 2888e1680e Update the patches and fix the shell script 2012-04-05 11:42:33 -04:00
Christian Weeks 7bf22659e7 Reorganize the code a little bit- move some stuff that was on FMLHandler to the common handler. Add a delegate
into the common handler that delegates to the right sided handler
2012-04-05 11:34:57 -04:00
Christian Weeks 86f8bbd47d Clean up extraneous print statements from the build 2012-04-05 10:42:15 -04:00
Christian Weeks 5bc8929795 Fix INSTALL-fml.txt file location in the server zip 2012-04-05 10:37:05 -04:00
Christian Weeks b2853aa811 Append a .class to the diff file list. Now you should just be able to iterate it and read every file in it directly. 2012-04-05 10:16:23 -04:00
Christian Weeks c06fc00f24 Run Astyle over the FML code. Happy lex? 2012-04-05 10:07:52 -04:00
Christian Weeks 1e6eec768c OK. Now the script works 2012-04-05 08:42:10 -04:00
Christian Weeks 33d7d77775 Crap at writing good python apparently 2012-04-05 08:29:07 -04:00
Christian Weeks 83b060b573 Tweak file list script to print obf names 2012-04-05 08:25:04 -04:00
LexManos df656cb98d Merge remote-tracking branch 'origin/master' 2012-04-05 00:10:36 -07:00
LexManos cb21ddc438 Rebuilt patches with new scripts. 2012-04-05 00:10:13 -07:00
LexManos 7b45203461 Cleaned up update_patches to fix a few bugs. Updated applypatches to normalize the patch file's line endings to make them work cross platform. Added download_firnflower and setup script. As well as added the GnuWin32's diff binary, so windows can create patches as well. http://gnuwin32.sourceforge.net/ 2012-04-05 00:09:29 -07:00
LexManos ecb07e2abb Created eclipse workspace, should allow simple and quick access to working on FML 2012-04-05 00:06:11 -07:00
Christian Weeks 647c40ba5e Missed a couple of wording tweaks 2012-04-05 00:58:17 -04:00
Christian Weeks 9210fe1a57 Tweak the build a bit, add some more data and generate the
touched file list for forge
2012-04-04 11:05:31 -04:00
Christian Weeks 9efb9741d1 Tidy up some of the installation media 2012-04-04 09:48:36 -04:00
Christian Weeks 87b5c870d5 links to implementation 2012-04-03 23:09:22 -04:00
Christian Weeks bd34b97e9b Channel validation 2012-04-03 22:45:27 -04:00
Christian Weeks c74e119993 NetworkHandler doesn't care about channel ownership 2012-04-03 17:06:02 -04:00
Christian Weeks 96e23dda6b Update patches for network handler 2012-04-03 17:04:57 -04:00
Christian Weeks c6a0bc2487 Modloader complete 2012-04-03 17:04:26 -04:00
Christian Weeks d1efbce945 Generic container 2012-04-03 16:12:19 -04:00
Christian Weeks 381b2b8aa1 Config dir handling 2012-04-03 15:53:59 -04:00
Christian Weeks 72478fac83 MLProp 2012-04-03 15:41:25 -04:00
Christian Weeks c4fd53d628 Mod sorting 2012-04-03 12:03:21 -04:00
Christian Weeks ec4750f422 Everything except ordering 2012-04-02 23:06:30 -04:00
Christian Weeks bc0caee371 Fix build script for generating md5s 2012-04-02 18:12:49 -04:00
Christian Weeks 8087bd82bf Update to 1.2.5 and hopefully forge compatibility 2012-04-02 18:09:06 -04:00
Christian Weeks ec3fb620dc Forge support 2012-04-01 02:14:14 -04:00
Christian Weeks d6e5df9092 Initial attempts to support forge stuff 2012-03-31 02:28:14 -04:00
Christian Weeks 160399cee7 Fix NPE 2012-03-31 01:04:29 -04:00
Christian Weeks 4b4e4b30a9 More logging and maybe fix default package mods 2012-03-31 00:59:43 -04:00
Christian Weeks 67ed21052f Logging fun. Whee! 2012-03-31 00:52:50 -04:00
Christian Weeks 532f8cfce9 Fail 2012-03-31 00:46:47 -04:00
Christian Weeks a45af9ac39 More logging 2012-03-31 00:43:54 -04:00
Christian Weeks 3b487511d7 Tweak class loader 2012-03-31 00:22:08 -04:00
Christian Weeks a1cbb799be Add more patches 2012-03-30 22:28:12 -04:00
Christian Weeks 8b9545d622 Some implementation 2012-03-30 22:26:16 -04:00
Christian Weeks cd325dc3fd tweak MC server hook 2012-03-30 21:23:04 -04:00
Christian Weeks 9768774896 some build and logging tweaks 2012-03-30 21:21:43 -04:00
Christian Weeks e1781bf2ae Fix build 2012-03-30 21:10:43 -04:00
Christian Weeks b566a7b692 Fix derpy 2012-03-30 21:07:42 -04:00
Christian Weeks e7aa295b47 Tweak loader a bit 2012-03-30 21:03:25 -04:00
Christian Weeks 2d44b44372 Fix patching 2012-03-30 20:43:58 -04:00
Christian Weeks 17e19b8cc6 More build stuff 2012-03-30 20:38:31 -04:00
Christian Weeks e88b897635 More building fun 2012-03-30 17:36:50 -04:00
Christian Weeks 7a0bd95113 fix build script 2012-03-30 17:00:49 -04:00
Christian Weeks be52c01b9f Add in more ignore stuff and a sample "fmlbuild.properties" file 2012-03-30 16:42:11 -04:00
Christian Weeks c02319cec1 More build stuff, adding in readme etc copied from forge 2012-03-30 16:40:54 -04:00
Christian Weeks f7507d3f79 Move more stuff around 2012-03-30 16:25:49 -04:00
Christian Weeks 31d2c84541 Build system 2012-03-30 16:22:10 -04:00
Christian Weeks 84d4f7765c Start patching fun 2012-03-30 13:33:29 -04:00
Christian Weeks aed6bcc737 Ignore stuff 2012-03-30 11:35:35 -04:00
Christian Weeks 73e2229fb4 We're Forge Mod Loader, not Forge ModLoader 2012-03-30 11:35:04 -04:00
Christian Weeks a0633ae5e3 Tweak license to refer to github 2012-03-30 10:16:36 -04:00
Christian Weeks bdce70e891 Add licenses reorganize code 2012-03-30 10:11:13 -04:00
Christian Weeks 3197817a76 Starting to get somewhere 2012-03-30 01:12:59 -04:00
Christian Weeks 0a7e8a8c3e Thoughts on how to do the modloading properly 2012-03-28 16:44:36 -04:00
Christian Weeks b23bdc628b Tab cleanup 2012-03-28 13:29:23 -04:00
Christian Weeks d727aed293 Initial commit 2012-03-28 12:53:08 -04:00
499 changed files with 76741 additions and 26208 deletions

No files matched your search

+1
View File
@@ -0,0 +1 @@
* text=auto
+12
View File
@@ -0,0 +1,12 @@
/bin
/minecraft_server
/mods
/fmlbuild.properties
/fmlversion.properties
/difflist.txt
/.metadata/
/eclipse/.metadata/
/target
fmlbranding.properties
/fernflower.zip
/commands.py.bck
+467
View File
@@ -0,0 +1,467 @@
This minecraft mod, Forge Mod Loader, including all parts herein, is licensed
under the GNU LGPL v2.1 or later.
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
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.
========
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
+14
View File
@@ -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()
+366
View File
@@ -0,0 +1,366 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- ======================================================================
30 Mar 2012 13:35:40
FML
The Forge Mod Loader
cpw
====================================================================== -->
<project name="FML" default="jenkinsbuild">
<description>The Forge Mod Loader</description>
<macrodef name="side">
<attribute name="prop" />
<attribute name="src" />
<attribute name="side" />
<sequential>
<property name="@{prop}" value="${@{side}.@{src}}" />
<condition property="is.client">
<equals arg1="@{side}" arg2="client" />
</condition>
<condition property="is.server">
<equals arg1="@{side}" arg2="server" />
</condition>
</sequential>
</macrodef>
<target name="writeversion" depends="buildenvsetup">
<exec executable="${python.exe}" dir="${basedir}" failonerror="true">
<arg value="${basedir}/getversion.py" />
<arg value="${mcp.home}" />
</exec>
<propertyfile file="fmlversion.properties">
<entry key="fmlbuild.build.number" type="int" value="${version.build}"/>
</propertyfile>
</target>
<target name="buildenvsetup">
<tstamp>
<format pattern="yyMMddHHmmss" property="timestamp" />
</tstamp>
<property environment="env" />
<property file="fmlbuild.properties" />
<property name="modname" value="fml" />
<condition property="dev.home" value="${env.WORKSPACE}" else="${default.dev.home}">
<isset property="env.WORKSPACE" />
</condition>
<condition property="mcp.home" value="${env.WORKSPACE}/mcpworkspace" else="${default.mcp.home}">
<isset property="env.WORKSPACE" />
</condition>
<condition property="python.exe" value="${mcp.home}/runtime/bin/python/python_mcp" else="python">
<os family="Windows" />
</condition>
<property name="mcp.obfoutput" location="${mcp.home}/reobf" />
<property name="client.mcp.obfoutput" location="${mcp.obfoutput}/minecraft" />
<property name="mcp.srcdir" location="${mcp.home}/src" />
<property name="common.mcp.srcdir" location="${mcp.srcdir}/common" />
<property name="client.mcp.srcdir" location="${mcp.srcdir}/minecraft" />
<property name="clean.mcp.srcdir" location="${mcp.home}/src-base" />
<property name="patch.mcp.srcdir" location="${mcp.home}/src-work" />
<property name="tmp.mcp.srcdir" location="${mcp.home}/src-tmp" />
<property name="renamed.mcp.srcdir" location="${mcp.home}/src-renamed" />
<property name="common.src.dir" location="${basedir}/common" />
<property name="client.src.dir" location="${basedir}/client" />
<property name="patch.src.dir" location="${basedir}/patches" />
<property name="fml.conf.dir" location="${basedir}/conf" />
<condition property="version.build" value="${env.BUILD_NUMBER}" else="1">
<isset property="env.BUILD_NUMBER" />
</condition>
</target>
<target name="makeversion" depends="buildenvsetup">
<antcall target="writeversion" />
<property file="fmlversion.properties" />
<property name="build.number" value="${fmlbuild.major.number}.${fmlbuild.minor.number}.${fmlbuild.revision.number}" />
<property name="version.major" value="${fmlbuild.major.number}" />
<property name="version.minor" value="${fmlbuild.minor.number}" />
<property name="version.rev" value="${fmlbuild.revision.number}" />
<property name="version" value="${version.major}.${version.minor}.${version.rev}.${version.build}" />
</target>
<target name="clean" depends="buildenvsetup">
<exec executable="${python.exe}" dir="${mcp.home}">
<arg value="${mcp.home}/runtime/cleanup.py" />
<arg value="-f" />
</exec>
<exec executable="${python.exe}" dir="${mcp.home}">
<arg value="${mcp.home}/runtime/decompile.py" />
<arg value="-d" />
<arg value="-n" />
</exec>
</target>
<target name="reobfuscate" depends="buildenvsetup,recompile">
<exec executable="${python.exe}" dir="${mcp.home}" failonerror="true">
<arg value="${mcp.home}/runtime/reobfuscate.py" />
</exec>
<fail message="Reobfuscation failed">
<condition>
<not>
<and>
<available file="${mcp.home}/temp/client.md5"/>
<available file="${mcp.home}/temp/client_reobf.md5"/>
</and>
</not>
</condition>
</fail>
<exec executable="${python.exe}" dir="${mcp.home}">
<arg value="${basedir}/generatechangedfilelist.py"/>
<arg value="${mcp.home}"/>
<arg value="${basedir}/difflist.txt"/>
</exec>
</target>
<target name="recompile" depends="buildenvsetup">
<exec executable="${python.exe}" dir="${mcp.home}" failonerror="true">
<arg value="${mcp.home}/runtime/recompile.py" />
</exec>
<fail message="Compilation failed">
<condition>
<not>
<available file="${mcp.home}/bin/minecraft/net/minecraft/client/Minecraft.class"/>
</not>
</condition>
</fail>
</target>
<target name="merge-client" depends="buildenvsetup">
<copy todir="${client.mcp.srcdir}" overwrite="true" verbose="true">
<fileset dir="${client.src.dir}" includes="**/*.java" />
</copy>
</target>
<target name="merge-common">
<copy todir="${common.mcp.srcdir}" overwrite="true" verbose="true">
<fileset dir="${common.src.dir}" includes="**/*.java" />
</copy>
</target>
<target name="merge-source" depends="buildenvsetup,merge-client,merge-common" />
<target name="build-client" depends="buildenvsetup,merge-client,merge-common,reobfuscate,makeversion"/>
<target name="extract-built-jar">
<side prop="output" src="mcp.obfoutput" side="${side}" />
<property name="jarname" value="${modname}-${side}-${version}" />
<mkdir dir="${basedir}/target" />
<zip destfile="${basedir}/target/${jarname}.zip">
<fileset dir="${output}" includes="**/*.class" />
<zipfileset dir="${basedir}" includes="fmlversion.properties"/>
<zipfileset dir="${basedir}" includes="LICENSE-fml.txt" />
<zipfileset dir="${basedir}" includes="install/CREDITS-fml.txt" fullpath="CREDITS-fml.txt"/>
<zipfileset dir="${common.src.dir}" includes="*.cfg" />
<mappedresources>
<concat>
<fileset dir="${basedir}/install" includes="README.txt" />
<filterchain>
<replacetokens>
<token key="MAJOR" value="${version.major}" />
<token key="MINOR" value="${version.minor}" />
<token key="REV" value="${version.rev}" />
<token key="BUILD" value="${version.build}" />
<token key="MCVERSION" value="${version.minecraft}" />
</replacetokens>
</filterchain>
</concat>
<mergemapper to="README-fml.txt" />
</mappedresources>
</zip>
</target>
<target name="build-universal" depends="build-client">
<property name="universal.jarname" value="${modname}-universal-${version}" />
<mkdir dir="${basedir}/target" />
<jar destfile="${basedir}/target/${universal.jarname}.zip" duplicate="preserve">
<manifest>
<attribute name="Main-Class" value="net.minecraft.server.MinecraftServer"/>
</manifest>
<fileset dir="${client.mcp.obfoutput}" includes="**/*.class" />
<zipfileset dir="${basedir}" includes="fmlversion.properties"/>
<zipfileset dir="${basedir}" includes="LICENSE-fml.txt" />
<zipfileset dir="${basedir}" includes="install/CREDITS-fml.txt" fullpath="CREDITS-fml.txt"/>
<zipfileset dir="${common.src.dir}" includes="*.cfg" />
<mappedresources>
<concat>
<fileset dir="${basedir}/install" includes="README.txt" />
<filterchain>
<replacetokens>
<token key="MAJOR" value="${version.major}" />
<token key="MINOR" value="${version.minor}" />
<token key="REV" value="${version.rev}" />
<token key="BUILD" value="${version.build}" />
<token key="MCVERSION" value="${version.minecraft}" />
</replacetokens>
</filterchain>
</concat>
<mergemapper to="README-fml.txt" />
</mappedresources>
</jar>
</target>
<target name="build-source-pack" depends="makeversion">
<property name="srcpack.jarname" value="${modname}-src-${version}" />
<zip destfile="${basedir}/target/${srcpack.jarname}.zip">
<zipfileset dir="${basedir}" includes="LICENSE-fml.txt,difflist.txt,commands.patch,mcp_merge.cfg" prefix="fml" />
<zipfileset dir="${common.src.dir}" includes="**/*.java" prefix="fml/common" />
<zipfileset dir="${client.src.dir}" includes="**/*.java" prefix="fml/client" />
<zipfileset dir="${basedir}" includes="fmlversion.properties" prefix="fml/common" />
<zipfileset dir="${common.src.dir}" includes="*.cfg" prefix="fml/common" />
<zipfileset dir="${patch.src.dir}" includes="**/*.patch" prefix="fml/patches" />
<zipfileset dir="${fml.conf.dir}" prefix="fml/conf" />
<mappedresources>
<concat>
<fileset dir="${basedir}/install" includes="README.txt" />
<filterchain>
<replacetokens>
<token key="MAJOR" value="${version.major}" />
<token key="MINOR" value="${version.minor}" />
<token key="REV" value="${version.rev}" />
<token key="BUILD" value="${version.build}" />
<token key="MCVERSION" value="${version.minecraft}" />
</replacetokens>
</filterchain>
</concat>
<mergemapper to="fml/README-fml.txt" />
</mappedresources>
<zipfileset dir="${basedir}/install" excludes="README.txt,fml.pyc" prefix="fml" />
</zip>
</target>
<target name="build" depends="buildenvsetup,merge-client,merge-common,build-client,build-universal,build-source-pack" />
<target name="jenkinsbuild" depends="buildenvsetup,jenkinsfmldecompile,patch,build"/>
<target name="patch" depends="buildenvsetup">
<exec executable="${python.exe}" dir="${basedir}">
<arg value="${basedir}/applypatches.py" />
<arg value="${basedir}" />
<arg value="${mcp.srcdir}" />
<arg value="${mcp.home}" />
</exec>
</target>
<target name="setupenvironment" depends="buildenvsetup">
<input message="This will clean the mcp environment at ${mcp.home} and backup any src-work folder there (src-base will be erased). Continue?" validargs="y,n" addproperty="do.continue" />
<condition property="do.not.continue">
<equals arg1="n" arg2="${do.continue}" />
</condition>
<fail if="do.not.continue">You have decided not to continue. This script will stop now.</fail>
<echo>Preparing the MCP environment at ${mcp.home}</echo>
<antcall target="fmldecompile"/>
<echo>Moving old patched sources at ${patch.mcp.srcdir} out of the way</echo>
<move todir="${mcp.home}/src-work${timestamp}" failonerror="false" verbose="true">
<fileset dir="${patch.mcp.srcdir}"/>
</move>
<echo>Deleting old patch references at ${clean.mcp.srcdir}</echo>
<delete dir="${clean.mcp.srcdir}" failonerror="false"/>
<echo>Creating new patch references at ${clean.mcp.srcdir}</echo>
<copy todir="${clean.mcp.srcdir}">
<fileset dir="${mcp.srcdir}"/>
</copy>
<antcall target="cleanargo"/>
<antcall target="patch"/>
<echo>Creating clean patched references at ${patch.mcp.srcdir}</echo>
<copy todir="${patch.mcp.srcdir}">
<fileset dir="${mcp.srcdir}"/>
</copy>
<antcall target="writeversion"/>
<echo>Setup complete! You should now be able to open ${basedir}/eclipse as a workspace in eclipse and import/refresh the FML-Server and FML-Client projects</echo>
</target>
<target name="fmldecompile" depends="buildenvsetup">
<exec executable="${python.exe}" dir="${mcp.home}">
<arg value="${mcp.home}/runtime/cleanup.py" />
<arg value="-f" />
</exec>
<exec executable="${python.exe}" dir="${basedir}">
<arg value="${basedir}/decompile.py" />
<arg value="${mcp.home}" />
<arg value="${basedir}" />
</exec>
</target>
<target name="jenkinsfmldecompile" depends="buildenvsetup">
<exec executable="${python.exe}" dir="${mcp.home}">
<arg value="${mcp.home}/runtime/cleanup.py" />
<arg value="-f" />
</exec>
<exec executable="${python.exe}" dir="${basedir}">
<arg value="${basedir}/decompile.py" />
<arg value="${mcp.home}" />
<arg value="${basedir}" />
<arg value="-no_gen_conf" />
</exec>
</target>
<target name="repatch" depends="buildenvsetup,checkpatches">
<echo>Moving old patched sources at ${mcp.home}/src-work out of the way</echo>
<move todir="${mcp.home}/src-work${timestamp}" failonerror="false" verbose="true">
<fileset dir="${patch.mcp.srcdir}"/>
</move>
<delete dir="${mcp.srcdir}"/>
<copy todir="${mcp.srcdir}">
<fileset dir="${clean.mcp.srcdir}"/>
</copy>
<antcall target="cleanargo"/>
<antcall target="patch"/>
<copy todir="${patch.mcp.srcdir}">
<fileset dir="${mcp.srcdir}"/>
</copy>
</target>
<target name="repatchclean" depends="buildenvsetup">
<delete dir="${mcp.srcdir}"/>
<copy todir="${mcp.srcdir}">
<fileset dir="${clean.mcp.srcdir}"/>
</copy>
<antcall target="cleanargo"/>
<antcall target="patch"/>
</target>
<target name="cleanargo" depends="buildenvsetup">
<delete dir="${client.mcp.srcdir}/argo"/>
</target>
<target name="checkpatches" depends="buildenvsetup">
<uptodate property="checkUptodate.uptodate">
<srcfiles dir="${patch.mcp.srcdir}" includes="**/*.java">
<present targetdir="${patch.src.dir}">
<globmapper from="*.java" to="*.java.patch"/>
</present>
</srcfiles>
<globmapper from="*.java" to="${patch.src.dir}/*.java.patch"/>
</uptodate>
<fail unless="checkUptodate.uptodate">
A patch is out of date. Update your patches!
</fail>
</target>
<target name="updatepatches" depends="buildenvsetup">
<exec executable="${python.exe}" dir="${basedir}">
<arg value="${basedir}/update_patches.py" />
<arg value="${mcp.home}"/>
<arg value="${basedir}"/>
</exec>
</target>
<target name="makerenamedsource" depends="buildenvsetup,repatch,merge-client,merge-common,reobfuscate">
<copy todir="${tmp.mcp.srcdir}">
<fileset dir="${mcp.srcdir}"/>
</copy>
<exec executable="${python.exe}" dir="${mcp.home}">
<arg value="${mcp.home}/runtime/updatenames.py" />
<arg value="-f" />
</exec>
<copy todir="${renamed.mcp.srcdir}">
<fileset dir="${mcp.srcdir}"/>
</copy>
<move todir="${mcp.srcdir}">
<fileset dir="${tmp.mcp.srcdir}"/>
</move>
</target>
</project>
@@ -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;
}
}
+409
View File
@@ -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);
}
}
}
+48
View File
@@ -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 "";
}
+780
View File
@@ -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 {
}
+5
View File
@@ -0,0 +1,5 @@
package net.minecraft.src;
public interface Block {
}
+5
View File
@@ -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 {
}
+5
View File
@@ -0,0 +1,5 @@
package net.minecraft.src;
public interface IRecipe {
}
+5
View File
@@ -0,0 +1,5 @@
package net.minecraft.src;
public interface ItemBlock {
}
+5
View File
@@ -0,0 +1,5 @@
package net.minecraft.src;
public interface ItemStack {
}
+5
View File
@@ -0,0 +1,5 @@
package net.minecraft.src;
public interface TileEntity {
}
+43
View File
@@ -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,424 @@
/*
* The FML Forge Mod Loader suite. Copyright (C) 2012 cpw
*
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package cpw.mods.fml.client;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.minecraft.client.Minecraft;
import net.minecraft.server.MinecraftServer;
import net.minecraft.src.CrashReport;
import net.minecraft.src.Entity;
import net.minecraft.src.EntityLiving;
import net.minecraft.src.EntityPlayer;
import net.minecraft.src.GuiScreen;
import net.minecraft.src.NetClientHandler;
import net.minecraft.src.NetHandler;
import net.minecraft.src.Packet;
import net.minecraft.src.Packet131MapData;
import net.minecraft.src.Render;
import net.minecraft.src.RenderManager;
import net.minecraft.src.World;
import net.minecraft.src.WorldClient;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableMap;
import cpw.mods.fml.client.modloader.ModLoaderClientHelper;
import cpw.mods.fml.client.registry.KeyBindingRegistry;
import cpw.mods.fml.client.registry.RenderingRegistry;
import cpw.mods.fml.common.DummyModContainer;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.FMLLog;
import cpw.mods.fml.common.IFMLSidedHandler;
import cpw.mods.fml.common.Loader;
import cpw.mods.fml.common.LoaderException;
import cpw.mods.fml.common.MetadataCollection;
import cpw.mods.fml.common.MissingModsException;
import cpw.mods.fml.common.ModContainer;
import cpw.mods.fml.common.ModMetadata;
import cpw.mods.fml.common.ObfuscationReflectionHelper;
import cpw.mods.fml.common.Side;
import cpw.mods.fml.common.network.EntitySpawnAdjustmentPacket;
import cpw.mods.fml.common.network.EntitySpawnPacket;
import cpw.mods.fml.common.network.ModMissingPacket;
import cpw.mods.fml.common.registry.EntityRegistry.EntityRegistration;
import cpw.mods.fml.common.registry.IEntityAdditionalSpawnData;
import cpw.mods.fml.common.registry.IThrowableEntity;
import cpw.mods.fml.common.registry.LanguageRegistry;
/**
* Handles primary communication from hooked code into the system
*
* The FML entry point is {@link #beginMinecraftLoading(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;
/**
* Called to start the whole game off from
* {@link MinecraftServer#startServer}
*
* @param minecraftServer
*/
private DummyModContainer optifineContainer;
private boolean guiLoaded;
private boolean serverIsRunning;
private MissingModsException modsMissing;
private boolean loading;
public void beginMinecraftLoading(Minecraft minecraft)
{
if (minecraft.func_71355_q())
{
FMLLog.severe("DEMO MODE DETECTED, FML will not work. Finishing now.");
haltGame("FML will not run in demo mode", new RuntimeException());
return;
}
loading = true;
client = minecraft;
ObfuscationReflectionHelper.detectObfuscation(World.class);
TextureFXManager.instance().setClient(client);
FMLCommonHandler.instance().beginLoading(this);
new ModLoaderClientHelper(client);
try
{
Class<?> optifineConfig = Class.forName("Config", false, Loader.instance().getModClassLoader());
String optifineVersion = (String) optifineConfig.getField("VERSION").get(null);
Map<String,Object> dummyOptifineMeta = ImmutableMap.<String,Object>builder().put("name", "Optifine").put("version", optifineVersion).build();
ModMetadata optifineMetadata = MetadataCollection.from(getClass().getResourceAsStream("optifinemod.info"),"optifine").getMetadataForId("optifine", dummyOptifineMeta);
optifineContainer = new DummyModContainer(optifineMetadata);
FMLLog.info("Forge Mod Loader has detected optifine %s, enabling compatibility features",optifineContainer.getVersion());
}
catch (Exception e)
{
optifineContainer = null;
}
try
{
Loader.instance().loadMods();
}
catch (MissingModsException missing)
{
modsMissing = missing;
}
catch (LoaderException le)
{
haltGame("There was a severe problem during mod loading that has caused the game to fail", le);
return;
}
}
@Override
public void haltGame(String message, Throwable t)
{
client.func_71377_b(new CrashReport(message, t));
throw Throwables.propagate(t);
}
/**
* Called a bit later on during initialization to finish loading mods
* Also initializes key bindings
*
*/
@SuppressWarnings("deprecation")
public void finishMinecraftLoading()
{
if (modsMissing != null)
{
return;
}
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;
}
LanguageRegistry.reloadLanguageTable();
RenderingRegistry.instance().loadEntityRenderers((Map<Class<? extends Entity>, Render>)RenderManager.field_78727_a.field_78729_o);
loading = false;
KeyBindingRegistry.instance().uploadKeyBindingsToGame(client.field_71474_y);
}
public void onInitializationComplete()
{
if (modsMissing != null)
{
client.func_71373_a(new GuiModsMissing(modsMissing));
}
else
{
TextureFXManager.instance().loadTextures(client.field_71418_C.func_77292_e());
}
}
/**
* 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);
}
}
/**
* @param mods
*/
public void addSpecialModEntries(ArrayList<ModContainer> mods)
{
if (optifineContainer!=null) {
mods.add(optifineContainer);
}
}
@Override
public List<String> getAdditionalBrandingInformation()
{
if (optifineContainer!=null)
{
return Arrays.asList(String.format("Optifine %s",optifineContainer.getVersion()));
} else {
return Collections.emptyList();
}
}
@Override
public Side getSide()
{
return Side.CLIENT;
}
public boolean hasOptifine()
{
return optifineContainer!=null;
}
@Override
public void showGuiScreen(Object clientGuiElement)
{
GuiScreen gui = (GuiScreen) clientGuiElement;
client.func_71373_a(gui);
}
@Override
public Entity spawnEntityIntoClientWorld(EntityRegistration er, EntitySpawnPacket packet)
{
WorldClient wc = client.field_71441_e;
Class<? extends Entity> cls = er.getEntityClass();
try
{
Entity entity;
if (er.hasCustomSpawning())
{
entity = er.doCustomSpawning(packet);
}
else
{
entity = (Entity)(cls.getConstructor(World.class).newInstance(wc));
entity.field_70157_k = packet.entityId;
entity.func_70012_b(packet.scaledX, packet.scaledY, packet.scaledZ, packet.scaledYaw, packet.scaledPitch);
if (entity instanceof EntityLiving)
{
((EntityLiving)entity).field_70759_as = packet.scaledHeadYaw;
}
}
entity.field_70118_ct = packet.rawX;
entity.field_70117_cu = packet.rawY;
entity.field_70116_cv = packet.rawZ;
if (entity instanceof IThrowableEntity)
{
Entity thrower = client.field_71439_g.field_70157_k == packet.throwerId ? client.field_71439_g : wc.func_73024_a(packet.throwerId);
((IThrowableEntity)entity).setThrower(thrower);
}
Entity parts[] = entity.func_70021_al();
if (parts != null)
{
int i = packet.entityId - entity.field_70157_k;
for (int j = 0; j < parts.length; j++)
{
parts[j].field_70157_k += i;
}
}
if (packet.metadata != null)
{
entity.func_70096_w().func_75687_a((List)packet.metadata);
}
if (packet.throwerId > 0)
{
entity.func_70016_h(packet.speedScaledX, packet.speedScaledY, packet.speedScaledZ);
}
if (entity instanceof IEntityAdditionalSpawnData)
{
((IEntityAdditionalSpawnData)entity).readSpawnData(packet.dataStream);
}
wc.func_73027_a(packet.entityId, entity);
return entity;
}
catch (Exception e)
{
FMLLog.log(Level.SEVERE, e, "A severe problem occurred during the spawning of an entity");
throw Throwables.propagate(e);
}
}
@Override
public void adjustEntityLocationOnClient(EntitySpawnAdjustmentPacket packet)
{
Entity ent = client.field_71441_e.func_73024_a(packet.entityId);
if (ent != null)
{
ent.field_70118_ct = packet.serverX;
ent.field_70117_cu = packet.serverY;
ent.field_70116_cv = packet.serverZ;
}
else
{
FMLLog.fine("Attempted to adjust the position of entity %d which is not present on the client", packet.entityId);
}
}
@Override
public void beginServerLoading(MinecraftServer server)
{
// NOOP
}
@Override
public void finishServerLoading()
{
// NOOP
}
@Override
public MinecraftServer getServer()
{
return client.func_71401_C();
}
@Override
public void sendPacket(Packet packet)
{
client.field_71439_g.field_71174_a.func_72552_c(packet);
}
@Override
public void displayMissingMods(ModMissingPacket modMissingPacket)
{
client.func_71373_a(new GuiModsMissingForServer(modMissingPacket));
}
/**
* If the client is in the midst of loading, we disable saving so that custom settings aren't wiped out
* @return
*/
public boolean isLoading()
{
return loading;
}
@Override
public void handleTinyPacket(NetHandler handler, Packet131MapData mapData)
{
((NetClientHandler)handler).fmlPacket131Callback(mapData);
}
@Override
public void setClientCompatibilityLevel(byte compatibilityLevel)
{
NetClientHandler.setConnectionCompatibilityLevel(compatibilityLevel);
}
@Override
public byte getClientCompatibilityLevel()
{
return NetClientHandler.getConnectionCompatibilityLevel();
}
}
@@ -0,0 +1,69 @@
/*
* The FML Forge Mod Loader suite.
* Copyright (C) 2012 cpw
*
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package cpw.mods.fml.client;
import java.awt.Dimension;
import java.util.List;
import java.util.logging.Logger;
import net.minecraft.src.RenderEngine;
import net.minecraft.src.TextureFX;
import net.minecraft.src.TexturePackBase;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.FMLLog;
public class FMLTextureFX extends TextureFX implements ITextureFX
{
public int tileSizeBase = 16;
public int tileSizeSquare = 256;
public int tileSizeMask = 15;
public int tileSizeSquareMask = 255;
public boolean errored = false;
protected Logger log = FMLLog.getLogger();
public FMLTextureFX(int icon)
{
super(icon);
}
@Override public void setErrored(boolean err){ errored = err; }
@Override public boolean getErrored(){ return errored; }
@Override
public void onTexturePackChanged(RenderEngine engine, 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;
}
}
+177
View File
@@ -0,0 +1,177 @@
/*
* The FML Forge Mod Loader suite.
* Copyright (C) 2012 cpw
*
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package cpw.mods.fml.client;
import java.awt.Dimension;
import java.util.ArrayList;
import net.minecraft.client.Minecraft;
import net.minecraft.src.FontRenderer;
import net.minecraft.src.GuiButton;
import net.minecraft.src.GuiScreen;
import net.minecraft.src.GuiSmallButton;
import net.minecraft.src.StringTranslate;
import net.minecraft.src.Tessellator;
import org.lwjgl.opengl.GL11;
import cpw.mods.fml.common.Loader;
import cpw.mods.fml.common.ModContainer;
/**
* @author cpw
*
*/
public class GuiModList extends GuiScreen
{
private GuiScreen mainMenu;
private GuiSlotModList modList;
private int selected = -1;
private ModContainer selectedMod;
private int listWidth;
private ArrayList<ModContainer> mods;
/**
* @param 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) {
GL11.glEnable(GL11.GL_BLEND);
if (!selectedMod.getMetadata().autogenerated) {
int shifty = 35;
if (!selectedMod.getMetadata().logoFile.isEmpty())
{
int texture = this.field_73882_e.field_71446_o.func_78341_b(selectedMod.getMetadata().logoFile);
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
this.field_73882_e.field_71446_o.func_78342_b(texture);
Dimension dim = TextureFXManager.instance().getTextureDimensions(texture);
int top = 32;
Tessellator tess = Tessellator.field_78398_a;
tess.func_78382_b();
tess.func_78374_a(offset, top + dim.height, field_73735_i, 0, 1);
tess.func_78374_a(offset + dim.width, top + dim.height, field_73735_i, 1, 1);
tess.func_78374_a(offset + dim.width, top, field_73735_i, 1, 0);
tess.func_78374_a(offset, top, field_73735_i, 0, 0);
tess.func_78381_a();
shifty += 65;
}
this.field_73886_k.func_78261_a(selectedMod.getMetadata().name, offset, shifty, 0xFFFFFF);
shifty += 12;
shifty = drawLine(String.format("Version: %s (%s)", selectedMod.getDisplayVersion(), selectedMod.getVersion()), offset, shifty);
shifty = drawLine(String.format("Mod State: %s", Loader.instance().getModState(selectedMod)), offset, shifty);
if (!selectedMod.getMetadata().credits.isEmpty()) {
shifty = drawLine(String.format("Credits: %s", selectedMod.getMetadata().credits), offset, shifty);
}
shifty = drawLine(String.format("Authors: %s", selectedMod.getMetadata().getAuthorList()), offset, shifty);
shifty = drawLine(String.format("URL: %s", selectedMod.getMetadata().url), offset, shifty);
shifty = drawLine(selectedMod.getMetadata().childMods.isEmpty() ? "No child mods for this mod" : String.format("Child mods: %s", selectedMod.getMetadata().getChildModList()), offset, shifty);
this.getFontRenderer().func_78279_b(selectedMod.getMetadata().description, offset, shifty + 10, this.field_73880_f - offset - 20, 0xDDDDDD);
} else {
offset = ( this.listWidth + this.field_73880_f ) / 2;
this.func_73732_a(this.field_73886_k, selectedMod.getName(), offset, 35, 0xFFFFFF);
this.func_73732_a(this.field_73886_k, String.format("Version: %s",selectedMod.getVersion()), offset, 45, 0xFFFFFF);
this.func_73732_a(this.field_73886_k, String.format("Mod State: %s",Loader.instance().getModState(selectedMod)), offset, 55, 0xFFFFFF);
this.func_73732_a(this.field_73886_k, "No mod information found", offset, 65, 0xDDDDDD);
this.func_73732_a(this.field_73886_k, "Ask your mod author to provide a mod mcmod.info file", offset, 75, 0xDDDDDD);
}
GL11.glDisable(GL11.GL_BLEND);
}
super.func_73863_a(p_571_1_, p_571_2_, p_571_3_);
}
Minecraft getMinecraftInstance() {
return field_73882_e;
}
FontRenderer getFontRenderer() {
return field_73886_k;
}
/**
* @param var1
*/
public void selectModIndex(int var1)
{
this.selected=var1;
if (var1>=0 && var1<=mods.size()) {
this.selectedMod=mods.get(selected);
} else {
this.selectedMod=null;
}
}
/**
* @param var1
* @return
*/
public boolean modIndexSelected(int var1)
{
return var1==selected;
}
}
@@ -0,0 +1,39 @@
package cpw.mods.fml.client;
import cpw.mods.fml.common.MissingModsException;
import cpw.mods.fml.common.versioning.ArtifactVersion;
import net.minecraft.src.GuiErrorScreen;
public class GuiModsMissing extends GuiErrorScreen
{
private MissingModsException modsMissing;
public GuiModsMissing(MissingModsException modsMissing)
{
this.modsMissing = modsMissing;
}
@Override
public void func_73866_w_()
{
super.func_73866_w_();
}
@Override
public void func_73863_a(int p_73863_1_, int p_73863_2_, float p_73863_3_)
{
this.func_73873_v_();
int offset = 85 - modsMissing.missingMods.size() * 10;
this.func_73732_a(this.field_73886_k, "Forge Mod Loader has found a problem with your minecraft installation", this.field_73880_f / 2, offset, 0xFFFFFF);
offset+=10;
this.func_73732_a(this.field_73886_k, "The mods and versions listed below could not be found", this.field_73880_f / 2, offset, 0xFFFFFF);
offset+=5;
for (ArtifactVersion v : modsMissing.missingMods)
{
offset+=10;
this.func_73732_a(this.field_73886_k, String.format("%s : %s", v.getLabel(), v.getRangeString()), this.field_73880_f / 2, offset, 0xEEEEEE);
}
offset+=20;
this.func_73732_a(this.field_73886_k, "The file 'ForgeModLoader-client-0.log' contains more information", this.field_73880_f / 2, offset, 0xFFFFFF);
}
}
@@ -0,0 +1,52 @@
package cpw.mods.fml.client;
import net.minecraft.src.GuiButton;
import net.minecraft.src.GuiScreen;
import net.minecraft.src.GuiSmallButton;
import net.minecraft.src.StringTranslate;
import cpw.mods.fml.common.network.ModMissingPacket;
import cpw.mods.fml.common.versioning.ArtifactVersion;
public class GuiModsMissingForServer extends GuiScreen
{
private ModMissingPacket modsMissing;
public GuiModsMissingForServer(ModMissingPacket modsMissing)
{
this.modsMissing = modsMissing;
}
@Override
public void func_73866_w_()
{
StringTranslate translations = StringTranslate.func_74808_a();
this.field_73887_h.add(new GuiSmallButton(1, this.field_73880_f / 2 - 75, this.field_73881_g - 38, translations.func_74805_b("gui.done")));
}
@Override
protected void func_73875_a(GuiButton p_73875_1_)
{
if (p_73875_1_.field_73742_g && p_73875_1_.field_73741_f == 1)
{
FMLClientHandler.instance().getClient().func_71373_a(null);
}
}
@Override
public void func_73863_a(int p_73863_1_, int p_73863_2_, float p_73863_3_)
{
this.func_73873_v_();
int offset = 85 - modsMissing.getModList().size() * 10;
this.func_73732_a(this.field_73886_k, "Forge Mod Loader could not connect to this server", this.field_73880_f / 2, offset, 0xFFFFFF);
offset += 10;
this.func_73732_a(this.field_73886_k, "The mods and versions listed below could not be found", this.field_73880_f / 2, offset, 0xFFFFFF);
offset += 10;
this.func_73732_a(this.field_73886_k, "They are required to play on this server", this.field_73880_f / 2, offset, 0xFFFFFF);
offset += 5;
for (ArtifactVersion v : modsMissing.getModList())
{
offset += 10;
this.func_73732_a(this.field_73886_k, String.format("%s : %s", v.getLabel(), v.getRangeString()), this.field_73880_f / 2, offset, 0xEEEEEE);
}
super.func_73863_a(p_73863_1_, p_73863_2_, p_73863_3_);
}
}
@@ -0,0 +1,400 @@
package cpw.mods.fml.client;
import java.util.List;
import net.minecraft.client.Minecraft;
import net.minecraft.src.GuiButton;
import net.minecraft.src.Tessellator;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.GL11;
public abstract class GuiScrollingList
{
private final Minecraft client;
protected final int listWidth;
protected final int listHeight;
protected final int top;
protected final int bottom;
private final int right;
protected final int left;
protected final int slotHeight;
private int scrollUpActionId;
private int scrollDownActionId;
protected int mouseX;
protected int mouseY;
private float initialMouseClickY = -2.0F;
private float scrollFactor;
private float scrollDistance;
private int selectedIndex = -1;
private long lastClickTime = 0L;
private boolean field_25123_p = true;
private boolean field_27262_q;
private int field_27261_r;
public GuiScrollingList(Minecraft client, int width, int height, int top, int bottom, int left, int entryHeight)
{
this.client = client;
this.listWidth = width;
this.listHeight = height;
this.top = top;
this.bottom = bottom;
this.slotHeight = entryHeight;
this.left = left;
this.right = width + this.left;
}
public void func_27258_a(boolean p_27258_1_)
{
this.field_25123_p = p_27258_1_;
}
protected void func_27259_a(boolean p_27259_1_, int p_27259_2_)
{
this.field_27262_q = p_27259_1_;
this.field_27261_r = p_27259_2_;
if (!p_27259_1_)
{
this.field_27261_r = 0;
}
}
protected abstract int getSize();
protected abstract void elementClicked(int index, boolean doubleClick);
protected abstract boolean isSelected(int index);
protected int getContentHeight()
{
return this.getSize() * this.slotHeight + this.field_27261_r;
}
protected abstract void drawBackground();
protected abstract void drawSlot(int var1, int var2, int var3, int var4, Tessellator var5);
protected void func_27260_a(int p_27260_1_, int p_27260_2_, Tessellator p_27260_3_) {}
protected void func_27255_a(int p_27255_1_, int p_27255_2_) {}
protected void func_27257_b(int p_27257_1_, int p_27257_2_) {}
public int func_27256_c(int p_27256_1_, int p_27256_2_)
{
int var3 = this.left + 1;
int var4 = this.left + this.listWidth - 7;
int var5 = p_27256_2_ - this.top - this.field_27261_r + (int)this.scrollDistance - 4;
int var6 = var5 / this.slotHeight;
return p_27256_1_ >= var3 && p_27256_1_ <= var4 && var6 >= 0 && var5 >= 0 && var6 < this.getSize() ? var6 : -1;
}
public void registerScrollButtons(List p_22240_1_, int p_22240_2_, int p_22240_3_)
{
this.scrollUpActionId = p_22240_2_;
this.scrollDownActionId = p_22240_3_;
}
private void applyScrollLimits()
{
int var1 = this.getContentHeight() - (this.bottom - this.top - 4);
if (var1 < 0)
{
var1 /= 2;
}
if (this.scrollDistance < 0.0F)
{
this.scrollDistance = 0.0F;
}
if (this.scrollDistance > (float)var1)
{
this.scrollDistance = (float)var1;
}
}
public void actionPerformed(GuiButton button)
{
if (button.field_73742_g)
{
if (button.field_73741_f == this.scrollUpActionId)
{
this.scrollDistance -= (float)(this.slotHeight * 2 / 3);
this.initialMouseClickY = -2.0F;
this.applyScrollLimits();
}
else if (button.field_73741_f == this.scrollDownActionId)
{
this.scrollDistance += (float)(this.slotHeight * 2 / 3);
this.initialMouseClickY = -2.0F;
this.applyScrollLimits();
}
}
}
public void drawScreen(int mouseX, int mouseY, float p_22243_3_)
{
this.mouseX = mouseX;
this.mouseY = mouseY;
this.drawBackground();
int listLength = this.getSize();
int scrollBarXStart = this.left + this.listWidth - 6;
int scrollBarXEnd = scrollBarXStart + 6;
int boxLeft = this.left;
int boxRight = scrollBarXStart-1;
int var10;
int var11;
int var13;
int var19;
if (Mouse.isButtonDown(0))
{
if (this.initialMouseClickY == -1.0F)
{
boolean var7 = true;
if (mouseY >= this.top && mouseY <= this.bottom)
{
var10 = mouseY - this.top - this.field_27261_r + (int)this.scrollDistance - 4;
var11 = var10 / this.slotHeight;
if (mouseX >= boxLeft && mouseX <= boxRight && var11 >= 0 && var10 >= 0 && var11 < listLength)
{
boolean var12 = var11 == this.selectedIndex && System.currentTimeMillis() - this.lastClickTime < 250L;
this.elementClicked(var11, var12);
this.selectedIndex = var11;
this.lastClickTime = System.currentTimeMillis();
}
else if (mouseX >= boxLeft && mouseX <= boxRight && var10 < 0)
{
this.func_27255_a(mouseX - boxLeft, mouseY - this.top + (int)this.scrollDistance - 4);
var7 = false;
}
if (mouseX >= scrollBarXStart && mouseX <= scrollBarXEnd)
{
this.scrollFactor = -1.0F;
var19 = this.getContentHeight() - (this.bottom - this.top - 4);
if (var19 < 1)
{
var19 = 1;
}
var13 = (int)((float)((this.bottom - this.top) * (this.bottom - this.top)) / (float)this.getContentHeight());
if (var13 < 32)
{
var13 = 32;
}
if (var13 > this.bottom - this.top - 8)
{
var13 = this.bottom - this.top - 8;
}
this.scrollFactor /= (float)(this.bottom - this.top - var13) / (float)var19;
}
else
{
this.scrollFactor = 1.0F;
}
if (var7)
{
this.initialMouseClickY = (float)mouseY;
}
else
{
this.initialMouseClickY = -2.0F;
}
}
else
{
this.initialMouseClickY = -2.0F;
}
}
else if (this.initialMouseClickY >= 0.0F)
{
this.scrollDistance -= ((float)mouseY - this.initialMouseClickY) * this.scrollFactor;
this.initialMouseClickY = (float)mouseY;
}
}
else
{
while (Mouse.next())
{
int var16 = Mouse.getEventDWheel();
if (var16 != 0)
{
if (var16 > 0)
{
var16 = -1;
}
else if (var16 < 0)
{
var16 = 1;
}
this.scrollDistance += (float)(var16 * this.slotHeight / 2);
}
}
this.initialMouseClickY = -1.0F;
}
this.applyScrollLimits();
GL11.glDisable(GL11.GL_LIGHTING);
GL11.glDisable(GL11.GL_FOG);
Tessellator var18 = Tessellator.field_78398_a;
GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.client.field_71446_o.func_78341_b("/gui/background.png"));
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
float var17 = 32.0F;
var18.func_78382_b();
var18.func_78378_d(2105376);
var18.func_78374_a((double)this.left, (double)this.bottom, 0.0D, (double)((float)this.left / var17), (double)((float)(this.bottom + (int)this.scrollDistance) / var17));
var18.func_78374_a((double)this.right, (double)this.bottom, 0.0D, (double)((float)this.right / var17), (double)((float)(this.bottom + (int)this.scrollDistance) / var17));
var18.func_78374_a((double)this.right, (double)this.top, 0.0D, (double)((float)this.right / var17), (double)((float)(this.top + (int)this.scrollDistance) / var17));
var18.func_78374_a((double)this.left, (double)this.top, 0.0D, (double)((float)this.left / var17), (double)((float)(this.top + (int)this.scrollDistance) / var17));
var18.func_78381_a();
// boxRight = this.listWidth / 2 - 92 - 16;
var10 = this.top + 4 - (int)this.scrollDistance;
if (this.field_27262_q)
{
this.func_27260_a(boxRight, var10, var18);
}
int var14;
for (var11 = 0; var11 < listLength; ++var11)
{
var19 = var10 + var11 * this.slotHeight + this.field_27261_r;
var13 = this.slotHeight - 4;
if (var19 <= this.bottom && var19 + var13 >= this.top)
{
if (this.field_25123_p && this.isSelected(var11))
{
var14 = boxLeft;
int var15 = boxRight;
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
GL11.glDisable(GL11.GL_TEXTURE_2D);
var18.func_78382_b();
var18.func_78378_d(8421504);
var18.func_78374_a((double)var14, (double)(var19 + var13 + 2), 0.0D, 0.0D, 1.0D);
var18.func_78374_a((double)var15, (double)(var19 + var13 + 2), 0.0D, 1.0D, 1.0D);
var18.func_78374_a((double)var15, (double)(var19 - 2), 0.0D, 1.0D, 0.0D);
var18.func_78374_a((double)var14, (double)(var19 - 2), 0.0D, 0.0D, 0.0D);
var18.func_78378_d(0);
var18.func_78374_a((double)(var14 + 1), (double)(var19 + var13 + 1), 0.0D, 0.0D, 1.0D);
var18.func_78374_a((double)(var15 - 1), (double)(var19 + var13 + 1), 0.0D, 1.0D, 1.0D);
var18.func_78374_a((double)(var15 - 1), (double)(var19 - 1), 0.0D, 1.0D, 0.0D);
var18.func_78374_a((double)(var14 + 1), (double)(var19 - 1), 0.0D, 0.0D, 0.0D);
var18.func_78381_a();
GL11.glEnable(GL11.GL_TEXTURE_2D);
}
this.drawSlot(var11, boxRight, var19, var13, var18);
}
}
GL11.glDisable(GL11.GL_DEPTH_TEST);
byte var20 = 4;
this.overlayBackground(0, this.top, 255, 255);
this.overlayBackground(this.bottom, this.listHeight, 255, 255);
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL11.glDisable(GL11.GL_ALPHA_TEST);
GL11.glShadeModel(GL11.GL_SMOOTH);
GL11.glDisable(GL11.GL_TEXTURE_2D);
var18.func_78382_b();
var18.func_78384_a(0, 0);
var18.func_78374_a((double)this.left, (double)(this.top + var20), 0.0D, 0.0D, 1.0D);
var18.func_78374_a((double)this.right, (double)(this.top + var20), 0.0D, 1.0D, 1.0D);
var18.func_78384_a(0, 255);
var18.func_78374_a((double)this.right, (double)this.top, 0.0D, 1.0D, 0.0D);
var18.func_78374_a((double)this.left, (double)this.top, 0.0D, 0.0D, 0.0D);
var18.func_78381_a();
var18.func_78382_b();
var18.func_78384_a(0, 255);
var18.func_78374_a((double)this.left, (double)this.bottom, 0.0D, 0.0D, 1.0D);
var18.func_78374_a((double)this.right, (double)this.bottom, 0.0D, 1.0D, 1.0D);
var18.func_78384_a(0, 0);
var18.func_78374_a((double)this.right, (double)(this.bottom - var20), 0.0D, 1.0D, 0.0D);
var18.func_78374_a((double)this.left, (double)(this.bottom - var20), 0.0D, 0.0D, 0.0D);
var18.func_78381_a();
var19 = this.getContentHeight() - (this.bottom - this.top - 4);
if (var19 > 0)
{
var13 = (this.bottom - this.top) * (this.bottom - this.top) / this.getContentHeight();
if (var13 < 32)
{
var13 = 32;
}
if (var13 > this.bottom - this.top - 8)
{
var13 = this.bottom - this.top - 8;
}
var14 = (int)this.scrollDistance * (this.bottom - this.top - var13) / var19 + this.top;
if (var14 < this.top)
{
var14 = this.top;
}
var18.func_78382_b();
var18.func_78384_a(0, 255);
var18.func_78374_a((double)scrollBarXStart, (double)this.bottom, 0.0D, 0.0D, 1.0D);
var18.func_78374_a((double)scrollBarXEnd, (double)this.bottom, 0.0D, 1.0D, 1.0D);
var18.func_78374_a((double)scrollBarXEnd, (double)this.top, 0.0D, 1.0D, 0.0D);
var18.func_78374_a((double)scrollBarXStart, (double)this.top, 0.0D, 0.0D, 0.0D);
var18.func_78381_a();
var18.func_78382_b();
var18.func_78384_a(8421504, 255);
var18.func_78374_a((double)scrollBarXStart, (double)(var14 + var13), 0.0D, 0.0D, 1.0D);
var18.func_78374_a((double)scrollBarXEnd, (double)(var14 + var13), 0.0D, 1.0D, 1.0D);
var18.func_78374_a((double)scrollBarXEnd, (double)var14, 0.0D, 1.0D, 0.0D);
var18.func_78374_a((double)scrollBarXStart, (double)var14, 0.0D, 0.0D, 0.0D);
var18.func_78381_a();
var18.func_78382_b();
var18.func_78384_a(12632256, 255);
var18.func_78374_a((double)scrollBarXStart, (double)(var14 + var13 - 1), 0.0D, 0.0D, 1.0D);
var18.func_78374_a((double)(scrollBarXEnd - 1), (double)(var14 + var13 - 1), 0.0D, 1.0D, 1.0D);
var18.func_78374_a((double)(scrollBarXEnd - 1), (double)var14, 0.0D, 1.0D, 0.0D);
var18.func_78374_a((double)scrollBarXStart, (double)var14, 0.0D, 0.0D, 0.0D);
var18.func_78381_a();
}
this.func_27257_b(mouseX, mouseY);
GL11.glEnable(GL11.GL_TEXTURE_2D);
GL11.glShadeModel(GL11.GL_FLAT);
GL11.glEnable(GL11.GL_ALPHA_TEST);
GL11.glDisable(GL11.GL_BLEND);
}
private void overlayBackground(int p_22239_1_, int p_22239_2_, int p_22239_3_, int p_22239_4_)
{
Tessellator var5 = Tessellator.field_78398_a;
GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.client.field_71446_o.func_78341_b("/gui/background.png"));
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
float var6 = 32.0F;
var5.func_78382_b();
var5.func_78384_a(4210752, p_22239_4_);
var5.func_78374_a(0.0D, (double)p_22239_2_, 0.0D, 0.0D, (double)((float)p_22239_2_ / var6));
var5.func_78374_a((double)this.listWidth + 30, (double)p_22239_2_, 0.0D, (double)((float)(this.listWidth + 30) / var6), (double)((float)p_22239_2_ / var6));
var5.func_78384_a(4210752, p_22239_3_);
var5.func_78374_a((double)this.listWidth + 30, (double)p_22239_1_, 0.0D, (double)((float)(this.listWidth + 30) / var6), (double)((float)p_22239_1_ / var6));
var5.func_78374_a(0.0D, (double)p_22239_1_, 0.0D, 0.0D, (double)((float)p_22239_1_ / var6));
var5.func_78381_a();
}
}
@@ -0,0 +1,88 @@
/*
* The FML Forge Mod Loader suite.
* Copyright (C) 2012 cpw
*
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package cpw.mods.fml.client;
import java.util.ArrayList;
import net.minecraft.src.Tessellator;
import cpw.mods.fml.common.Loader;
import cpw.mods.fml.common.LoaderState.ModState;
import cpw.mods.fml.common.ModContainer;
/**
* @author cpw
*
*/
public class GuiSlotModList extends GuiScrollingList
{
private GuiModList parent;
private ArrayList<ModContainer> mods;
public GuiSlotModList(GuiModList parent, ArrayList<ModContainer> mods, int listWidth)
{
super(parent.getMinecraftInstance(), listWidth, parent.field_73881_g, 32, parent.field_73881_g - 65 + 4, 10, 35);
this.parent=parent;
this.mods=mods;
}
@Override
protected int getSize()
{
return mods.size();
}
@Override
protected void elementClicked(int var1, boolean var2)
{
this.parent.selectModIndex(var1);
}
@Override
protected boolean isSelected(int var1)
{
return this.parent.modIndexSelected(var1);
}
@Override
protected void drawBackground()
{
this.parent.func_73873_v_();
}
@Override
protected int getContentHeight()
{
return (this.getSize()) * 35 + 1;
}
@Override
protected void drawSlot(int listIndex, int var2, int var3, int var4, Tessellator var5)
{
ModContainer mc=mods.get(listIndex);
if (Loader.instance().getModState(mc)==ModState.DISABLED)
{
this.parent.getFontRenderer().func_78276_b(this.parent.getFontRenderer().func_78269_a(mc.getName(), listWidth - 10), this.left + 3 , var3 + 2, 0xFF2222);
this.parent.getFontRenderer().func_78276_b(this.parent.getFontRenderer().func_78269_a(mc.getDisplayVersion(), listWidth - 10), this.left + 3 , var3 + 12, 0xFF2222);
this.parent.getFontRenderer().func_78276_b(this.parent.getFontRenderer().func_78269_a("DISABLED", listWidth - 10), this.left + 3 , var3 + 22, 0xFF2222);
}
else
{
this.parent.getFontRenderer().func_78276_b(this.parent.getFontRenderer().func_78269_a(mc.getName(), listWidth - 10), this.left + 3 , var3 + 2, 0xFFFFFF);
this.parent.getFontRenderer().func_78276_b(this.parent.getFontRenderer().func_78269_a(mc.getDisplayVersion(), listWidth - 10), this.left + 3 , var3 + 12, 0xCCCCCC);
this.parent.getFontRenderer().func_78276_b(this.parent.getFontRenderer().func_78269_a(mc.getMetadata() !=null ? mc.getMetadata().getChildModCountString() : "Metadata not found", listWidth - 10), this.left + 3 , var3 + 22, 0xCCCCCC);
}
}
}
@@ -0,0 +1,31 @@
/*
* The FML Forge Mod Loader suite.
* Copyright (C) 2012 cpw
*
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package cpw.mods.fml.client;
import java.awt.Dimension;
import net.minecraft.src.RenderEngine;
import net.minecraft.src.TexturePackBase;
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,142 @@
/*
* The FML Forge Mod Loader suite.
* Copyright (C) 2012 cpw
*
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package cpw.mods.fml.client;
import java.util.BitSet;
import java.util.HashMap;
import java.util.logging.Level;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.FMLLog;
/**
* @author cpw
*
*/
public class SpriteHelper
{
private static HashMap<String, BitSet> spriteInfo = new HashMap<String, BitSet>();
private static void initMCSpriteMaps() {
BitSet slots =
SpriteHelper.toBitSet(
"0000000000000000" +
"0000000000110000" +
"0000000001100000" +
"0000000001100000" +
"0000000000000000" +
"0000000000000000" +
"0000000000000000" +
"0000000000000000" +
"0000000000000000" +
"0000000000000000" +
"0000000000000000" +
"0000000011111111" +
"0000000011111000" +
"0000000111111100" +
"0000000111111000" +
"0000000000000000");
spriteInfo.put("/terrain.png", slots);
slots = SpriteHelper.toBitSet(
"0000000000000000" +
"0000000000000000" +
"0000000000000000" +
"0000000000000000" +
"0000000000000000" +
"0000000000000000" +
"0000001000000000" +
"0000001110000000" +
"0000001000000000" +
"1111101010000000" +
"1111101010000000" +
"1111101110000000" +
"1111111111110000" +
"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,340 @@
package cpw.mods.fml.client;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_BINDING_2D;
import java.awt.Dimension;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import javax.imageio.ImageIO;
import net.minecraft.client.Minecraft;
import net.minecraft.src.ModTextureStatic;
import net.minecraft.src.RenderEngine;
import net.minecraft.src.TextureFX;
import net.minecraft.src.TexturePackBase;
import org.lwjgl.opengl.GL11;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.FMLLog;
import cpw.mods.fml.common.ModContainer;
public class TextureFXManager
{
private static final TextureFXManager INSTANCE = new TextureFXManager();
private class TextureProperties
{
private int textureId;
private Dimension dim;
}
private Map<Integer,TextureProperties> textureProperties = Maps.newHashMap();
private Multimap<String, OverrideInfo> overrideInfo = ArrayListMultimap.create();
private HashSet<OverrideInfo> animationSet = new HashSet<OverrideInfo>();
private List<TextureFX> addedTextureFX = new ArrayList<TextureFX>();
private Minecraft client;
void setClient(Minecraft client)
{
this.client = client;
}
public boolean onUpdateTextureEffect(TextureFX effect)
{
ITextureFX ifx = (effect instanceof ITextureFX ? ((ITextureFX)effect) : null);
if (ifx != null && ifx.getErrored())
{
return false;
}
String name = effect.getClass().getSimpleName();
client.field_71424_I.func_76320_a(name);
try
{
if (!FMLClientHandler.instance().hasOptifine())
{
effect.func_76846_a();
}
}
catch (Exception e)
{
FMLLog.warning("Texture FX %s has failed to animate. Likely caused by a texture pack change that they did not respond correctly to", name);
if (ifx != null)
{
ifx.setErrored(true);
}
client.field_71424_I.func_76319_b();
return false;
}
client.field_71424_I.func_76319_b();
if (ifx != null)
{
Dimension dim = getTextureDimensions(effect);
int target = ((dim.width >> 4) * (dim.height >> 4)) << 2;
if (effect.field_76852_a.length != target)
{
FMLLog.warning("Detected a texture FX sizing discrepancy in %s (%d, %d)", name, effect.field_76852_a.length, target);
ifx.setErrored(true);
return false;
}
}
return true;
}
//Quick and dirty image scaling, no smoothing or fanciness, meant for speed as it will be called every tick.
public void scaleTextureFXData(byte[] data, ByteBuffer buf, int target, int length)
{
int sWidth = (int)Math.sqrt(data.length / 4);
int factor = target / sWidth;
byte[] tmp = new byte[4];
buf.clear();
if (factor > 1)
{
for (int y = 0; y < sWidth; y++)
{
int sRowOff = sWidth * y;
int tRowOff = target * y * factor;
for (int x = 0; x < sWidth; x++)
{
int sPos = (x + sRowOff) * 4;
tmp[0] = data[sPos + 0];
tmp[1] = data[sPos + 1];
tmp[2] = data[sPos + 2];
tmp[3] = data[sPos + 3];
int tPosTop = (x * factor) + tRowOff;
for (int y2 = 0; y2 < factor; y2++)
{
buf.position((tPosTop + (y2 * target)) * 4);
for (int x2 = 0; x2 < factor; x2++)
{
buf.put(tmp);
}
}
}
}
}
buf.position(0).limit(length);
}
public void onPreRegisterEffect(TextureFX effect)
{
Dimension dim = getTextureDimensions(effect);
if (effect instanceof ITextureFX)
{
((ITextureFX)effect).onTextureDimensionsUpdate(dim.width, dim.height);
}
}
public int getEffectTexture(TextureFX effect)
{
Integer id = effectTextures.get(effect);
if (id != null)
{
return id;
}
int old = GL11.glGetInteger(GL_TEXTURE_BINDING_2D);
effect.func_76845_a(client.field_71446_o);
id = GL11.glGetInteger(GL_TEXTURE_BINDING_2D);
GL11.glBindTexture(GL_TEXTURE_2D, old);
effectTextures.put(effect, id);
return id;
}
public void onTexturePackChange(RenderEngine engine, 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 (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
*/
protected 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,83 @@
/*
* The FML Forge Mod Loader suite.
* Copyright (C) 2012 cpw
*
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package cpw.mods.fml.client.modloader;
import net.minecraft.src.BaseMod;
import net.minecraft.src.Block;
import net.minecraft.src.IBlockAccess;
import net.minecraft.src.RenderBlocks;
import cpw.mods.fml.client.registry.ISimpleBlockRenderingHandler;
/**
* @author cpw
*
*/
public class ModLoaderBlockRendererHandler implements ISimpleBlockRenderingHandler
{
private int renderId;
private boolean render3dInInventory;
private BaseMod mod;
/**
* @param mod
*
*/
public ModLoaderBlockRendererHandler(int renderId, boolean render3dInInventory, BaseMod mod)
{
this.renderId=renderId;
this.render3dInInventory=render3dInInventory;
this.mod=mod;
}
@Override
public int getRenderId()
{
return renderId;
}
@Override
public boolean shouldRender3DInInventory()
{
return render3dInInventory;
}
/**
* @param world
* @param x
* @param y
* @param z
* @param block
* @param modelId
* @param renderer
*/
@Override
public boolean renderWorldBlock(IBlockAccess world, int x, int y, int z, Block block, int modelId, RenderBlocks renderer)
{
return mod.renderWorldBlock(renderer, world, x, y, z, block, modelId);
}
/**
* @param block
* @param metadata
* @param modelID
* @param renderer
*/
@Override
public void renderInventoryBlock(Block block, int metadata, int modelID, RenderBlocks renderer)
{
mod.renderInvBlock(renderer, block, metadata, modelID);
}
}
@@ -0,0 +1,159 @@
package cpw.mods.fml.client.modloader;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Map.Entry;
import java.util.logging.Level;
import net.minecraft.client.Minecraft;
import net.minecraft.src.BaseMod;
import net.minecraft.src.Entity;
import net.minecraft.src.EntityClientPlayerMP;
import net.minecraft.src.EntityPlayer;
import net.minecraft.src.KeyBinding;
import net.minecraft.src.Packet250CustomPayload;
import net.minecraft.src.Render;
import net.minecraft.src.RenderManager;
import com.google.common.base.Equivalences;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.Iterables;
import com.google.common.collect.Iterators;
import com.google.common.collect.MapDifference;
import com.google.common.collect.MapDifference.ValueDifference;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps;
import cpw.mods.fml.client.FMLClientHandler;
import cpw.mods.fml.client.registry.KeyBindingRegistry;
import cpw.mods.fml.client.registry.RenderingRegistry;
import cpw.mods.fml.common.FMLLog;
import cpw.mods.fml.common.Loader;
import cpw.mods.fml.common.modloader.BaseModProxy;
import cpw.mods.fml.common.modloader.IModLoaderSidedHelper;
import cpw.mods.fml.common.modloader.ModLoaderHelper;
import cpw.mods.fml.common.modloader.ModLoaderModContainer;
import cpw.mods.fml.common.network.EntitySpawnPacket;
import cpw.mods.fml.common.registry.EntityRegistry.EntityRegistration;
public class ModLoaderClientHelper implements IModLoaderSidedHelper
{
/**
* @param mod
* @param inventoryRenderer
* @return
*/
public static int obtainBlockModelIdFor(BaseMod mod, boolean inventoryRenderer)
{
int renderId=RenderingRegistry.getNextAvailableRenderId();
ModLoaderBlockRendererHandler bri=new ModLoaderBlockRendererHandler(renderId, inventoryRenderer, mod);
RenderingRegistry.registerBlockHandler(bri);
return renderId;
}
public static void handleFinishLoadingFor(ModLoaderModContainer mc, Minecraft game)
{
FMLLog.finer("Handling post startup activities for ModLoader mod %s", mc.getModId());
BaseMod mod = (BaseMod) mc.getMod();
Map<Class<? extends Entity>, Render> renderers = Maps.newHashMap(RenderManager.field_78727_a.field_78729_o);
try
{
FMLLog.finest("Requesting renderers from basemod %s", mc.getModId());
mod.addRenderer(renderers);
FMLLog.finest("Received %d renderers from basemod %s", renderers.size(), mc.getModId());
}
catch (Exception e)
{
FMLLog.log(Level.SEVERE, e, "A severe problem was detected with the mod %s during the addRenderer call. Continuing, but expect odd results", mc.getModId());
}
MapDifference<Class<? extends Entity>, Render> difference = Maps.difference(RenderManager.field_78727_a.field_78729_o, renderers, Equivalences.identity());
for ( Entry<Class<? extends Entity>, Render> e : difference.entriesOnlyOnLeft().entrySet())
{
FMLLog.warning("The mod %s attempted to remove an entity renderer %s from the entity map. This will be ignored.", mc.getModId(), e.getKey().getName());
}
for (Entry<Class<? extends Entity>, Render> e : difference.entriesOnlyOnRight().entrySet())
{
FMLLog.finest("Registering ModLoader entity renderer %s as instance of %s", e.getKey().getName(), e.getValue().getClass().getName());
RenderingRegistry.registerEntityRenderingHandler(e.getKey(), e.getValue());
}
for (Entry<Class<? extends Entity>, ValueDifference<Render>> e : difference.entriesDiffering().entrySet())
{
FMLLog.finest("Registering ModLoader entity rendering override for %s as instance of %s", e.getKey().getName(), e.getValue().rightValue().getClass().getName());
RenderingRegistry.registerEntityRenderingHandler(e.getKey(), e.getValue().rightValue());
}
try
{
mod.registerAnimation(game);
}
catch (Exception e)
{
FMLLog.log(Level.SEVERE, e, "A severe problem was detected with the mod %s during the registerAnimation call. Continuing, but expect odd results", mc.getModId());
}
}
public ModLoaderClientHelper(Minecraft client)
{
this.client = client;
ModLoaderHelper.sidedHelper = this;
keyBindingContainers = Multimaps.newMultimap(Maps.<ModLoaderModContainer, Collection<ModLoaderKeyBindingHandler>>newHashMap(), new Supplier<Collection<ModLoaderKeyBindingHandler>>()
{
@Override
public Collection<ModLoaderKeyBindingHandler> get()
{
return Collections.singleton(new ModLoaderKeyBindingHandler());
}
});
}
private Minecraft client;
private static Multimap<ModLoaderModContainer, ModLoaderKeyBindingHandler> keyBindingContainers;
@Override
public void finishModLoading(ModLoaderModContainer mc)
{
handleFinishLoadingFor(mc, client);
}
public static void registerKeyBinding(BaseModProxy mod, KeyBinding keyHandler, boolean allowRepeat)
{
ModLoaderModContainer mlmc = (ModLoaderModContainer) Loader.instance().activeModContainer();
ModLoaderKeyBindingHandler handler = Iterables.getOnlyElement(keyBindingContainers.get(mlmc));
handler.setModContainer(mlmc);
handler.addKeyBinding(keyHandler, allowRepeat);
KeyBindingRegistry.registerKeyBinding(handler);
}
@Override
public Object getClientGui(BaseModProxy mod, EntityPlayer player, int ID, int x, int y, int z)
{
return ((net.minecraft.src.BaseMod)mod).getContainerGUI((EntityClientPlayerMP) player, ID, x, y, z);
}
@Override
public Entity spawnEntity(BaseModProxy mod, EntitySpawnPacket input, EntityRegistration er)
{
return ((net.minecraft.src.BaseMod)mod).spawnEntity(er.getModEntityId(), client.field_71441_e, input.scaledX, input.scaledY, input.scaledZ);
}
@Override
public void sendClientPacket(BaseModProxy mod, Packet250CustomPayload packet)
{
((net.minecraft.src.BaseMod)mod).clientCustomPayload(client.field_71439_g.field_71174_a, packet);
}
}
@@ -0,0 +1,115 @@
/*
* The FML Forge Mod Loader suite.
* Copyright (C) 2012 cpw
*
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package cpw.mods.fml.client.modloader;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.List;
import org.lwjgl.input.Mouse;
import com.google.common.collect.ObjectArrays;
import com.google.common.primitives.Booleans;
import net.minecraft.src.KeyBinding;
import cpw.mods.fml.client.registry.KeyBindingRegistry;
import cpw.mods.fml.common.TickType;
import cpw.mods.fml.common.modloader.ModLoaderModContainer;
/**
* @author cpw
*
*/
public class ModLoaderKeyBindingHandler extends KeyBindingRegistry.KeyHandler
{
private ModLoaderModContainer modContainer;
private List<KeyBinding> helper;
private boolean[] active = new boolean[0];
private boolean[] mlRepeats = new boolean[0];
private boolean[] armed = new boolean[0];
/**
* @param keyHandler
*/
public ModLoaderKeyBindingHandler()
{
super(new KeyBinding[0], new boolean[0]);
}
void setModContainer(ModLoaderModContainer modContainer)
{
this.modContainer = modContainer;
}
public void fireKeyEvent(KeyBinding kb)
{
((net.minecraft.src.BaseMod)modContainer.getMod()).keyboardEvent(kb);
}
@Override
public void keyDown(EnumSet<TickType> type, KeyBinding kb, boolean end, boolean repeats)
{
if (!end)
{
return;
}
int idx = helper.indexOf(kb);
if (type.contains(TickType.CLIENT))
{
armed[idx] = true;
}
if (armed[idx] && type.contains(TickType.RENDER) && (!active[idx] || mlRepeats[idx]))
{
fireKeyEvent(kb);
active[idx] = true;
armed[idx] = false;
}
}
@Override
public void keyUp(EnumSet<TickType> type, KeyBinding kb, boolean end)
{
if (!end)
{
return;
}
int idx = helper.indexOf(kb);
active[idx] = false;
}
@Override
public EnumSet<TickType> ticks()
{
return EnumSet.of(TickType.CLIENT, TickType.RENDER);
}
@Override
public String getLabel()
{
return modContainer.getModId() +" KB "+keyBindings[0].field_74512_d;
}
void addKeyBinding(KeyBinding binding, boolean repeats)
{
this.keyBindings = ObjectArrays.concat(this.keyBindings, binding);
this.repeatings = new boolean[this.keyBindings.length];
Arrays.fill(this.repeatings, true);
this.active = new boolean[this.keyBindings.length];
this.armed = new boolean[this.keyBindings.length];
this.mlRepeats = Booleans.concat(this.mlRepeats, new boolean[] { repeats });
this.keyDown = new boolean[this.keyBindings.length];
this.helper = Arrays.asList(this.keyBindings);
}
}
@@ -0,0 +1,29 @@
package cpw.mods.fml.client.registry;
import net.minecraft.src.TileEntity;
import net.minecraft.src.TileEntityRenderer;
import net.minecraft.src.TileEntitySpecialRenderer;
import cpw.mods.fml.common.registry.GameRegistry;
public class ClientRegistry
{
/**
*
* Utility method for registering a tile entity and it's renderer at once - generally you should register them separately
*
* @param tileEntityClass
* @param id
* @param specialRenderer
*/
public static void registerTileEntity(Class <? extends TileEntity > tileEntityClass, String id, TileEntitySpecialRenderer specialRenderer)
{
GameRegistry.registerTileEntity(tileEntityClass, id);
bindTileEntitySpecialRenderer(tileEntityClass, specialRenderer);
}
public static void bindTileEntitySpecialRenderer(Class <? extends TileEntity> tileEntityClass, TileEntitySpecialRenderer specialRenderer)
{
TileEntityRenderer.field_76963_a.field_76966_m.put(tileEntityClass, specialRenderer);
specialRenderer.func_76893_a(TileEntityRenderer.field_76963_a);
}
}
@@ -0,0 +1,16 @@
package cpw.mods.fml.client.registry;
import net.minecraft.src.Block;
import net.minecraft.src.IBlockAccess;
import net.minecraft.src.RenderBlocks;
public interface ISimpleBlockRenderingHandler
{
public abstract void renderInventoryBlock(Block block, int metadata, int modelID, RenderBlocks renderer);
public abstract boolean renderWorldBlock(IBlockAccess world, int x, int y, int z, Block block, int modelId, RenderBlocks renderer);
public abstract boolean shouldRender3DInInventory();
public abstract int getRenderId();
}
@@ -0,0 +1,187 @@
package cpw.mods.fml.client.registry;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.Set;
import net.minecraft.src.GameSettings;
import net.minecraft.src.KeyBinding;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import cpw.mods.fml.common.ITickHandler;
import cpw.mods.fml.common.Side;
import cpw.mods.fml.common.TickType;
import cpw.mods.fml.common.registry.TickRegistry;
public class KeyBindingRegistry
{
/**
* Register a KeyHandler to the game. This handler will be called on certain tick events
* if any of its key is inactive or has recently changed state
*
* @param handler
*/
public static void registerKeyBinding(KeyHandler handler) {
instance().keyHandlers.add(handler);
if (!handler.isDummy)
{
TickRegistry.registerTickHandler(handler, Side.CLIENT);
}
}
/**
* Extend this class to register a KeyBinding and recieve callback
* when the key binding is triggered
*
* @author cpw
*
*/
public static abstract class KeyHandler implements ITickHandler
{
protected KeyBinding[] keyBindings;
protected boolean[] keyDown;
protected boolean[] repeatings;
private boolean isDummy;
/**
* Pass an array of keybindings and a repeat flag for each one
*
* @param keyBindings
* @param repeatings
*/
public KeyHandler(KeyBinding[] keyBindings, boolean[] repeatings)
{
assert keyBindings.length == repeatings.length : "You need to pass two arrays of identical length";
this.keyBindings = keyBindings;
this.repeatings = repeatings;
this.keyDown = new boolean[keyBindings.length];
}
/**
* Register the keys into the system. You will do your own keyboard management elsewhere. No events will fire
* if you use this method
*
* @param keyBindings
*/
public KeyHandler(KeyBinding[] keyBindings)
{
this.keyBindings = keyBindings;
this.isDummy = true;
}
public KeyBinding[] getKeyBindings()
{
return this.keyBindings;
}
/**
* Not to be overridden - KeyBindings are tickhandlers under the covers
*/
@Override
public final void tickStart(EnumSet<TickType> type, Object... tickData)
{
keyTick(type, false);
}
/**
* Not to be overridden - KeyBindings are tickhandlers under the covers
*/
@Override
public final void tickEnd(EnumSet<TickType> type, Object... tickData)
{
keyTick(type, true);
}
private void keyTick(EnumSet<TickType> type, boolean tickEnd)
{
for (int i = 0; i < keyBindings.length; i++)
{
KeyBinding keyBinding = keyBindings[i];
int keyCode = keyBinding.field_74512_d;
boolean state = (keyCode < 0 ? Mouse.isButtonDown(keyCode + 100) : Keyboard.isKeyDown(keyCode));
if (state != keyDown[i] || (state && repeatings[i]))
{
if (state)
{
keyDown(type, keyBinding, tickEnd, state!=keyDown[i]);
}
else
{
keyUp(type, keyBinding, tickEnd);
}
if (tickEnd)
{
keyDown[i] = state;
}
}
}
}
/**
* Called when the key is first in the down position on any tick from the {@link #ticks()}
* set. Will be called subsequently with isRepeat set to true
*
* @see #keyUp(EnumSet, boolean)
*
* @param types the type(s) of tick that fired when this key was first down
* @param tickEnd was it an end or start tick which fired the key
* @param isRepeat is it a repeat key event
*/
public abstract void keyDown(EnumSet<TickType> types, KeyBinding kb, boolean tickEnd, boolean isRepeat);
/**
* Fired once when the key changes state from down to up
*
* @see #keyDown(EnumSet, boolean, boolean)
*
* @param types the type(s) of tick that fired when this key was first down
* @param tickEnd was it an end or start tick which fired the key
*/
public abstract void keyUp(EnumSet<TickType> types, KeyBinding kb, boolean tickEnd);
/**
* This is the list of ticks for which the key binding should trigger. The only
* valid ticks are client side ticks, obviously.
*
* @see cpw.mods.fml.common.ITickHandler#ticks()
*/
public abstract EnumSet<TickType> ticks();
}
private static final KeyBindingRegistry INSTANCE = new KeyBindingRegistry();
private Set<KeyHandler> keyHandlers = Sets.newLinkedHashSet();
@Deprecated
public static KeyBindingRegistry instance()
{
return INSTANCE;
}
public void uploadKeyBindingsToGame(GameSettings settings)
{
ArrayList<KeyBinding> harvestedBindings = Lists.newArrayList();
for (KeyHandler key : keyHandlers)
{
for (KeyBinding kb : key.keyBindings)
{
harvestedBindings.add(kb);
}
}
KeyBinding[] modKeyBindings = harvestedBindings.toArray(new KeyBinding[harvestedBindings.size()]);
KeyBinding[] allKeys = new KeyBinding[settings.field_74324_K.length + modKeyBindings.length];
System.arraycopy(settings.field_74324_K, 0, allKeys, 0, settings.field_74324_K.length);
System.arraycopy(modKeyBindings, 0, allKeys, settings.field_74324_K.length, modKeyBindings.length);
settings.field_74324_K = allKeys;
settings.func_74300_a();
}
}
@@ -0,0 +1,192 @@
package cpw.mods.fml.client.registry;
import java.util.List;
import java.util.Map;
import net.minecraft.src.Block;
import net.minecraft.src.Entity;
import net.minecraft.src.IBlockAccess;
import net.minecraft.src.Render;
import net.minecraft.src.RenderBlocks;
import net.minecraft.src.RenderManager;
import net.minecraft.src.RenderPlayer;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.ObjectArrays;
import cpw.mods.fml.client.SpriteHelper;
import cpw.mods.fml.client.TextureFXManager;
/**
* @author cpw
*
*/
public class RenderingRegistry
{
private static final RenderingRegistry INSTANCE = new RenderingRegistry();
private int nextRenderId = 32;
private Map<Integer, ISimpleBlockRenderingHandler> blockRenderers = Maps.newHashMap();
private List<EntityRendererInfo> entityRenderers = Lists.newArrayList();
/**
* Add a new armour prefix to the RenderPlayer
*
* @param armor
* @return
*/
public static int addNewArmourRendererPrefix(String armor)
{
RenderPlayer.field_77110_j = ObjectArrays.concat(RenderPlayer.field_77110_j, armor);
return RenderPlayer.field_77110_j.length - 1;
}
/**
* Register an entity rendering handler. This will, after mod initialization, be inserted into the main
* render map for entities
*
* @param entityClass
* @param renderer
*/
public static void registerEntityRenderingHandler(Class<? extends Entity> entityClass, Render renderer)
{
instance().entityRenderers.add(new EntityRendererInfo(entityClass, renderer));
}
/**
* Register a simple block rendering handler
*
* @param handler
*/
public static void registerBlockHandler(ISimpleBlockRenderingHandler handler)
{
instance().blockRenderers.put(handler.getRenderId(), handler);
}
/**
* Register the simple block rendering handler
* This version will not call getRenderId on the passed in handler, instead using the supplied ID, so you
* can easily re-use the same rendering handler for multiple IDs
*
* @param renderId
* @param handler
*/
public static void registerBlockHandler(int renderId, ISimpleBlockRenderingHandler handler)
{
instance().blockRenderers.put(renderId, handler);
}
/**
* Get the next available renderId from the block render ID list
*
* @return
*/
public static int getNextAvailableRenderId()
{
return instance().nextRenderId++;
}
/**
* Add a texture override for the given path and return the used index
*
* @param fileToOverride
* @param fileToAdd
* @return
*/
public static int addTextureOverride(String fileToOverride, String fileToAdd)
{
int idx = SpriteHelper.getUniqueSpriteIndex(fileToOverride);
addTextureOverride(fileToOverride, fileToAdd, idx);
return idx;
}
/**
* Add a texture override for the given path and index
*
* @param path
* @param overlayPath
* @param index
*/
public static void addTextureOverride(String path, String overlayPath, int index)
{
TextureFXManager.instance().addNewTextureOverride(path, overlayPath, index);
}
/**
* Get and reserve a unique texture index for the supplied path
*
* @param path
* @return
*/
public static int getUniqueTextureIndex(String path)
{
return SpriteHelper.getUniqueSpriteIndex(path);
}
@Deprecated public static RenderingRegistry instance()
{
return INSTANCE;
}
private static class EntityRendererInfo
{
public EntityRendererInfo(Class<? extends Entity> target, Render renderer)
{
this.target = target;
this.renderer = renderer;
}
private Class<? extends Entity> target;
private Render renderer;
}
/**
* @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);
info.renderer.func_76976_a(RenderManager.field_78727_a);
}
}
}
+462
View File
@@ -0,0 +1,462 @@
/*
* The FML Forge Mod Loader suite. Copyright (C) 2012 cpw
*
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraft.src;
import static cpw.mods.fml.common.Side.CLIENT;
import java.util.Map;
import java.util.Random;
import net.minecraft.client.Minecraft;
import net.minecraft.server.MinecraftServer;
import cpw.mods.fml.client.FMLClientHandler;
import cpw.mods.fml.common.FMLLog;
import cpw.mods.fml.common.TickType;
import cpw.mods.fml.common.asm.SideOnly;
public abstract class BaseMod implements cpw.mods.fml.common.modloader.BaseModProxy
{
// CALLBACK MECHANISMS
public final boolean doTickInGame(TickType tick, boolean tickEnd, Object... data)
{
Minecraft mc = FMLClientHandler.instance().getClient();
boolean hasWorld = mc.field_71441_e != null;
// World and render ticks
if (tickEnd && ( tick==TickType.RENDER || tick==TickType.CLIENT ) && hasWorld) {
return onTickInGame((Float) data[0], mc);
}
return true;
}
public final boolean doTickInGUI(TickType tick, boolean tickEnd, Object... data)
{
Minecraft mc = FMLClientHandler.instance().getClient();
boolean hasWorld = mc.field_71441_e != null;
if (tickEnd && ( tick==TickType.RENDER || ( tick==TickType.CLIENT && hasWorld))) {
return onTickInGUI((Float) data[0], mc, mc.field_71462_r);
}
return true;
}
/**
* @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;
}
@SideOnly(CLIENT)
public void addRenderer(Map<Class<? extends Entity>, Render> renderers)
{
}
/**
* Override if you wish to perform some action other than just dispensing the item from the dispenser
*
* @param world
* @param x
* @param y
* @param z
* @param xVel
* @param zVel
* @param item
* @return
*/
@Override
public int dispenseEntity(World world, ItemStack item, Random rnd, int x, int y, int z, int xVel, int zVel, double entX, double entY, double entZ)
{
return -1;
}
/**
* Override if you wish to generate Nether (Hell biome) blocks
*
* @param world
* @param random
* @param chunkX
* @param chunkZ
*/
public void generateNether(World world, Random random, int chunkX, int chunkZ)
{
}
/**
* Override if you wish to generate Overworld (not hell or the end) blocks
*
* @param world
* @param random
* @param chunkX
* @param chunkZ
*/
public void generateSurface(World world, Random random, int chunkX, int chunkZ)
{
}
/**
* Callback to return a gui screen to display
* @param player
* @param containerID
* @param x
* @param y
* @param z
* @return
*/
@SideOnly(CLIENT)
public GuiContainer getContainerGUI(EntityClientPlayerMP player, int containerID, int x, int y, int z)
{
return null;
}
/**
* Return the name of your mod. Defaults to the class name
*
* @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();
@SideOnly(CLIENT)
public void keyboardEvent(KeyBinding event)
{
}
/**
* Load your mod
*/
public abstract void load();
/**
* Finish loading your mod
*/
public void modsLoaded()
{
}
/**
* Handle item pickup
*
* @param player
* @param item
*/
public void onItemPickup(EntityPlayer player, ItemStack item)
{
}
/**
* Ticked every game tick if you have subscribed to tick events through {@link ModLoader#setInGameHook(BaseMod, boolean, boolean)}
*
* @param time the rendering subtick time (0.0-1.0)
* @param minecraftInstance the client
* @return true to continue receiving ticks
*/
@SideOnly(CLIENT)
public boolean onTickInGame(float time, Minecraft minecraftInstance)
{
return false;
}
public boolean onTickInGame(MinecraftServer minecraftServer)
{
return false;
}
@SideOnly(CLIENT)
public boolean onTickInGUI(float tick, Minecraft game, GuiScreen gui)
{
return false;
}
/**
* Only implemented on the client side
* {@link #serverChat(EntityPlayer, Packet3Chat)}
*
* @param text
*/
@Override
public void clientChat(String text)
{
// TODO
}
/**
* Called client side to receive a custom payload for this mod
*
* @param packet
*/
@Override
public void receiveCustomPacket(Packet250CustomPayload packet)
{
// TODO
}
@SideOnly(CLIENT)
public void registerAnimation(Minecraft game)
{
}
@SideOnly(CLIENT)
public void renderInvBlock(RenderBlocks renderer, Block block, int metadata, int modelID)
{
}
@SideOnly(CLIENT)
public boolean renderWorldBlock(RenderBlocks renderer, IBlockAccess world, int x, int y, int z, Block block, int modelID)
{
return false;
}
@Override
public void serverConnect(NetHandler handler) {
}
@Override
public void serverCustomPayload(NetServerHandler handler, Packet250CustomPayload packet)
{
}
@Override
public void serverDisconnect() {
}
/**
* Called when someone crafts an item from a crafting table
*
* @param player
* @param item
* @param matrix
*/
public void takenFromCrafting(EntityPlayer player, ItemStack item, IInventory matrix)
{
}
/**
* Called when someone takes a smelted item from a furnace
*
* @param player
* @param item
*/
public void takenFromFurnace(EntityPlayer player, ItemStack item)
{
}
/**
* The identifier string for the mod- used in client<->server negotiation
*/
@Override
public String toString()
{
return getName() + " " + getVersion();
}
/**
* Called when a chat message is received. Return true to stop further processing
*
* @param source
* @param chat
* @return true if you want to consume the message so it is not available for further processing
*/
@Override
public void serverChat(NetServerHandler source, String message)
{
}
/**
* Called when a new client logs in.
*
* @param player
*/
@Override
public void onClientLogin(EntityPlayer player)
{
}
/**
* Called when a client logs out of the server.
*
* @param player
*/
@Override
public void onClientLogout(NetworkManager mgr)
{
}
/**
*
* Spawn the entity of the supplied type, if it is your mod's
* @param entityId
* @param world
* @param scaledX
* @param scaledY
* @param scaledZ
* @return
*/
@SideOnly(CLIENT)
public Entity spawnEntity(int entityId, World world, double scaledX, double scaledY, double scaledZ)
{
return null;
}
public void clientCustomPayload(NetClientHandler handler, Packet250CustomPayload packet)
{
}
}
@@ -0,0 +1,36 @@
/*
* The FML Forge Mod Loader suite.
* Copyright (C) 2012 cpw
*
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraft.src;
import net.minecraft.client.Minecraft;
public class EntityRendererProxy extends EntityRenderer
{
public static final String fmlMarker = "This is an FML marker";
private Minecraft game;
public EntityRendererProxy(Minecraft minecraft)
{
super(minecraft);
game = minecraft;
}
@Override
public void func_78480_b(float tick)
{
super.func_78480_b(tick);
//This is where ModLoader does all of it's ticking
}
}
@@ -0,0 +1,92 @@
/*
* The FML Forge Mod Loader suite.
* Copyright (C) 2012 cpw
*
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraft.src;
import java.awt.Dimension;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import cpw.mods.fml.client.TextureFXManager;
import cpw.mods.fml.client.registry.RenderingRegistry;
import cpw.mods.fml.common.FMLLog;
/**
*
* A static hook library for optifine and other basemod editing code to access FML functions
*
* @author cpw
*
*/
public class FMLRenderAccessLibrary
{
public static Logger getLogger()
{
return FMLLog.getLogger();
}
public static void log(Level level, String message)
{
FMLLog.log(level, message);
}
public static void log(Level level, String message, Throwable throwable)
{
FMLLog.log(level, throwable, message);
}
public static void setTextureDimensions(int textureId, int width, int height, List<TextureFX> textureFXList)
{
TextureFXManager.instance().setTextureDimensions(textureId, width, height, textureFXList);
}
public static void preRegisterEffect(TextureFX textureFX)
{
TextureFXManager.instance().onPreRegisterEffect(textureFX);
}
public static boolean onUpdateTextureEffect(TextureFX textureFX)
{
return TextureFXManager.instance().onUpdateTextureEffect(textureFX);
}
public static Dimension getTextureDimensions(TextureFX textureFX)
{
return TextureFXManager.instance().getTextureDimensions(textureFX);
}
public static void onTexturePackChange(RenderEngine engine, TexturePackBase texturePack, List<TextureFX> textureFXList)
{
TextureFXManager.instance().onTexturePackChange(engine, texturePack, textureFXList);
}
@SuppressWarnings("deprecation")
public static boolean renderWorldBlock(RenderBlocks renderer, IBlockAccess world, int x, int y, int z, Block block, int modelId)
{
return RenderingRegistry.instance().renderWorldBlock(renderer, world, x, y, z, block, modelId);
}
@SuppressWarnings("deprecation")
public static void renderInventoryBlock(RenderBlocks renderer, Block block, int metadata, int modelID)
{
RenderingRegistry.instance().renderInventoryBlock(renderer, block, metadata, modelID);
}
@SuppressWarnings("deprecation")
public static boolean renderItemAsFull3DBlock(int modelId)
{
return RenderingRegistry.instance().renderItemAsFull3DBlock(modelId);
}
}
+49
View File
@@ -0,0 +1,49 @@
/*
* The FML Forge Mod Loader suite. Copyright (C) 2012 cpw
*
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraft.src;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
/**
* @author cpw
*
*/
@Retention(value = RUNTIME)
@Target(value = FIELD)
public @interface MLProp
{
/**
* Adds additional help to top of configuration file.
*/
String info() default "";
/**
* Maximum value allowed if field is a number.
*/
double max() default Double.MAX_VALUE;
/**
* Minimum value allowed if field is a number.
*/
double min() default Double.MIN_VALUE;
/**
* Overrides the field name for property key.
*/
String name() default "";
}
+875
View File
@@ -0,0 +1,875 @@
/*
* The FML Forge Mod Loader suite. Copyright (C) 2012 cpw
*
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraft.src;
import static cpw.mods.fml.common.Side.CLIENT;
import java.awt.image.BufferedImage;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import net.minecraft.client.Minecraft;
import net.minecraft.server.MinecraftServer;
import cpw.mods.fml.client.FMLClientHandler;
import cpw.mods.fml.client.SpriteHelper;
import cpw.mods.fml.client.TextureFXManager;
import cpw.mods.fml.client.modloader.ModLoaderClientHelper;
import cpw.mods.fml.client.modloader.ModLoaderKeyBindingHandler;
import cpw.mods.fml.client.registry.ClientRegistry;
import cpw.mods.fml.client.registry.KeyBindingRegistry;
import cpw.mods.fml.client.registry.RenderingRegistry;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.FMLLog;
import cpw.mods.fml.common.Loader;
import cpw.mods.fml.common.ObfuscationReflectionHelper;
import cpw.mods.fml.common.asm.SideOnly;
import cpw.mods.fml.common.modloader.ModLoaderHelper;
import cpw.mods.fml.common.modloader.ModLoaderModContainer;
import cpw.mods.fml.common.network.NetworkRegistry;
import cpw.mods.fml.common.network.PacketDispatcher;
import cpw.mods.fml.common.network.Player;
import cpw.mods.fml.common.registry.EntityRegistry;
import cpw.mods.fml.common.registry.GameRegistry;
import cpw.mods.fml.common.registry.LanguageRegistry;
import cpw.mods.fml.server.FMLServerHandler;
/**
* @author cpw
*
*/
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
@SideOnly(CLIENT)
public static void addAllRenderers(Map<Class<? extends Entity>, Render> renderers)
{
}
@SideOnly(CLIENT)
public static void addAnimation(TextureFX anim)
{
TextureFXManager.instance().addAnimation(anim);
}
/**
*
* @param armor
* @return
*/
@SideOnly(CLIENT)
public static int addArmor(String armor)
{
return RenderingRegistry.addNewArmourRendererPrefix(armor);
}
/**
* This method adds the supplied biome to the set of candidate biomes for the default world generator type.
*
* @param biome
*/
public static void addBiome(BiomeGenBase biome)
{
GameRegistry.addBiome(biome);
}
public static void addEntityTracker(BaseMod mod, Class<? extends Entity> entityClass, int entityTypeId, int updateRange, int updateInterval, boolean sendVelocityInfo)
{
ModLoaderHelper.buildEntityTracker(mod, entityClass, entityTypeId, updateRange, updateInterval, sendVelocityInfo);
}
public static void addCommand(ICommand command)
{
ModLoaderHelper.addCommand(command);
}
/**
* Add localization for the specified string
*
* @param key
* @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
*/
@SideOnly(CLIENT)
public static int addOverride(String fileToOverride, String fileToAdd)
{
return RenderingRegistry.addTextureOverride(fileToOverride, fileToAdd);
}
/**
* Unimplemented on the server as it does not render textures
*
* @param path
* @param overlayPath
* @param index
*/
@SideOnly(CLIENT)
public static void addOverride(String path, String overlayPath, int index)
{
RenderingRegistry.addTextureOverride(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 new product to be smelted
*
* @param input
* @param output
*/
public static void addSmelting(int input, ItemStack output, float experience)
{
GameRegistry.addSmelting(input, output, experience);
}
/**
* Add a mob to the spawn list
*
* @param entityClass
* @param weightedProb
* @param min
* @param max
* @param spawnList
*/
public static void addSpawn(Class<? extends EntityLiving> entityClass, int weightedProb, int min, int max, EnumCreatureType spawnList)
{
EntityRegistry.addSpawn(entityClass, weightedProb, min, max, spawnList, WorldType.base12Biomes);
}
/**
* Add a mob to the spawn list
*
* @param entityClass
* @param weightedProb
* @param min
* @param max
* @param spawnList
* @param biomes
*/
public static void addSpawn(Class<? extends EntityLiving> entityClass, int weightedProb, int min, int max, EnumCreatureType spawnList, BiomeGenBase... biomes)
{
EntityRegistry.addSpawn(entityClass, weightedProb, min, max, spawnList, biomes);
}
/**
* Add a mob to the spawn list
*
* @param entityName
* @param weightedProb
* @param min
* @param max
* @param spawnList
*/
public static void addSpawn(String entityName, int weightedProb, int min, int max, EnumCreatureType spawnList)
{
EntityRegistry.addSpawn(entityName, weightedProb, min, max, spawnList, WorldType.base12Biomes);
}
/**
* Add a mob to the spawn list
*
* @param entityName
* @param weightedProb
* @param min
* @param max
* @param spawnList
* @param biomes
*/
public static void addSpawn(String entityName, int weightedProb, int min, int max, EnumCreatureType spawnList, BiomeGenBase... biomes)
{
EntityRegistry.addSpawn(entityName, weightedProb, min, max, spawnList, biomes);
}
public static void addTrade(int profession, TradeEntry entry)
{
ModLoaderHelper.registerTrade(profession, entry);
}
/**
* Send a packet from the client
* @param packet
*/
public static void clientSendPacket(Packet packet)
{
PacketDispatcher.sendPacketToServer(packet);
}
/**
* This method is a call in hook from modified external code. Implemented elsewhere.
*
* @param world
* @param x
* @param y
* @param z
* @param xVel
* @param zVel
* @param item
* @return
*/
@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();
}
@SideOnly(CLIENT)
public static Minecraft getMinecraftInstance()
{
return FMLClientHandler.instance().getClient();
}
/**
*
* @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
*
*/
@SideOnly(CLIENT)
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();
}
@SideOnly(CLIENT)
public static int getUniqueSpriteIndex(String path)
{
return SpriteHelper.getUniqueSpriteIndex(path);
}
/**
* To properly implement packet 250 protocol you should always check your
* channel is active prior to sending the packet
*
* @param player
* @param channel
* @return
*/
public static boolean isChannelActive(EntityPlayer player, String channel)
{
return NetworkRegistry.instance().isChannelActive(channel, (Player)player);
}
@SideOnly(CLIENT)
public static boolean isGUIOpen(Class<? extends GuiScreen> gui)
{
return FMLClientHandler.instance().getClient().field_71462_r != null && FMLClientHandler.instance().getClient().field_71462_r.equals(gui);
}
/**
* Is the named mod loaded?
* {@link Loader#isModLoaded(String)}
*
* @param modname
* @return
*/
public static boolean isModLoaded(String modname)
{
return Loader.isModLoaded(modname);
}
/**
* Implemented elsewhere
*/
@Deprecated
public static void loadConfig()
{
}
@SideOnly(CLIENT)
public static BufferedImage loadImage(RenderEngine renderEngine, String path) throws Exception
{
return TextureFXManager.instance().loadImageFromTexturePack(renderEngine, path);
}
/**
* Call in from elsewhere. Unimplemented here.
* @param player
* @param item
*/
@Deprecated
public static void onItemPickup(EntityPlayer player, ItemStack item)
{
}
/**
* Call in from elsewhere. Unimplemented here.
*/
@Deprecated
@SideOnly(CLIENT)
public static void onTick(float tick, Minecraft game)
{
}
@SideOnly(CLIENT)
public static void openGUI(EntityPlayer player, GuiScreen gui)
{
FMLClientHandler.instance().displayGuiScreen(player, gui);
}
@Deprecated
public static void populateChunk(IChunkProvider generator, int chunkX, int chunkZ, World world)
{
}
/**
* This method is a call in hook from modified external code. Implemented elsewhere.
* {@link FMLServerHandler#handlePacket250(Packet250CustomPayload, EntityPlayer)}
*
* @param packet
*/
@Deprecated
public static void receivePacket(Packet250CustomPayload packet)
{
}
@Deprecated
@SideOnly(CLIENT)
public static KeyBinding[] registerAllKeys(KeyBinding[] keys)
{
return keys;
}
@Deprecated
@SideOnly(CLIENT)
public static void registerAllTextureOverrides(RenderEngine cache)
{
}
/**
* Register a new block
*
* @param block
*/
public static void registerBlock(Block block)
{
GameRegistry.registerBlock(block);
}
/**
* Register a new block
*
* @param block
* @param itemclass
*/
public static void registerBlock(Block block, Class<? extends ItemBlock> itemclass)
{
GameRegistry.registerBlock(block, itemclass);
}
public static void registerContainerID(BaseMod mod, int id)
{
ModLoaderHelper.buildGuiHelper(mod, id);
}
/**
* Register a new entity ID
*
* @param entityClass
* @param entityName
* @param id
*/
public static void registerEntityID(Class<? extends Entity> entityClass, String entityName, int id)
{
EntityRegistry.registerGlobalEntityID(entityClass, entityName, id);
}
/**
* Register a new entity ID
*
* @param entityClass
* @param entityName
* @param id
* @param background
* @param foreground
*/
public static void registerEntityID(Class<? extends Entity> entityClass, String entityName, int id, int background, int foreground)
{
EntityRegistry.registerGlobalEntityID(entityClass, entityName, id, background, foreground);
}
@SideOnly(CLIENT)
public static void registerKey(BaseMod mod, KeyBinding keyHandler, boolean allowRepeat)
{
ModLoaderClientHelper.registerKeyBinding(mod, keyHandler, allowRepeat);
}
/**
* Register the mod for packets on this channel.
* {@link 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);
}
@SideOnly(CLIENT)
public static void registerTileEntity(Class<? extends TileEntity> tileEntityClass, String id, TileEntitySpecialRenderer renderer)
{
ClientRegistry.registerTileEntity(tileEntityClass, id, renderer);
}
/**
* Remove a biome from the list of generated biomes
*
* @param biome
*/
public static void removeBiome(BiomeGenBase biome)
{
GameRegistry.removeBiome(biome);
}
/**
* Remove a spawn
*
* @param entityClass
* @param spawnList
*/
public static void removeSpawn(Class<? extends EntityLiving> entityClass, EnumCreatureType spawnList)
{
EntityRegistry.removeSpawn(entityClass, spawnList, WorldType.base12Biomes);
}
/**
* Remove a spawn
*
* @param entityClass
* @param spawnList
* @param biomes
*/
public static void removeSpawn(Class<? extends EntityLiving> entityClass, EnumCreatureType spawnList, BiomeGenBase... biomes)
{
EntityRegistry.removeSpawn(entityClass, spawnList, biomes);
}
/**
* Remove a spawn
*
* @param entityName
* @param spawnList
*/
public static void removeSpawn(String entityName, EnumCreatureType spawnList)
{
EntityRegistry.removeSpawn(entityName, spawnList, WorldType.base12Biomes);
}
/**
* Remove a spawn
*
* @param entityName
* @param spawnList
* @param biomes
*/
public static void removeSpawn(String entityName, EnumCreatureType spawnList, BiomeGenBase... biomes)
{
EntityRegistry.removeSpawn(entityName, spawnList, biomes);
}
@Deprecated
@SideOnly(CLIENT)
public static boolean renderBlockIsItemFull3D(int modelID)
{
return RenderingRegistry.instance().renderItemAsFull3DBlock(modelID);
}
@Deprecated
@SideOnly(CLIENT)
public static void renderInvBlock(RenderBlocks renderer, Block block, int metadata, int modelID)
{
RenderingRegistry.instance().renderInventoryBlock(renderer, block, metadata, modelID);
}
@Deprecated
@SideOnly(CLIENT)
public static boolean renderWorldBlock(RenderBlocks renderer, IBlockAccess world, int x, int y, int z, Block block, int modelID)
{
return RenderingRegistry.instance().renderWorldBlock(renderer, world, x, y, z, block, modelID);
}
/**
* Configuration is handled elsewhere
* {@link ModLoaderModContainer}
*/
@Deprecated
public static void saveConfig()
{
}
/**
* Send a packet from client to server
*
* @param packet
*/
public static void sendPacket(Packet packet) {
PacketDispatcher.sendPacketToServer(packet);
}
/**
* Send a chat message to the server
* {@link FMLClientHandler#handleChatPacket(Packet3Chat, EntityPlayer)}
*
* @param text
*/
@Deprecated
public static void serverChat(String text)
{
//TODO
}
@Deprecated
@SideOnly(CLIENT)
public static void serverLogin(NetClientHandler handler, Packet1Login loginPacket)
{
//TODO
}
public static void serverSendPacket(NetServerHandler handler, Packet packet)
{
if (handler != null)
{
PacketDispatcher.sendPacketToPlayer(packet, (Player)handler.getPlayer());
}
}
public static void serverOpenWindow(EntityPlayerMP player, Container container, int ID, int x, int y, int z)
{
ModLoaderHelper.openGui(ID, player, container, x, y, z);
}
/**
* Indicate that you want to receive ticks
*
* @param mod receiving the events
* @param enable indicates whether you want to recieve them or not
* @param useClock don't receive render subticks, just world ticks
*/
public static void setInGameHook(BaseMod mod, boolean enable, boolean useClock)
{
ModLoaderHelper.updateStandardTicks(mod, enable, useClock);
}
public static void setInGUIHook(BaseMod mod, boolean enable, boolean useClock)
{
ModLoaderHelper.updateGUITicks(mod, enable, useClock);
}
/**
* Set a private field to a value using reflection
* {@link ObfuscationReflectionHelper#setPrivateValue(Class, Object, int, Object)}
*
* @param instanceclass
* @param instance
* @param fieldindex
* @param value
*/
public static <T, E> void setPrivateValue(Class<? super T> instanceclass, T instance, int fieldindex, E value)
{
ObfuscationReflectionHelper.setPrivateValue(instanceclass, instance, value, fieldindex);
}
/**
* Set a private field to a value using reflection
* {@link ObfuscationReflectionHelper#setPrivateValue(Class, Object, String, Object)}
*
* @param instanceclass
* @param instance
* @param field
* @param value
*/
public static <T, E> void setPrivateValue(Class<? super T> instanceclass, T instance, String field, E value)
{
ObfuscationReflectionHelper.setPrivateValue(instanceclass, instance, value, field);
}
/**
* This method is a call in hook from modified external code. Implemented elsewhere.
*
* @param player
* @param item
* @param matrix
*/
@Deprecated
public static void takenFromCrafting(EntityPlayer player, ItemStack item, IInventory matrix)
{
}
/**
* This method is a call in hook from modified external code. Implemented elsewhere.
*
* @param player
* @param item
*/
@Deprecated
public static void takenFromFurnace(EntityPlayer player, ItemStack item)
{
}
/**
* Throw the offered exception. Likely will stop the game.
*
* @param message
* @param e
*/
public static void throwException(String message, Throwable e)
{
FMLCommonHandler.instance().raiseException(e, message, true);
}
public static void throwException(Throwable e)
{
throwException("Exception in ModLoader", e);
}
}
@@ -0,0 +1,124 @@
/*
* 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 cpw.mods.fml.client.FMLClientHandler;
import cpw.mods.fml.client.FMLTextureFX;
/**
* A texture override for animations, it takes a vertical image of
* texture frames and constantly rotates them in the texture.
*/
public class ModTextureAnimation extends FMLTextureFX
{
private final int tickRate;
private byte[][] images;
private int index = 0;
private int ticks = 0;
private String targetTex = null;
private BufferedImage imgData = null;
public ModTextureAnimation(int icon, int target, BufferedImage image, int tickCount)
{
this(icon, 1, target, image, tickCount);
}
public ModTextureAnimation(int icon, int size, int target, BufferedImage image, int tickCount)
{
this(icon, size, (target == 0 ? "/terrain.png" : "/gui/items.png"), image, tickCount);
}
public ModTextureAnimation(int icon, int size, String target, BufferedImage image, int tickCount)
{
super(icon);
RenderEngine re = FMLClientHandler.instance().getClient().field_71446_o;
targetTex = target;
field_76849_e = size;
field_76847_f = re.func_78341_b(target);
tickRate = tickCount;
ticks = tickCount;
imgData = image;
}
@Override
public void setup()
{
super.setup();
int sWidth = imgData.getWidth();
int sHeight = imgData.getHeight();
int tWidth = tileSizeBase;
int tHeight = tileSizeBase;
int frames = (int)Math.floor((double)(sHeight / sWidth));
if (frames < 1)
{
throw new IllegalArgumentException(String.format("Attempted to create a TextureAnimation with no complete frames: %dx%d", sWidth, sHeight));
}
else
{
images = new byte[frames][];
BufferedImage image = imgData;
if (sWidth != tWidth)
{
BufferedImage b = new BufferedImage(tWidth, tHeight * frames, 6);
Graphics2D g = b.createGraphics();
g.drawImage(imgData, 0, 0, tWidth, tHeight * frames, 0, 0, sWidth, sHeight, (ImageObserver)null);
g.dispose();
image = b;
}
for (int frame = 0; frame < frames; frame++)
{
int[] pixels = new int[tileSizeSquare];
image.getRGB(0, tHeight * frame, tWidth, tHeight, pixels, 0, tWidth);
images[frame] = new byte[tileSizeSquare << 2];
for (int i = 0; i < pixels.length; i++)
{
int i4 = i * 4;
images[frame][i4 + 0] = (byte)(pixels[i] >> 16 & 255);
images[frame][i4 + 1] = (byte)(pixels[i] >> 8 & 255);
images[frame][i4 + 2] = (byte)(pixels[i] >> 0 & 255);
images[frame][i4 + 3] = (byte)(pixels[i] >> 24 & 255);
}
}
}
}
public void func_783_a()
{
if (++ticks >= tickRate)
{
if (++index >= images.length)
{
index = 0;
}
field_76852_a = images[index];
ticks = 0;
}
}
}
@@ -0,0 +1,181 @@
/*
* The FML Forge Mod Loader suite.
* Copyright (C) 2012 cpw
*
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraft.src;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.awt.image.ImageObserver;
import org.lwjgl.opengl.GL11;
import cpw.mods.fml.client.FMLClientHandler;
import cpw.mods.fml.client.FMLTextureFX;
public class ModTextureStatic extends FMLTextureFX
{
private boolean oldanaglyph = false;
private int[] pixels = null;
private String targetTex = null;
private int storedSize;
private BufferedImage overrideData = null;
private int needApply = 2;
public ModTextureStatic(int icon, int target, BufferedImage image)
{
this(icon, 1, target, image);
}
public ModTextureStatic(int icon, int size, int target, BufferedImage image)
{
this(icon, size, (target == 0 ? "/terrain.png" : "/gui/items.png"), image);
}
public ModTextureStatic(int icon, int size, String target, BufferedImage image)
{
super(icon);
RenderEngine re = FMLClientHandler.instance().getClient().field_71446_o;
targetTex = target;
storedSize = size;
field_76849_e = size;
field_76847_f = re.func_78341_b(target);
overrideData = image;
}
@Override
public void setup()
{
super.setup();
int sWidth = overrideData.getWidth();
int sHeight = overrideData.getHeight();
pixels = new int[tileSizeSquare];
if (tileSizeBase == sWidth && tileSizeBase == sHeight)
{
overrideData.getRGB(0, 0, sWidth, sHeight, pixels, 0, sWidth);
}
else
{
BufferedImage tmp = new BufferedImage(tileSizeBase, tileSizeBase, 6);
Graphics2D gfx = tmp.createGraphics();
gfx.drawImage(overrideData, 0, 0, tileSizeBase, tileSizeBase, 0, 0, sWidth, sHeight, (ImageObserver)null);
tmp.getRGB(0, 0, tileSizeBase, tileSizeBase, pixels, 0, tileSizeBase);
gfx.dispose();
}
update();
}
@Override
public void func_76846_a()
{
if (oldanaglyph != field_76851_c)
{
update();
}
// This makes it so we only apply the texture to the target texture when we need to,
//due to the fact that update is called when the Effect is first registered, we actually
//need to wait for the next one.
field_76849_e = (needApply == 0 ? 0 : storedSize);
if (needApply > 0)
{
needApply--;
}
}
@Override
public void func_76845_a(RenderEngine p_76845_1_)
{
GL11.glBindTexture(GL_TEXTURE_2D, p_76845_1_.func_78341_b(targetTex));
}
public void update()
{
needApply = 2;
for (int idx = 0; idx < pixels.length; idx++)
{
int i = idx * 4;
int a = pixels[idx] >> 24 & 255;
int r = pixels[idx] >> 16 & 255;
int g = pixels[idx] >> 8 & 255;
int b = pixels[idx] >> 0 & 255;
if (field_76851_c)
{
r = g = b = (r + g + b) / 3;
}
field_76852_a[i + 0] = (byte)r;
field_76852_a[i + 1] = (byte)g;
field_76852_a[i + 2] = (byte)b;
field_76852_a[i + 3] = (byte)a;
}
oldanaglyph = field_76851_c;
}
//Implementation of http://scale2x.sourceforge.net/algorithm.html
public static BufferedImage scale2x(BufferedImage image)
{
int w = image.getWidth();
int h = image.getHeight();
BufferedImage tmp = new BufferedImage(w * 2, h * 2, 2);
for (int x = 0; x < h; ++x)
{
int x2 = x * 2;
for (int y = 0; y < w; ++y)
{
int y2 = y * 2;
int E = image.getRGB(y, x);
int D = (x == 0 ? E : image.getRGB(y, x - 1));
int B = (y == 0 ? E : image.getRGB(y - 1, x ));
int H = (y >= w - 1 ? E : image.getRGB(y + 1, x ));
int F = (x >= h - 1 ? E : image.getRGB(y, x + 1));
int e0, e1, e2, e3;
if (B != H && D != F)
{
e0 = D == B ? D : E;
e1 = B == F ? F : E;
e2 = D == H ? D : E;
e3 = H == F ? F : E;
}
else
{
e0 = e1 = e2 = e3 = E;
}
tmp.setRGB(y2, x2, e0);
tmp.setRGB(y2 + 1, x2, e1);
tmp.setRGB(y2, x2 + 1, e2);
tmp.setRGB(y2 + 1, x2 + 1, e3);
}
}
return tmp;
}
@Override
public String toString()
{
return String.format("ModTextureStatic %s @ %d", targetTex, field_76850_b);
}
}
+30
View File
@@ -0,0 +1,30 @@
package net.minecraft.src;
/**
* Compatibility class for ModLoader -- do not use
*
* @author cpw
*
*/
public class TradeEntry
{
public final int id;
public float chance;
public boolean buying;
public int min = 0;
public int max = 0;
public TradeEntry(int id, float chance, boolean buying, int min, int max)
{
this.id = id;
this.chance = chance;
this.buying = buying;
this.min = min;
this.max = max;
}
public TradeEntry(int id, float chance, boolean buying)
{
this(id, chance, buying, 0, 0);
}
}
+209
View File
@@ -0,0 +1,209 @@
--- commands.py
+++ commands.py
@@ -58,6 +58,8 @@
def reallyrmtree(path):
+ if os.path.isfile(os.path.join(path, 'asm-all-4.0.jar')): #Check if asm exists, indicating the libs folder, if so, don't delete it
+ return
if not sys.platform.startswith('win'):
if os.path.exists(path):
shutil.rmtree(path)
@@ -584,6 +586,9 @@
self.has_astyle_cfg = False
if os.path.isfile(self.astyleconf):
self.has_astyle_cfg = True
+
+ #FML Entries
+ self.srcshared = os.path.normpath(os.path.join(self.dirsrc, 'common'))
def creatergcfg(self, reobf=False, keep_lvt=False, keep_generics=False, rg_update=False):
"""Create the files necessary for RetroGuard"""
@@ -781,7 +786,8 @@
testlk = {CLIENT: self.testclient, SERVER: self.testserver}
if not os.path.exists(os.path.join(srclk[side], os.path.normpath(testlk[side] + '.java'))):
- return False
+ if not os.path.exists(os.path.join(self.srcshared, os.path.normpath(testlk[side] + '.java'))):
+ return False
return True
def checkbins(self, side):
@@ -1029,6 +1035,10 @@
pathsrclk = {CLIENT: self.srcclient, SERVER: self.srcserver}
pathlog = {CLIENT: self.clientrecomplog, SERVER: self.serverrecomplog}
+ if side == SERVER: #Disable server because FML recombines it into client
+ self.logger.info('Server side recompiling skipped, this is normal')
+ return
+
if not os.path.exists(pathbinlk[side]):
os.makedirs(pathbinlk[side])
@@ -1041,6 +1051,7 @@
all_files = True
append_pattern = False
pkglist = filterdirs(pathsrclk[side], '*.java', append_pattern=append_pattern, all_files=all_files)
+ pkglist = pkglist + filterdirs(self.srcshared, '*.java', append_pattern=append_pattern, all_files=all_files) #FML, Add Common folder
dirs = ' '.join(pkglist)
classpath = os.pathsep.join(cplk[side])
forkcmd = self.cmdrecomp.format(classpath=classpath, sourcepath=pathsrclk[side], outpath=pathbinlk[side],
@@ -1062,7 +1073,7 @@
raise
def startserver(self):
- classpath = [self.binserver] + self.cpathserver
+ classpath = [self.binserver, self.srcshared] + self.cpathserver
classpath = [os.path.join('..', p) for p in classpath]
classpath = os.pathsep.join(classpath)
os.chdir(self.dirjars)
@@ -1070,7 +1081,7 @@
self.runmc(forkcmd)
def startclient(self):
- classpath = [self.binclient] + self.cpathclient
+ classpath = [self.binclient, self.srcshared] + self.cpathclient
classpath = [os.path.join('..', p) for p in classpath]
classpath = os.pathsep.join(classpath)
natives = os.path.join('..', self.dirnatives)
@@ -1197,20 +1208,20 @@
with open(self.csvmethods, 'rb') as fh:
methodsreader = csv.DictReader(fh)
for row in methodsreader:
- if int(row['side']) == side:
+ if int(row['side']) == side or int(row['side']) == 2:
if row['name'] != row['searge']:
names['methods'][row['searge']] = row['name']
with open(self.csvfields, 'rb') as fh:
fieldsreader = csv.DictReader(fh)
for row in fieldsreader:
- if int(row['side']) == side:
+ if int(row['side']) == side or int(row['side']) == 2:
if row['name'] != row['searge']:
names['fields'][row['searge']] = row['name']
if self.has_param_csv:
with open(self.csvparams, 'rb') as fh:
paramsreader = csv.DictReader(fh)
for row in paramsreader:
- if int(row['side']) == side:
+ if int(row['side']) == side or int(row['side']) == 2:
names['params'][row['param']] = row['name']
regexps = {
@@ -1240,6 +1251,11 @@
# HINT: We pathwalk the sources
for path, _, filelist in os.walk(pathsrclk[side], followlinks=True):
+ for cur_file in fnmatch.filter(filelist, '*.java'):
+ updatefile(os.path.normpath(os.path.join(path, cur_file)))
+
+ # FML, copy of the above, for the common folder
+ for path, _, filelist in os.walk(self.srcshared, followlinks=True):
for cur_file in fnmatch.filter(filelist, '*.java'):
updatefile(os.path.normpath(os.path.join(path, cur_file)))
return True
@@ -1322,12 +1338,14 @@
pathsrclk = {CLIENT: self.srcclient, SERVER: self.srcserver}
strip_comments(pathsrclk[side])
+ strip_comments(self.srcshared)
def process_cleanup(self, side):
"""Do lots of random cleanups including stripping comments, trailing whitespace and extra blank lines"""
pathsrclk = {CLIENT: self.srcclient, SERVER: self.srcserver}
src_cleanup(pathsrclk[side], fix_imports=True, fix_unicode=True, fix_charval=True, fix_pi=True, fix_round=False)
+ src_cleanup(self.srcshared, fix_imports=True, fix_unicode=True, fix_charval=True, fix_pi=True, fix_round=False)
def process_javadoc(self, side):
"""Add CSV descriptions to methods and fields as javadoc"""
@@ -1336,6 +1354,21 @@
if not self.has_doc_csv:
self.logger.warning('!! javadoc disabled due to no csvs !!')
return False
+
+ #FML Recall this function on the common folder
+ #Potential bug: If this is called without a subsiquent rename call, will cause double comments
+ if pathsrclk[side] != self.srcshared:
+ if side == CLIENT:
+ tmp = self.srcclient
+ self.srcclient = self.srcshared
+ self.process_javadoc(side)
+ self.srcclient = tmp
+ else:
+ tmp = self.srcserver
+ self.srcserver = self.srcshared
+ self.process_javadoc(side)
+ self.srcserver = tmp
+
#HINT: We read the relevant CSVs
methodsreader = csv.DictReader(open(self.csvmethods, 'r'))
@@ -1344,13 +1377,13 @@
methods = {}
for row in methodsreader:
#HINT: Only include methods that have a non-empty description
- if int(row['side']) == side and row['desc']:
+ if (int(row['side']) == side or int(row['side']) == 2) and row['desc']:
methods[row['searge']] = row['desc'].replace('*/', '* /')
fields = {}
for row in fieldsreader:
#HINT: Only include fields that have a non-empty description
- if int(row['side']) == side and row['desc']:
+ if (int(row['side']) == side or int(row['side']) == 2) and row['desc']:
fields[row['searge']] = row['desc'].replace('*/', '* /')
regexps = {
@@ -1422,12 +1455,13 @@
# HINT: We create the list of source directories based on the list of packages
pkglist = filterdirs(pathsrclk[side], '*.java', append_pattern=True)
+ pkglist = pkglist + filterdirs(self.srcshared, '*.java', append_pattern=True) #FML, Add Common folder
dirs = ' '.join(pkglist)
forkcmd = self.cmdastyle.format(classes=dirs, conffile=self.astyleconf)
self.runcmd(forkcmd)
return True
- def gathermd5s(self, side, reobf=False):
+ def gathermd5s(self, side, reobf=False, skip_fml=False):
if not reobf:
md5lk = {CLIENT: self.md5client, SERVER: self.md5server}
else:
@@ -1442,6 +1476,9 @@
class_path = ''
else:
class_path += '/'
+ if skip_fml:
+ if class_path.startswith('cpw/'):
+ continue
for class_file in fnmatch.filter(filelist, '*.class'):
class_name = class_path + os.path.splitext(class_file)[0]
bin_file = os.path.normpath(os.path.join(path, class_file))
@@ -1594,6 +1631,9 @@
sys.exit(1)
for entry in newfiles:
+ if 'commands.py' in entry[0]: #FML, Disable updating of Commands.py
+ print 'Update to runtime/commands.py found, but disbled due to using fml'
+ continue
if entry[3] == 'U':
self.logger.info('Retrieving file from server : %s', entry[0])
cur_file = os.path.normpath(entry[0])
@@ -1614,6 +1654,9 @@
md5reoblk = {CLIENT: self.md5reobfclient, SERVER: self.md5reobfserver}
outpathlk = {CLIENT: self.srcmodclient, SERVER: self.srcmodserver}
src = {CLIENT: self.srcclient, SERVER: self.srcserver}
+
+ if side == SERVER: #Noop out server side stuff
+ return
# HINT: We need a table for the old md5 and the new ones
md5table = {}
@@ -1656,3 +1699,6 @@
except IOError:
self.logger.error('* File %s copy failed', in_class)
+def commands_sanity_check():
+ print 'Commands patch applied successfully'
+
@@ -0,0 +1,135 @@
package cpw.mods.fml.common;
import java.io.File;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import com.google.common.eventbus.EventBus;
import cpw.mods.fml.common.versioning.ArtifactVersion;
import cpw.mods.fml.common.versioning.DefaultArtifactVersion;
public class DummyModContainer implements ModContainer
{
private ModMetadata md;
private ArtifactVersion processedVersion;
public DummyModContainer(ModMetadata md)
{
this.md = md;
}
public DummyModContainer()
{
}
@Override
public void bindMetadata(MetadataCollection mc)
{
}
@Override
public List<ArtifactVersion> getDependants()
{
return Collections.emptyList();
}
@Override
public List<ArtifactVersion> getDependencies()
{
return Collections.emptyList();
}
@Override
public Set<ArtifactVersion> getRequirements()
{
return Collections.emptySet();
}
@Override
public ModMetadata getMetadata()
{
return md;
}
@Override
public Object getMod()
{
return null;
}
@Override
public String getModId()
{
return md.modId;
}
@Override
public String getName()
{
return md.name;
}
@Override
public String getSortingRules()
{
return "";
}
@Override
public File getSource()
{
return null;
}
@Override
public String getVersion()
{
return md.version;
}
public boolean matches(Object mod)
{
return false;
}
@Override
public void setEnabledState(boolean enabled)
{
}
@Override
public boolean registerBus(EventBus bus, LoadController controller)
{
return false;
}
@Override
public ArtifactVersion getProcessedVersion()
{
if (processedVersion == null)
{
processedVersion = new DefaultArtifactVersion(getModId(), getVersion());
}
return processedVersion;
}
@Override
public boolean isImmutable()
{
return false;
}
@Override
public boolean isNetworkMod()
{
return false;
}
@Override
public String getDisplayVersion()
{
return md.version;
}
}
@@ -0,0 +1,411 @@
/*
* The FML Forge Mod Loader suite.
* Copyright (C) 2012 cpw
*
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package cpw.mods.fml.common;
import java.util.EnumSet;
import java.util.List;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.minecraft.server.MinecraftServer;
import net.minecraft.src.CrashReport;
import net.minecraft.src.DedicatedServer;
import net.minecraft.src.Entity;
import net.minecraft.src.EntityPlayer;
import net.minecraft.src.EntityPlayerMP;
import net.minecraft.src.NetHandler;
import net.minecraft.src.Packet131MapData;
import net.minecraft.src.ServerListenThread;
import net.minecraft.src.ThreadServerApplication;
import net.minecraft.src.World;
import com.google.common.base.Objects;
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.network.EntitySpawnAdjustmentPacket;
import cpw.mods.fml.common.network.EntitySpawnPacket;
import cpw.mods.fml.common.registry.EntityRegistry.EntityRegistration;
import cpw.mods.fml.common.registry.TickRegistry;
import cpw.mods.fml.server.FMLServerHandler;
/**
* The main class for non-obfuscated hook handling code
*
* Anything that doesn't require obfuscated or client/server specific code should
* go in this handler
*
* It also contains a reference to the sided handler instance that is valid
* allowing for common code to access specific properties from the obfuscated world
* without a direct dependency
*
* @author cpw
*
*/
public class FMLCommonHandler
{
/**
* The singleton
*/
private static final FMLCommonHandler INSTANCE = new FMLCommonHandler();
/**
* The delegate for side specific data and functions
*/
private IFMLSidedHandler sidedDelegate;
private List<IScheduledTickHandler> scheduledClientTicks = Lists.newArrayList();
private List<IScheduledTickHandler> scheduledServerTicks = Lists.newArrayList();
private Class<?> forge;
private boolean noForge;
private List<String> brandings;
private List<ICrashCallable> crashCallables = Lists.newArrayList(Loader.instance().getCallableCrashInformation());
public void beginLoading(IFMLSidedHandler handler)
{
sidedDelegate = handler;
FMLLog.info("Attempting early MinecraftForge initialization");
callForgeMethod("initialize");
callForgeMethod("registerCrashCallable");
FMLLog.info("Completed early MinecraftForge initialization");
}
public void rescheduleTicks(Side side)
{
TickRegistry.updateTickQueue(side.isClient() ? scheduledClientTicks : scheduledServerTicks, side);
}
public void tickStart(EnumSet<TickType> ticks, Side side, Object ... data)
{
List<IScheduledTickHandler> scheduledTicks = side.isClient() ? scheduledClientTicks : scheduledServerTicks;
if (scheduledTicks.size()==0)
{
return;
}
for (IScheduledTickHandler ticker : scheduledTicks)
{
EnumSet<TickType> ticksToRun = EnumSet.copyOf(Objects.firstNonNull(ticker.ticks(), EnumSet.noneOf(TickType.class)));
ticksToRun.removeAll(EnumSet.complementOf(ticks));
if (!ticksToRun.isEmpty())
{
ticker.tickStart(ticksToRun, data);
}
}
}
public void tickEnd(EnumSet<TickType> ticks, Side side, Object ... data)
{
List<IScheduledTickHandler> scheduledTicks = side.isClient() ? scheduledClientTicks : scheduledServerTicks;
if (scheduledTicks.size()==0)
{
return;
}
for (IScheduledTickHandler ticker : scheduledTicks)
{
EnumSet<TickType> ticksToRun = EnumSet.copyOf(Objects.firstNonNull(ticker.ticks(), EnumSet.noneOf(TickType.class)));
ticksToRun.removeAll(EnumSet.complementOf(ticks));
if (!ticksToRun.isEmpty())
{
ticker.tickEnd(ticksToRun, data);
}
}
}
/**
* @return the instance
*/
public static FMLCommonHandler instance()
{
return INSTANCE;
}
/**
* Find the container that associates with the supplied mod object
* @param mod
* @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();
}
/**
* Return the effective side for the context in the game. This is dependent
* on thread analysis to try and determine whether the code is running in the
* server or not. Use at your own risk
*
* @return
*/
public Side getEffectiveSide()
{
Thread thr = Thread.currentThread();
if ((thr instanceof ThreadServerApplication) || (thr instanceof ServerListenThread))
{
return Side.SERVER;
}
return Side.CLIENT;
}
/**
* 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<?> 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("FML v"+Loader.instance().getFMLVersionString());
String forgeBranding = (String) callForgeMethod("getBrandingVersion");
if (!Strings.isNullOrEmpty(forgeBranding))
{
brd.add(forgeBranding);
}
brd.addAll(sidedDelegate.getAdditionalBrandingInformation());
try {
Properties props=new Properties();
props.load(getClass().getClassLoader().getResourceAsStream("fmlbranding.properties"));
brd.add(props.getProperty("fmlbranding"));
} catch (Exception ex) {
// Ignore - no branding file found
}
int tModCount = Loader.instance().getModList().size();
int aModCount = Loader.instance().getActiveModList().size();
brd.add(String.format("%d mod%s loaded, %d mod%s active", tModCount, tModCount!=1 ? "s" :"", aModCount, aModCount!=1 ? "s" :"" ));
brandings = brd.build();
}
}
public List<String> getBrandings()
{
if (brandings == null)
{
computeBranding();
}
return ImmutableList.copyOf(brandings);
}
/**
* @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(EntityRegistration registration, EntitySpawnPacket entitySpawnPacket)
{
return sidedDelegate.spawnEntityIntoClientWorld(registration, entitySpawnPacket);
}
public void adjustEntityLocationOnClient(EntitySpawnAdjustmentPacket entitySpawnAdjustmentPacket)
{
sidedDelegate.adjustEntityLocationOnClient(entitySpawnAdjustmentPacket);
}
public void onServerStart(DedicatedServer dedicatedServer)
{
FMLServerHandler.instance();
sidedDelegate.beginServerLoading(dedicatedServer);
}
public void onServerStarted()
{
sidedDelegate.finishServerLoading();
}
public void onPreClientTick()
{
tickStart(EnumSet.of(TickType.CLIENT), Side.CLIENT);
}
public void onPostClientTick()
{
tickEnd(EnumSet.of(TickType.CLIENT), Side.CLIENT);
}
public void onRenderTickStart(float timer)
{
tickStart(EnumSet.of(TickType.RENDER), Side.CLIENT, timer);
}
public void onRenderTickEnd(float timer)
{
tickEnd(EnumSet.of(TickType.RENDER), Side.CLIENT, timer);
}
public void onPlayerPreTick(EntityPlayer player)
{
Side side = player instanceof EntityPlayerMP ? Side.SERVER : Side.CLIENT;
tickStart(EnumSet.of(TickType.PLAYER), side, player);
}
public void onPlayerPostTick(EntityPlayer player)
{
Side side = player instanceof EntityPlayerMP ? Side.SERVER : Side.CLIENT;
tickEnd(EnumSet.of(TickType.PLAYER), side, player);
}
public void registerCrashCallable(ICrashCallable callable)
{
crashCallables.add(callable);
}
public void enhanceCrashReport(CrashReport crashReport)
{
for (ICrashCallable call: crashCallables)
{
crashReport.func_71500_a(call.getLabel(), call);
}
}
public void handleTinyPacket(NetHandler handler, Packet131MapData mapData)
{
sidedDelegate.handleTinyPacket(handler, mapData);
}
}
@@ -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;
}
}
+53
View File
@@ -0,0 +1,53 @@
package cpw.mods.fml.common;
import java.util.logging.Level;
import java.util.logging.Logger;
public class FMLLog
{
private static cpw.mods.fml.relauncher.FMLRelaunchLog coreLog = cpw.mods.fml.relauncher.FMLRelaunchLog.log;
public static void log(Level level, String format, Object... data)
{
coreLog.log(level, format, data);
}
public static void log(Level level, Throwable ex, String format, Object... data)
{
coreLog.log(level, ex, format, data);
}
public static void severe(String format, Object... data)
{
log(Level.SEVERE, format, data);
}
public static void warning(String format, Object... data)
{
log(Level.WARNING, format, data);
}
public static void info(String format, Object... data)
{
log(Level.INFO, format, data);
}
public static void fine(String format, Object... data)
{
log(Level.FINE, format, data);
}
public static void finer(String format, Object... data)
{
log(Level.FINER, format, data);
}
public static void finest(String format, Object... data)
{
log(Level.FINEST, format, data);
}
public static Logger getLogger()
{
return coreLog.getLogger();
}
}
@@ -0,0 +1,407 @@
/*
* 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.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import com.google.common.base.Function;
import com.google.common.base.Strings;
import com.google.common.base.Throwables;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.BiMap;
import com.google.common.collect.ImmutableBiMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.google.common.collect.SetMultimap;
import com.google.common.collect.Sets;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;
import cpw.mods.fml.common.Mod.Instance;
import cpw.mods.fml.common.Mod.Metadata;
import cpw.mods.fml.common.discovery.ASMDataTable;
import cpw.mods.fml.common.discovery.ASMDataTable.ASMData;
import cpw.mods.fml.common.event.FMLConstructionEvent;
import cpw.mods.fml.common.event.FMLInitializationEvent;
import cpw.mods.fml.common.event.FMLPostInitializationEvent;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import cpw.mods.fml.common.event.FMLServerStartedEvent;
import cpw.mods.fml.common.event.FMLServerStartingEvent;
import cpw.mods.fml.common.event.FMLServerStoppingEvent;
import cpw.mods.fml.common.event.FMLStateEvent;
import cpw.mods.fml.common.network.FMLNetworkHandler;
import cpw.mods.fml.common.versioning.ArtifactVersion;
import cpw.mods.fml.common.versioning.DefaultArtifactVersion;
public class FMLModContainer implements ModContainer
{
private Mod modDescriptor;
private Object modInstance;
private File source;
private ModMetadata modMetadata;
private String className;
private Map<String, Object> descriptor;
private boolean enabled = true;
private String internalVersion;
private boolean overridesMetadata;
private EventBus eventBus;
private LoadController controller;
private Multimap<Class<? extends Annotation>, Object> annotations;
private DefaultArtifactVersion processedVersion;
private boolean isNetworkMod;
private static final BiMap<Class<? extends FMLStateEvent>, Class<? extends Annotation>> modAnnotationTypes = ImmutableBiMap.<Class<? extends FMLStateEvent>, Class<? extends Annotation>>builder()
.put(FMLPreInitializationEvent.class, Mod.PreInit.class)
.put(FMLInitializationEvent.class, Mod.Init.class)
.put(FMLPostInitializationEvent.class, Mod.PostInit.class)
.put(FMLServerStartingEvent.class, Mod.ServerStarting.class)
.put(FMLServerStartedEvent.class, Mod.ServerStarted.class)
.put(FMLServerStoppingEvent.class, Mod.ServerStopping.class)
.build();
private static final BiMap<Class<? extends Annotation>, Class<? extends FMLStateEvent>> modTypeAnnotations = modAnnotationTypes.inverse();
private String annotationDependencies;
public FMLModContainer(String className, File modSource, Map<String,Object> modDescriptor)
{
this.className = className;
this.source = modSource;
this.descriptor = modDescriptor;
}
@Override
public String getModId()
{
return (String) descriptor.get("modid");
}
@Override
public String getName()
{
return modMetadata.name;
}
@Override
public String getVersion()
{
return internalVersion;
}
@Override
public File getSource()
{
return source;
}
@Override
public ModMetadata getMetadata()
{
return modMetadata;
}
@Override
public void bindMetadata(MetadataCollection mc)
{
modMetadata = mc.getMetadataForId(getModId(), descriptor);
if (descriptor.containsKey("usesMetadata"))
{
overridesMetadata = !((Boolean)descriptor.get("usesMetadata")).booleanValue();
}
if (overridesMetadata || !modMetadata.useDependencyInformation)
{
Set<ArtifactVersion> requirements = Sets.newHashSet();
List<ArtifactVersion> dependencies = Lists.newArrayList();
List<ArtifactVersion> dependants = Lists.newArrayList();
annotationDependencies = (String) descriptor.get("dependencies");
Loader.instance().computeDependencies(annotationDependencies, requirements, dependencies, dependants);
modMetadata.requiredMods = requirements;
modMetadata.dependencies = dependencies;
modMetadata.dependants = dependants;
FMLLog.finest("Parsed dependency info : %s %s %s", requirements, dependencies, dependants);
}
else
{
FMLLog.finest("Using mcmod dependency info : %s %s %s", modMetadata.requiredMods, modMetadata.dependencies, modMetadata.dependants);
}
if (Strings.isNullOrEmpty(modMetadata.name))
{
FMLLog.info("Mod %s is missing the required element 'name'. Substituting %s", getModId(), getModId());
modMetadata.name = getModId();
}
internalVersion = (String) descriptor.get("version");
if (Strings.isNullOrEmpty(internalVersion) && !Strings.isNullOrEmpty(modMetadata.version))
{
FMLLog.warning("Mod %s is missing the required element 'version'. Falling back to metadata version %s", getModId(), modMetadata.version);
modMetadata.version = internalVersion;
}
if (Strings.isNullOrEmpty(internalVersion))
{
FMLLog.warning("Mod %s is missing the required element 'version' and no fallback can be found. Substituting '1.0'.", getModId());
modMetadata.version = internalVersion = "1.0";
}
}
@Override
public void setEnabledState(boolean enabled)
{
this.enabled = enabled;
}
@Override
public Set<ArtifactVersion> getRequirements()
{
return modMetadata.requiredMods;
}
@Override
public List<ArtifactVersion> getDependencies()
{
return modMetadata.dependencies;
}
@Override
public List<ArtifactVersion> getDependants()
{
return modMetadata.dependants;
}
@Override
public String getSortingRules()
{
return ((overridesMetadata || !modMetadata.useDependencyInformation) ? Strings.nullToEmpty(annotationDependencies) : modMetadata.printableSortingRules());
}
@Override
public boolean matches(Object mod)
{
return mod == modInstance;
}
@Override
public Object getMod()
{
return modInstance;
}
@Override
public boolean registerBus(EventBus bus, LoadController controller)
{
if (this.enabled)
{
FMLLog.fine("Enabling mod %s", getModId());
this.eventBus = bus;
this.controller = controller;
eventBus.register(this);
return true;
}
else
{
return false;
}
}
private Multimap<Class<? extends Annotation>, Object> gatherAnnotations(Class<?> clazz) throws Exception
{
Multimap<Class<? extends Annotation>,Object> anns = ArrayListMultimap.create();
for (Method m : clazz.getDeclaredMethods())
{
for (Annotation a : m.getAnnotations())
{
if (modTypeAnnotations.containsKey(a.annotationType()))
{
Class<?>[] paramTypes = new Class[] { modTypeAnnotations.get(a.annotationType()) };
if (Arrays.equals(m.getParameterTypes(), paramTypes))
{
m.setAccessible(true);
anns.put(a.annotationType(), m);
}
else
{
FMLLog.severe("The mod %s appears to have an invalid method annotation %s. This annotation can only apply to methods with argument types %s -it will not be called", getModId(), a.annotationType().getSimpleName(), Arrays.toString(paramTypes));
}
}
}
}
return anns;
}
private void processFieldAnnotations(ASMDataTable asmDataTable) throws Exception
{
SetMultimap<String, ASMData> annotations = asmDataTable.getAnnotationsFor(this);
parseSimpleFieldAnnotation(annotations, Instance.class.getName(), new Function<ModContainer, Object>()
{
public Object apply(ModContainer mc)
{
return mc.getMod();
}
});
parseSimpleFieldAnnotation(annotations, Metadata.class.getName(), new Function<ModContainer, Object>()
{
public Object apply(ModContainer mc)
{
return mc.getMetadata();
}
});
//TODO
// for (Object o : annotations.get(Block.class))
// {
// Field f = (Field) o;
// f.set(modInstance, GameRegistry.buildBlock(this, f.getType(), f.getAnnotation(Block.class)));
// }
}
private void parseSimpleFieldAnnotation(SetMultimap<String, ASMData> annotations, String annotationClassName, Function<ModContainer, Object> retreiver) throws IllegalAccessException
{
String[] annName = annotationClassName.split("\\.");
String annotationName = annName[annName.length - 1];
for (ASMData targets : annotations.get(annotationClassName))
{
String targetMod = (String) targets.getAnnotationInfo().get("value");
Field f = null;
Object injectedMod = null;
ModContainer mc = this;
boolean isStatic = false;
Class<?> clz = modInstance.getClass();
if (!Strings.isNullOrEmpty(targetMod))
{
if (Loader.isModLoaded(targetMod))
{
mc = Loader.instance().getIndexedModList().get(targetMod);
}
else
{
mc = null;
}
}
if (mc != null)
{
try
{
clz = Class.forName(targets.getClassName(), true, Loader.instance().getModClassLoader());
f = clz.getDeclaredField(targets.getObjectName());
f.setAccessible(true);
isStatic = Modifier.isStatic(f.getModifiers());
injectedMod = retreiver.apply(mc);
}
catch (Exception e)
{
Throwables.propagateIfPossible(e);
FMLLog.log(Level.WARNING, e, "Attempting to load @%s in class %s for %s and failing", annotationName, targets.getClassName(), mc.getModId());
}
}
if (f != null)
{
Object target = null;
if (!isStatic)
{
target = modInstance;
if (!modInstance.getClass().equals(clz))
{
FMLLog.warning("Unable to inject @%s in non-static field %s.%s for %s as it is NOT the primary mod instance", annotationName, targets.getClassName(), targets.getObjectName(), mc.getModId());
continue;
}
}
f.set(target, injectedMod);
}
}
}
@Subscribe
public void constructMod(FMLConstructionEvent event)
{
try
{
ModClassLoader modClassLoader = event.getModClassLoader();
modClassLoader.addFile(source);
Class<?> clazz = Class.forName(className, true, modClassLoader);
ASMDataTable asmHarvestedAnnotations = event.getASMHarvestedData();
// TODO
asmHarvestedAnnotations.getAnnotationsFor(this);
annotations = gatherAnnotations(clazz);
isNetworkMod = FMLNetworkHandler.instance().registerNetworkMod(this, clazz, event.getASMHarvestedData());
modInstance = clazz.newInstance();
ProxyInjector.inject(this, event.getASMHarvestedData(), FMLCommonHandler.instance().getSide());
processFieldAnnotations(event.getASMHarvestedData());
}
catch (Throwable e)
{
controller.errorOccurred(this, e);
Throwables.propagateIfPossible(e);
}
}
@Subscribe
public void handleModStateEvent(FMLStateEvent event)
{
Class<? extends Annotation> annotation = modAnnotationTypes.get(event.getClass());
if (annotation == null)
{
return;
}
try
{
for (Object o : annotations.get(annotation))
{
Method m = (Method) o;
m.invoke(modInstance, event);
}
}
catch (Throwable t)
{
controller.errorOccurred(this, t);
Throwables.propagateIfPossible(t);
}
}
@Override
public ArtifactVersion getProcessedVersion()
{
if (processedVersion == null)
{
processedVersion = new DefaultArtifactVersion(getModId(), getVersion());
}
return processedVersion;
}
@Override
public boolean isImmutable()
{
return false;
}
@Override
public boolean isNetworkMod()
{
return isNetworkMod;
}
@Override
public String getDisplayVersion()
{
return modMetadata.version;
}
}
@@ -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,8 @@
package cpw.mods.fml.common;
import java.util.concurrent.Callable;
public interface ICrashCallable extends Callable<String>
{
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.ItemStack;
import net.minecraft.src.World;
public interface IDispenseHandler
{
/**
* Return -1 if you don't want to dispense anything. the other values seem to have specific meanings
* to blockdispenser.
*
* @param x
* @param y
* @param z
* @param xVelocity
* @param zVelocity
* @param world
* @param item
* @param random
* @param entX
* @param entY
* @param entZ
* @return
*/
@Deprecated
int dispense(double x, double y, double z, int xVelocity, int zVelocity, World world, ItemStack item, Random random, double entX, double entY, double entZ);
}
@@ -0,0 +1,30 @@
package cpw.mods.fml.common;
import java.util.Random;
import net.minecraft.src.ItemStack;
import net.minecraft.src.World;
/**
* @author cpw
*
*/
public interface IDispenserHandler
{
/**
* Called to dispense an entity
* @param x
* @param y
* @param z
* @param xVelocity
* @param zVelocity
* @param world
* @param item
* @param random
* @param entX
* @param entY
* @param entZ
* @return
*/
int dispense(int x, int y, int z, int xVelocity, int zVelocity, World world, ItemStack item, Random random, double entX, double entY, double entZ);
}
@@ -0,0 +1,44 @@
package cpw.mods.fml.common;
import java.util.List;
import net.minecraft.server.MinecraftServer;
import net.minecraft.src.Entity;
import net.minecraft.src.NetHandler;
import net.minecraft.src.Packet;
import net.minecraft.src.Packet131MapData;
import cpw.mods.fml.common.network.EntitySpawnAdjustmentPacket;
import cpw.mods.fml.common.network.EntitySpawnPacket;
import cpw.mods.fml.common.network.ModMissingPacket;
import cpw.mods.fml.common.registry.EntityRegistry.EntityRegistration;
public interface IFMLSidedHandler
{
List<String> getAdditionalBrandingInformation();
Side getSide();
void haltGame(String message, Throwable exception);
void showGuiScreen(Object clientGuiElement);
Entity spawnEntityIntoClientWorld(EntityRegistration registration, EntitySpawnPacket packet);
void adjustEntityLocationOnClient(EntitySpawnAdjustmentPacket entitySpawnAdjustmentPacket);
void beginServerLoading(MinecraftServer server);
void finishServerLoading();
MinecraftServer getServer();
void sendPacket(Packet packet);
void displayMissingMods(ModMissingPacket modMissingPacket);
void handleTinyPacket(NetHandler handler, Packet131MapData mapData);
void setClientCompatibilityLevel(byte compatibilityLevel);
byte getClientCompatibilityLevel();
}
@@ -0,0 +1,8 @@
package cpw.mods.fml.common;
import net.minecraft.src.ItemStack;
public interface IFuelHandler
{
int getBurnTime(ItemStack fuel);
}
@@ -0,0 +1,26 @@
/*
* The FML Forge Mod Loader suite. Copyright (C) 2012 cpw
*
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package cpw.mods.fml.common;
/**
* @author cpw
*
*/
public interface INetworkHandler
{
boolean onChat(Object... data);
void onPacket250Packet(Object... data);
void onServerLogin(Object handler);
}
@@ -0,0 +1,22 @@
/*
* The FML Forge Mod Loader suite.
* Copyright (C) 2012 cpw
*
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package cpw.mods.fml.common;
import net.minecraft.src.EntityItem;
import net.minecraft.src.EntityPlayer;
public interface IPickupNotifier
{
void notifyPickup(EntityItem item, EntityPlayer player);
}
@@ -0,0 +1,32 @@
/*
* The FML Forge Mod Loader suite.
* Copyright (C) 2012 cpw
*
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package cpw.mods.fml.common;
import net.minecraft.src.EntityPlayer;
/**
* @author cpw
*
*/
public interface IPlayerTracker
{
void onPlayerLogin(EntityPlayer player);
void onPlayerLogout(EntityPlayer player);
void onPlayerChangedDimension(EntityPlayer player);
void onPlayerRespawn(EntityPlayer player);
}
@@ -0,0 +1,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 chunk X coordinate of this chunk.
* @param chunkZ the chunk Z coordinate of this chunk.
* @param world : additionalData[0] The minecraft {@link World} we're generating for.
* @param 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,113 @@
package cpw.mods.fml.common;
import java.io.File;
import java.util.List;
import java.util.Set;
import com.google.common.eventbus.EventBus;
import cpw.mods.fml.common.versioning.ArtifactVersion;
public class InjectedModContainer implements ModContainer
{
private File source;
private ModContainer wrappedContainer;
public InjectedModContainer(ModContainer mc, File source)
{
this.source = source;
this.wrappedContainer = mc;
}
public String getModId()
{
return wrappedContainer.getModId();
}
public String getName()
{
return wrappedContainer.getName();
}
public String getVersion()
{
return wrappedContainer.getVersion();
}
public File getSource()
{
return source;
}
public ModMetadata getMetadata()
{
return wrappedContainer.getMetadata();
}
public void bindMetadata(MetadataCollection mc)
{
wrappedContainer.bindMetadata(mc);
}
public void setEnabledState(boolean enabled)
{
wrappedContainer.setEnabledState(enabled);
}
public Set<ArtifactVersion> getRequirements()
{
return wrappedContainer.getRequirements();
}
public List<ArtifactVersion> getDependencies()
{
return wrappedContainer.getDependencies();
}
public List<ArtifactVersion> getDependants()
{
return wrappedContainer.getDependants();
}
public String getSortingRules()
{
return wrappedContainer.getSortingRules();
}
public boolean registerBus(EventBus bus, LoadController controller)
{
return wrappedContainer.registerBus(bus, controller);
}
public boolean matches(Object mod)
{
return wrappedContainer.matches(mod);
}
public Object getMod()
{
return wrappedContainer.getMod();
}
public ArtifactVersion getProcessedVersion()
{
return wrappedContainer.getProcessedVersion();
}
@Override
public boolean isNetworkMod()
{
return wrappedContainer.isNetworkMod();
}
@Override
public boolean isImmutable()
{
return true;
}
@Override
public String getDisplayVersion()
{
return wrappedContainer.getDisplayVersion();
}
}
@@ -0,0 +1,210 @@
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.ImmutableBiMap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;
import cpw.mods.fml.common.LoaderState.ModState;
import cpw.mods.fml.common.event.FMLLoadEvent;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import cpw.mods.fml.common.event.FMLStateEvent;
public class LoadController
{
private Loader loader;
private EventBus masterChannel;
private ImmutableMap<String,EventBus> eventChannels;
private LoaderState state;
private Multimap<String, ModState> modStates = ArrayListMultimap.create();
private Multimap<String, Throwable> errors = ArrayListMultimap.create();
private Map<String, ModContainer> modList;
private List<ModContainer> activeModList = Lists.newArrayList();
private ModContainer activeContainer;
private BiMap<ModContainer, Object> modObjectList;
public LoadController(Loader loader)
{
this.loader = loader;
this.masterChannel = new EventBus("FMLMainChannel");
this.masterChannel.register(this);
state = LoaderState.NOINIT;
}
@Subscribe
public void buildModList(FMLLoadEvent event)
{
this.modList = loader.getIndexedModList();
Builder<String, EventBus> eventBus = ImmutableMap.builder();
for (ModContainer mod : loader.getModList())
{
EventBus bus = new EventBus(mod.getModId());
boolean isActive = mod.registerBus(bus, this);
if (isActive)
{
FMLLog.fine("Activating mod %s", mod.getModId());
activeModList.add(mod);
modStates.put(mod.getModId(), ModState.UNLOADED);
eventBus.put(mod.getModId(), bus);
}
else
{
FMLLog.warning("Mod %s has been disabled through configuration", mod.getModId());
modStates.put(mod.getModId(), ModState.UNLOADED);
modStates.put(mod.getModId(), ModState.DISABLED);
}
}
eventChannels = eventBus.build();
}
public void distributeStateMessage(LoaderState state, Object... eventData)
{
if (state.hasEvent())
{
masterChannel.post(state.getEvent(eventData));
}
}
public void transition(LoaderState desiredState)
{
LoaderState oldState = state;
state = state.transition(!errors.isEmpty());
if (state != desiredState)
{
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;
}
@Subscribe
public void propogateStateMessage(FMLStateEvent stateEvent)
{
if (stateEvent instanceof FMLPreInitializationEvent)
{
modObjectList = buildModObjectList();
}
for (ModContainer mc : activeModList)
{
activeContainer = mc;
String modId = mc.getModId();
stateEvent.applyModContainer(activeContainer());
FMLLog.finer("Posting state event %s to mod %s", stateEvent, modId);
eventChannels.get(modId).post(stateEvent);
FMLLog.finer("State event %s delivered to mod %s", stateEvent, modId);
activeContainer = null;
if (!errors.containsKey(modId))
{
modStates.put(modId, stateEvent.getModState());
}
else
{
modStates.put(modId, ModState.ERRORED);
}
}
}
public ImmutableBiMap<ModContainer, Object> buildModObjectList()
{
ImmutableBiMap.Builder<ModContainer, Object> builder = ImmutableBiMap.<ModContainer, Object>builder();
for (ModContainer mc : activeModList)
{
if (!mc.isImmutable() && mc.getMod()!=null)
{
builder.put(mc, mc.getMod());
}
if (mc.getMod()==null && !mc.isImmutable() && state!=LoaderState.CONSTRUCTING)
{
FMLLog.severe("There is a severe problem with %s - it appears not to have constructed correctly", mc.getModId());
if (state != LoaderState.CONSTRUCTING)
{
this.errorOccurred(mc, new RuntimeException());
}
}
}
return builder.build();
}
public void errorOccurred(ModContainer modContainer, Throwable exception)
{
errors.put(modContainer.getModId(), exception);
}
public void printModStates(StringBuilder ret)
{
for (ModContainer mc : loader.getModList())
{
ret.append("\n\t").append(mc.getModId()).append(" [").append(mc.getName()).append("] (").append(mc.getSource().getName()).append(") ");
Joiner.on("->"). appendTo(ret, modStates.get(mc.getModId()));
}
}
public List<ModContainer> getActiveModList()
{
return activeModList;
}
public ModState getModState(ModContainer selectedMod)
{
return Iterables.getLast(modStates.get(selectedMod.getModId()), ModState.AVAILABLE);
}
public void distributeStateMessage(Class<?> customEvent)
{
try
{
masterChannel.post(customEvent.newInstance());
}
catch (Exception e)
{
FMLLog.log(Level.SEVERE, e, "An unexpected exception");
throw new LoaderException(e);
}
}
public BiMap<ModContainer, Object> getModObjectList()
{
if (modObjectList == null)
{
FMLLog.severe("Detected an attempt by a mod %s to perform game activity during mod construction. This is a serious programming error.", activeContainer);
return buildModObjectList();
}
return ImmutableBiMap.copyOf(modObjectList);
}
public boolean isInState(LoaderState state)
{
return this.state == state;
}
}
+719
View File
@@ -0,0 +1,719 @@
/*
* The FML Forge Mod Loader suite.
* Copyright (C) 2012 cpw
*
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package cpw.mods.fml.common;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.logging.Level;
import net.minecraft.src.CallableMinecraftVersion;
import com.google.common.base.CharMatcher;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMultiset;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.common.collect.Multiset.Entry;
import com.google.common.collect.Multisets;
import com.google.common.collect.Ordering;
import com.google.common.collect.Sets.SetView;
import com.google.common.collect.TreeMultimap;
import cpw.mods.fml.common.LoaderState.ModState;
import cpw.mods.fml.common.discovery.ModDiscoverer;
import cpw.mods.fml.common.event.FMLLoadEvent;
import cpw.mods.fml.common.functions.ModIdFunction;
import cpw.mods.fml.common.modloader.BaseModProxy;
import cpw.mods.fml.common.toposort.ModSorter;
import cpw.mods.fml.common.toposort.ModSortingException;
import cpw.mods.fml.common.toposort.TopologicalSort;
import cpw.mods.fml.common.versioning.ArtifactVersion;
import cpw.mods.fml.common.versioning.VersionParser;
/**
* The loader class performs the actual loading of the mod code from disk.
*
* <p>
* There are several {@link LoaderState}s to mod loading, triggered in two
* different stages from the FML handler code's hooks into the minecraft code.
* </p>
*
* <ol>
* <li>LOADING. Scanning the filesystem for mod containers to load (zips, jars,
* directories), adding them to the {@link #modClassLoader} Scanning, the loaded
* containers for mod classes to load and registering them appropriately.</li>
* <li>PREINIT. The mod classes are configured, they are sorted into a load
* order, and instances of the mods are constructed.</li>
* <li>INIT. The mod instances are initialized. For BaseMod mods, this involves
* calling the load method.</li>
* <li>POSTINIT. The mod instances are post initialized. For BaseMod mods this
* involves calling the modsLoaded method.</li>
* <li>UP. The Loader is complete</li>
* <li>ERRORED. The loader encountered an error during the LOADING phase and
* dropped to this state instead. It will not complete loading from this state,
* but it attempts to continue loading before abandoning and giving a fatal
* error.</li>
* </ol>
*
* Phase 1 code triggers the LOADING and PREINIT states. Phase 2 code triggers
* the INIT and POSTINIT states.
*
* @author cpw
*
*/
public class Loader
{
private static final Splitter DEPENDENCYPARTSPLITTER = Splitter.on(":").omitEmptyStrings().trimResults();
private static final Splitter DEPENDENCYSPLITTER = Splitter.on(";").omitEmptyStrings().trimResults();
/**
* The singleton instance
*/
private static Loader instance;
/**
* Build information for tracking purposes.
*/
private static String major;
private static String minor;
private static String rev;
private static String build;
private static String mccversion;
private static String mcsversion;
/**
* The class loader we load the mods into.
*/
private ModClassLoader modClassLoader;
/**
* The sorted list of mods.
*/
private List<ModContainer> mods;
/**
* A named list of mods
*/
private Map<String, ModContainer> namedMods;
/**
* The canonical configuration directory
*/
private File canonicalConfigDir;
/**
* The canonical minecraft directory
*/
private File canonicalMinecraftDir;
/**
* The captured error
*/
private Exception capturedError;
private File canonicalModsDir;
private LoadController modController;
private static File minecraftDir;
private static List<String> injectedContainers;
public static Loader instance()
{
if (instance == null)
{
instance = new Loader();
}
return instance;
}
public static void injectData(Object... data)
{
major = (String) data[0];
minor = (String) data[1];
rev = (String) data[2];
build = (String) data[3];
mccversion = (String) data[4];
mcsversion = (String) data[5];
minecraftDir = (File) data[6];
injectedContainers = (List<String>)data[7];
}
private Loader()
{
modClassLoader = new ModClassLoader(getClass().getClassLoader());
String actualMCVersion = new CallableMinecraftVersion(null).func_71493_a();
if (!mccversion.equals(actualMCVersion))
{
FMLLog.severe("This version of FML is built for Minecraft %s, we have detected Minecraft %s in your minecraft jar file", mccversion, actualMCVersion);
throw new LoaderException();
}
}
/**
* Sort the mods into a sorted list, using dependency information from the
* containers. The sorting is performed using a {@link TopologicalSort}
* based on the pre- and post- dependency information provided by the mods.
*/
private void sortModList()
{
FMLLog.fine("Verifying mod requirements are satisfied");
try
{
BiMap<String, ArtifactVersion> modVersions = HashBiMap.create();
for (ModContainer mod : getActiveModList())
{
modVersions.put(mod.getModId(), mod.getProcessedVersion());
}
for (ModContainer mod : getActiveModList())
{
Map<String,ArtifactVersion> names = Maps.uniqueIndex(mod.getRequirements(), new Function<ArtifactVersion, String>()
{
public String apply(ArtifactVersion v)
{
return v.getLabel();
}
});
Set<String> missingMods = Sets.difference(names.keySet(), modVersions.keySet());
Set<ArtifactVersion> versionMissingMods = Sets.newHashSet();
if (!missingMods.isEmpty())
{
FMLLog.severe("The mod %s (%s) requires mods %s to be available", mod.getModId(), mod.getName(), missingMods);
for (String modid : missingMods)
{
versionMissingMods.add(names.get(modid));
}
throw new MissingModsException(versionMissingMods);
}
ImmutableList<ArtifactVersion> allDeps = ImmutableList.<ArtifactVersion>builder().addAll(mod.getDependants()).addAll(mod.getDependencies()).build();
for (ArtifactVersion v : allDeps)
{
if (modVersions.containsKey(v.getLabel()))
{
if (!v.containsVersion(modVersions.get(v.getLabel())))
{
versionMissingMods.add(v);
}
}
}
if (!versionMissingMods.isEmpty())
{
FMLLog.severe("The mod %s (%s) requires mod versions %s to be available", mod.getModId(), mod.getName(), versionMissingMods);
throw new MissingModsException(versionMissingMods);
}
}
FMLLog.fine("All mod requirements are satisfied");
ModSorter sorter = new ModSorter(getActiveModList(), namedMods);
try
{
FMLLog.fine("Sorting mods into an ordered list");
List<ModContainer> sortedMods = sorter.sort();
// Reset active list to the sorted list
modController.getActiveModList().clear();
modController.getActiveModList().addAll(sortedMods);
// And inject the sorted list into the overall list
mods.removeAll(sortedMods);
sortedMods.addAll(mods);
mods = sortedMods;
FMLLog.fine("Mod sorting completed successfully");
}
catch (ModSortingException sortException)
{
FMLLog.severe("A dependency cycle was detected in the input mod set so an ordering cannot be determined");
FMLLog.severe("The visited mod list is %s", sortException.getExceptionData().getVisitedNodes());
FMLLog.severe("The first mod in the cycle is %s", sortException.getExceptionData().getFirstBadNode());
FMLLog.log(Level.SEVERE, sortException, "The full error");
throw new LoaderException(sortException);
}
}
finally
{
FMLLog.fine("Mod sorting data:");
for (ModContainer mod : getActiveModList())
{
if (!mod.isImmutable())
{
FMLLog.fine("\t%s(%s:%s): %s (%s)", mod.getModId(), mod.getName(), mod.getVersion(), mod.getSource().getName(), mod.getSortingRules());
}
}
if (mods.size()==0)
{
FMLLog.fine("No mods found to sort");
}
}
}
/**
* The primary loading code
*
* This is visited during first initialization by Minecraft to scan and load
* the mods from all sources 1. The minecraft jar itself (for loading of in
* jar mods- I would like to remove this if possible but forge depends on it
* at present) 2. The mods directory with expanded subdirs, searching for
* mods named mod_*.class 3. The mods directory for zip and jar files,
* searching for mod classes named mod_*.class again
*
* The found resources are first loaded into the {@link #modClassLoader}
* (always) then scanned for class resources matching the specification
* above.
*
* If they provide the {@link Mod} annotation, they will be loaded as
* "FML mods", which currently is effectively a NO-OP. If they are
* determined to be {@link BaseModProxy} subclasses they are loaded as such.
*
* Finally, if they are successfully loaded as classes, they are then added
* to the available mod list.
*/
private ModDiscoverer identifyMods()
{
FMLLog.fine("Building injected Mod Containers %s", injectedContainers);
File coremod = new File(minecraftDir,"coremods");
for (String cont : injectedContainers)
{
ModContainer mc;
try
{
mc = (ModContainer) Class.forName(cont,true,modClassLoader).newInstance();
}
catch (Exception e)
{
FMLLog.log(Level.SEVERE, e, "A problem occured instantiating the injected mod container %s", cont);
throw new LoaderException(e);
}
mods.add(new InjectedModContainer(mc,coremod));
}
ModDiscoverer discoverer = new ModDiscoverer();
FMLLog.fine("Attempting to load mods contained in the minecraft jar file and associated classes");
discoverer.findClasspathMods(modClassLoader);
FMLLog.fine("Minecraft jar mods loaded successfully");
FMLLog.info("Searching %s for mods", canonicalModsDir.getAbsolutePath());
discoverer.findModDirMods(canonicalModsDir);
mods.addAll(discoverer.identifyMods());
identifyDuplicates(mods);
namedMods = Maps.uniqueIndex(mods, new ModIdFunction());
FMLLog.info("Forge Mod Loader has identified %d mod%s to load", mods.size(), mods.size() != 1 ? "s" : "");
return discoverer;
}
private class ModIdComparator implements Comparator<ModContainer>
{
@Override
public int compare(ModContainer o1, ModContainer o2)
{
return o1.getModId().compareTo(o2.getModId());
}
}
private void identifyDuplicates(List<ModContainer> mods)
{
boolean foundDupe = false;
TreeMultimap<ModContainer, File> dupsearch = TreeMultimap.create(new ModIdComparator(), Ordering.arbitrary());
for (ModContainer mc : mods)
{
if (mc.getSource() != null)
{
dupsearch.put(mc, mc.getSource());
}
}
ImmutableMultiset<ModContainer> duplist = Multisets.copyHighestCountFirst(dupsearch.keys());
for (Entry<ModContainer> e : duplist.entrySet())
{
if (e.getCount() > 1)
{
FMLLog.severe("Found a duplicate mod %s at %s", e.getElement().getModId(), dupsearch.get(e.getElement()));
foundDupe = true;
}
}
if (foundDupe) { throw new LoaderException(); }
}
/**
* @return
*/
private void initializeLoader()
{
File modsDir = new File(minecraftDir, "mods");
File configDir = new File(minecraftDir, "config");
String canonicalModsPath;
String canonicalConfigPath;
try
{
canonicalMinecraftDir = minecraftDir.getCanonicalFile();
canonicalModsPath = modsDir.getCanonicalPath();
canonicalConfigPath = configDir.getCanonicalPath();
canonicalConfigDir = configDir.getCanonicalFile();
canonicalModsDir = modsDir.getCanonicalFile();
}
catch (IOException ioe)
{
FMLLog.log(Level.SEVERE, ioe, "Failed to resolve loader directories: mods : %s ; config %s", canonicalModsDir.getAbsolutePath(),
configDir.getAbsolutePath());
throw new LoaderException(ioe);
}
if (!canonicalModsDir.exists())
{
FMLLog.info("No mod directory found, creating one: %s", canonicalModsPath);
boolean dirMade = canonicalModsDir.mkdir();
if (!dirMade)
{
FMLLog.severe("Unable to create the mod directory %s", canonicalModsPath);
throw new LoaderException();
}
FMLLog.info("Mod directory created successfully");
}
if (!canonicalConfigDir.exists())
{
FMLLog.fine("No config directory found, creating one: %s", canonicalConfigPath);
boolean dirMade = canonicalConfigDir.mkdir();
if (!dirMade)
{
FMLLog.severe("Unable to create the config directory %s", canonicalConfigPath);
throw new LoaderException();
}
FMLLog.info("Config directory created successfully");
}
if (!canonicalModsDir.isDirectory())
{
FMLLog.severe("Attempting to load mods from %s, which is not a directory", canonicalModsPath);
throw new LoaderException();
}
if (!configDir.isDirectory())
{
FMLLog.severe("Attempting to load configuration from %s, which is not a directory", canonicalConfigPath);
throw new LoaderException();
}
}
public List<ModContainer> getModList()
{
return 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();
modController.distributeStateMessage(FMLLoadEvent.class);
sortModList();
mods = ImmutableList.copyOf(mods);
for (File nonMod : disc.getNonModLibs())
{
if (nonMod.isFile())
{
FMLLog.severe("FML has found a non-mod file %s in your mods directory. It will now be injected into your classpath. This could severe stability issues, it should be removed if possible.", nonMod.getName());
try
{
modClassLoader.addFile(nonMod);
}
catch (MalformedURLException e)
{
FMLLog.log(Level.SEVERE, e, "Encountered a weird problem with non-mod file injection : %s", nonMod.getName());
}
}
}
modController.transition(LoaderState.CONSTRUCTING);
modController.distributeStateMessage(LoaderState.CONSTRUCTING, modClassLoader, disc.getASMTable());
modController.transition(LoaderState.PREINITIALIZATION);
modController.distributeStateMessage(LoaderState.PREINITIALIZATION, disc.getASMTable(), canonicalConfigDir);
modController.transition(LoaderState.INITIALIZATION);
}
private void disableRequestedMods()
{
String forcedModList = System.getProperty("fml.modStates", "");
FMLLog.fine("Received a system property request \'%s\'",forcedModList);
Map<String, String> sysPropertyStateList = Splitter.on(CharMatcher.anyOf(";:"))
.omitEmptyStrings().trimResults().withKeyValueSeparator("=")
.split(forcedModList);
FMLLog.fine("System property request managing the state of %d mods", sysPropertyStateList.size());
Map<String, String> modStates = Maps.newHashMap();
File forcedModFile = new File(canonicalConfigDir, "fmlModState.properties");
Properties forcedModListProperties = new Properties();
if (forcedModFile.exists() && forcedModFile.isFile())
{
FMLLog.fine("Found a mod state file %s", forcedModFile.getName());
try
{
forcedModListProperties.load(new FileReader(forcedModFile));
FMLLog.fine("Loaded states for %d mods from file", forcedModListProperties.size());
}
catch (Exception e)
{
FMLLog.log(Level.INFO, e, "An error occurred reading the fmlModState.properties file");
}
}
modStates.putAll(Maps.fromProperties(forcedModListProperties));
modStates.putAll(sysPropertyStateList);
FMLLog.fine("After merging, found state information for %d mods", modStates.size());
Map<String, Boolean> isEnabled = Maps.transformValues(modStates, new Function<String, Boolean>()
{
public Boolean apply(String input)
{
return Boolean.parseBoolean(input);
}
});
for (Map.Entry<String, Boolean> entry : isEnabled.entrySet())
{
if (namedMods.containsKey(entry.getKey()))
{
FMLLog.info("Setting mod %s to enabled state %b", entry.getKey(), entry.getValue());
namedMods.get(entry.getKey()).setEnabledState(entry.getValue());
}
}
}
/**
* Query if we know of a mod named modname
*
* @param modname
* @return
*/
public static boolean isModLoaded(String modname)
{
return instance().namedMods.containsKey(modname) && instance().modController.getModState(instance.namedMods.get(modname))!=ModState.DISABLED;
}
/**
* @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("%s.%s.%s.%s", major, minor, rev, build);
}
/**
* @return
*/
public ClassLoader getModClassLoader()
{
return modClassLoader;
}
public void computeDependencies(String dependencyString, Set<ArtifactVersion> requirements, List<ArtifactVersion> dependencies, List<ArtifactVersion> dependants)
{
if (dependencyString == null || dependencyString.length() == 0)
{
return;
}
boolean parseFailure=false;
for (String dep : DEPENDENCYSPLITTER.split(dependencyString))
{
List<String> depparts = Lists.newArrayList(DEPENDENCYPARTSPLITTER.split(dep));
// Need two parts to the string
if (depparts.size() != 2)
{
parseFailure=true;
continue;
}
String instruction = depparts.get(0);
String target = depparts.get(1);
boolean targetIsAll = target.startsWith("*");
// Cannot have an "all" relationship with anything except pure *
if (targetIsAll && target.length()>1)
{
parseFailure = true;
continue;
}
// If this is a required element, add it to the required list
if ("required-before".equals(instruction) || "required-after".equals(instruction))
{
// You can't require everything
if (!targetIsAll)
{
requirements.add(VersionParser.parseVersionReference(target));
}
else
{
parseFailure=true;
continue;
}
}
// You cannot have a versioned dependency on everything
if (targetIsAll && target.indexOf('@')>-1)
{
parseFailure = true;
continue;
}
// before elements are things we are loaded before (so they are our dependants)
if ("required-before".equals(instruction) || "before".equals(instruction))
{
dependants.add(VersionParser.parseVersionReference(target));
}
// after elements are things that load before we do (so they are out dependencies)
else if ("required-after".equals(instruction) || "after".equals(instruction))
{
dependencies.add(VersionParser.parseVersionReference(target));
}
else
{
parseFailure=true;
}
}
if (parseFailure)
{
FMLLog.log(Level.WARNING, "Unable to parse dependency string %s", dependencyString);
throw new LoaderException();
}
}
public Map<String,ModContainer> getIndexedModList()
{
return ImmutableMap.copyOf(namedMods);
}
public void initializeMods()
{
// Mod controller should be in the initialization state here
modController.distributeStateMessage(LoaderState.INITIALIZATION);
modController.transition(LoaderState.POSTINITIALIZATION);
modController.distributeStateMessage(LoaderState.POSTINITIALIZATION);
modController.transition(LoaderState.AVAILABLE);
modController.distributeStateMessage(LoaderState.AVAILABLE);
FMLLog.info("Forge Mod Loader has successfully loaded %d mod%s", mods.size(), mods.size()==1 ? "" : "s");
}
public ICrashCallable getCallableCrashInformation()
{
return new ICrashCallable() {
@Override
public String call() throws Exception
{
return getCrashInformation();
}
@Override
public String getLabel()
{
return "FML";
}
};
}
public List<ModContainer> getActiveModList()
{
return modController.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();
}
public ModContainer activeModContainer()
{
return modController.activeContainer();
}
public boolean isInState(LoaderState state)
{
return modController.isInState(state);
}
}
@@ -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()
{
}
}
+103
View File
@@ -0,0 +1,103 @@
package cpw.mods.fml.common;
import com.google.common.base.Throwables;
import cpw.mods.fml.common.event.FMLConstructionEvent;
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.FMLServerStartedEvent;
import cpw.mods.fml.common.event.FMLServerStartingEvent;
import cpw.mods.fml.common.event.FMLServerStoppingEvent;
import cpw.mods.fml.common.event.FMLStateEvent;
/**
* The state enum used to help track state progression for the loader
* @author cpw
*
*/
public enum LoaderState
{
NOINIT("Uninitialized",null),
LOADING("Loading",null),
CONSTRUCTING("Constructing mods",FMLConstructionEvent.class),
PREINITIALIZATION("Pre-initializing mods", FMLPreInitializationEvent.class),
INITIALIZATION("Initializing mods", FMLInitializationEvent.class),
POSTINITIALIZATION("Post-initializing mods", FMLPostInitializationEvent.class),
AVAILABLE("Mod loading complete", FMLLoadCompleteEvent.class),
SERVER_STARTING("Server starting", FMLServerStartingEvent.class),
SERVER_STARTED("Server started", FMLServerStartedEvent.class),
SERVER_STOPPING("Server stopping", FMLServerStoppingEvent.class),
ERRORED("Mod Loading errored",null);
private Class<? extends FMLStateEvent> eventClass;
private String name;
private LoaderState(String name, Class<? extends FMLStateEvent> event)
{
this.name = name;
this.eventClass = event;
}
public LoaderState transition(boolean errored)
{
if (errored)
{
return ERRORED;
}
// stopping -> available
if (this == SERVER_STOPPING)
{
return AVAILABLE;
}
return values()[ordinal() < values().length ? ordinal()+1 : ordinal()];
}
public boolean hasEvent()
{
return eventClass != null;
}
public FMLStateEvent getEvent(Object... eventData)
{
try
{
return eventClass.getConstructor(Object[].class).newInstance((Object)eventData);
}
catch (Exception e)
{
throw Throwables.propagate(e);
}
}
public LoaderState requiredState()
{
if (this == NOINIT) return NOINIT;
return LoaderState.values()[this.ordinal()-1];
}
public enum ModState
{
UNLOADED("Unloaded"),
LOADED("Loaded"),
CONSTRUCTED("Constructed"),
PREINITIALIZED("Pre-initialized"),
INITIALIZED("Initialized"),
POSTINITIALIZED("Post-initialized"),
AVAILABLE("Available"),
DISABLED("Disabled"),
ERRORED("Errored");
private String label;
private ModState(String label)
{
this.label = label;
}
public String toString()
{
return this.label;
}
}
}
@@ -0,0 +1,91 @@
package cpw.mods.fml.common;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Map;
import java.util.logging.Level;
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.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, String sourceName)
{
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 (InvalidSyntaxException e)
{
FMLLog.log(Level.SEVERE, e, "The mcmod.info file in %s cannot be parsed as valid JSON. It will be ignored", sourceName);
return new MetadataCollection();
}
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,18 @@
package cpw.mods.fml.common;
import java.util.Set;
import com.google.common.collect.Sets.SetView;
import cpw.mods.fml.common.versioning.ArtifactVersion;
public class MissingModsException extends RuntimeException
{
public Set<ArtifactVersion> missingMods;
public MissingModsException(Set<ArtifactVersion> missingMods)
{
this.missingMods = missingMods;
}
}
+174
View File
@@ -0,0 +1,174 @@
/*
* 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 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,89 @@
/*
* 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.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.asm.ASMTransformer;
import cpw.mods.fml.common.asm.transformers.AccessTransformer;
import cpw.mods.fml.common.modloader.BaseModProxy;
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;
}
public Class<? extends BaseModProxy> loadBaseModClass(String modClazzName) throws Exception
{
AccessTransformer transformer = (AccessTransformer)mainClassLoader.getTransformers().get(0);
transformer.ensurePublicAccessFor(modClazzName);
return (Class<? extends BaseModProxy>) Class.forName(modClazzName, true, this);
}
}
@@ -0,0 +1,155 @@
/*
* 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.util.List;
import java.util.Set;
import com.google.common.eventbus.EventBus;
import cpw.mods.fml.common.versioning.ArtifactVersion;
/**
* The container that wraps around mods in the system.
* <p>
* The philosophy is that individual mod implementation technologies should not
* impact the actual loading and management of mod code. This interface provides
* a mechanism by which we can wrap actual mod code so that the loader and other
* facilities can treat mods at arms length.
* </p>
*
* @author cpw
*
*/
public interface ModContainer
{
/**
* 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();
/**
* A list of modids that should be loaded prior to this one. The special
* 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>after</em> any
* other mod.
*
* @return
*/
List<ArtifactVersion> getDependants();
/**
* A representative string encapsulating the sorting preferences for this
* mod
*
* @return
*/
String getSortingRules();
/**
* Register the event bus for the mod and the controller for error handling
* Returns if this bus was successfully registered - disabled mods and other
* mods that don't need real events should return false and avoid further
* processing
*
* @param bus
* @param controller
* @return
*/
boolean registerBus(EventBus bus, LoadController controller);
/**
* Does this mod match the supplied mod
*
* @param mod
* @return
*/
boolean matches(Object mod);
/**
* Get the actual mod object
*
* @return
*/
Object getMod();
ArtifactVersion getProcessedVersion();
boolean isImmutable();
boolean isNetworkMod();
String getDisplayVersion();
}
@@ -0,0 +1,58 @@
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.ModCandidate;
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, ModCandidate container)
{
String className = modParser.getASMType().getClassName();
if (modParser.isBaseMod(container.getRememberedBaseMods()) && modClass.matcher(className).find())
{
FMLLog.fine("Identified a BaseMod type mod %s", className);
return new ModLoaderModContainer(className, modSource, modParser.getBaseModProperties());
}
else if (modClass.matcher(className).find())
{
FMLLog.fine("Identified a class %s following modloader naming convention but not directly a BaseMod or currently seen subclass", className);
container.rememberModCandidateType(modParser);
}
else if (modParser.isBaseMod(container.getRememberedBaseMods()))
{
FMLLog.fine("Found a basemod %s of non-standard naming format", className);
container.rememberBaseModType(className);
}
// We warn if it's not a basemod instance -- compatibility requires it to be in net.minecraft.src *sigh*
if (className.startsWith("net.minecraft.src.") && container.isClasspath() && !container.isMinecraftJar())
{
FMLLog.severe("FML has detected a mod that is using a package name based on 'net.minecraft.src' : %s. This is generally a severe programming error. "
+ " There should be no mod code in the minecraft namespace. MOVE YOUR MOD! If you're in eclipse, select your source code and 'refactor' it into "
+ "a new package. Go on. DO IT NOW!",className);
}
for (ModAnnotation ann : modParser.getAnnotations())
{
if (ann.getASMType().equals(Type.getType(Mod.class)))
{
FMLLog.fine("Identified an FMLMod type mod %s", className);
return new FMLModContainer(className, modSource, ann.getValues());
}
}
return null;
}
}
+173
View File
@@ -0,0 +1,173 @@
/*
* 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 static argo.jdom.JsonNodeBuilders.aStringBuilder;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
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.versioning.ArtifactVersion;
import cpw.mods.fml.common.versioning.VersionParser;
/**
* @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 Set<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"));
if (Strings.isNullOrEmpty(modId))
{
FMLLog.log(Level.SEVERE, "Found an invalid mod metadata file - missing modid");
throw new LoaderException();
}
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 = Objects.firstNonNull(((List<String>)processedFields.get(aStringBuilder("authors"))),Objects.firstNonNull(((List<String>)processedFields.get(aStringBuilder("authorList"))), authorList));
requiredMods = processReferences(processedFields.get(aStringBuilder("requiredMods")), HashSet.class);
dependencies = processReferences(processedFields.get(aStringBuilder("dependencies")), ArrayList.class);
dependants = processReferences(processedFields.get(aStringBuilder("dependants")), ArrayList.class);
useDependencyInformation = Boolean.parseBoolean(Strings.nullToEmpty((String)processedFields.get(aStringBuilder("useDependencyInformation"))));
}
public ModMetadata()
{
}
private <T extends Collection<ArtifactVersion>> T processReferences(Object refs, Class<? extends T> retType)
{
T res = null;
try
{
res = retType.newInstance();
}
catch (Exception e)
{
// unpossible
}
if (refs == null)
{
return res;
}
for (String ref : ((List<String>)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 "";
}
}
@@ -0,0 +1,116 @@
/*
* The FML Forge Mod Loader suite. Copyright (C) 2012 cpw
*
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package cpw.mods.fml.common;
import java.util.Arrays;
import java.util.logging.Level;
import cpw.mods.fml.relauncher.ReflectionHelper;
import cpw.mods.fml.relauncher.ReflectionHelper.UnableToAccessFieldException;
import cpw.mods.fml.relauncher.ReflectionHelper.UnableToFindFieldException;
/**
* Some reflection helper code.
*
* @author cpw
*
*/
public class ObfuscationReflectionHelper
{
public static boolean obfuscation;
@SuppressWarnings("unchecked")
public static <T, E> T getPrivateValue(Class<? super E> classToAccess, E instance, int fieldIndex)
{
try
{
return ReflectionHelper.getPrivateValue(classToAccess, instance, fieldIndex);
}
catch (UnableToAccessFieldException e)
{
FMLLog.log(Level.SEVERE, e, "There was a problem getting field index %d from %s", fieldIndex, classToAccess.getName());
throw e;
}
}
@SuppressWarnings("unchecked")
public static <T, E> T getPrivateValue(Class<? super E> classToAccess, E instance, String... fieldNames)
{
try
{
return ReflectionHelper.getPrivateValue(classToAccess, instance, fieldNames);
}
catch (UnableToFindFieldException e)
{
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.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
{
ReflectionHelper.setPrivateValue(classToAccess, instance, value, fieldIndex);
}
catch (UnableToAccessFieldException e)
{
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, fieldNames);
}
catch (UnableToFindFieldException e)
{
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.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,72 @@
/*
* 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 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);
}
}
}
}
+35
View File
@@ -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;
}
}
+83
View File
@@ -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,72 @@
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.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,15 @@
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();
}
@@ -0,0 +1,418 @@
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 java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
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.net.URL;
import java.util.Collection;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.FieldNode;
import org.objectweb.asm.tree.MethodNode;
import com.google.common.base.Charsets;
import com.google.common.base.Splitter;
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.LineProcessor;
import com.google.common.io.Resources;
import cpw.mods.fml.relauncher.IClassTransformer;
public class AccessTransformer implements IClassTransformer
{
private static final boolean DEBUG = false;
private class Modifier
{
public String name = "";
public String desc = "";
public int oldAccess = 0;
public int newAccess = 0;
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;
markFinal = false;
}
else if (name.endsWith("+f"))
{
changeFinal = true;
markFinal = true;
}
}
}
private Multimap<String, Modifier> modifiers = ArrayListMultimap.create();
public AccessTransformer() throws IOException
{
this("fml_at.cfg");
}
protected AccessTransformer(String rulesFile) throws IOException
{
readMapFile(rulesFile);
}
private void readMapFile(String rulesFile) throws IOException
{
File file = new File(rulesFile);
URL rulesResource;
if (file.exists())
{
rulesResource = file.toURI().toURL();
}
else
{
rulesResource = Resources.getResource(rulesFile);
}
Resources.readLines(rulesResource, Charsets.UTF_8, new LineProcessor<Void>()
{
@Override
public Void getResult()
{
return null;
}
@Override
public boolean processLine(String input) throws IOException
{
String line = Iterables.getFirst(Splitter.on('#').limit(2).split(input), "").trim();
if (line.length()==0)
{
return true;
}
List<String> parts = Lists.newArrayList(Splitter.on(" ").trimResults().split(line));
if (parts.size()>2)
{
throw new RuntimeException("Invalid config file line "+ input);
}
Modifier m = new Modifier();
m.setTargetAccess(parts.get(0));
List<String> descriptor = Lists.newArrayList(Splitter.on(".").trimResults().split(parts.get(1)));
if (descriptor.size() == 1)
{
m.modifyClassVisibility = true;
}
else
{
String nameReference = descriptor.get(1);
int parenIdx = nameReference.indexOf('(');
if (parenIdx>0)
{
m.desc = nameReference.substring(parenIdx);
m.name = nameReference.substring(0,parenIdx);
}
else
{
m.name = nameReference;
}
}
modifiers.put(descriptor.get(0).replace('/', '.'), m);
return true;
}
});
}
@SuppressWarnings("unchecked")
@Override
public byte[] transform(String name, byte[] 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(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 : (List<FieldNode>) classNode.fields)
{
if (n.name.equals(m.name) || m.name.equals("*"))
{
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;
}
}
}
}
else
{
for (MethodNode n : (List<MethodNode>) classNode.methods)
{
if ((n.name.equals(m.name) && n.desc.equals(m.desc)) || m.name.equals("*"))
{
n.access = getFixedAccess(n.access, m);
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;
}
}
}
}
}
ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
classNode.accept(writer);
return writer.toByteArray();
}
private String toBinary(int num)
{
return String.format("%16s", Integer.toBinaryString(num)).replace(' ', '0');
}
private int getFixedAccess(int access, Modifier target)
{
target.oldAccess = access;
int t = target.targetAccess;
int ret = (access & ~7);
switch (access & 7)
{
case ACC_PRIVATE:
ret |= t;
break;
case 0: // default
ret |= (t != ACC_PRIVATE ? t : 0 /* default */);
break;
case ACC_PROTECTED:
ret |= (t != ACC_PRIVATE && t != 0 /* default */? t : ACC_PROTECTED);
break;
case ACC_PUBLIC:
ret |= (t != ACC_PRIVATE && t != 0 /* default */&& t != ACC_PROTECTED ? t : ACC_PUBLIC);
break;
default:
throw new RuntimeException("The fuck?");
}
// Clear the "final" marker on fields only if specified in control field
if (target.changeFinal && target.desc == "")
{
if (target.markFinal)
{
ret |= ACC_FINAL;
}
else
{
ret &= ~ACC_FINAL;
}
}
target.newAccess = ret;
return ret;
}
public static void main(String[] args)
{
if (args.length < 2)
{
System.out.println("Usage: AccessTransformer <JarPath> <MapFile> [MapFile2]... ");
System.exit(1);
}
boolean hasTransformer = false;
AccessTransformer[] trans = new AccessTransformer[args.length - 1];
for (int x = 1; x < args.length; x++)
{
try
{
trans[x - 1] = new AccessTransformer(args[x]);
hasTransformer = true;
}
catch (IOException e)
{
System.out.println("Could not read Transformer Map: " + args[x]);
e.printStackTrace();
}
}
if (!hasTransformer)
{
System.out.println("Culd not find a valid transformer to perform");
System.exit(1);
}
File orig = new File(args[0]);
File temp = new File(args[0] + ".ATBack");
if (!orig.exists() && !temp.exists())
{
System.out.println("Could not find target jar: " + orig);
System.exit(1);
}
if (!orig.renameTo(temp))
{
System.out.println("Could not rename file: " + orig + " -> " + temp);
System.exit(1);
}
try
{
processJar(temp, orig, trans);
}
catch (IOException e)
{
e.printStackTrace();
System.exit(1);
}
if (!temp.delete())
{
System.out.println("Could not delete temp file: " + temp);
}
}
private static void processJar(File inFile, File outFile, AccessTransformer[] transformers) throws IOException
{
ZipInputStream inJar = null;
ZipOutputStream outJar = null;
try
{
try
{
inJar = new ZipInputStream(new BufferedInputStream(new FileInputStream(inFile)));
}
catch (FileNotFoundException e)
{
throw new FileNotFoundException("Could not open input file: " + e.getMessage());
}
try
{
outJar = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(outFile)));
}
catch (FileNotFoundException e)
{
throw new FileNotFoundException("Could not open output file: " + e.getMessage());
}
ZipEntry entry;
while ((entry = inJar.getNextEntry()) != null)
{
if (entry.isDirectory())
{
outJar.putNextEntry(entry);
continue;
}
byte[] data = new byte[4096];
ByteArrayOutputStream entryBuffer = new ByteArrayOutputStream();
int len;
do
{
len = inJar.read(data);
if (len > 0)
{
entryBuffer.write(data, 0, len);
}
}
while (len != -1);
byte[] entryData = entryBuffer.toByteArray();
String entryName = entry.getName();
if (entryName.endsWith(".class") && !entryName.startsWith("."))
{
ClassNode cls = new ClassNode();
ClassReader rdr = new ClassReader(entryData);
rdr.accept(cls, 0);
String name = cls.name.replace('/', '.').replace('\\', '.');
for (AccessTransformer trans : transformers)
{
entryData = trans.transform(name, entryData);
}
}
ZipEntry newEntry = new ZipEntry(entryName);
outJar.putNextEntry(newEntry);
outJar.write(entryData);
}
}
finally
{
if (outJar != null)
{
try
{
outJar.close();
}
catch (IOException e)
{
}
}
if (inJar != null)
{
try
{
inJar.close();
}
catch (IOException e)
{
}
}
}
}
public void ensurePublicAccessFor(String modClazzName)
{
Modifier m = new Modifier();
m.setTargetAccess("public");
m.modifyClassVisibility = true;
modifiers.put(modClazzName, m);
}
}
@@ -0,0 +1,636 @@
package cpw.mods.fml.common.asm.transformers;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
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.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map.Entry;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.AnnotationNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.FieldNode;
import org.objectweb.asm.tree.MethodNode;
import com.google.common.base.Objects;
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>();
private static final boolean DEBUG = false;
public static void main(String[] args)
{
if (args.length != 3)
{
System.out.println("Usage: AccessTransformer <MapFile> <minecraft.jar> <minecraft_server.jar>");
System.exit(1);
}
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);
System.exit(1);
}
if (!server_jar.exists())
{
System.out.println("Could not find minecraft_server.jar: " + server_jar);
System.exit(1);
}
if (!client_jar.renameTo(client_jar_tmp))
{
System.out.println("Could not rename file: " + client_jar + " -> " + client_jar_tmp);
System.exit(1);
}
if (!server_jar.renameTo(server_jar_tmp))
{
System.out.println("Could not rename file: " + server_jar + " -> " + server_jar_tmp);
System.exit(1);
}
if (!readMapFile(map_file))
{
System.out.println("Could not read map file: " + map_file);
System.exit(1);
}
try
{
processJar(client_jar_tmp, server_jar_tmp, client_jar, server_jar);
}
catch (IOException e)
{
e.printStackTrace();
System.exit(1);
}
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);
HashSet<String> cAdded = new HashSet<String>();
HashSet<String> sAdded = new HashSet<String>();
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))
{
copyClass(cInJar, cEntry, cOutJar, null, true);
cAdded.add(name);
}
else
{
if (DEBUG)
{
System.out.println("Copy class c->s : " + name);
}
copyClass(cInJar, cEntry, cOutJar, sOutJar, true);
cAdded.add(name);
sAdded.add(name);
}
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);
cAdded.add(name);
sAdded.add(name);
}
for (Entry<String, ZipEntry> entry : sClasses.entrySet())
{
if (!copyToClient.contains(entry.getKey()))
{
copyClass(sInJar, entry.getValue(), null, sOutJar, false);
}
else
{
if (DEBUG)
{
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()})
{
String eName = name.replace(".", "/");
byte[] data = getClassBytes(name);
ZipEntry newEntry = new ZipEntry(name.replace(".", "/").concat(".class"));
if (!cAdded.contains(eName))
{
cOutJar.putNextEntry(newEntry);
cOutJar.write(data);
}
if (!sAdded.contains(eName))
{
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.name.equals("ayn")) //Special case CodecMus so I dont have to make a new patch, anyone who uses this in production code is.. bad.
{
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());
if (outJar != null)
{
outJar.putNextEntry(newEntry);
outJar.write(data);
}
if (outJar2 != null)
{
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("."))
{
ZipEntry newEntry = new ZipEntry(entry.getName());
outFile.putNextEntry(newEntry);
outFile.write(readEntry(inFile, entry));
}
else
{
ret.put(entryName.replace(".class", ""), entry);
}
}
return ret;
}
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;
if (DEBUG)
{
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)
{
if (DEBUG)
{
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);
if (DEBUG)
{
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)
{
if (DEBUG)
{
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);
if (DEBUG)
{
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)
{
if (DEBUG)
{
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){}
}
}
}
}
@@ -0,0 +1,276 @@
package cpw.mods.fml.common.asm.transformers;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
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.net.URL;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.tree.ClassNode;
import com.google.common.base.Charsets;
import com.google.common.base.Splitter;
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.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();
public MarkerTransformer() throws IOException
{
this("fml_marker.cfg");
}
protected MarkerTransformer(String rulesFile) throws IOException
{
readMapFile(rulesFile);
}
private void readMapFile(String rulesFile) throws IOException
{
File file = new File(rulesFile);
URL rulesResource;
if (file.exists())
{
rulesResource = file.toURI().toURL();
}
else
{
rulesResource = Resources.getResource(rulesFile);
}
Resources.readLines(rulesResource, Charsets.UTF_8, new LineProcessor<Void>()
{
@Override
public Void getResult()
{
return null;
}
@Override
public boolean processLine(String input) throws IOException
{
String line = Iterables.getFirst(Splitter.on('#').limit(2).split(input), "").trim();
if (line.length()==0)
{
return true;
}
List<String> parts = Lists.newArrayList(Splitter.on(" ").trimResults().split(line));
if (parts.size()!=2)
{
throw new RuntimeException("Invalid config file line "+ input);
}
List<String> markerInterfaces = Lists.newArrayList(Splitter.on(",").trimResults().split(parts.get(1)));
for (String marker : markerInterfaces)
{
markers.put(parts.get(0), marker);
}
return true;
}
});
}
@SuppressWarnings("unchecked")
@Override
public byte[] transform(String name, byte[] bytes)
{
if (!markers.containsKey(name)) { return bytes; }
ClassNode classNode = new ClassNode();
ClassReader classReader = new ClassReader(bytes);
classReader.accept(classNode, 0);
for (String marker : markers.get(name))
{
classNode.interfaces.add(marker);
}
ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
classNode.accept(writer);
return writer.toByteArray();
}
public static void main(String[] args)
{
if (args.length < 2)
{
System.out.println("Usage: MarkerTransformer <JarPath> <MapFile> [MapFile2]... ");
return;
}
boolean hasTransformer = false;
MarkerTransformer[] trans = new MarkerTransformer[args.length - 1];
for (int x = 1; x < args.length; x++)
{
try
{
trans[x - 1] = new MarkerTransformer(args[x]);
hasTransformer = true;
}
catch (IOException e)
{
System.out.println("Could not read Transformer Map: " + args[x]);
e.printStackTrace();
}
}
if (!hasTransformer)
{
System.out.println("Culd not find a valid transformer to perform");
return;
}
File orig = new File(args[0]);
File temp = new File(args[0] + ".ATBack");
if (!orig.exists() && !temp.exists())
{
System.out.println("Could not find target jar: " + orig);
return;
}
/*
if (temp.exists())
{
if (orig.exists() && !orig.renameTo(new File(args[0] + (new SimpleDateFormat(".yyyy.MM.dd.HHmmss")).format(new Date()))))
{
System.out.println("Could not backup existing file: " + orig);
return;
}
if (!temp.renameTo(orig))
{
System.out.println("Could not restore backup from previous run: " + temp);
return;
}
}
*/
if (!orig.renameTo(temp))
{
System.out.println("Could not rename file: " + orig + " -> " + temp);
return;
}
try
{
processJar(temp, orig, trans);
}
catch (IOException e)
{
e.printStackTrace();
}
if (!temp.delete())
{
System.out.println("Could not delete temp file: " + temp);
}
}
private static void processJar(File inFile, File outFile, MarkerTransformer[] transformers) throws IOException
{
ZipInputStream inJar = null;
ZipOutputStream outJar = null;
try
{
try
{
inJar = new ZipInputStream(new BufferedInputStream(new FileInputStream(inFile)));
}
catch (FileNotFoundException e)
{
throw new FileNotFoundException("Could not open input file: " + e.getMessage());
}
try
{
outJar = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(outFile)));
}
catch (FileNotFoundException e)
{
throw new FileNotFoundException("Could not open output file: " + e.getMessage());
}
ZipEntry entry;
while ((entry = inJar.getNextEntry()) != null)
{
if (entry.isDirectory())
{
outJar.putNextEntry(entry);
continue;
}
byte[] data = new byte[4096];
ByteArrayOutputStream entryBuffer = new ByteArrayOutputStream();
int len;
do
{
len = inJar.read(data);
if (len > 0)
{
entryBuffer.write(data, 0, len);
}
}
while (len != -1);
byte[] entryData = entryBuffer.toByteArray();
String entryName = entry.getName();
if (entryName.endsWith(".class") && !entryName.startsWith("."))
{
ClassNode cls = new ClassNode();
ClassReader rdr = new ClassReader(entryData);
rdr.accept(cls, 0);
String name = cls.name.replace('/', '.').replace('\\', '.');
for (MarkerTransformer trans : transformers)
{
entryData = trans.transform(name, entryData);
}
}
ZipEntry newEntry = new ZipEntry(entryName);
outJar.putNextEntry(newEntry);
outJar.write(entryData);
}
}
finally
{
if (outJar != null)
{
try
{
outJar.close();
}
catch (IOException e)
{
}
}
if (inJar != null)
{
try
{
inJar.close();
}
catch (IOException e)
{
}
}
}
}
}
@@ -0,0 +1,103 @@
package cpw.mods.fml.common.asm.transformers;
import java.util.Iterator;
import java.util.List;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.AnnotationNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.FieldNode;
import org.objectweb.asm.tree.MethodNode;
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 = FMLRelauncher.side();
private static final boolean DEBUG = false;
@SuppressWarnings("unchecked")
@Override
public byte[] transform(String name, byte[] bytes)
{
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));
}
return null;
}
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));
}
fields.remove();
}
}
Iterator<MethodNode> methods = classNode.methods.iterator();
while(methods.hasNext())
{
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));
}
methods.remove();
}
}
ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
classNode.accept(writer);
return writer.toByteArray();
}
private boolean remove(List<AnnotationNode> anns, String side)
{
if (anns == null)
{
return false;
}
for (AnnotationNode ann : anns)
{
if (ann.desc.equals(Type.getDescriptor(SideOnly.class)))
{
if (ann.values != null)
{
for (int x = 0; x < ann.values.size() - 1; x += 2)
{
Object key = ann.values.get(x);
Object value = ann.values.get(x+1);
if (key instanceof String && key.equals("value"))
{
if (value instanceof String[] )
{
if (!((String[])value)[1].equals(side))
{
return true;
}
}
}
}
}
}
}
return false;
}
}
@@ -0,0 +1,103 @@
package cpw.mods.fml.common.discovery;
import java.util.List;
import java.util.Map;
import java.util.Set;
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.Lists;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps;
import com.google.common.collect.SetMultimap;
import cpw.mods.fml.common.ModContainer;
public class ASMDataTable
{
public static class ASMData
{
private ModCandidate candidate;
private String annotationName;
private String className;
private String objectName;
private Map<String,Object> annotationInfo;
public ASMData(ModCandidate candidate, String annotationName, String className, String objectName, Map<String,Object> info)
{
this.candidate = candidate;
this.annotationName = annotationName;
this.className = className;
this.objectName = objectName;
this.annotationInfo = info;
}
public ModCandidate getCandidate()
{
return candidate;
}
public String getAnnotationName()
{
return annotationName;
}
public String getClassName()
{
return className;
}
public String getObjectName()
{
return objectName;
}
public Map<String, Object> getAnnotationInfo()
{
return annotationInfo;
}
}
private static class ModContainerPredicate implements Predicate<ASMData>
{
private ModContainer container;
public ModContainerPredicate(ModContainer container)
{
this.container = container;
}
public boolean apply(ASMData data)
{
return container.getSource().equals(data.candidate.getModContainer());
}
}
private SetMultimap<String, ASMData> globalAnnotationData = HashMultimap.create();
private Map<ModContainer, SetMultimap<String,ASMData>> containerAnnotationData;
private List<ModContainer> containers = Lists.newArrayList();
public SetMultimap<String,ASMData> getAnnotationsFor(ModContainer container)
{
if (containerAnnotationData == null)
{
ImmutableMap.Builder<ModContainer, SetMultimap<String, ASMData>> mapBuilder = ImmutableMap.<ModContainer, SetMultimap<String,ASMData>>builder();
for (ModContainer cont : containers)
{
Multimap<String, ASMData> values = Multimaps.filterValues(globalAnnotationData, new ModContainerPredicate(cont));
mapBuilder.put(cont, ImmutableSetMultimap.copyOf(values));
}
containerAnnotationData = mapBuilder.build();
}
return containerAnnotationData.get(container);
}
public Set<ASMData> getAll(String annotation)
{
return globalAnnotationData.get(annotation);
}
public void addASMData(ModCandidate candidate, String annotation, String className, String objectName, Map<String,Object> annotationInfo)
{
globalAnnotationData.put(annotation, new ASMData(candidate, annotation, className, objectName, annotationInfo));
}
public void addContainer(ModContainer container)
{
this.containers.add(container);
}
}
@@ -0,0 +1,32 @@
package cpw.mods.fml.common.discovery;
import java.util.List;
import com.google.common.base.Throwables;
import cpw.mods.fml.common.ModContainer;
public enum ContainerType
{
JAR(JarDiscoverer.class),
DIR(DirectoryDiscoverer.class);
private ITypeDiscoverer discoverer;
private ContainerType(Class<? extends ITypeDiscoverer> discovererClass)
{
try
{
this.discoverer = discovererClass.newInstance();
}
catch (Exception e)
{
throw Throwables.propagate(e);
}
}
public List<ModContainer> findMods(ModCandidate candidate, ASMDataTable table)
{
return discoverer.discover(candidate, table);
}
}
@@ -0,0 +1,114 @@
package cpw.mods.fml.common.discovery;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import java.util.regex.Matcher;
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;
import cpw.mods.fml.common.discovery.asm.ASMModParser;
public class DirectoryDiscoverer implements ITypeDiscoverer
{
private class ClassFilter implements FileFilter
{
@Override
public boolean accept(File file)
{
return (file.isFile() && classFile.matcher(file.getName()).find()) || file.isDirectory();
}
}
private ASMDataTable table;
@Override
public List<ModContainer> discover(ModCandidate candidate, ASMDataTable table)
{
this.table = table;
List<ModContainer> found = Lists.newArrayList();
FMLLog.fine("Examining directory %s for potential mods", candidate.getModContainer().getName());
exploreFileSystem("", candidate.getModContainer(), found, candidate, null);
for (ModContainer mc : found)
{
table.addContainer(mc);
}
return found;
}
public void exploreFileSystem(String path, File modDir, List<ModContainer> harvestedMods, ModCandidate candidate, MetadataCollection mc)
{
if (path.length() == 0)
{
File metadata = new File(modDir, "mcmod.info");
try
{
FileInputStream fis = new FileInputStream(metadata);
mc = MetadataCollection.from(fis,modDir.getName());
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());
}
}
File[] content = modDir.listFiles(new ClassFilter());
// Always sort our content
Arrays.sort(content);
for (File file : content)
{
if (file.isDirectory())
{
FMLLog.finest("Recursing into package %s", path + file.getName());
exploreFileSystem(path + file.getName() + ".", file, harvestedMods, candidate, mc);
continue;
}
Matcher match = classFile.matcher(file.getName());
if (match.matches())
{
ASMModParser modParser = null;
try
{
FileInputStream fis = new FileInputStream(file);
modParser = new ASMModParser(fis);
fis.close();
}
catch (LoaderException e)
{
FMLLog.log(Level.SEVERE, e, "There was a problem reading the file %s - probably this is a corrupt file", file.getPath());
throw e;
}
catch (Exception e)
{
Throwables.propagate(e);
}
modParser.validate();
modParser.sendToTable(table, candidate);
ModContainer container = ModContainerFactory.instance().build(modParser, candidate.getModContainer(), candidate);
if (container!=null)
{
harvestedMods.add(container);
container.bindMetadata(mc);
}
}
}
}
}
@@ -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,91 @@
package cpw.mods.fml.common.discovery;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
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.LoaderException;
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), candidate.getModContainer().getName());
}
else
{
FMLLog.fine("The mod container %s appears to be missing an mcmod.info file", candidate.getModContainer().getName());
mc = MetadataCollection.from(null, "");
}
for (ZipEntry ze : Collections.list(jar.entries()))
{
Matcher match = classFile.matcher(ze.getName());
if (match.matches())
{
ASMModParser modParser;
try
{
modParser = new ASMModParser(jar.getInputStream(ze));
}
catch (LoaderException e)
{
FMLLog.log(Level.SEVERE, e, "There was a problem reading the entry %s in the jar %s - probably a corrupt zip", ze.getName(), candidate.getModContainer().getPath());
jar.close();
throw e;
}
modParser.validate();
modParser.sendToTable(table, candidate);
ModContainer container = ModContainerFactory.instance().build(modParser, candidate.getModContainer(), candidate);
if (container!=null)
{
table.addContainer(container);
foundMods.add(container);
container.bindMetadata(mc);
}
}
}
}
catch (Exception e)
{
FMLLog.log(Level.WARNING, e, "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,84 @@
package cpw.mods.fml.common.discovery;
import java.io.File;
import java.util.List;
import com.google.common.collect.Lists;
import cpw.mods.fml.common.FMLLog;
import cpw.mods.fml.common.ModContainer;
import cpw.mods.fml.common.discovery.asm.ASMModParser;
public class ModCandidate
{
private File classPathRoot;
private File modContainer;
private ContainerType sourceType;
private boolean classpath;
private List<String> baseModTypes = Lists.newArrayList();
private boolean isMinecraft;
private List<ASMModParser> baseModCandidateTypes = Lists.newArrayListWithCapacity(1);
public ModCandidate(File classPathRoot, File modContainer, ContainerType sourceType)
{
this(classPathRoot, modContainer, sourceType, false, false);
}
public ModCandidate(File classPathRoot, File modContainer, ContainerType sourceType, boolean isMinecraft, boolean classpath)
{
this.classPathRoot = classPathRoot;
this.modContainer = modContainer;
this.sourceType = sourceType;
this.isMinecraft = isMinecraft;
this.classpath = classpath;
}
public File getClassPathRoot()
{
return classPathRoot;
}
public File getModContainer()
{
return modContainer;
}
public ContainerType getSourceType()
{
return sourceType;
}
public List<ModContainer> explore(ASMDataTable table)
{
List<ModContainer> mods = sourceType.findMods(this, table);
if (!baseModCandidateTypes.isEmpty())
{
FMLLog.info("Attempting to reparse the mod container %s", getModContainer().getName());
return sourceType.findMods(this, table);
}
else
{
return mods;
}
}
public boolean isClasspath()
{
return classpath;
}
public void rememberBaseModType(String className)
{
baseModTypes.add(className);
}
public List<String> getRememberedBaseMods()
{
return baseModTypes;
}
public boolean isMinecraftJar()
{
return isMinecraft;
}
public void rememberModCandidateType(ASMModParser modParser)
{
baseModCandidateTypes.add(modParser);
}
}
@@ -0,0 +1,136 @@
package cpw.mods.fml.common.discovery;
import java.io.File;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
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.RelaunchLibraryManager;
public class ModDiscoverer
{
private static Pattern zipJar = Pattern.compile("(.+).(zip|jar)$");
private List<ModCandidate> candidates = Lists.newArrayList();
private ASMDataTable dataTable = new ASMDataTable();
private List<File> nonModLibs = Lists.newArrayList();
public void findClasspathMods(ModClassLoader modClassLoader)
{
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));
}
else
{
for (int i = 0; i < minecraftSources.length; i++)
{
if (minecraftSources[i].isFile())
{
if (knownLibraries.contains(minecraftSources[i].getName()))
{
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));
}
}
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));
}
}
}
}
public void findModDirMods(File modsDir)
{
File[] modList = modsDir.listFiles();
// Sort the files into alphabetical order first
Arrays.sort(modList);
for (File modFile : modList)
{
if (modFile.isDirectory())
{
FMLLog.fine("Found a candidate mod directory %s", modFile.getName());
candidates.add(new ModCandidate(modFile, modFile, ContainerType.DIR));
}
else
{
Matcher matcher = zipJar.matcher(modFile.getName());
if (matcher.matches())
{
FMLLog.fine("Found a candidate zip or jar file %s", matcher.group(0));
candidates.add(new ModCandidate(modFile, modFile, ContainerType.JAR));
}
else
{
FMLLog.fine("Ignoring unknown file %s in mods directory", modFile.getName());
}
}
}
}
public List<ModContainer> identifyMods()
{
List<ModContainer> modList = Lists.newArrayList();
for (ModCandidate candidate : candidates)
{
try
{
List<ModContainer> mods = candidate.explore(dataTable);
if (mods.isEmpty() && !candidate.isClasspath())
{
nonModLibs.add(candidate.getModContainer());
}
else
{
modList.addAll(mods);
}
}
catch (LoaderException le)
{
FMLLog.log(Level.WARNING, le, "Identified a problem with the mod candidate %s, ignoring this source", candidate.getModContainer());
}
catch (Throwable t)
{
Throwables.propagate(t);
}
}
return modList;
}
public ASMDataTable getASMTable()
{
return dataTable;
}
public List<File> getNonModLibs()
{
return nonModLibs;
}
}
@@ -0,0 +1,169 @@
package cpw.mods.fml.common.discovery.asm;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level;
import net.minecraft.src.BaseMod;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.Type;
import com.google.common.base.Objects;
import com.google.common.collect.Lists;
import cpw.mods.fml.common.FMLLog;
import cpw.mods.fml.common.LoaderException;
import cpw.mods.fml.common.discovery.ASMDataTable;
import cpw.mods.fml.common.discovery.ModCandidate;
public class ASMModParser
{
private Type asmType;
private int classVersion;
private Type asmSuperType;
private LinkedList<ModAnnotation> annotations = Lists.newLinkedList();
private String baseModProperties;
static enum AnnotationType
{
CLASS, FIELD, METHOD, SUBTYPE;
}
public ASMModParser(InputStream stream) throws IOException
{
try
{
ClassReader reader = new ClassReader(stream);
reader.accept(new ModClassVisitor(this), 0);
}
catch (Exception ex)
{
FMLLog.log(Level.SEVERE, ex, "Unable to read a class file correctly");
throw new LoaderException(ex);
}
}
public void beginNewTypeName(String typeQName, int classVersion, String superClassQName)
{
this.asmType = Type.getObjectType(typeQName);
this.classVersion = classVersion;
this.asmSuperType = Type.getObjectType(superClassQName);
}
public void startClassAnnotation(String annotationName)
{
ModAnnotation ann = new ModAnnotation(AnnotationType.CLASS, Type.getType(annotationName), this.asmType.getClassName());
annotations.addFirst(ann);
}
public void addAnnotationProperty(String key, Object value)
{
annotations.getFirst().addProperty(key, value);
}
public void startFieldAnnotation(String fieldName, String annotationName)
{
ModAnnotation ann = new ModAnnotation(AnnotationType.FIELD, Type.getType(annotationName), fieldName);
annotations.addFirst(ann);
}
@Override
public String toString()
{
return Objects.toStringHelper("ASMAnnotationDiscoverer")
.add("className", asmType.getClassName())
.add("classVersion", classVersion)
.add("superName", asmSuperType.getClassName())
.add("annotations", annotations)
.add("isBaseMod", isBaseMod(Collections.<String>emptyList()))
.add("baseModProperties", baseModProperties)
.toString();
}
public Type getASMType()
{
return asmType;
}
public int getClassVersion()
{
return classVersion;
}
public Type getASMSuperType()
{
return asmSuperType;
}
public LinkedList<ModAnnotation> getAnnotations()
{
return annotations;
}
public void validate()
{
// if (classVersion > 50.0)
// {
//
// throw new LoaderException(new RuntimeException("Mod compiled for Java 7 detected"));
// }
}
public boolean isBaseMod(List<String> rememberedTypes)
{
return getASMSuperType().equals(Type.getType(BaseMod.class)) || rememberedTypes.contains(getASMSuperType().getClassName());
}
public void setBaseModProperties(String foundProperties)
{
this.baseModProperties = foundProperties;
}
public String getBaseModProperties()
{
return this.baseModProperties;
}
public void sendToTable(ASMDataTable table, ModCandidate candidate)
{
for (ModAnnotation ma : annotations)
{
table.addASMData(candidate, ma.asmType.getClassName(), this.asmType.getClassName(), ma.member, ma.values);
}
}
public void addAnnotationArray(String name)
{
annotations.getFirst().addArray(name);
}
public void addAnnotationEnumProperty(String name, String desc, String value)
{
annotations.getFirst().addEnumProperty(name, desc, value);
}
public void endArray()
{
annotations.getFirst().endArray();
}
public void addSubAnnotation(String name, String desc)
{
ModAnnotation ma = annotations.getFirst();
annotations.addFirst(ma.addChildAnnotation(name, desc));
}
public void endSubAnnotation()
{
// take the child and stick it at the end
ModAnnotation child = annotations.removeFirst();
annotations.addLast(child);
}
}
Loaded 100 of 499 files, more files were not shown because too many files have changed in this diff. Show more