Compare commits

..
196 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
191 changed files with 17513 additions and 14531 deletions

No files matched your search

+12 -42
View File
@@ -51,18 +51,15 @@
</condition>
<property name="mcp.obfoutput" location="${mcp.home}/reobf" />
<property name="client.mcp.obfoutput" location="${mcp.obfoutput}/minecraft" />
<property name="server.mcp.obfoutput" location="${mcp.obfoutput}/minecraft_server" />
<property name="mcp.srcdir" location="${mcp.home}/src" />
<property name="common.mcp.srcdir" location="${mcp.srcdir}/common" />
<property name="client.mcp.srcdir" location="${mcp.srcdir}/minecraft" />
<property name="server.mcp.srcdir" location="${mcp.srcdir}/minecraft_server" />
<property name="clean.mcp.srcdir" location="${mcp.home}/src-base" />
<property name="patch.mcp.srcdir" location="${mcp.home}/src-work" />
<property name="tmp.mcp.srcdir" location="${mcp.home}/src-tmp" />
<property name="renamed.mcp.srcdir" location="${mcp.home}/src-renamed" />
<property name="common.src.dir" location="${basedir}/common" />
<property name="client.src.dir" location="${basedir}/client" />
<property name="server.src.dir" location="${basedir}/server" />
<property name="patch.src.dir" location="${basedir}/patches" />
<property name="fml.conf.dir" location="${basedir}/conf" />
<condition property="version.build" value="${env.BUILD_NUMBER}" else="1">
@@ -92,7 +89,7 @@
</exec>
</target>
<target name="buildandreobfmcp" depends="buildenvsetup,recompile">
<target name="reobfuscate" depends="buildenvsetup,recompile">
<exec executable="${python.exe}" dir="${mcp.home}" failonerror="true">
<arg value="${mcp.home}/runtime/reobfuscate.py" />
</exec>
@@ -100,8 +97,6 @@
<condition>
<not>
<and>
<available file="${mcp.home}/temp/server.md5"/>
<available file="${mcp.home}/temp/server_reobf.md5"/>
<available file="${mcp.home}/temp/client.md5"/>
<available file="${mcp.home}/temp/client_reobf.md5"/>
</and>
@@ -114,7 +109,7 @@
<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" />
@@ -122,10 +117,7 @@
<fail message="Compilation failed">
<condition>
<not>
<and>
<available file="${mcp.home}/bin/minecraft/net/minecraft/client/Minecraft.class"/>
<available file="${mcp.home}/bin/minecraft_server/net/minecraft/server/MinecraftServer.class"/>
</and>
<available file="${mcp.home}/bin/minecraft/net/minecraft/client/Minecraft.class"/>
</not>
</condition>
</fail>
@@ -137,31 +129,15 @@
</copy>
</target>
<target name="merge-server" depends="buildenvsetup">
<copy todir="${server.mcp.srcdir}" overwrite="true" verbose="true">
<fileset dir="${server.src.dir}" includes="**/*.java" />
</copy>
</target>
<target name="merge-common">
<copy todir="${common.mcp.srcdir}" overwrite="true" verbose="true">
<fileset dir="${common.src.dir}" includes="**/*.java" />
</copy>
</target>
<target name="merge-source" depends="buildenvsetup,merge-client,merge-server,merge-common" />
<target name="build-client" depends="buildenvsetup,merge-client,merge-common,buildandreobfmcp,makeversion">
<antcall target="extract-built-jar">
<param name="side" value="client" />
</antcall>
</target>
<target name="merge-source" depends="buildenvsetup,merge-client,merge-common" />
<target name="build-server" depends="buildenvsetup,merge-server,merge-common,buildandreobfmcp,makeversion">
<antcall target="extract-built-jar">
<param name="side" value="server" />
</antcall>
</target>
<target name="build-client" depends="buildenvsetup,merge-client,merge-common,reobfuscate,makeversion"/>
<target name="extract-built-jar">
<side prop="output" src="mcp.obfoutput" side="${side}" />
@@ -191,14 +167,13 @@
</zip>
</target>
<target name="build-universal">
<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">
<jar destfile="${basedir}/target/${universal.jarname}.zip" duplicate="preserve">
<manifest>
<attribute name="Main-Class" value="net.minecraft.server.MinecraftServer"/>
</manifest>
<fileset dir="${server.mcp.obfoutput}" includes="**/*.class" />
<fileset dir="${client.mcp.obfoutput}" includes="**/*.class" />
<zipfileset dir="${basedir}" includes="fmlversion.properties"/>
<zipfileset dir="${basedir}" includes="LICENSE-fml.txt" />
@@ -228,7 +203,6 @@
<zipfileset dir="${basedir}" includes="LICENSE-fml.txt,difflist.txt,commands.patch,mcp_merge.cfg" prefix="fml" />
<zipfileset dir="${common.src.dir}" includes="**/*.java" prefix="fml/common" />
<zipfileset dir="${client.src.dir}" includes="**/*.java" prefix="fml/client" />
<zipfileset dir="${server.src.dir}" includes="**/*.java" prefix="fml/server" />
<zipfileset dir="${basedir}" includes="fmlversion.properties" prefix="fml/common" />
<zipfileset dir="${common.src.dir}" includes="*.cfg" prefix="fml/common" />
<zipfileset dir="${patch.src.dir}" includes="**/*.patch" prefix="fml/patches" />
@@ -252,7 +226,7 @@
</zip>
</target>
<target name="build" depends="buildenvsetup,merge-server,merge-client,merge-common,build-server,build-client,build-universal,build-source-pack" />
<target name="build" depends="buildenvsetup,merge-client,merge-common,build-client,build-universal,build-source-pack" />
<target name="jenkinsbuild" depends="buildenvsetup,jenkinsfmldecompile,patch,build"/>
@@ -273,10 +247,6 @@
</condition>
<fail if="do.not.continue">You have decided not to continue. This script will stop now.</fail>
<echo>Preparing the MCP environment at ${mcp.home}</echo>
<!--<exec executable="${python.exe}" dir="${basedir}">
<arg value="${basedir}/download_fernflower.py" />
<arg value="${mcp.home}"/>
</exec>-->
<antcall target="fmldecompile"/>
<echo>Moving old patched sources at ${patch.mcp.srcdir} out of the way</echo>
<move todir="${mcp.home}/src-work${timestamp}" failonerror="false" verbose="true">
@@ -297,7 +267,7 @@
<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" />
@@ -309,7 +279,7 @@
<arg value="${basedir}" />
</exec>
</target>
<target name="jenkinsfmldecompile" depends="buildenvsetup">
<exec executable="${python.exe}" dir="${mcp.home}">
<arg value="${mcp.home}/runtime/cleanup.py" />
@@ -340,7 +310,7 @@
<fileset dir="${mcp.srcdir}"/>
</copy>
</target>
<target name="repatchclean" depends="buildenvsetup">
<delete dir="${mcp.srcdir}"/>
<copy todir="${mcp.srcdir}">
@@ -378,7 +348,7 @@
</exec>
</target>
<target name="makerenamedsource" depends="buildenvsetup,repatch,merge-client,merge-server,buildandreobfmcp">
<target name="makerenamedsource" depends="buildenvsetup,repatch,merge-client,merge-common,reobfuscate">
<copy todir="${tmp.mcp.srcdir}">
<fileset dir="${mcp.srcdir}"/>
</copy>
+121 -102
View File
@@ -12,107 +12,55 @@
*/
package cpw.mods.fml.client;
import static org.lwjgl.opengl.GL11.*;
import java.awt.image.BufferedImage;
import java.awt.Dimension;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Properties;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import org.lwjgl.opengl.GL11;
import 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 net.minecraft.client.Minecraft;
import net.minecraft.server.MinecraftServer;
import net.minecraft.src.BaseMod;
import net.minecraft.src.BiomeGenBase;
import net.minecraft.src.Block;
import net.minecraft.src.CrashReport;
import net.minecraft.src.Entity;
import net.minecraft.src.EntityItem;
import net.minecraft.src.EntityLiving;
import net.minecraft.src.EntityPlayer;
import net.minecraft.src.GameSettings;
import net.minecraft.src.GuiScreen;
import net.minecraft.src.IBlockAccess;
import net.minecraft.src.IChunkProvider;
import net.minecraft.src.IInventory;
import net.minecraft.src.Item;
import net.minecraft.src.ItemStack;
import net.minecraft.src.KeyBinding;
import net.minecraft.src.MLProp;
import net.minecraft.src.ModTextureStatic;
import net.minecraft.src.NetClientHandler;
import net.minecraft.src.NetworkManager;
import net.minecraft.src.Packet;
import net.minecraft.src.Packet1Login;
import net.minecraft.src.Packet250CustomPayload;
import net.minecraft.src.Packet3Chat;
import net.minecraft.src.Profiler;
import net.minecraft.src.Render;
import net.minecraft.src.RenderBlocks;
import net.minecraft.src.RenderEngine;
import net.minecraft.src.RenderManager;
import net.minecraft.src.RenderPlayer;
import net.minecraft.src.StringTranslate;
import net.minecraft.src.TextureFX;
import net.minecraft.src.TexturePackBase;
import net.minecraft.src.World;
import net.minecraft.src.WorldClient;
import net.minecraft.src.WorldType;
import argo.jdom.JdomParser;
import argo.jdom.JsonNode;
import cpw.mods.fml.client.modloader.ModLoaderClientHelper;
import cpw.mods.fml.client.registry.ClientRegistry;
import cpw.mods.fml.client.registry.KeyBindingRegistry;
import cpw.mods.fml.client.registry.RenderingRegistry;
import cpw.mods.fml.common.DummyModContainer;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.FMLDummyContainer;
import cpw.mods.fml.common.FMLLog;
import cpw.mods.fml.common.IFMLSidedHandler;
import cpw.mods.fml.common.Loader;
import cpw.mods.fml.common.LoaderException;
import cpw.mods.fml.common.LoaderState;
import cpw.mods.fml.common.MetadataCollection;
import cpw.mods.fml.common.MissingModsException;
import cpw.mods.fml.common.ModContainer;
import cpw.mods.fml.common.ModMetadata;
import cpw.mods.fml.common.ProxyInjector;
import cpw.mods.fml.common.ObfuscationReflectionHelper;
import cpw.mods.fml.common.Side;
import cpw.mods.fml.common.SidedProxy;
import cpw.mods.fml.common.TickType;
import cpw.mods.fml.common.modloader.ModLoaderHelper;
import cpw.mods.fml.common.modloader.ModLoaderModContainer;
import cpw.mods.fml.common.modloader.ModProperty;
import cpw.mods.fml.common.network.EntitySpawnAdjustmentPacket;
import cpw.mods.fml.common.network.EntitySpawnPacket;
import cpw.mods.fml.common.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;
/**
@@ -146,8 +94,6 @@ public class FMLClientHandler implements IFMLSidedHandler
*/
private Minecraft client;
private boolean firstTick;
/**
* Called to start the whole game off from
* {@link MinecraftServer#startServer}
@@ -161,6 +107,10 @@ public class FMLClientHandler implements IFMLSidedHandler
private boolean serverIsRunning;
private MissingModsException modsMissing;
private boolean loading;
public void beginMinecraftLoading(Minecraft minecraft)
{
if (minecraft.func_71355_q())
@@ -170,6 +120,7 @@ public class FMLClientHandler implements IFMLSidedHandler
return;
}
loading = true;
client = minecraft;
ObfuscationReflectionHelper.detectObfuscation(World.class);
TextureFXManager.instance().setClient(client);
@@ -180,7 +131,7 @@ public class FMLClientHandler implements IFMLSidedHandler
Class<?> optifineConfig = Class.forName("Config", false, Loader.instance().getModClassLoader());
String optifineVersion = (String) optifineConfig.getField("VERSION").get(null);
Map<String,Object> dummyOptifineMeta = ImmutableMap.<String,Object>builder().put("name", "Optifine").put("version", optifineVersion).build();
ModMetadata optifineMetadata = MetadataCollection.from(getClass().getResourceAsStream("optifinemod.info")).getMetadataForId("optifine", dummyOptifineMeta);
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());
}
@@ -192,6 +143,10 @@ public class FMLClientHandler implements IFMLSidedHandler
{
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);
@@ -210,8 +165,13 @@ public class FMLClientHandler implements IFMLSidedHandler
* Also initializes key bindings
*
*/
@SuppressWarnings("deprecation")
public void finishMinecraftLoading()
{
if (modsMissing != null)
{
return;
}
try
{
Loader.instance().initializeMods();
@@ -221,12 +181,23 @@ public class FMLClientHandler implements IFMLSidedHandler
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);
KeyBindingRegistry.uploadKeyBindingsToGame(client.field_71474_y);
loading = false;
KeyBindingRegistry.instance().uploadKeyBindingsToGame(client.field_71474_y);
}
// Mark this as a "first tick"
firstTick = true;
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
@@ -266,16 +237,6 @@ public class FMLClientHandler implements IFMLSidedHandler
}
}
@Override
public void profileStart(String profileLabel) {
client.field_71424_I.func_76320_a(profileLabel);
}
@Override
public void profileEnd() {
client.field_71424_I.func_76319_b();
}
/**
* @param mods
*/
@@ -316,22 +277,41 @@ public class FMLClientHandler implements IFMLSidedHandler
}
@Override
public Entity spawnEntityIntoClientWorld(Class<? extends Entity> cls, EntitySpawnPacket packet)
public Entity spawnEntityIntoClientWorld(EntityRegistration er, EntitySpawnPacket packet)
{
WorldClient wc = client.field_71441_e;
Class<? extends Entity> cls = er.getEntityClass();
try
{
Entity entity = (Entity)(cls.getConstructor(World.class).newInstance(wc));
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.field_70118_ct = packet.rawX;
entity.field_70117_cu = packet.rawY;
entity.field_70116_cv = packet.rawZ;
Entity parts[] = entity.func_70021_al();
if (parts != null)
@@ -343,13 +323,6 @@ public class FMLClientHandler implements IFMLSidedHandler
}
}
entity.field_70157_k = packet.entityId;
entity.func_70056_a(packet.scaledX, packet.scaledY, packet.scaledZ, packet.scaledYaw, packet.scaledPitch, 1);
if (entity instanceof EntityLiving)
{
((EntityLiving)entity).field_70759_as = packet.scaledHeadYaw;
}
if (packet.metadata != null)
{
@@ -380,9 +353,16 @@ public class FMLClientHandler implements IFMLSidedHandler
public void adjustEntityLocationOnClient(EntitySpawnAdjustmentPacket packet)
{
Entity ent = client.field_71441_e.func_73024_a(packet.entityId);
ent.field_70118_ct = packet.serverX;
ent.field_70117_cu = packet.serverY;
ent.field_70116_cv = packet.serverZ;
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
@@ -402,4 +382,43 @@ public class FMLClientHandler implements IFMLSidedHandler
{
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();
}
}
+3 -3
View File
@@ -18,11 +18,11 @@ import java.awt.Dimension;
import java.util.List;
import java.util.logging.Logger;
import cpw.mods.fml.common.FMLCommonHandler;
import net.minecraft.src.RenderEngine;
import net.minecraft.src.TextureFX;
import net.minecraft.src.TexturePackBase;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.FMLLog;
public class FMLTextureFX extends TextureFX implements ITextureFX
{
@@ -31,7 +31,7 @@ public class FMLTextureFX extends TextureFX implements ITextureFX
public int tileSizeMask = 15;
public int tileSizeSquareMask = 255;
public boolean errored = false;
protected Logger log = FMLCommonHandler.instance().getFMLLogger();
protected Logger log = FMLLog.getLogger();
public FMLTextureFX(int icon)
{
+8 -9
View File
@@ -16,15 +16,7 @@ package cpw.mods.fml.client;
import java.awt.Dimension;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import org.lwjgl.opengl.GL11;
import cpw.mods.fml.common.FMLModContainer;
import cpw.mods.fml.common.FMLDummyContainer;
import cpw.mods.fml.common.Loader;
import cpw.mods.fml.common.ModContainer;
import net.minecraft.client.Minecraft;
import net.minecraft.src.FontRenderer;
import net.minecraft.src.GuiButton;
@@ -33,6 +25,11 @@ 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
*
@@ -103,6 +100,7 @@ public class GuiModList extends GuiScreen
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())
@@ -125,7 +123,7 @@ public class GuiModList extends GuiScreen
this.field_73886_k.func_78261_a(selectedMod.getMetadata().name, offset, shifty, 0xFFFFFF);
shifty += 12;
shifty = drawLine(String.format("Version: %s (%s)", selectedMod.getMetadata().version, selectedMod.getVersion()), offset, shifty);
shifty = drawLine(String.format("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);
@@ -142,6 +140,7 @@ public class GuiModList extends GuiScreen
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_);
}
@@ -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_);
}
}
@@ -1,6 +1,7 @@
package cpw.mods.fml.client;
import java.util.List;
import net.minecraft.client.Minecraft;
import net.minecraft.src.GuiButton;
import net.minecraft.src.Tessellator;
@@ -81,9 +82,10 @@ public abstract class GuiScrollingList
protected void func_27257_b(int p_27257_1_, int p_27257_2_) {}
public int func_27256_c(int p_27256_1_, int p_27256_2_)
{
int var3 = this.listWidth / 2 - 110;
int var4 = this.listWidth / 2 + 110;
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;
+7 -12
View File
@@ -16,15 +16,10 @@ 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;
import cpw.mods.fml.common.ModMetadata;
import net.minecraft.client.Minecraft;
import net.minecraft.src.GuiLanguage;
import net.minecraft.src.GuiSlot;
import net.minecraft.src.StringTranslate;
import net.minecraft.src.Tessellator;
/**
* @author cpw
@@ -78,15 +73,15 @@ public class GuiSlotModList extends GuiScrollingList
ModContainer mc=mods.get(listIndex);
if (Loader.instance().getModState(mc)==ModState.DISABLED)
{
this.parent.getFontRenderer().func_78276_b(this.parent.getFontRenderer().func_78269_a(mc.getName(), listWidth - 11), this.left + 3 , var3 + 2, 0xFF2222);
this.parent.getFontRenderer().func_78276_b(this.parent.getFontRenderer().func_78269_a(mc.getVersion(), listWidth - 11), this.left + 3 , var3 + 12, 0xFF2222);
this.parent.getFontRenderer().func_78276_b(this.parent.getFontRenderer().func_78269_a("DISABLED", listWidth - 11), this.left + 3 , var3 + 22, 0xFF2222);
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 - 11), this.left + 3 , var3 + 2, 0xFFFFFF);
this.parent.getFontRenderer().func_78276_b(this.parent.getFontRenderer().func_78269_a(mc.getVersion(), listWidth - 11), this.left + 3 , var3 + 12, 0xCCCCCC);
this.parent.getFontRenderer().func_78276_b(this.parent.getFontRenderer().func_78269_a(mc.getMetadata() !=null ? mc.getMetadata().getChildModCountString() : "Metadata not found", listWidth - 9), this.left + 3 , var3 + 22, 0xCCCCCC);
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);
}
}
+2 -1
View File
@@ -16,7 +16,8 @@ package cpw.mods.fml.client;
import java.awt.Dimension;
import net.minecraft.src.*;
import net.minecraft.src.RenderEngine;
import net.minecraft.src.TexturePackBase;
public interface ITextureFX
{
+7 -9
View File
@@ -18,10 +18,8 @@ import java.util.BitSet;
import java.util.HashMap;
import java.util.logging.Level;
import net.minecraft.src.ModLoader;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.FMLLog;
import cpw.mods.fml.common.LoaderException;
/**
* @author cpw
@@ -35,6 +33,9 @@ public class SpriteHelper
BitSet slots =
SpriteHelper.toBitSet(
"0000000000000000" +
"0000000000110000" +
"0000000001100000" +
"0000000001100000" +
"0000000000000000" +
"0000000000000000" +
"0000000000000000" +
@@ -42,9 +43,6 @@ public class SpriteHelper
"0000000000000000" +
"0000000000000000" +
"0000000000000000" +
"0000000000000000" +
"0000000000000000" +
"0000000011111100" +
"0000000011111111" +
"0000000011111000" +
"0000000111111100" +
@@ -62,10 +60,10 @@ public class SpriteHelper
"0000001000000000" +
"0000001110000000" +
"0000001000000000" +
"1111111010000000" +
"1111111010100000" +
"1111111111111100" +
"1111111111111111" +
"1111101010000000" +
"1111101010000000" +
"1111101110000000" +
"1111111111110000" +
"1111111111111111" +
"1111111111111111" +
"0000000000000000");
@@ -18,22 +18,20 @@ 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 net.minecraft.client.Minecraft;
import net.minecraft.src.KeyBinding;
import net.minecraft.src.ModTextureStatic;
import net.minecraft.src.Profiler;
import net.minecraft.src.RenderEngine;
import net.minecraft.src.TextureFX;
import net.minecraft.src.TexturePackBase;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.FMLLog;
import cpw.mods.fml.common.Loader;
import cpw.mods.fml.common.ModContainer;
public class TextureFXManager
@@ -53,12 +51,12 @@ public class TextureFXManager
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);
@@ -69,8 +67,7 @@ public class TextureFXManager
}
String name = effect.getClass().getSimpleName();
FMLClientHandler.instance().profileStart(name);
client.field_71424_I.func_76320_a(name);
try
{
if (!FMLClientHandler.instance().hasOptifine())
@@ -85,10 +82,10 @@ public class TextureFXManager
{
ifx.setErrored(true);
}
FMLClientHandler.instance().profileEnd();
client.field_71424_I.func_76319_b();
return false;
}
FMLClientHandler.instance().profileEnd();
client.field_71424_I.func_76319_b();
if (ifx != null)
{
@@ -242,10 +239,6 @@ public class TextureFXManager
public void registerTextureOverrides(RenderEngine renderer) {
for (ModContainer mod : Loader.instance().getActiveModList()) {
registerAnimatedTexturesFor(mod);
}
for (OverrideInfo animationOverride : animationSet) {
renderer.func_78355_a(animationOverride.textureFX);
addedTextureFX.add(animationOverride.textureFX);
@@ -273,7 +266,7 @@ public class TextureFXManager
/**
* @param mod
*/
private void registerAnimatedTexturesFor(ModContainer mod)
protected void registerAnimatedTexturesFor(ModContainer mod)
{
}
@@ -19,8 +19,6 @@ import net.minecraft.src.Block;
import net.minecraft.src.IBlockAccess;
import net.minecraft.src.RenderBlocks;
import cpw.mods.fml.client.registry.ISimpleBlockRenderingHandler;
import cpw.mods.fml.common.ModContainer;
import cpw.mods.fml.common.modloader.ModLoaderModContainer;
/**
* @author cpw
@@ -1,18 +1,43 @@
package cpw.mods.fml.client.modloader;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Map.Entry;
import com.google.common.collect.Maps;
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
{
@@ -24,40 +49,111 @@ public class ModLoaderClientHelper implements IModLoaderSidedHelper
*/
public static int obtainBlockModelIdFor(BaseMod mod, boolean inventoryRenderer)
{
int renderId=RenderingRegistry.instance().getNextAvailableRenderId();
int renderId=RenderingRegistry.getNextAvailableRenderId();
ModLoaderBlockRendererHandler bri=new ModLoaderBlockRendererHandler(renderId, inventoryRenderer, mod);
RenderingRegistry.instance().registerBlockHandler(bri);
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();
Map<Class<? extends Entity>, Render> renderers = Maps.newHashMap(RenderManager.field_78727_a.field_78729_o);
mod.addRenderer(renderers);
for (Entry<Class<? extends Entity>, Render> e : renderers.entrySet())
try
{
RenderingRegistry.instance().registerEntityRenderingHandler(e.getKey(), e.getValue());
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());
}
mod.registerAnimation(game);
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);
}
}
@@ -14,17 +14,19 @@
package cpw.mods.fml.client.modloader;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.List;
import net.minecraft.src.KeyBinding;
import org.lwjgl.input.Keyboard;
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;
import cpw.mods.fml.common.registry.TickRegistry;
/**
* @author cpw
@@ -33,61 +35,58 @@ import cpw.mods.fml.common.registry.TickRegistry;
public class ModLoaderKeyBindingHandler extends KeyBindingRegistry.KeyHandler
{
private ModLoaderModContainer modContainer;
private boolean downArmed;
private boolean upArmed;
private List<KeyBinding> helper;
private boolean[] active = new boolean[0];
private boolean[] mlRepeats = new boolean[0];
private boolean[] armed = new boolean[0];
/**
* @param keyHandler
* @param allowRepeat
* @param modContainer
*/
public ModLoaderKeyBindingHandler(KeyBinding keyBinding, boolean allowRepeat, ModLoaderModContainer modContainer)
public ModLoaderKeyBindingHandler()
{
super(keyBinding, allowRepeat);
this.modContainer=modContainer;
super(new KeyBinding[0], new boolean[0]);
}
public void onRenderEndTick()
void setModContainer(ModLoaderModContainer modContainer)
{
((net.minecraft.src.BaseMod)modContainer.getMod()).keyboardEvent(keyBinding);
this.modContainer = modContainer;
}
public void fireKeyEvent(KeyBinding kb)
{
((net.minecraft.src.BaseMod)modContainer.getMod()).keyboardEvent(kb);
}
@Override
public void keyDown(EnumSet<TickType> type, boolean end, boolean repeats)
public void keyDown(EnumSet<TickType> type, KeyBinding kb, boolean end, boolean repeats)
{
if (!end)
{
return;
}
upArmed = false;
int idx = helper.indexOf(kb);
if (type.contains(TickType.CLIENT))
{
downArmed = true;
armed[idx] = true;
}
if (type.contains(TickType.RENDER) && downArmed)
if (armed[idx] && type.contains(TickType.RENDER) && (!active[idx] || mlRepeats[idx]))
{
onRenderEndTick();
downArmed = false;
fireKeyEvent(kb);
active[idx] = true;
armed[idx] = false;
}
}
@Override
public void keyUp(EnumSet<TickType> type, boolean end)
public void keyUp(EnumSet<TickType> type, KeyBinding kb, boolean end)
{
if (!end)
{
return;
}
downArmed = false;
if (type.contains(TickType.CLIENT))
{
upArmed = true;
}
if (type.contains(TickType.RENDER) && upArmed)
{
onRenderEndTick();
upArmed = false;
}
int idx = helper.indexOf(kb);
active[idx] = false;
}
@Override
@@ -99,6 +98,18 @@ public class ModLoaderKeyBindingHandler extends KeyBindingRegistry.KeyHandler
@Override
public String getLabel()
{
return modContainer.getModId() +" KB "+keyBinding.field_74512_d;
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);
}
}
@@ -1,14 +1,8 @@
package cpw.mods.fml.client.registry;
import java.util.Collections;
import net.minecraft.src.BiomeGenBase;
import net.minecraft.src.TileEntity;
import net.minecraft.src.TileEntityRenderer;
import net.minecraft.src.TileEntitySpecialRenderer;
import cpw.mods.fml.client.FMLClientHandler;
import cpw.mods.fml.common.ObfuscationReflectionHelper;
import cpw.mods.fml.common.registry.GameRegistry;
public class ClientRegistry
@@ -2,15 +2,16 @@ package cpw.mods.fml.client.registry;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
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 net.minecraft.src.GameSettings;
import net.minecraft.src.KeyBinding;
import com.google.common.collect.Sets;
import cpw.mods.fml.common.ITickHandler;
import cpw.mods.fml.common.Side;
@@ -19,29 +20,79 @@ 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 keyBinding;
protected boolean keyDown;
protected boolean repeating;
protected KeyBinding[] keyBindings;
protected boolean[] keyDown;
protected boolean[] repeatings;
private boolean isDummy;
public KeyHandler(KeyBinding keyBinding, boolean repeating)
/**
* Pass an array of keybindings and a repeat flag for each one
*
* @param keyBindings
* @param repeatings
*/
public KeyHandler(KeyBinding[] keyBindings, boolean[] repeatings)
{
this.keyBinding = keyBinding;
this.repeating = repeating;
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];
}
public KeyBinding getKeyBinding()
/**
* 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)
{
return this.keyBinding;
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)
{
@@ -50,39 +101,81 @@ public class KeyBindingRegistry
private void keyTick(EnumSet<TickType> type, boolean tickEnd)
{
int keyCode = keyBinding.field_74512_d;
boolean state = (keyCode < 0 ? Mouse.isButtonDown(keyCode + 100) : Keyboard.isKeyDown(keyCode));
if (state != keyDown || (state && repeating))
for (int i = 0; i < keyBindings.length; i++)
{
if (state)
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]))
{
keyDown(type, tickEnd, state!=keyDown);
if (state)
{
keyDown(type, keyBinding, tickEnd, state!=keyDown[i]);
}
else
{
keyUp(type, keyBinding, tickEnd);
}
if (tickEnd)
{
keyDown[i] = state;
}
}
else
{
keyUp(type, tickEnd);
}
keyDown = state;
}
}
public abstract void keyDown(EnumSet<TickType> types, boolean tickEnd, boolean isRepeat);
public abstract void keyUp(EnumSet<TickType> types, boolean tickEnd);
/**
* 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 List<KeyHandler> keyHandlers = Lists.newArrayList();
private static final KeyBindingRegistry INSTANCE = new KeyBindingRegistry();
public static void registerKeyBinding(KeyHandler handler) {
keyHandlers.add(handler);
TickRegistry.registerTickHandler(handler, Side.CLIENT);
private Set<KeyHandler> keyHandlers = Sets.newLinkedHashSet();
@Deprecated
public static KeyBindingRegistry instance()
{
return INSTANCE;
}
public static void uploadKeyBindingsToGame(GameSettings settings)
public void uploadKeyBindingsToGame(GameSettings settings)
{
ArrayList<KeyBinding> harvestedBindings = Lists.newArrayList();
for (KeyHandler key : keyHandlers)
{
harvestedBindings.add(key.keyBinding);
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];
@@ -1,44 +1,136 @@
package cpw.mods.fml.client.registry;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.ObjectArrays;
import net.minecraft.src.Block;
import net.minecraft.src.Entity;
import net.minecraft.src.IBlockAccess;
import net.minecraft.src.Render;
import net.minecraft.src.RenderBlocks;
import net.minecraft.src.RenderManager;
import net.minecraft.src.RenderPlayer;
import cpw.mods.fml.client.modloader.ModLoaderBlockRendererHandler;
import cpw.mods.fml.common.ObfuscationReflectionHelper;
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 = 30;
private int nextRenderId = 32;
private Map<Integer, ISimpleBlockRenderingHandler> blockRenderers = Maps.newHashMap();
private List<EntityRendererInfo> entityRenderers = Lists.newArrayList();
public int addNewArmourRendererPrefix(String armor)
/**
* 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;
}
public static RenderingRegistry instance()
/**
* 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 class EntityRendererInfo
private static class EntityRendererInfo
{
public EntityRendererInfo(Class<? extends Entity> target, Render renderer)
{
@@ -49,20 +141,6 @@ public class RenderingRegistry
private Render renderer;
}
public void registerEntityRenderingHandler(Class<? extends Entity> entityClass, Render renderer)
{
entityRenderers.add(new EntityRendererInfo(entityClass, renderer));
}
public void registerBlockHandler(ISimpleBlockRenderingHandler handler)
{
blockRenderers.put(handler.getRenderId(), handler);
}
public int getNextAvailableRenderId()
{
return nextRenderId++;
}
/**
* @param renderer
* @param world
@@ -108,6 +186,7 @@ public class RenderingRegistry
for (EntityRendererInfo info : entityRenderers)
{
rendererMap.put(info.target, info.renderer);
info.renderer.func_76976_a(RenderManager.field_78727_a);
}
}
}
+65 -43
View File
@@ -12,19 +12,17 @@
*/
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.IConsoleHandler;
import cpw.mods.fml.common.ICraftingHandler;
import cpw.mods.fml.common.IDispenseHandler;
import cpw.mods.fml.common.INetworkHandler;
import cpw.mods.fml.common.IPickupNotifier;
import cpw.mods.fml.common.IPlayerTracker;
import cpw.mods.fml.common.IWorldGenerator;
import cpw.mods.fml.common.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
{
@@ -33,7 +31,7 @@ public abstract class BaseMod implements cpw.mods.fml.common.modloader.BaseModPr
public final boolean doTickInGame(TickType tick, boolean tickEnd, Object... data)
{
Minecraft mc = FMLClientHandler.instance().getClient();
boolean hasWorld = true;
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);
@@ -44,7 +42,10 @@ public abstract class BaseMod implements cpw.mods.fml.common.modloader.BaseModPr
public final boolean doTickInGUI(TickType tick, boolean tickEnd, Object... data)
{
Minecraft mc = FMLClientHandler.instance().getClient();
if (tickEnd && ( tick==TickType.RENDER || tick==TickType.CLIENT)) {
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;
@@ -177,9 +178,9 @@ public abstract class BaseMod implements cpw.mods.fml.common.modloader.BaseModPr
return 0;
}
@SideOnly(CLIENT)
public void addRenderer(Map<Class<? extends Entity>, Render> renderers)
{
}
/**
@@ -194,9 +195,10 @@ public abstract class BaseMod implements cpw.mods.fml.common.modloader.BaseModPr
* @param item
* @return
*/
public boolean dispenseEntity(World world, double x, double y, double z, int xVel, int zVel, ItemStack item)
@Override
public int dispenseEntity(World world, ItemStack item, Random rnd, int x, int y, int z, int xVel, int zVel, double entX, double entY, double entZ)
{
return false;
return -1;
}
/**
@@ -223,6 +225,21 @@ public abstract class BaseMod implements cpw.mods.fml.common.modloader.BaseModPr
{
}
/**
* 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
*
@@ -250,6 +267,7 @@ public abstract class BaseMod implements cpw.mods.fml.common.modloader.BaseModPr
*/
public abstract String getVersion();
@SideOnly(CLIENT)
public void keyboardEvent(KeyBinding event)
{
@@ -284,11 +302,18 @@ public abstract class BaseMod implements cpw.mods.fml.common.modloader.BaseModPr
* @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;
@@ -296,19 +321,18 @@ public abstract class BaseMod implements cpw.mods.fml.common.modloader.BaseModPr
/**
* Only implemented on the client side
* {@link #onChatMessageReceived(EntityPlayer, Packet3Chat)}
* {@link #serverChat(EntityPlayer, Packet3Chat)}
*
* @param text
*/
@Override
public void receiveChatPacket(String text)
public void clientChat(String text)
{
// TODO
}
/**
* Only called on the client side
* {@link #onPacket250Received(EntityPlayer, Packet250CustomPayload)}
* Called client side to receive a custom payload for this mod
*
* @param packet
*/
@@ -318,16 +342,19 @@ public abstract class BaseMod implements cpw.mods.fml.common.modloader.BaseModPr
// 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;
@@ -339,6 +366,12 @@ public abstract class BaseMod implements cpw.mods.fml.common.modloader.BaseModPr
}
@Override
public void serverCustomPayload(NetServerHandler handler, Packet250CustomPayload packet)
{
}
@Override
public void serverDisconnect() {
@@ -373,17 +406,6 @@ public abstract class BaseMod implements cpw.mods.fml.common.modloader.BaseModPr
return getName() + " " + getVersion();
}
/**
* Called when a 250 packet is received on a channel registered to this mod
*
* @param source
* @param payload
*/
@Override
public void onPacket250Received(EntityPlayer source, Packet250CustomPayload payload)
{
}
/**
* Called when a chat message is received. Return true to stop further processing
*
@@ -391,20 +413,10 @@ public abstract class BaseMod implements cpw.mods.fml.common.modloader.BaseModPr
* @param chat
* @return true if you want to consume the message so it is not available for further processing
*/
public boolean onChatMessageReceived(EntityPlayer source, Packet3Chat chat)
@Override
public void serverChat(NetServerHandler source, String message)
{
return false;
}
/**
* Called when a server command is received
* @param command
* @return true if you want to consume the message so it is not available for further processing
*/
public boolean onServerCommand(String command, String sender, Object listener)
{
return false;
}
/**
* Called when a new client logs in.
*
@@ -428,11 +440,21 @@ public abstract class BaseMod implements cpw.mods.fml.common.modloader.BaseModPr
/**
*
* Called when a client changes dimensions on the server.
*
* @param player
* Spawn the entity of the supplied type, if it is your mod's
* @param entityId
* @param world
* @param scaledX
* @param scaledY
* @param scaledZ
* @return
*/
public void onClientDimensionChanged(EntityPlayer player)
@SideOnly(CLIENT)
public Entity spawnEntity(int entityId, World world, double scaledX, double scaledY, double scaledZ)
{
return null;
}
public void clientCustomPayload(NetClientHandler handler, Packet250CustomPayload packet)
{
}
@@ -19,10 +19,8 @@ import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import cpw.mods.fml.client.FMLClientHandler;
import cpw.mods.fml.client.TextureFXManager;
import cpw.mods.fml.client.registry.RenderingRegistry;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.FMLLog;
/**
@@ -74,16 +72,19 @@ public class FMLRenderAccessLibrary
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);
+3 -2
View File
@@ -12,10 +12,11 @@
*/
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;
import static java.lang.annotation.RetentionPolicy.*;
import static java.lang.annotation.ElementType.*;
/**
* @author cpw
+88 -20
View File
@@ -12,17 +12,16 @@
*/
package net.minecraft.src;
import static cpw.mods.fml.common.Side.CLIENT;
import java.awt.image.BufferedImage;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import net.minecraft.client.Minecraft;
import net.minecraft.server.MinecraftServer;
import cpw.mods.fml.client.FMLClientHandler;
import cpw.mods.fml.client.SpriteHelper;
import cpw.mods.fml.client.TextureFXManager;
@@ -34,15 +33,22 @@ 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.common.ObfuscationReflectionHelper;
import cpw.mods.fml.server.FMLServerHandler;
/**
* @author cpw
*
*/
public class ModLoader
{
public static final String fmlMarker = "This is an FML marker";
@@ -79,24 +85,26 @@ public class ModLoader
}
@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);
}
/**
* This method is unimplemented in server versions to date.
*
* @param armor
* @return
*/
@SideOnly(CLIENT)
public static int addArmor(String armor)
{
return RenderingRegistry.instance().addNewArmourRendererPrefix(armor);
return RenderingRegistry.addNewArmourRendererPrefix(armor);
}
/**
@@ -109,6 +117,15 @@ public class ModLoader
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
*
@@ -162,11 +179,10 @@ public class ModLoader
* @param fileToAdd
* @return
*/
@SideOnly(CLIENT)
public static int addOverride(String fileToOverride, String fileToAdd)
{
int idx = SpriteHelper.getUniqueSpriteIndex(fileToOverride);
addOverride(fileToOverride, fileToAdd, idx);
return idx;
return RenderingRegistry.addTextureOverride(fileToOverride, fileToAdd);
}
/**
@@ -176,9 +192,10 @@ public class ModLoader
* @param overlayPath
* @param index
*/
@SideOnly(CLIENT)
public static void addOverride(String path, String overlayPath, int index)
{
TextureFXManager.instance().addNewTextureOverride(path, overlayPath, index);
RenderingRegistry.addTextureOverride(path, overlayPath, index);
}
/**
@@ -214,6 +231,16 @@ public class ModLoader
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
*
@@ -272,9 +299,21 @@ public class ModLoader
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.
* {@link FMLClientHandler#tryDispensingEntity(World, double, double, double, byte, byte, ItemStack)}
*
* @param world
* @param x
@@ -370,14 +409,13 @@ public class ModLoader
return FMLLog.getLogger();
}
@SideOnly(CLIENT)
public static Minecraft getMinecraftInstance()
{
return FMLClientHandler.instance().getClient();
}
/**
* This is not the server
* {@link FMLClientHandler#getServer()}
*
* @return
*/
@@ -418,6 +456,7 @@ public class ModLoader
* 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);
@@ -434,6 +473,7 @@ public class ModLoader
return EntityRegistry.findGlobalUniqueEntityId();
}
@SideOnly(CLIENT)
public static int getUniqueSpriteIndex(String path)
{
return SpriteHelper.getUniqueSpriteIndex(path);
@@ -452,6 +492,7 @@ public class ModLoader
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);
@@ -477,6 +518,7 @@ public class ModLoader
{
}
@SideOnly(CLIENT)
public static BufferedImage loadImage(RenderEngine renderEngine, String path) throws Exception
{
return TextureFXManager.instance().loadImageFromTexturePack(renderEngine, path);
@@ -495,10 +537,12 @@ public class ModLoader
* 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);
@@ -521,12 +565,14 @@ public class ModLoader
}
@Deprecated
@SideOnly(CLIENT)
public static KeyBinding[] registerAllKeys(KeyBinding[] keys)
{
return keys;
}
@Deprecated
@SideOnly(CLIENT)
public static void registerAllTextureOverrides(RenderEngine cache)
{
}
@@ -552,6 +598,10 @@ public class ModLoader
GameRegistry.registerBlock(block, itemclass);
}
public static void registerContainerID(BaseMod mod, int id)
{
ModLoaderHelper.buildGuiHelper(mod, id);
}
/**
* Register a new entity ID
*
@@ -578,10 +628,10 @@ public class ModLoader
EntityRegistry.registerGlobalEntityID(entityClass, entityName, id, background, foreground);
}
@SideOnly(CLIENT)
public static void registerKey(BaseMod mod, KeyBinding keyHandler, boolean allowRepeat)
{
ModLoaderModContainer mlmc=ModLoaderHelper.registerKeyHelper(mod);
KeyBindingRegistry.registerKeyBinding(new ModLoaderKeyBindingHandler(keyHandler, allowRepeat, mlmc));
ModLoaderClientHelper.registerKeyBinding(mod, keyHandler, allowRepeat);
}
/**
@@ -607,6 +657,7 @@ public class ModLoader
GameRegistry.registerTileEntity(tileEntityClass, id);
}
@SideOnly(CLIENT)
public static void registerTileEntity(Class<? extends TileEntity> tileEntityClass, String id, TileEntitySpecialRenderer renderer)
{
ClientRegistry.registerTileEntity(tileEntityClass, id, renderer);
@@ -669,18 +720,21 @@ public class ModLoader
}
@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);
@@ -695,9 +749,13 @@ public class ModLoader
{
}
/**
* Send a packet from client to server
*
* @param packet
*/
public static void sendPacket(Packet packet) {
// TODO
// FMLClientHandler.instance().sendPacket(packet);
PacketDispatcher.sendPacketToServer(packet);
}
/**
* Send a chat message to the server
@@ -712,11 +770,24 @@ public class ModLoader
}
@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
*
@@ -765,7 +836,6 @@ public class ModLoader
/**
* This method is a call in hook from modified external code. Implemented elsewhere.
* {@link FMLClientHandler#onItemCrafted(EntityPlayer, ItemStack, IInventory)}
*
* @param player
* @param item
@@ -778,7 +848,6 @@ public class ModLoader
/**
* This method is a call in hook from modified external code. Implemented elsewhere.
* {@link FMLClientHandler#onItemSmelted(EntityPlayer, ItemStack)}
*
* @param player
* @param item
@@ -790,7 +859,6 @@ public class ModLoader
/**
* Throw the offered exception. Likely will stop the game.
* {@link FMLClientHandler#raiseException(Throwable, String, boolean)}
*
* @param message
* @param e
@@ -18,12 +18,8 @@ import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.awt.image.ImageObserver;
import org.lwjgl.opengl.GL11;
import cpw.mods.fml.client.FMLClientHandler;
import cpw.mods.fml.client.FMLTextureFX;
import cpw.mods.fml.common.FMLCommonHandler;
import static org.lwjgl.opengl.GL11.*;
/**
* A texture override for animations, it takes a vertical image of
+21 -19
View File
@@ -14,6 +14,8 @@
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;
@@ -22,8 +24,6 @@ import org.lwjgl.opengl.GL11;
import cpw.mods.fml.client.FMLClientHandler;
import cpw.mods.fml.client.FMLTextureFX;
import cpw.mods.fml.common.FMLCommonHandler;
import static org.lwjgl.opengl.GL11.*;
public class ModTextureStatic extends FMLTextureFX
{
@@ -33,30 +33,30 @@ public class ModTextureStatic extends FMLTextureFX
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)
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()
{
@@ -80,16 +80,17 @@ public class ModTextureStatic extends FMLTextureFX
update();
}
public void func_783_a()
@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.
// 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)
{
@@ -97,11 +98,12 @@ public class ModTextureStatic extends FMLTextureFX
}
}
public void func_782_a(RenderEngine p_782_1_)
@Override
public void func_76845_a(RenderEngine p_76845_1_)
{
GL11.glBindTexture(GL_TEXTURE_2D, p_782_1_.func_78341_b(targetTex));
GL11.glBindTexture(GL_TEXTURE_2D, p_76845_1_.func_78341_b(targetTex));
}
public void update()
{
needApply = 2;
@@ -126,7 +128,7 @@ public class ModTextureStatic extends FMLTextureFX
oldanaglyph = field_76851_c;
}
//Implementation of http://scale2x.sourceforge.net/algorithm.html
public static BufferedImage scale2x(BufferedImage image)
{
@@ -170,9 +172,9 @@ public class ModTextureStatic extends FMLTextureFX
return tmp;
}
@Override
public String toString()
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);
}
}
+57 -12
View File
@@ -9,7 +9,7 @@
if not sys.platform.startswith('win'):
if os.path.exists(path):
shutil.rmtree(path)
@@ -582,6 +584,9 @@
@@ -584,6 +586,9 @@
self.has_astyle_cfg = False
if os.path.isfile(self.astyleconf):
self.has_astyle_cfg = True
@@ -19,7 +19,7 @@
def creatergcfg(self, reobf=False, keep_lvt=False, keep_generics=False, rg_update=False):
"""Create the files necessary for RetroGuard"""
@@ -779,7 +784,8 @@
@@ -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'))):
@@ -29,7 +29,18 @@
return True
def checkbins(self, side):
@@ -1039,6 +1045,7 @@
@@ -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)
@@ -37,7 +48,7 @@
dirs = ' '.join(pkglist)
classpath = os.pathsep.join(cplk[side])
forkcmd = self.cmdrecomp.format(classpath=classpath, sourcepath=pathsrclk[side], outpath=pathbinlk[side],
@@ -1060,7 +1067,7 @@
@@ -1062,7 +1073,7 @@
raise
def startserver(self):
@@ -46,7 +57,7 @@
classpath = [os.path.join('..', p) for p in classpath]
classpath = os.pathsep.join(classpath)
os.chdir(self.dirjars)
@@ -1068,7 +1075,7 @@
@@ -1070,7 +1081,7 @@
self.runmc(forkcmd)
def startclient(self):
@@ -55,7 +66,7 @@
classpath = [os.path.join('..', p) for p in classpath]
classpath = os.pathsep.join(classpath)
natives = os.path.join('..', self.dirnatives)
@@ -1195,20 +1202,20 @@
@@ -1197,20 +1208,20 @@
with open(self.csvmethods, 'rb') as fh:
methodsreader = csv.DictReader(fh)
for row in methodsreader:
@@ -79,7 +90,7 @@
names['params'][row['param']] = row['name']
regexps = {
@@ -1238,6 +1245,11 @@
@@ -1240,6 +1251,11 @@
# HINT: We pathwalk the sources
for path, _, filelist in os.walk(pathsrclk[side], followlinks=True):
@@ -91,7 +102,7 @@
for cur_file in fnmatch.filter(filelist, '*.java'):
updatefile(os.path.normpath(os.path.join(path, cur_file)))
return True
@@ -1320,12 +1332,14 @@
@@ -1322,12 +1338,14 @@
pathsrclk = {CLIENT: self.srcclient, SERVER: self.srcserver}
strip_comments(pathsrclk[side])
@@ -106,7 +117,7 @@
def process_javadoc(self, side):
"""Add CSV descriptions to methods and fields as javadoc"""
@@ -1334,6 +1348,21 @@
@@ -1336,6 +1354,21 @@
if not self.has_doc_csv:
self.logger.warning('!! javadoc disabled due to no csvs !!')
return False
@@ -128,7 +139,7 @@
#HINT: We read the relevant CSVs
methodsreader = csv.DictReader(open(self.csvmethods, 'r'))
@@ -1342,13 +1371,13 @@
@@ -1344,13 +1377,13 @@
methods = {}
for row in methodsreader:
#HINT: Only include methods that have a non-empty description
@@ -144,7 +155,7 @@
fields[row['searge']] = row['desc'].replace('*/', '* /')
regexps = {
@@ -1420,6 +1449,7 @@
@@ -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)
@@ -152,7 +163,24 @@
dirs = ' '.join(pkglist)
forkcmd = self.cmdastyle.format(classes=dirs, conffile=self.astyleconf)
self.runcmd(forkcmd)
@@ -1592,6 +1622,9 @@
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:
@@ -162,3 +190,20 @@
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'
+
@@ -3,17 +3,17 @@ package cpw.mods.fml.common;
import java.io.File;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.google.common.eventbus.EventBus;
import cpw.mods.fml.common.LoaderState.ModState;
import cpw.mods.fml.common.discovery.ContainerType;
import cpw.mods.fml.common.versioning.ArtifactVersion;
import cpw.mods.fml.common.versioning.DefaultArtifactVersion;
public class DummyModContainer implements ModContainer
{
private ModMetadata md;
private ArtifactVersion processedVersion;
public DummyModContainer(ModMetadata md)
{
@@ -42,9 +42,9 @@ public class DummyModContainer implements ModContainer
}
@Override
public List<ArtifactVersion> getRequirements()
public Set<ArtifactVersion> getRequirements()
{
return Collections.emptyList();
return Collections.emptySet();
}
@Override
@@ -108,7 +108,11 @@ public class DummyModContainer implements ModContainer
@Override
public ArtifactVersion getProcessedVersion()
{
return null;
if (processedVersion == null)
{
processedVersion = new DefaultArtifactVersion(getModId(), getVersion());
}
return processedVersion;
}
@Override
@@ -122,4 +126,10 @@ public class DummyModContainer implements ModContainer
{
return false;
}
@Override
public String getDisplayVersion()
{
return md.version;
}
}
@@ -13,45 +13,36 @@
*/
package cpw.mods.fml.common;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
import net.minecraft.server.MinecraftServer;
import net.minecraft.src.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.discovery.ContainerType;
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.common.registry.GameRegistry;
import cpw.mods.fml.server.FMLServerHandler;
/**
@@ -80,20 +71,24 @@ public class FMLCommonHandler
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)
{
sidedDelegate.profileStart("modTickScheduling");
TickRegistry.updateTickQueue(side.isClient() ? scheduledClientTicks : scheduledServerTicks, side);
sidedDelegate.profileEnd();
}
public void tickStart(EnumSet<TickType> ticks, Side side, Object ... data)
{
@@ -103,19 +98,15 @@ public class FMLCommonHandler
{
return;
}
sidedDelegate.profileStart("modTickStart$"+ticks);
for (IScheduledTickHandler ticker : scheduledTicks)
{
EnumSet<TickType> ticksToRun = EnumSet.copyOf(ticker.ticks());
EnumSet<TickType> ticksToRun = EnumSet.copyOf(Objects.firstNonNull(ticker.ticks(), EnumSet.noneOf(TickType.class)));
ticksToRun.removeAll(EnumSet.complementOf(ticks));
if (!ticksToRun.isEmpty())
{
sidedDelegate.profileStart(ticker.getLabel());
ticker.tickStart(ticksToRun, data);
sidedDelegate.profileEnd();
}
}
sidedDelegate.profileEnd();
}
public void tickEnd(EnumSet<TickType> ticks, Side side, Object ... data)
@@ -126,19 +117,15 @@ public class FMLCommonHandler
{
return;
}
sidedDelegate.profileStart("modTickEnd$"+ticks);
for (IScheduledTickHandler ticker : scheduledTicks)
{
EnumSet<TickType> ticksToRun = EnumSet.copyOf(ticker.ticks());
EnumSet<TickType> ticksToRun = EnumSet.copyOf(Objects.firstNonNull(ticker.ticks(), EnumSet.noneOf(TickType.class)));
ticksToRun.removeAll(EnumSet.complementOf(ticks));
if (!ticksToRun.isEmpty())
{
sidedDelegate.profileStart(ticker.getLabel());
ticker.tickEnd(ticksToRun, data);
sidedDelegate.profileEnd();
}
}
sidedDelegate.profileEnd();
}
/**
@@ -181,6 +168,23 @@ public class FMLCommonHandler
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
*
@@ -198,9 +202,6 @@ public class FMLCommonHandler
}
private Class<?> forge;
private boolean noForge;
private List<String> brandings;
private Class<?> findMinecraftForge()
{
if (forge==null && !noForge)
@@ -238,7 +239,12 @@ public class FMLCommonHandler
{
Builder brd = ImmutableList.<String>builder();
brd.add(Loader.instance().getMCVersionString());
brd.add(Loader.instance().getFMLVersionString());
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();
@@ -330,9 +336,9 @@ public class FMLCommonHandler
sidedDelegate.showGuiScreen(clientGuiElement);
}
public Entity spawnEntityIntoClientWorld(Class<? extends Entity> cls, EntitySpawnPacket entitySpawnPacket)
public Entity spawnEntityIntoClientWorld(EntityRegistration registration, EntitySpawnPacket entitySpawnPacket)
{
return sidedDelegate.spawnEntityIntoClientWorld(cls, entitySpawnPacket);
return sidedDelegate.spawnEntityIntoClientWorld(registration, entitySpawnPacket);
}
public void adjustEntityLocationOnClient(EntitySpawnAdjustmentPacket entitySpawnAdjustmentPacket)
@@ -342,16 +348,7 @@ public class FMLCommonHandler
public void onServerStart(DedicatedServer dedicatedServer)
{
try
{
// Done this way so that the client doesn't depend on server side handler
Class<?> cls = Class.forName("cpw.mods.fml.server.FMLServerHandler", true, getClass().getClassLoader());
}
catch (ClassNotFoundException e)
{
FMLLog.log(Level.SEVERE, e, "Unable to load the FML server handler");
throw Throwables.propagate(e);
}
FMLServerHandler.instance();
sidedDelegate.beginServerLoading(dedicatedServer);
}
@@ -384,11 +381,31 @@ public class FMLCommonHandler
public void onPlayerPreTick(EntityPlayer player)
{
tickStart(EnumSet.of(TickType.PLAYER), Side.SERVER, player);
Side side = player instanceof EntityPlayerMP ? Side.SERVER : Side.CLIENT;
tickStart(EnumSet.of(TickType.PLAYER), side, player);
}
public void onPlayerPostTick(EntityPlayer player)
{
tickEnd(EnumSet.of(TickType.PLAYER), Side.SERVER, 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);
}
}
+2 -2
View File
@@ -9,12 +9,12 @@ public class FMLLog
public static void log(Level level, String format, Object... data)
{
coreLog.log(level, String.format(format, data));
coreLog.log(level, format, data);
}
public static void log(Level level, Throwable ex, String format, Object... data)
{
coreLog.log(level, String.format(format, data), ex);
coreLog.log(level, ex, format, data);
}
public static void severe(String format, Object... data)
+127 -48
View File
@@ -16,32 +16,30 @@ import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.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.ImmutableList;
import com.google.common.collect.Iterators;
import com.google.common.collect.ImmutableBiMap.Builder;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.google.common.collect.Table;
import com.google.common.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.LoaderState.ModState;
import cpw.mods.fml.common.Mod.Block;
import cpw.mods.fml.common.Mod.Instance;
import cpw.mods.fml.common.Mod.Metadata;
import cpw.mods.fml.common.discovery.ASMDataTable;
import cpw.mods.fml.common.discovery.ASMDataTable.ASMData;
import cpw.mods.fml.common.discovery.ContainerType;
import cpw.mods.fml.common.event.FMLConstructionEvent;
import cpw.mods.fml.common.event.FMLInitializationEvent;
import cpw.mods.fml.common.event.FMLPostInitializationEvent;
@@ -51,7 +49,6 @@ import cpw.mods.fml.common.event.FMLServerStartingEvent;
import cpw.mods.fml.common.event.FMLServerStoppingEvent;
import cpw.mods.fml.common.event.FMLStateEvent;
import cpw.mods.fml.common.network.FMLNetworkHandler;
import cpw.mods.fml.common.registry.GameRegistry;
import cpw.mods.fml.common.versioning.ArtifactVersion;
import cpw.mods.fml.common.versioning.DefaultArtifactVersion;
@@ -64,9 +61,7 @@ public class FMLModContainer implements ModContainer
private String className;
private Map<String, Object> descriptor;
private boolean enabled = true;
private List<ArtifactVersion> requirements;
private List<ArtifactVersion> dependencies;
private List<ArtifactVersion> dependants;
private String internalVersion;
private boolean overridesMetadata;
private EventBus eventBus;
private LoadController controller;
@@ -83,6 +78,7 @@ public class FMLModContainer implements ModContainer
.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)
@@ -107,7 +103,7 @@ public class FMLModContainer implements ModContainer
@Override
public String getVersion()
{
return modMetadata.version;
return internalVersion;
}
@Override
@@ -134,13 +130,35 @@ public class FMLModContainer implements ModContainer
if (overridesMetadata || !modMetadata.useDependencyInformation)
{
List<ArtifactVersion> requirements = Lists.newArrayList();
Set<ArtifactVersion> requirements = Sets.newHashSet();
List<ArtifactVersion> dependencies = Lists.newArrayList();
List<ArtifactVersion> dependants = Lists.newArrayList();
Loader.instance().computeDependencies((String) descriptor.get("dependencies"), requirements, dependencies, dependants);
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";
}
}
@@ -151,7 +169,7 @@ public class FMLModContainer implements ModContainer
}
@Override
public List<ArtifactVersion> getRequirements()
public Set<ArtifactVersion> getRequirements()
{
return modMetadata.requiredMods;
}
@@ -171,7 +189,7 @@ public class FMLModContainer implements ModContainer
@Override
public String getSortingRules()
{
return modMetadata.printableSortingRules();
return ((overridesMetadata || !modMetadata.useDependencyInformation) ? Strings.nullToEmpty(annotationDependencies) : modMetadata.printableSortingRules());
}
@Override
@@ -207,49 +225,48 @@ public class FMLModContainer implements ModContainer
{
Multimap<Class<? extends Annotation>,Object> anns = ArrayListMultimap.create();
for (Field f : clazz.getDeclaredFields())
{
for (Annotation a : f.getAnnotations())
{
f.setAccessible(true);
anns.put(a.annotationType(), f);
}
}
for (Method m : clazz.getDeclaredMethods())
{
for (Annotation a : m.getAnnotations())
{
Class<?>[] paramTypes = new Class[] { modTypeAnnotations.get(a.annotationType()) };
if (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));
if (Arrays.equals(m.getParameterTypes(), paramTypes))
{
m.setAccessible(true);
anns.put(a.annotationType(), m);
}
else
{
FMLLog.severe("The mod %s appears to have an invalid method annotation %s. This annotation can only apply to methods with argument types %s -it will not be called", getModId(), a.annotationType().getSimpleName(), Arrays.toString(paramTypes));
}
}
}
}
return anns;
}
private void processFieldAnnotations() throws Exception
private void processFieldAnnotations(ASMDataTable asmDataTable) throws Exception
{
// Instance annotation
for (Object o : annotations.get(Instance.class))
{
Field f = (Field) o;
f.set(modInstance, modInstance);
}
SetMultimap<String, ASMData> annotations = asmDataTable.getAnnotationsFor(this);
for (Object o : annotations.get(Metadata.class))
parseSimpleFieldAnnotation(annotations, Instance.class.getName(), new Function<ModContainer, Object>()
{
Field f = (Field) o;
f.set(modInstance, modMetadata);
}
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))
// {
@@ -258,6 +275,62 @@ public class FMLModContainer implements ModContainer
// }
}
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)
{
@@ -273,7 +346,7 @@ public class FMLModContainer implements ModContainer
isNetworkMod = FMLNetworkHandler.instance().registerNetworkMod(this, clazz, event.getASMHarvestedData());
modInstance = clazz.newInstance();
ProxyInjector.inject(this, event.getASMHarvestedData(), FMLCommonHandler.instance().getSide());
processFieldAnnotations();
processFieldAnnotations(event.getASMHarvestedData());
}
catch (Throwable e)
{
@@ -325,4 +398,10 @@ public class FMLModContainer implements ModContainer
{
return isNetworkMod;
}
@Override
public String getDisplayVersion()
{
return modMetadata.version;
}
}
@@ -0,0 +1,8 @@
package cpw.mods.fml.common;
import java.util.concurrent.Callable;
public interface ICrashCallable extends Callable<String>
{
String getLabel();
}
@@ -12,6 +12,8 @@
*/
package cpw.mods.fml.common;
import java.util.Random;
import net.minecraft.src.ItemStack;
import net.minecraft.src.World;
@@ -21,13 +23,20 @@ public interface IDispenseHandler
/**
* Return -1 if you don't want to dispense anything. the other values seem to have specific meanings
* to blockdispenser.
*
* @param x
* @param y
* @param z
* @param xVelocity
* @param zVelocity
* @param data
* @param world
* @param item
* @param random
* @param entX
* @param entY
* @param entZ
* @return
*/
int dispense(double x, double y, double z, int xVelocity, int zVelocity, World world, ItemStack item);
@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);
}
@@ -1,27 +1,19 @@
package cpw.mods.fml.common;
import java.io.File;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Properties;
import java.util.logging.Logger;
import net.minecraft.server.MinecraftServer;
import net.minecraft.src.DedicatedServer;
import net.minecraft.src.Entity;
import net.minecraft.src.World;
import cpw.mods.fml.common.modloader.ModProperty;
import 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
{
void profileStart(String profileLabel);
void profileEnd();
List<String> getAdditionalBrandingInformation();
Side getSide();
@@ -30,7 +22,7 @@ public interface IFMLSidedHandler
void showGuiScreen(Object clientGuiElement);
Entity spawnEntityIntoClientWorld(Class<? extends Entity> entityClass, EntitySpawnPacket packet);
Entity spawnEntityIntoClientWorld(EntityRegistration registration, EntitySpawnPacket packet);
void adjustEntityLocationOnClient(EntitySpawnAdjustmentPacket entitySpawnAdjustmentPacket);
@@ -39,4 +31,14 @@ public interface IFMLSidedHandler
void finishServerLoading();
MinecraftServer getServer();
void sendPacket(Packet packet);
void displayMissingMods(ModMissingPacket modMissingPacket);
void handleTinyPacket(NetHandler handler, Packet131MapData mapData);
void setClientCompatibilityLevel(byte compatibilityLevel);
byte getClientCompatibilityLevel();
}
@@ -13,7 +13,10 @@
*/
package cpw.mods.fml.common;
import net.minecraft.src.EntityItem;
import net.minecraft.src.EntityPlayer;
public interface IPickupNotifier
{
void notifyPickup(Object... pickupData);
void notifyPickup(EntityItem item, EntityPlayer player);
}
@@ -14,13 +14,19 @@
package cpw.mods.fml.common;
import net.minecraft.src.EntityPlayer;
/**
* @author cpw
*
*/
public interface IPlayerTracker
{
void onPlayerLogin(Object player);
void onPlayerLogout(Object player);
void onPlayerChangedDimension(Object player);
void onPlayerLogin(EntityPlayer player);
void onPlayerLogout(EntityPlayer player);
void onPlayerChangedDimension(EntityPlayer player);
void onPlayerRespawn(EntityPlayer player);
}
@@ -31,8 +31,8 @@ public interface IWorldGenerator
* Generate some world
*
* @param random the chunk specific {@link Random}.
* @param chunkX the block X coordinate of this chunk.
* @param chunkZ the block Z coordinate of this chunk.
* @param 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.
@@ -2,6 +2,7 @@ package cpw.mods.fml.common;
import java.io.File;
import java.util.List;
import java.util.Set;
import com.google.common.eventbus.EventBus;
@@ -53,7 +54,7 @@ public class InjectedModContainer implements ModContainer
wrappedContainer.setEnabledState(enabled);
}
public List<ArtifactVersion> getRequirements()
public Set<ArtifactVersion> getRequirements()
{
return wrappedContainer.getRequirements();
}
@@ -103,4 +104,10 @@ public class InjectedModContainer implements ModContainer
{
return true;
}
@Override
public String getDisplayVersion()
{
return wrappedContainer.getDisplayVersion();
}
}
+43 -26
View File
@@ -8,23 +8,19 @@ import java.util.logging.Level;
import com.google.common.base.Joiner;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.google.common.collect.ImmutableBiMap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.ImmutableMap.Builder;
import com.google.common.collect.Iterators;
import com.google.common.collect.Multimap;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;
import cpw.mods.fml.common.LoaderState.ModState;
import cpw.mods.fml.common.event.FMLConstructionEvent;
import cpw.mods.fml.common.event.FMLLoadEvent;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import cpw.mods.fml.common.event.FMLStateEvent;
import cpw.mods.fml.common.network.FMLNetworkHandler;
public class LoadController
{
@@ -36,7 +32,7 @@ public class LoadController
private Multimap<String, Throwable> errors = ArrayListMultimap.create();
private Map<String, ModContainer> modList;
private List<ModContainer> activeModList = Lists.newArrayList();
private String activeContainer;
private ModContainer activeContainer;
private BiMap<ModContainer, Object> modObjectList;
public LoadController(Loader loader)
@@ -109,43 +105,55 @@ public class LoadController
public ModContainer activeContainer()
{
return activeContainer!=null ? modList.get(activeContainer) : null;
return activeContainer;
}
@Subscribe
public void propogateStateMessage(FMLStateEvent stateEvent)
{
for (Map.Entry<String,EventBus> entry : eventChannels.entrySet())
if (stateEvent instanceof FMLPreInitializationEvent)
{
activeContainer = entry.getKey();
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, entry.getKey());
entry.getValue().post(stateEvent);
FMLLog.finer("State event %s delivered to mod %s", stateEvent, entry.getKey());
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(entry.getKey()))
if (!errors.containsKey(modId))
{
modStates.put(entry.getKey(), stateEvent.getModState());
modStates.put(modId, stateEvent.getModState());
}
else
{
modStates.put(entry.getKey(), ModState.ERRORED);
modStates.put(modId, ModState.ERRORED);
}
}
if (stateEvent instanceof FMLConstructionEvent)
{
buildModObjectList();
}
}
public void buildModObjectList()
public ImmutableBiMap<ModContainer, Object> buildModObjectList()
{
ImmutableBiMap.Builder<ModContainer, Object> builder = ImmutableBiMap.<ModContainer, Object>builder();
for (ModContainer mc : activeModList)
{
builder.put(mc, mc.getMod());
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());
}
}
}
modObjectList = builder.build();
return builder.build();
}
public void errorOccurred(ModContainer modContainer, Throwable exception)
@@ -155,11 +163,10 @@ public class LoadController
public void printModStates(StringBuilder ret)
{
for (String modId : modStates.keySet())
for (ModContainer mc : loader.getModList())
{
ModContainer mod = modList.get(modId);
ret.append("\n\t").append(mod.getName()).append(" (").append(mod.getSource().getName()).append(") ");
Joiner.on("->"). appendTo(ret, modStates.get(modId));
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()));
}
}
@@ -188,6 +195,16 @@ public class LoadController
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;
}
}
+140 -38
View File
@@ -14,42 +14,43 @@
package cpw.mods.fml.common;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.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 java.util.regex.Matcher;
import net.minecraft.server.MinecraftServer;
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.base.Splitter.MapSplitter;
import com.google.common.base.Throwables;
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.ContainerType;
import cpw.mods.fml.common.discovery.ModDiscoverer;
import cpw.mods.fml.common.event.FMLLoadEvent;
import cpw.mods.fml.common.functions.ModIdFunction;
import cpw.mods.fml.common.modloader.BaseModProxy;
import cpw.mods.fml.common.toposort.ModSorter;
import cpw.mods.fml.common.toposort.ModSortingException;
import cpw.mods.fml.common.toposort.TopologicalSort;
@@ -160,6 +161,12 @@ public class Loader
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();
}
}
/**
@@ -172,14 +179,32 @@ public class Loader
FMLLog.fine("Verifying mod requirements are satisfied");
try
{
Map<String, ArtifactVersion> modVersions = Maps.newHashMap();
for (ModContainer mod : mods)
BiMap<String, ArtifactVersion> modVersions = HashBiMap.create();
for (ModContainer mod : getActiveModList())
{
modVersions.put(mod.getModId(), mod.getProcessedVersion());
}
for (ModContainer mod : mods)
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)
{
@@ -187,21 +212,32 @@ public class Loader
{
if (!v.containsVersion(modVersions.get(v.getLabel())))
{
FMLLog.log(Level.SEVERE, "The mod %s (%s) requires mods %s to be available, one or more are not", mod.getModId(), mod.getName(), allDeps);
throw new LoaderException();
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(mods, namedMods);
ModSorter sorter = new ModSorter(getActiveModList(), namedMods);
try
{
FMLLog.fine("Sorting mods into an ordered list");
mods = sorter.sort();
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)
@@ -216,11 +252,11 @@ public class Loader
finally
{
FMLLog.fine("Mod sorting data:");
for (ModContainer mod : mods)
for (ModContainer mod : getActiveModList())
{
if (!mod.isImmutable())
{
FMLLog.fine("\t%s(%s): %s (%s)", mod.getModId(), mod.getName(), mod.getSource().getName(), mod.getSortingRules());
FMLLog.fine("\t%s(%s:%s): %s (%s)", mod.getModId(), mod.getName(), mod.getVersion(), mod.getSource().getName(), mod.getSortingRules());
}
}
if (mods.size()==0)
@@ -279,11 +315,46 @@ public class Loader
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
*/
@@ -365,9 +436,24 @@ public class Loader
modController.transition(LoaderState.LOADING);
ModDiscoverer disc = identifyMods();
disableRequestedMods();
modController.distributeStateMessage(FMLLoadEvent.class);
sortModList();
mods = ImmutableList.copyOf(mods);
modController.distributeStateMessage(FMLLoadEvent.class);
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);
@@ -377,30 +463,30 @@ public class Loader
private void disableRequestedMods()
{
String disabledModList = System.getProperty("fml.modStates", "");
FMLLog.fine("Received a system property request \'%s\'",disabledModList);
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(disabledModList);
.split(forcedModList);
FMLLog.fine("System property request managing the state of %d mods", sysPropertyStateList.size());
Map<String, String> modStates = Maps.newHashMap();
File disabledModFile = new File(canonicalConfigDir, "fmlModState.properties");
Properties disabledModListProperties = new Properties();
if (disabledModFile.exists() && disabledModFile.isFile())
File forcedModFile = new File(canonicalConfigDir, "fmlModState.properties");
Properties forcedModListProperties = new Properties();
if (forcedModFile.exists() && forcedModFile.isFile())
{
FMLLog.fine("Found a mod state file %s", disabledModFile.getName());
FMLLog.fine("Found a mod state file %s", forcedModFile.getName());
try
{
disabledModListProperties.load(new FileReader(disabledModFile));
FMLLog.fine("Loaded states for %d mods from file", disabledModListProperties.size());
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(disabledModListProperties));
modStates.putAll(Maps.fromProperties(forcedModListProperties));
modStates.putAll(sysPropertyStateList);
FMLLog.fine("After merging, found state information for %d mods", modStates.size());
@@ -408,7 +494,7 @@ public class Loader
{
public Boolean apply(String input)
{
return !Boolean.parseBoolean(input);
return Boolean.parseBoolean(input);
}
});
@@ -430,7 +516,7 @@ public class Loader
*/
public static boolean isModLoaded(String modname)
{
return instance().namedMods.containsKey(modname);
return instance().namedMods.containsKey(modname) && instance().modController.getModState(instance.namedMods.get(modname))!=ModState.DISABLED;
}
/**
@@ -459,7 +545,7 @@ public class Loader
*/
public String getFMLVersionString()
{
return String.format("FML v%s.%s.%s.%s", major, minor, rev, build);
return String.format("%s.%s.%s.%s", major, minor, rev, build);
}
/**
@@ -470,7 +556,7 @@ public class Loader
return modClassLoader;
}
public void computeDependencies(String dependencyString, List<ArtifactVersion> requirements, List<ArtifactVersion> dependencies, List<ArtifactVersion> dependants)
public void computeDependencies(String dependencyString, Set<ArtifactVersion> requirements, List<ArtifactVersion> dependencies, List<ArtifactVersion> dependants)
{
if (dependencyString == null || dependencyString.length() == 0)
{
@@ -559,14 +645,20 @@ public class Loader
FMLLog.info("Forge Mod Loader has successfully loaded %d mod%s", mods.size(), mods.size()==1 ? "" : "s");
}
public Callable getCallableCrashInformation()
public ICrashCallable getCallableCrashInformation()
{
return new Callable<String>() {
return new ICrashCallable() {
@Override
public String call() throws Exception
{
return getCrashInformation();
}
@Override
public String getLabel()
{
return "FML";
}
};
}
@@ -614,4 +706,14 @@ public class Loader
{
return getModObjectList().inverse();
}
public ModContainer activeModContainer()
{
return modController.activeContainer();
}
public boolean isInState(LoaderState state)
{
return modController.isInState(state);
}
}
@@ -1,12 +1,9 @@
package cpw.mods.fml.common;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import argo.jdom.JdomParser;
import argo.jdom.JsonNode;
@@ -14,7 +11,6 @@ import argo.jdom.JsonRootNode;
import argo.saj.InvalidSyntaxException;
import com.google.common.base.Throwables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
public class MetadataCollection
@@ -23,13 +19,13 @@ public class MetadataCollection
private Map<String, ModMetadata> metadatas = Maps.newHashMap();
private int metadataVersion = 1;
public static MetadataCollection from(InputStream inputStream)
public static MetadataCollection from(InputStream inputStream, String sourceName)
{
if (inputStream == null)
{
return new MetadataCollection();
}
InputStreamReader reader = new InputStreamReader(inputStream);
try
{
@@ -43,6 +39,11 @@ public class MetadataCollection
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);
@@ -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;
}
}
-7
View File
@@ -18,13 +18,6 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import cpw.mods.fml.common.event.FMLInitializationEvent;
import cpw.mods.fml.common.event.FMLPostInitializationEvent;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import cpw.mods.fml.common.event.FMLServerStartedEvent;
import cpw.mods.fml.common.event.FMLServerStartingEvent;
import cpw.mods.fml.common.event.FMLServerStoppingEvent;
import net.minecraft.src.ItemBlock;
/**
+10 -3
View File
@@ -14,7 +14,6 @@
package cpw.mods.fml.common;
import java.io.File;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
@@ -24,8 +23,9 @@ import java.util.logging.Level;
import com.google.common.collect.ImmutableList;
import cpw.mods.fml.common.discovery.ModCandidate;
import cpw.mods.fml.relauncher.FMLRelauncher;
import cpw.mods.fml.common.asm.ASMTransformer;
import cpw.mods.fml.common.asm.transformers.AccessTransformer;
import cpw.mods.fml.common.modloader.BaseModProxy;
import cpw.mods.fml.relauncher.RelaunchClassLoader;
/**
@@ -79,4 +79,11 @@ public class ModClassLoader extends URLClassLoader
{
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);
}
}
+4 -2
View File
@@ -15,10 +15,10 @@ 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.LoaderState.ModState;
import cpw.mods.fml.common.versioning.ArtifactVersion;
/**
@@ -91,7 +91,7 @@ public interface ModContainer
*
* @return
*/
List<ArtifactVersion> getRequirements();
Set<ArtifactVersion> getRequirements();
/**
* A list of modids that should be loaded prior to this one. The special
@@ -150,4 +150,6 @@ public interface ModContainer
boolean isImmutable();
boolean isNetworkMod();
String getDisplayVersion();
}
@@ -5,6 +5,7 @@ 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;
@@ -16,20 +17,38 @@ public class ModContainerFactory
public static ModContainerFactory instance() {
return INSTANCE;
}
public ModContainer build(ASMModParser modParser, File modSource)
public ModContainer build(ASMModParser modParser, File modSource, ModCandidate container)
{
String className = modParser.getASMType().getClassName();
if (modParser.isBaseMod() && modClass.matcher(className).find())
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 a FMLMod type mod %s", className);
FMLLog.fine("Identified an FMLMod type mod %s", className);
return new FMLModContainer(className, modSource, ann.getValues());
}
}
+29 -17
View File
@@ -14,14 +14,15 @@
package cpw.mods.fml.common;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
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.StringTokenizer;
import java.util.zip.ZipInputStream;
import java.util.Set;
import java.util.logging.Level;
import argo.jdom.JsonNode;
import argo.jdom.JsonStringNode;
@@ -35,12 +36,9 @@ import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import cpw.mods.fml.common.functions.ModNameFunction;
import cpw.mods.fml.common.modloader.ModLoaderModContainer;
import cpw.mods.fml.common.versioning.ArtifactVersion;
import cpw.mods.fml.common.versioning.VersionParser;
import static argo.jdom.JsonNodeBuilders.*;
/**
* @author cpw
*
@@ -88,7 +86,7 @@ public class ModMetadata
public List<ModContainer> childMods = Lists.newArrayList();
public boolean useDependencyInformation;
public List<ArtifactVersion> requiredMods;
public Set<ArtifactVersion> requiredMods;
public List<ArtifactVersion> dependencies;
public List<ArtifactVersion> dependants;
public boolean autogenerated;
@@ -101,6 +99,11 @@ public class ModMetadata
{
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")));
@@ -109,10 +112,10 @@ public class ModMetadata
version = Strings.nullToEmpty((String)processedFields.get(aStringBuilder("version")));
credits = Strings.nullToEmpty((String)processedFields.get(aStringBuilder("credits")));
parent = Strings.nullToEmpty((String)processedFields.get(aStringBuilder("parent")));
authorList = Optional.fromNullable((List<String>)processedFields.get(aStringBuilder("authorList"))).or(authorList);
requiredMods = processReferences((List<String>)processedFields.get(aStringBuilder("requiredMods")));
dependencies = processReferences((List<String>)processedFields.get(aStringBuilder("dependencies")));
dependants = processReferences((List<String>)processedFields.get(aStringBuilder("dependants")));
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"))));
}
@@ -120,14 +123,23 @@ public class ModMetadata
{
}
private List<ArtifactVersion> processReferences(List<String> refs)
private <T extends Collection<ArtifactVersion>> T processReferences(Object refs, Class<? extends T> retType)
{
List<ArtifactVersion> res = Lists.newArrayList();
T res = null;
try
{
res = retType.newInstance();
}
catch (Exception e)
{
// unpossible
}
if (refs == null)
{
return res;
}
for (String ref : refs)
for (String ref : ((List<String>)refs))
{
res.add(VersionParser.parseVersionReference(ref));
}
@@ -156,6 +168,6 @@ public class ModMetadata
public String printableSortingRules()
{
return null;
return "";
}
}
@@ -19,8 +19,6 @@ import java.lang.reflect.Modifier;
import java.util.Set;
import java.util.logging.Level;
import org.objectweb.asm.Type;
import cpw.mods.fml.common.discovery.ASMDataTable;
import cpw.mods.fml.common.discovery.ASMDataTable.ASMData;
@@ -9,7 +9,6 @@ import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.Opcodes;
import cpw.mods.fml.relauncher.FMLRelauncher;
import cpw.mods.fml.relauncher.IFMLCallHook;
import cpw.mods.fml.relauncher.RelaunchClassLoader;
@@ -4,6 +4,7 @@ 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)
@@ -1,27 +1,20 @@
package cpw.mods.fml.common.asm.transformers;
import static org.objectweb.asm.Opcodes.ACC_FINAL;
import static org.objectweb.asm.Opcodes.ACC_PRIVATE;
import static org.objectweb.asm.Opcodes.ACC_PROTECTED;
import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
import static org.objectweb.asm.Opcodes.ACC_FINAL;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
@@ -29,15 +22,12 @@ 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.ClassNode;
import org.objectweb.asm.tree.FieldNode;
import org.objectweb.asm.tree.MethodNode;
import com.google.common.base.CharMatcher;
import com.google.common.base.Charsets;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
@@ -49,6 +39,7 @@ import cpw.mods.fml.relauncher.IClassTransformer;
public class AccessTransformer implements IClassTransformer
{
private static final boolean DEBUG = false;
private class Modifier
{
public String name = "";
@@ -58,13 +49,14 @@ public class AccessTransformer implements IClassTransformer
public int targetAccess = 0;
public boolean changeFinal = false;
public boolean markFinal = false;
protected boolean modifyClassVisibility;
private void setTargetAccess(String name)
{
if (name.startsWith("public")) targetAccess = ACC_PUBLIC;
else if (name.startsWith("private")) targetAccess = ACC_PRIVATE;
else if (name.startsWith("protected")) targetAccess = ACC_PROTECTED;
if (name.endsWith("-f"))
{
changeFinal = true;
@@ -118,25 +110,32 @@ public class AccessTransformer implements IClassTransformer
return true;
}
List<String> parts = Lists.newArrayList(Splitter.on(" ").trimResults().split(line));
if (parts.size()>2 || parts.get(1).indexOf('.') == -1)
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)));
String nameReference = descriptor.get(1);
int parenIdx = nameReference.indexOf('(');
if (parenIdx>0)
if (descriptor.size() == 1)
{
m.desc = nameReference.substring(parenIdx);
m.name = nameReference.substring(0,parenIdx);
m.modifyClassVisibility = true;
}
else
{
m.name = nameReference;
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), m);
modifiers.put(descriptor.get(0).replace('/', '.'), m);
return true;
}
});
@@ -155,16 +154,31 @@ public class AccessTransformer implements IClassTransformer
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))
if (n.name.equals(m.name) || m.name.equals("*"))
{
n.access = getFixedAccess(n.access, m);
System.out.println(String.format("Field: %s.%s %s -> %s", name, m.name, Integer.toBinaryString(m.oldAccess),
Integer.toBinaryString(m.newAccess)));
break;
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;
}
}
}
}
@@ -172,11 +186,18 @@ public class AccessTransformer implements IClassTransformer
{
for (MethodNode n : (List<MethodNode>) classNode.methods)
{
if (n.name.equals(m.name) && n.desc.equals(m.desc))
if ((n.name.equals(m.name) && n.desc.equals(m.desc)) || m.name.equals("*"))
{
n.access = getFixedAccess(n.access, m);
System.out.println(String.format("Method: %s.%s%s %s -> %s", name, m.name, m.desc, toBinary(m.oldAccess), toBinary(m.newAccess)));
break;
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;
}
}
}
}
@@ -215,7 +236,7 @@ public class AccessTransformer implements IClassTransformer
default:
throw new RuntimeException("The fuck?");
}
// Clear the "final" marker on fields only if specified in control field
if (target.changeFinal && target.desc == "")
{
@@ -237,7 +258,7 @@ public class AccessTransformer implements IClassTransformer
if (args.length < 2)
{
System.out.println("Usage: AccessTransformer <JarPath> <MapFile> [MapFile2]... ");
return;
System.exit(1);
}
boolean hasTransformer = false;
@@ -259,7 +280,7 @@ public class AccessTransformer implements IClassTransformer
if (!hasTransformer)
{
System.out.println("Culd not find a valid transformer to perform");
return;
System.exit(1);
}
File orig = new File(args[0]);
@@ -267,13 +288,13 @@ public class AccessTransformer implements IClassTransformer
if (!orig.exists() && !temp.exists())
{
System.out.println("Could not find target jar: " + orig);
return;
System.exit(1);
}
if (!orig.renameTo(temp))
{
System.out.println("Could not rename file: " + orig + " -> " + temp);
return;
System.exit(1);
}
try
@@ -283,8 +304,9 @@ public class AccessTransformer implements IClassTransformer
catch (IOException e)
{
e.printStackTrace();
System.exit(1);
}
if (!temp.delete())
{
System.out.println("Could not delete temp file: " + temp);
@@ -386,4 +408,11 @@ public class AccessTransformer implements IClassTransformer
}
}
}
public void ensurePublicAccessFor(String modClazzName)
{
Modifier m = new Modifier();
m.setTargetAccess("public");
m.modifyClassVisibility = true;
modifiers.put(modClazzName, m);
}
}
@@ -1,17 +1,37 @@
package cpw.mods.fml.common.asm.transformers;
import java.io.*;
import java.net.URL;
import java.util.*;
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.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
import org.objectweb.asm.*;
import org.objectweb.asm.tree.*;
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.base.Optional;
import com.google.common.collect.Iterators;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
@@ -25,13 +45,14 @@ public class MCPMerger
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>");
return;
System.exit(1);
}
File map_file = new File(args[0]);
@@ -54,31 +75,31 @@ public class MCPMerger
if (!client_jar.exists())
{
System.out.println("Could not find minecraft.jar: " + client_jar);
return;
System.exit(1);
}
if (!server_jar.exists())
{
System.out.println("Could not find minecraft_server.jar: " + server_jar);
return;
System.exit(1);
}
if (!client_jar.renameTo(client_jar_tmp))
{
System.out.println("Could not rename file: " + client_jar + " -> " + client_jar_tmp);
return;
System.exit(1);
}
if (!server_jar.renameTo(server_jar_tmp))
{
System.out.println("Could not rename file: " + server_jar + " -> " + server_jar_tmp);
return;
System.exit(1);
}
if (!readMapFile(map_file))
{
System.out.println("Could not read map file: " + map_file);
return;
System.exit(1);
}
try
@@ -88,6 +109,7 @@ public class MCPMerger
catch (IOException e)
{
e.printStackTrace();
System.exit(1);
}
if (!client_jar_tmp.delete())
@@ -157,6 +179,8 @@ public class MCPMerger
}
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())
{
@@ -168,12 +192,18 @@ public class MCPMerger
{
if (!copyToServer.contains(name))
{
copyEntry(cInJar, cEntry, cOutJar);
copyClass(cInJar, cEntry, cOutJar, null, true);
cAdded.add(name);
}
else
{
System.out.println("Copy class c->s : " + name);
if (DEBUG)
{
System.out.println("Copy class c->s : " + name);
}
copyClass(cInJar, cEntry, cOutJar, sOutJar, true);
cAdded.add(name);
sAdded.add(name);
}
continue;
}
@@ -191,28 +221,40 @@ public class MCPMerger
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()))
{
copyEntry(sInJar, entry.getValue(), sOutJar);
copyClass(sInJar, entry.getValue(), null, sOutJar, false);
}
else
{
System.out.println("Copy class s->c : " + entry.getKey());
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"));
cOutJar.putNextEntry(newEntry);
cOutJar.write(data);
sOutJar.putNextEntry(newEntry);
sOutJar.write(data);
if (!cAdded.contains(eName))
{
cOutJar.putNextEntry(newEntry);
cOutJar.write(data);
}
if (!sAdded.contains(eName))
{
sOutJar.putNextEntry(newEntry);
sOutJar.write(data);
}
}
}
@@ -245,18 +287,28 @@ public class MCPMerger
ClassNode classNode = new ClassNode();
reader.accept(classNode, 0);
if (classNode.visibleAnnotations == null) classNode.visibleAnnotations = new ArrayList<AnnotationNode>();
classNode.visibleAnnotations.add(getSideAnn(isClientOnly));
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());
outJar.putNextEntry(newEntry);
outJar.write(data);
outJar2.putNextEntry(newEntry);
outJar2.write(data);
if (outJar != null)
{
outJar.putNextEntry(newEntry);
outJar.write(data);
}
if (outJar2 != null)
{
outJar2.putNextEntry(newEntry);
outJar2.write(data);
}
}
private static AnnotationNode getSideAnn(boolean isClientOnly)
@@ -282,7 +334,9 @@ public class MCPMerger
String entryName = entry.getName();
if (!entryName.endsWith(".class") || entryName.startsWith("."))
{
copyEntry(inFile, entry, outFile);
ZipEntry newEntry = new ZipEntry(entry.getName());
outFile.putNextEntry(newEntry);
outFile.write(readEntry(inFile, entry));
}
else
{
@@ -291,12 +345,6 @@ public class MCPMerger
}
return ret;
}
private static void copyEntry(ZipFile inFile, ZipEntry entry, ZipOutputStream outFile) throws IOException
{
ZipEntry newEntry = new ZipEntry(entry.getName());
outFile.putNextEntry(newEntry);
outFile.write(readEntry(inFile, entry));
}
private static byte[] readEntry(ZipFile inFile, ZipEntry entry) throws IOException
{
return readFully(inFile.getInputStream(entry));
@@ -444,7 +492,10 @@ public class MCPMerger
mw.server = this.server | mw.server;
this.client = this.client | mw.client;
this.server = this.server | mw.server;
System.out.printf(" eq: %s %s\n", this, mw);
if (DEBUG)
{
System.out.printf(" eq: %s %s\n", this, mw);
}
}
return eq;
}
@@ -486,13 +537,19 @@ public class MCPMerger
serverName = sM.name;
if (!serverName.equals(lastName) && cPos != cLen)
{
System.out.printf("Server -skip : %s %s %d (%s %d) %d [%s]\n", sClass.name, clientName, cLen - cPos, serverName, sLen - sPos, allMethods.size(), lastName);
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);
System.out.printf("Server *add* : %s %s %d (%s %d) %d [%s]\n", sClass.name, clientName, cLen - cPos, serverName, sLen - sPos, allMethods.size(), lastName);
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);
@@ -507,13 +564,19 @@ public class MCPMerger
clientName = cM.name;
if (!clientName.equals(lastName) && sPos != sLen)
{
System.out.printf("Client -skip : %s %s %d (%s %d) %d [%s]\n", cClass.name, clientName, cLen - cPos, serverName, sLen - sPos, allMethods.size(), lastName);
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);
System.out.printf("Client *add* : %s %s %d (%s %d) %d [%s]\n", cClass.name, clientName, cLen - cPos, serverName, sLen - sPos, allMethods.size(), lastName);
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);
@@ -524,7 +587,10 @@ public class MCPMerger
for (MethodWrapper mw : allMethods)
{
System.out.println(mw);
if (DEBUG)
{
System.out.println(mw);
}
cMethods.add(mw.node);
sMethods.add(mw.node);
if (mw.server && mw.client)
@@ -1,27 +1,14 @@
package cpw.mods.fml.common.asm.transformers;
import static org.objectweb.asm.Opcodes.ACC_PRIVATE;
import static org.objectweb.asm.Opcodes.ACC_PROTECTED;
import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
import static org.objectweb.asm.Opcodes.ACC_FINAL;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
@@ -29,20 +16,14 @@ 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.ClassNode;
import org.objectweb.asm.tree.FieldNode;
import org.objectweb.asm.tree.MethodNode;
import com.google.common.base.CharMatcher;
import com.google.common.base.Charsets;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Iterables;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.google.common.io.LineProcessor;
import com.google.common.io.Resources;
@@ -11,7 +11,6 @@ import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.FieldNode;
import org.objectweb.asm.tree.MethodNode;
import cpw.mods.fml.common.Side;
import cpw.mods.fml.common.asm.SideOnly;
import cpw.mods.fml.relauncher.FMLRelauncher;
import cpw.mods.fml.relauncher.IClassTransformer;
@@ -19,6 +18,7 @@ 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)
@@ -27,13 +27,25 @@ public class SideTransformer implements IClassTransformer
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))
{
System.out.println("Removing Field: " + field.name);
if (DEBUG)
{
System.out.println(String.format("Removing Field: %s.%s", classNode.name, field.name));
}
fields.remove();
}
}
@@ -43,7 +55,10 @@ public class SideTransformer implements IClassTransformer
MethodNode method = methods.next();
if (remove((List<AnnotationNode>)method.visibleAnnotations, SIDE))
{
System.out.println("Removing Method: " + method.name + " " + method.desc);
if (DEBUG)
{
System.out.println(String.format("Removing Method: %s.%s%s", classNode.name, method.name, method.desc));
}
methods.remove();
}
}
@@ -1,7 +1,5 @@
package cpw.mods.fml.common.discovery;
import java.io.File;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -10,12 +8,10 @@ import com.google.common.base.Predicate;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps;
import com.google.common.collect.SetMultimap;
import com.google.common.collect.ImmutableBiMap.Builder;
import cpw.mods.fml.common.ModContainer;
@@ -3,17 +3,16 @@ package cpw.mods.fml.common.discovery;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Logger;
import java.util.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;
@@ -54,12 +53,14 @@ public class DirectoryDiscoverer implements ITypeDiscoverer
try
{
FileInputStream fis = new FileInputStream(metadata);
mc = MetadataCollection.from(fis);
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);
mc = MetadataCollection.from(null,"");
FMLLog.fine("No mcmod.info file found in directory %s", modDir.getName());
}
}
@@ -86,6 +87,11 @@ public class DirectoryDiscoverer implements ITypeDiscoverer
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);
@@ -93,7 +99,7 @@ public class DirectoryDiscoverer implements ITypeDiscoverer
modParser.validate();
modParser.sendToTable(table, candidate);
ModContainer container = ModContainerFactory.instance().build(modParser, candidate.getModContainer());
ModContainer container = ModContainerFactory.instance().build(modParser, candidate.getModContainer(), candidate);
if (container!=null)
{
harvestedMods.add(container);
@@ -2,7 +2,7 @@ package cpw.mods.fml.common.discovery;
import java.util.Collections;
import java.util.List;
import java.util.logging.Logger;
import java.util.logging.Level;
import java.util.regex.Matcher;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
@@ -10,6 +10,7 @@ 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;
@@ -32,17 +33,32 @@ public class JarDiscoverer implements ITypeDiscoverer
if (modInfo != null)
{
FMLLog.finer("Located mcmod.info file in file %s", candidate.getModContainer().getName());
mc = MetadataCollection.from(jar.getInputStream(modInfo));
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 = new ASMModParser(jar.getInputStream(ze));
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());
ModContainer container = ModContainerFactory.instance().build(modParser, candidate.getModContainer(), candidate);
if (container!=null)
{
table.addContainer(container);
@@ -54,7 +70,7 @@ public class JarDiscoverer implements ITypeDiscoverer
}
catch (Exception e)
{
FMLLog.warning("Zip file %s failed to read properly, it will be ignored", candidate.getModContainer().getName());
FMLLog.log(Level.WARNING, e, "Zip file %s failed to read properly, it will be ignored", candidate.getModContainer().getName());
}
finally
{
@@ -3,7 +3,11 @@ 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
@@ -12,16 +16,20 @@ public class ModCandidate
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);
this(classPathRoot, modContainer, sourceType, false, false);
}
public ModCandidate(File classPathRoot, File modContainer, ContainerType sourceType, boolean classpath)
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;
}
@@ -41,6 +49,36 @@ public class ModCandidate
}
public List<ModContainer> explore(ASMDataTable table)
{
return sourceType.findMods(this, 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);
}
}
@@ -1,44 +1,15 @@
package cpw.mods.fml.common.discovery;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.nio.channels.FileChannel;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.Opcodes;
import com.google.common.base.Supplier;
import com.google.common.base.Throwables;
import com.google.common.collect.HashBasedTable;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableTable;
import com.google.common.collect.Tables;
import com.google.common.collect.ImmutableTable.Builder;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.google.common.collect.Table;
import com.google.common.collect.Table.Cell;
import cpw.mods.fml.common.FMLLog;
import cpw.mods.fml.common.LoaderException;
@@ -54,6 +25,8 @@ public class ModDiscoverer
private ASMDataTable dataTable = new ASMDataTable();
private List<File> nonModLibs = Lists.newArrayList();
public void findClasspathMods(ModClassLoader modClassLoader)
{
List<String> knownLibraries = ImmutableList.<String>builder().addAll(modClassLoader.getDefaultLibraries()).addAll(RelaunchLibraryManager.getLibraries()).build();
@@ -61,7 +34,7 @@ public class ModDiscoverer
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));
candidates.add(new ModCandidate(minecraftSources[0], minecraftSources[0], ContainerType.JAR, true, true));
}
else
{
@@ -76,13 +49,13 @@ public class ModDiscoverer
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, true));
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, true));
candidates.add(new ModCandidate(minecraftSources[i], minecraftSources[i], ContainerType.DIR, i==0, true));
}
}
}
@@ -128,7 +101,14 @@ public class ModDiscoverer
try
{
List<ModContainer> mods = candidate.explore(dataTable);
modList.addAll(mods);
if (mods.isEmpty() && !candidate.isClasspath())
{
nonModLibs.add(candidate.getModContainer());
}
else
{
modList.addAll(mods);
}
}
catch (LoaderException le)
{
@@ -148,4 +128,9 @@ public class ModDiscoverer
return dataTable;
}
public List<File> getNonModLibs()
{
return nonModLibs;
}
}
@@ -2,8 +2,10 @@ 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;
@@ -13,10 +15,10 @@ 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;
import cpw.mods.fml.common.discovery.ModDiscoverer;
public class ASMModParser
{
@@ -34,8 +36,16 @@ public class ASMModParser
public ASMModParser(InputStream stream) throws IOException
{
ClassReader reader = new ClassReader(stream);
reader.accept(new ModClassVisitor(this), 0);
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)
@@ -70,7 +80,7 @@ public class ASMModParser
.add("classVersion", classVersion)
.add("superName", asmSuperType.getClassName())
.add("annotations", annotations)
.add("isBaseMod", isBaseMod())
.add("isBaseMod", isBaseMod(Collections.<String>emptyList()))
.add("baseModProperties", baseModProperties)
.toString();
}
@@ -104,9 +114,9 @@ public class ASMModParser
// }
}
public boolean isBaseMod()
public boolean isBaseMod(List<String> rememberedTypes)
{
return getASMSuperType().equals(Type.getType(BaseMod.class));
return getASMSuperType().equals(Type.getType(BaseMod.class)) || rememberedTypes.contains(getASMSuperType().getClassName());
}
public void setBaseModProperties(String foundProperties)
@@ -135,13 +145,13 @@ public class ASMModParser
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)
@@ -1,5 +1,7 @@
package cpw.mods.fml.common.discovery.asm;
import java.util.Collections;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
@@ -16,32 +18,32 @@ public class ModClassVisitor extends ClassVisitor
super(Opcodes.ASM4);
this.discoverer = discoverer;
}
@Override
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces)
{
discoverer.beginNewTypeName(name, version, superName);
}
@Override
public AnnotationVisitor visitAnnotation(String annotationName, boolean runtimeVisible)
{
discoverer.startClassAnnotation(annotationName);
return new ModAnnotationVisitor(discoverer);
}
@Override
public FieldVisitor visitField(int access, String name, String desc, String signature, Object value)
{
return new ModFieldVisitor(name, discoverer);
}
@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions)
{
if (discoverer.isBaseMod() && name.equals("getPriorities") && desc.equals(Type.getMethodDescriptor(Type.getType(String.class))))
if (discoverer.isBaseMod(Collections.<String>emptyList()) && name.equals("getPriorities") && desc.equals(Type.getMethodDescriptor(Type.getType(String.class))))
{
return new ModMethodVisitor(name, discoverer);
}
@@ -5,7 +5,6 @@ import java.util.LinkedList;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import com.google.common.collect.Lists;
@@ -1,16 +1,8 @@
package cpw.mods.fml.common.event;
import java.util.List;
import java.util.Map;
import com.google.common.collect.Table;
import cpw.mods.fml.common.LoaderState.ModState;
import cpw.mods.fml.common.ModClassLoader;
import cpw.mods.fml.common.ModContainer;
import cpw.mods.fml.common.discovery.ASMDataTable;
import cpw.mods.fml.common.discovery.ASMDataTable.ASMData;
import cpw.mods.fml.common.discovery.ModDiscoverer;
public class FMLConstructionEvent extends FMLStateEvent
{
@@ -1,6 +1,5 @@
package cpw.mods.fml.common.event;
import cpw.mods.fml.common.LoaderState;
import cpw.mods.fml.common.LoaderState.ModState;
public class FMLLoadCompleteEvent extends FMLStateEvent
@@ -1,5 +1,8 @@
package cpw.mods.fml.common.event;
import com.google.common.base.Throwables;
import cpw.mods.fml.common.Loader;
import cpw.mods.fml.common.LoaderState.ModState;
public class FMLPostInitializationEvent extends FMLStateEvent
@@ -15,4 +18,21 @@ public class FMLPostInitializationEvent extends FMLStateEvent
return ModState.POSTINITIALIZED;
}
public Object buildSoftDependProxy(String modId, String className)
{
if (Loader.isModLoaded(modId))
{
try
{
Class<?> clz = Class.forName(className,true,Loader.instance().getModClassLoader());
return clz.newInstance();
}
catch (Exception e)
{
Throwables.propagateIfPossible(e);
return null;
}
}
return null;
}
}
@@ -2,12 +2,10 @@ package cpw.mods.fml.common.event;
import java.io.File;
import com.google.common.eventbus.EventBus;
import cpw.mods.fml.common.LoaderState.ModState;
import cpw.mods.fml.common.discovery.ASMDataTable;
import cpw.mods.fml.common.ModContainer;
import cpw.mods.fml.common.ModMetadata;
import cpw.mods.fml.common.discovery.ASMDataTable;
public class FMLPreInitializationEvent extends FMLStateEvent
{
@@ -1,6 +1,5 @@
package cpw.mods.fml.common.event;
import cpw.mods.fml.common.LoaderState;
import cpw.mods.fml.common.LoaderState.ModState;
public class FMLServerStartedEvent extends FMLStateEvent
@@ -1,17 +1,19 @@
package cpw.mods.fml.common.event;
import cpw.mods.fml.common.LoaderState;
import net.minecraft.server.MinecraftServer;
import net.minecraft.src.CommandHandler;
import net.minecraft.src.ICommand;
import cpw.mods.fml.common.LoaderState.ModState;
public class FMLServerStartingEvent extends FMLStateEvent
{
private Object server;
private MinecraftServer server;
public FMLServerStartingEvent(Object... data)
{
super(data);
this.server = data[0];
this.server = (MinecraftServer) data[0];
}
@Override
public ModState getModState()
@@ -19,4 +21,14 @@ public class FMLServerStartingEvent extends FMLStateEvent
return ModState.AVAILABLE;
}
public MinecraftServer getServer()
{
return server;
}
public void registerServerCommand(ICommand command)
{
CommandHandler ch = (CommandHandler) getServer().func_71187_D();
ch.func_71560_a(command);
}
}
@@ -1,6 +1,5 @@
package cpw.mods.fml.common.event;
import cpw.mods.fml.common.LoaderState;
import cpw.mods.fml.common.LoaderState.ModState;
public class FMLServerStoppingEvent extends FMLStateEvent
@@ -16,14 +16,20 @@ package cpw.mods.fml.common.modloader;
import java.util.Random;
import net.minecraft.src.Entity;
import net.minecraft.src.EntityPlayer;
import net.minecraft.src.GuiScreen;
import net.minecraft.src.IInventory;
import net.minecraft.src.ItemStack;
import net.minecraft.src.NetHandler;
import net.minecraft.src.NetServerHandler;
import net.minecraft.src.NetworkManager;
import net.minecraft.src.Packet250CustomPayload;
import net.minecraft.src.World;
import net.minecraft.src.WorldClient;
import cpw.mods.fml.common.Side;
import cpw.mods.fml.common.TickType;
import cpw.mods.fml.common.asm.SideOnly;
/**
*
@@ -71,13 +77,20 @@ public interface BaseModProxy
public abstract void onClientLogin(EntityPlayer player);
public abstract void onPacket250Received(EntityPlayer source, Packet250CustomPayload payload);
public abstract void serverDisconnect();
public abstract void serverConnect(NetHandler handler);
public abstract void receiveCustomPacket(Packet250CustomPayload packet);
public abstract void receiveChatPacket(String text);
public abstract void clientChat(String text);
public abstract void onItemPickup(EntityPlayer player, ItemStack item);
public abstract int dispenseEntity(World world, ItemStack item, Random rnd, int x, int y, int z, int xVel, int zVel, double entX,
double entY, double entZ);
public abstract void serverCustomPayload(NetServerHandler handler, Packet250CustomPayload packet);
public abstract void serverChat(NetServerHandler source, String message);
}
@@ -1,8 +1,20 @@
package cpw.mods.fml.common.modloader;
import cpw.mods.fml.common.network.EntitySpawnPacket;
import cpw.mods.fml.common.registry.EntityRegistry.EntityRegistration;
import net.minecraft.src.Entity;
import net.minecraft.src.EntityPlayer;
import net.minecraft.src.Packet250CustomPayload;
public interface IModLoaderSidedHelper
{
void finishModLoading(ModLoaderModContainer mc);
Object getClientGui(BaseModProxy mod, EntityPlayer player, int iD, int x, int y, int z);
Entity spawnEntity(BaseModProxy mod, EntitySpawnPacket input, EntityRegistration registration);
void sendClientPacket(BaseModProxy mod, Packet250CustomPayload packet);
}
@@ -0,0 +1,32 @@
package cpw.mods.fml.common.modloader;
import net.minecraft.src.NetHandler;
import net.minecraft.src.NetServerHandler;
import net.minecraft.src.Packet3Chat;
import cpw.mods.fml.common.network.IChatListener;
public class ModLoaderChatListener implements IChatListener
{
private BaseModProxy mod;
public ModLoaderChatListener(BaseModProxy mod)
{
this.mod = mod;
}
@Override
public Packet3Chat serverChat(NetHandler handler, Packet3Chat message)
{
mod.serverChat((NetServerHandler)handler, message.field_73476_b);
return message;
}
@Override
public Packet3Chat clientChat(NetHandler handler, Packet3Chat message)
{
mod.clientChat(message.field_73476_b);
return message;
}
}
@@ -0,0 +1,28 @@
package cpw.mods.fml.common.modloader;
import java.util.Random;
import net.minecraft.src.ItemStack;
import net.minecraft.src.World;
import cpw.mods.fml.common.IDispenseHandler;
import cpw.mods.fml.common.IDispenserHandler;
public class ModLoaderDispenseHelper implements IDispenserHandler
{
private BaseModProxy mod;
public ModLoaderDispenseHelper(BaseModProxy mod)
{
this.mod = mod;
}
@Override
public int dispense(int x, int y, int z, int xVelocity, int zVelocity, World world, ItemStack item, Random random, double entX, double entY,
double entZ)
{
int ret = mod.dispenseEntity(world, item, random, x, y, z, xVelocity, zVelocity, entX, entY, entZ);
return ret == 0 ? -1 : ret;
}
}
@@ -0,0 +1,31 @@
package cpw.mods.fml.common.modloader;
import java.util.concurrent.Callable;
import com.google.common.base.Function;
import cpw.mods.fml.client.FMLClientHandler;
import cpw.mods.fml.common.network.EntitySpawnPacket;
import cpw.mods.fml.common.registry.EntityRegistry.EntityRegistration;
import net.minecraft.src.Entity;
public class ModLoaderEntitySpawnCallback implements Function<EntitySpawnPacket, Entity>
{
private BaseModProxy mod;
private EntityRegistration registration;
private boolean isAnimal;
public ModLoaderEntitySpawnCallback(BaseModProxy mod, EntityRegistration er)
{
this.mod = mod;
this.registration = er;
}
@Override
public Entity apply(EntitySpawnPacket input)
{
return ModLoaderHelper.sidedHelper.spawnEntity(mod, input, registration);
}
}
@@ -0,0 +1,43 @@
package cpw.mods.fml.common.modloader;
import net.minecraft.src.Container;
import net.minecraft.src.EntityPlayer;
import net.minecraft.src.World;
import cpw.mods.fml.common.network.IGuiHandler;
public class ModLoaderGuiHelper implements IGuiHandler
{
private BaseModProxy mod;
private int id;
private Container container;
ModLoaderGuiHelper(BaseModProxy mod, int id)
{
this.mod = mod;
this.id = id;
}
@Override
public Object getServerGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z)
{
return container;
}
@Override
public Object getClientGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z)
{
return ModLoaderHelper.getClientSideGui(mod, player, ID, x, y, z);
}
public void injectContainer(Container container)
{
this.container = container;
}
public Object getMod()
{
return mod;
}
}
@@ -17,32 +17,53 @@ package cpw.mods.fml.common.modloader;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.Callable;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Maps;
import net.minecraft.src.BaseMod;
import net.minecraft.src.Container;
import net.minecraft.src.Entity;
import net.minecraft.src.EntityDragon;
import net.minecraft.src.EntityPlayer;
import net.minecraft.src.IAnimals;
import net.minecraft.src.ICommand;
import net.minecraft.src.TradeEntry;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.ICraftingHandler;
import cpw.mods.fml.common.IDispenseHandler;
import cpw.mods.fml.common.IDispenserHandler;
import cpw.mods.fml.common.IFuelHandler;
import cpw.mods.fml.common.IPickupNotifier;
import cpw.mods.fml.common.IWorldGenerator;
import cpw.mods.fml.common.ModContainer;
import cpw.mods.fml.common.Loader;
import cpw.mods.fml.common.TickType;
import cpw.mods.fml.common.network.IChatListener;
import cpw.mods.fml.common.network.IConnectionHandler;
import cpw.mods.fml.common.network.IGuiHandler;
import cpw.mods.fml.common.network.IPacketHandler;
import cpw.mods.fml.relauncher.ReflectionHelper;
import cpw.mods.fml.common.network.NetworkRegistry;
import cpw.mods.fml.common.registry.EntityRegistry;
import cpw.mods.fml.common.registry.EntityRegistry.EntityRegistration;
import cpw.mods.fml.common.registry.VillagerRegistry.IVillageTradeHandler;
import cpw.mods.fml.common.registry.VillagerRegistry;
/**
* @author cpw
*
*/
@SuppressWarnings("deprecation")
public class ModLoaderHelper
{
private static Map<BaseMod, ModLoaderModContainer> notModCallbacks=new HashMap<BaseMod, ModLoaderModContainer>();
public static IModLoaderSidedHelper sidedHelper;
public static void updateStandardTicks(BaseMod mod, boolean enable, boolean useClock)
private static Map<Integer, ModLoaderGuiHelper> guiHelpers = Maps.newHashMap();
public static void updateStandardTicks(BaseModProxy mod, boolean enable, boolean useClock)
{
ModLoaderModContainer mlmc = findOrBuildModContainer(mod);
ModLoaderModContainer mlmc = (ModLoaderModContainer) Loader.instance().activeModContainer();
BaseModTicker ticker = mlmc.getGameTickHandler();
EnumSet<TickType> ticks = ticker.ticks();
// If we're enabled we get render ticks
@@ -61,9 +82,9 @@ public class ModLoaderHelper
}
}
public static void updateGUITicks(BaseMod mod, boolean enable, boolean useClock)
public static void updateGUITicks(BaseModProxy mod, boolean enable, boolean useClock)
{
ModLoaderModContainer mlmc = findOrBuildModContainer(mod);
ModLoaderModContainer mlmc = (ModLoaderModContainer) Loader.instance().activeModContainer();
EnumSet<TickType> ticks = mlmc.getGUITickHandler().ticks();
// If we're enabled and we don't want clock ticks we get render ticks
if (enable && !useClock) {
@@ -81,34 +102,7 @@ public class ModLoaderHelper
}
}
/**
* @param mod
* @return
*/
private static ModLoaderModContainer findOrBuildModContainer(BaseMod mod)
{
ModLoaderModContainer mlmc=(ModLoaderModContainer) FMLCommonHandler.instance().findContainerFor(mod);
if (mlmc==null) {
mlmc=notModCallbacks.get(mod);
if (mlmc==null) {
mlmc=new ModLoaderModContainer(mod);
notModCallbacks.put(mod, mlmc);
}
}
return mlmc;
}
/**
* @param mod
* @return
*/
public static ModLoaderModContainer registerKeyHelper(BaseMod mod)
{
ModLoaderModContainer mlmc=findOrBuildModContainer(mod);
return mlmc;
}
public static IPacketHandler buildPacketHandlerFor(BaseMod mod)
public static IPacketHandler buildPacketHandlerFor(BaseModProxy mod)
{
return new ModLoaderPacketHandler(mod);
}
@@ -140,4 +134,73 @@ public class ModLoaderHelper
{
return new ModLoaderConnectionHandler(mod);
}
public static IPickupNotifier buildPickupHelper(BaseModProxy mod)
{
return new ModLoaderPickupNotifier(mod);
}
public static void buildGuiHelper(BaseModProxy mod, int id)
{
ModLoaderGuiHelper handler = new ModLoaderGuiHelper(mod, id);
guiHelpers.put(id, handler);
NetworkRegistry.instance().registerGuiHandler(mod, handler);
}
public static void openGui(int id, EntityPlayer player, Container container, int x, int y, int z)
{
ModLoaderGuiHelper helper = guiHelpers.get(id);
helper.injectContainer(container);
player.openGui(helper.getMod(), id, player.field_70170_p, x, y, z);
}
public static Object getClientSideGui(BaseModProxy mod, EntityPlayer player, int ID, int x, int y, int z)
{
if (sidedHelper != null)
{
return sidedHelper.getClientGui(mod, player, ID, x, y, z);
}
return null;
}
public static IDispenserHandler buildDispenseHelper(BaseModProxy mod)
{
return new ModLoaderDispenseHelper(mod);
}
public static void buildEntityTracker(BaseModProxy mod, Class<? extends Entity> entityClass, int entityTypeId, int updateRange, int updateInterval,
boolean sendVelocityInfo)
{
EntityRegistration er = EntityRegistry.registerModLoaderEntity(mod, entityClass, entityTypeId, updateRange, updateInterval, sendVelocityInfo);
er.setCustomSpawning(new ModLoaderEntitySpawnCallback(mod, er), EntityDragon.class.isAssignableFrom(entityClass) || IAnimals.class.isAssignableFrom(entityClass));
}
private static ModLoaderVillageTradeHandler[] tradeHelpers = new ModLoaderVillageTradeHandler[6];
public static void registerTrade(int profession, TradeEntry entry)
{
assert profession < tradeHelpers.length : "The profession is out of bounds";
if (tradeHelpers[profession] == null)
{
tradeHelpers[profession] = new ModLoaderVillageTradeHandler();
VillagerRegistry.instance().registerVillageTradeHandler(profession, tradeHelpers[profession]);
}
tradeHelpers[profession].addTrade(entry);
}
public static void addCommand(ICommand command)
{
ModLoaderModContainer mlmc = (ModLoaderModContainer) Loader.instance().activeModContainer();
if (mlmc!=null)
{
mlmc.addServerCommand(command);
}
}
public static IChatListener buildChatListener(BaseModProxy mod)
{
return new ModLoaderChatListener(mod);
}
}
@@ -17,22 +17,20 @@ import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.AbstractCollection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.logging.Level;
import net.minecraft.src.MLProp;
import net.minecraft.src.ICommand;
import com.google.common.base.Strings;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
@@ -42,46 +40,37 @@ import com.google.common.eventbus.Subscribe;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.FMLLog;
import cpw.mods.fml.common.IConsoleHandler;
import cpw.mods.fml.common.ICraftingHandler;
import cpw.mods.fml.common.IDispenseHandler;
import cpw.mods.fml.common.IFMLSidedHandler;
import cpw.mods.fml.common.INetworkHandler;
import cpw.mods.fml.common.IPickupNotifier;
import cpw.mods.fml.common.IPlayerTracker;
import cpw.mods.fml.common.IWorldGenerator;
import cpw.mods.fml.common.LoadController;
import cpw.mods.fml.common.Loader;
import cpw.mods.fml.common.LoaderException;
import cpw.mods.fml.common.LoaderState;
import cpw.mods.fml.common.ModClassLoader;
import cpw.mods.fml.common.Side;
import cpw.mods.fml.common.LoaderState.ModState;
import cpw.mods.fml.common.MetadataCollection;
import cpw.mods.fml.common.ModClassLoader;
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.discovery.ASMDataTable;
import cpw.mods.fml.common.discovery.ASMDataTable.ASMData;
import cpw.mods.fml.common.discovery.ContainerType;
import cpw.mods.fml.common.event.FMLConstructionEvent;
import cpw.mods.fml.common.event.FMLInitializationEvent;
import cpw.mods.fml.common.event.FMLLoadCompleteEvent;
import cpw.mods.fml.common.event.FMLPostInitializationEvent;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import cpw.mods.fml.common.event.FMLServerStartingEvent;
import cpw.mods.fml.common.network.FMLNetworkHandler;
import cpw.mods.fml.common.network.NetworkMod;
import cpw.mods.fml.common.network.NetworkRegistry;
import cpw.mods.fml.common.registry.TickRegistry;
import cpw.mods.fml.common.registry.GameRegistry;
import cpw.mods.fml.common.registry.TickRegistry;
import cpw.mods.fml.common.versioning.ArtifactVersion;
import cpw.mods.fml.common.versioning.DefaultArtifactVersion;
import cpw.mods.fml.common.ModContainer;
import cpw.mods.fml.common.ModMetadata;
import cpw.mods.fml.common.ProxyInjector;
import cpw.mods.fml.common.TickType;
public class ModLoaderModContainer implements ModContainer
{
public BaseModProxy mod;
private File modSource;
public List<ArtifactVersion> requirements = Lists.newArrayList();
public Set<ArtifactVersion> requirements = Sets.newHashSet();
public ArrayList<ArtifactVersion> dependencies = Lists.newArrayList();
public ArrayList<ArtifactVersion> dependants = Lists.newArrayList();
private ContainerType sourceType;
@@ -97,13 +86,14 @@ public class ModLoaderModContainer implements ModContainer
private String sortingProperties;
private ArtifactVersion processedVersion;
private boolean isNetworkMod;
private List<ICommand> serverCommands = Lists.newArrayList();
public ModLoaderModContainer(String className, File modSource, String sortingProperties)
{
this.modClazzName = className;
this.modSource = modSource;
this.modId = className.contains(".") ? className.substring(className.lastIndexOf('.')+1) : className;
this.sortingProperties = sortingProperties;
this.sortingProperties = Strings.isNullOrEmpty(sortingProperties) ? "" : sortingProperties;
}
/**
@@ -122,7 +112,7 @@ public class ModLoaderModContainer implements ModContainer
private void configureMod(Class<? extends BaseModProxy> modClazz, ASMDataTable asmData)
{
File configDir = Loader.instance().getConfigDir();
File modConfig = new File(configDir, String.format("%s.cfg", modClazzName));
File modConfig = new File(configDir, String.format("%s.cfg", getModId()));
Properties props = new Properties();
boolean existingConfigFound = false;
@@ -132,7 +122,7 @@ public class ModLoaderModContainer implements ModContainer
{
try
{
FMLLog.fine("Reading existing configuration file for %s : %s", modClazzName, modConfig.getName());
FMLLog.fine("Reading existing configuration file for %s : %s", getModId(), modConfig.getName());
FileReader configReader = new FileReader(modConfig);
props.load(configReader);
configReader.close();
@@ -159,6 +149,7 @@ public class ModLoaderModContainer implements ModContainer
try
{
mlPropFields.add(new ModProperty(modClazz.getDeclaredField(dat.getObjectName()), dat.getAnnotationInfo()));
FMLLog.finest("Found an MLProp field %s in %s", dat.getObjectName(), getModId());
}
catch (Exception e)
{
@@ -173,8 +164,9 @@ public class ModLoaderModContainer implements ModContainer
FMLLog.info("The MLProp field %s in mod %s appears not to be static", property.field().getName(), getModId());
continue;
}
FMLLog.finest("Considering MLProp field %s", property.field().getName());
Field f = property.field();
String propertyName = property.name().length() > 0 ? property.name() : f.getName();
String propertyName = !Strings.nullToEmpty(property.name()).isEmpty() ? property.name() : f.getName();
String propertyValue = null;
Object defaultValue = null;
@@ -182,7 +174,7 @@ public class ModLoaderModContainer implements ModContainer
{
defaultValue = f.get(null);
propertyValue = props.getProperty(propertyName, extractValue(defaultValue));
Object currentValue = parseValue(propertyValue, property, f.getType(), propertyName, modClazzName);
Object currentValue = parseValue(propertyValue, property, f.getType(), propertyName);
FMLLog.finest("Configuration for %s.%s found values default: %s, configured: %s, interpreted: %s", modClazzName, propertyName, defaultValue, propertyValue, currentValue);
if (currentValue != null && !currentValue.equals(defaultValue))
@@ -212,7 +204,7 @@ public class ModLoaderModContainer implements ModContainer
comments.append(")");
if (property.info().length() > 0)
if (!Strings.nullToEmpty(property.info()).isEmpty())
{
comments.append(" -- ").append(property.info());
}
@@ -230,22 +222,22 @@ public class ModLoaderModContainer implements ModContainer
{
if (!mlPropFound && !existingConfigFound)
{
FMLLog.fine("No MLProp configuration for %s found or required. No file written", modClazzName);
FMLLog.fine("No MLProp configuration for %s found or required. No file written", getModId());
return;
}
if (!mlPropFound && existingConfigFound)
{
File mlPropBackup = new File(modConfig.getParent(),modConfig.getName()+".bak");
FMLLog.fine("MLProp configuration file for %s found but not required. Attempting to rename file to %s", modClazzName, mlPropBackup.getName());
FMLLog.fine("MLProp configuration file for %s found but not required. Attempting to rename file to %s", getModId(), mlPropBackup.getName());
boolean renamed = modConfig.renameTo(mlPropBackup);
if (renamed)
{
FMLLog.fine("Unused MLProp configuration file for %s renamed successfully to %s", modClazzName, mlPropBackup.getName());
FMLLog.fine("Unused MLProp configuration file for %s renamed successfully to %s", getModId(), mlPropBackup.getName());
}
else
{
FMLLog.fine("Unused MLProp configuration file for %s renamed UNSUCCESSFULLY to %s", modClazzName, mlPropBackup.getName());
FMLLog.fine("Unused MLProp configuration file for %s renamed UNSUCCESSFULLY to %s", getModId(), mlPropBackup.getName());
}
return;
@@ -255,7 +247,7 @@ public class ModLoaderModContainer implements ModContainer
FileWriter configWriter = new FileWriter(modConfig);
props.store(configWriter, comments.toString());
configWriter.close();
FMLLog.fine("Configuration for %s written to %s", modClazzName, modConfig.getName());
FMLLog.fine("Configuration for %s written to %s", getModId(), modConfig.getName());
}
catch (IOException e)
{
@@ -265,7 +257,7 @@ public class ModLoaderModContainer implements ModContainer
}
}
private Object parseValue(String val, ModProperty property, Class<?> type, String propertyName, String modConfigName)
private Object parseValue(String val, ModProperty property, Class<?> type, String propertyName)
{
if (type.isAssignableFrom(String.class))
{
@@ -308,9 +300,10 @@ public class ModLoaderModContainer implements ModContainer
throw new IllegalArgumentException(String.format("MLProp declared on %s of type %s, an unsupported type",propertyName, type.getName()));
}
if (n.doubleValue() < property.min() || n.doubleValue() > property.max())
double dVal = n.doubleValue();
if ((property.min()!=Double.MIN_VALUE && dVal < property.min()) || (property.max()!=Double.MAX_VALUE && dVal > property.max()))
{
FMLLog.warning("Configuration for %s.%s found value %s outside acceptable range %s,%s", modConfigName,propertyName, n, property.min(), property.max());
FMLLog.warning("Configuration for %s.%s found value %s outside acceptable range %s,%s", modClazzName,propertyName, n, property.min(), property.max());
return null;
}
else
@@ -394,7 +387,7 @@ public class ModLoaderModContainer implements ModContainer
}
@Override
public List<ArtifactVersion> getRequirements()
public Set<ArtifactVersion> getRequirements()
{
return requirements;
}
@@ -457,7 +450,7 @@ public class ModLoaderModContainer implements ModContainer
@Override
public void bindMetadata(MetadataCollection mc)
{
Map<String, Object> dummyMetadata = ImmutableMap.<String,Object>builder().put("name", modId).put("version", "").build();
Map<String, Object> dummyMetadata = ImmutableMap.<String,Object>builder().put("name", modId).put("version", "1.0").build();
this.metadata = mc.getMetadataForId(modId, dummyMetadata);
Loader.instance().computeDependencies(sortingProperties, getRequirements(), getDependencies(), getDependants());
}
@@ -494,10 +487,26 @@ public class ModLoaderModContainer implements ModContainer
{
ModClassLoader modClassLoader = event.getModClassLoader();
modClassLoader.addFile(modSource);
Class<? extends BaseModProxy> modClazz = (Class<? extends BaseModProxy>) Class.forName(modClazzName, true, modClassLoader);
EnumSet<TickType> ticks = EnumSet.noneOf(TickType.class);
this.gameTickHandler = new BaseModTicker(ticks, false);
this.guiTickHandler = new BaseModTicker(ticks.clone(), true);
Class<? extends BaseModProxy> modClazz = (Class<? extends BaseModProxy>) modClassLoader.loadBaseModClass(modClazzName);
configureMod(modClazz, event.getASMHarvestedData());
isNetworkMod = FMLNetworkHandler.instance().registerNetworkMod(this, modClazz, event.getASMHarvestedData());
mod = (BaseModProxy)modClazz.newInstance();
ModLoaderNetworkHandler dummyHandler = null;
if (!isNetworkMod)
{
FMLLog.fine("Injecting dummy network mod handler for BaseMod %s", getModId());
dummyHandler = new ModLoaderNetworkHandler(this);
FMLNetworkHandler.instance().registerNetworkMod(dummyHandler);
}
Constructor<? extends BaseModProxy> ctor = modClazz.getConstructor();
ctor.setAccessible(true);
mod = modClazz.newInstance();
if (dummyHandler != null)
{
dummyHandler.setBaseMod(mod);
}
ProxyInjector.inject(this, event.getASMHarvestedData(), FMLCommonHandler.instance().getSide());
}
catch (Exception e)
@@ -512,9 +521,6 @@ public class ModLoaderModContainer implements ModContainer
{
try
{
EnumSet<TickType> ticks = EnumSet.noneOf(TickType.class);
this.gameTickHandler = new BaseModTicker(ticks, false);
this.guiTickHandler = new BaseModTicker(ticks.clone(), true);
this.gameTickHandler.setMod(mod);
this.guiTickHandler.setMod(mod);
TickRegistry.registerTickHandler(this.gameTickHandler, Side.CLIENT);
@@ -522,6 +528,9 @@ public class ModLoaderModContainer implements ModContainer
GameRegistry.registerWorldGenerator(ModLoaderHelper.buildWorldGenHelper(mod));
GameRegistry.registerFuelHandler(ModLoaderHelper.buildFuelHelper(mod));
GameRegistry.registerCraftingHandler(ModLoaderHelper.buildCraftingHelper(mod));
GameRegistry.registerPickupHandler(ModLoaderHelper.buildPickupHelper(mod));
GameRegistry.registerDispenserHandler(ModLoaderHelper.buildDispenseHelper(mod));
NetworkRegistry.instance().registerChatListener(ModLoaderHelper.buildChatListener(mod));
NetworkRegistry.instance().registerConnectionHandler(ModLoaderHelper.buildConnectionHelper(mod));
}
catch (Exception e)
@@ -560,6 +569,20 @@ public class ModLoaderModContainer implements ModContainer
}
}
@Subscribe
public void loadComplete(FMLLoadCompleteEvent complete)
{
ModLoaderHelper.finishModLoading(this);
}
@Subscribe
public void serverStarting(FMLServerStartingEvent evt)
{
for (ICommand cmd : serverCommands)
{
evt.registerServerCommand(cmd);
}
}
@Override
public ArtifactVersion getProcessedVersion()
{
@@ -581,4 +604,15 @@ public class ModLoaderModContainer implements ModContainer
{
return this.isNetworkMod;
}
@Override
public String getDisplayVersion()
{
return metadata!=null ? metadata.version : getVersion();
}
public void addServerCommand(ICommand command)
{
serverCommands .add(command);
}
}
@@ -0,0 +1,44 @@
package cpw.mods.fml.common.modloader;
import cpw.mods.fml.common.ModContainer;
import cpw.mods.fml.common.discovery.ASMDataTable;
import cpw.mods.fml.common.network.NetworkMod;
import cpw.mods.fml.common.network.NetworkModHandler;
public class ModLoaderNetworkHandler extends NetworkModHandler
{
private BaseModProxy baseMod;
public ModLoaderNetworkHandler(ModLoaderModContainer mlmc)
{
super(mlmc, null);
}
public void setBaseMod(BaseModProxy baseMod)
{
this.baseMod = baseMod;
}
@Override
public boolean requiresClientSide()
{
return false;
}
@Override
public boolean requiresServerSide()
{
return false;
}
@Override
public boolean acceptVersion(String version)
{
return baseMod.getVersion().equals(version);
}
@Override
public boolean isNetworkMod()
{
return true;
}
}
@@ -1,6 +1,5 @@
package cpw.mods.fml.common.modloader;
import net.minecraft.src.BaseMod;
import net.minecraft.src.EntityPlayer;
import net.minecraft.src.EntityPlayerMP;
import net.minecraft.src.NetworkManager;
@@ -10,9 +9,9 @@ import cpw.mods.fml.common.network.Player;
public class ModLoaderPacketHandler implements IPacketHandler
{
private BaseMod mod;
private BaseModProxy mod;
public ModLoaderPacketHandler(BaseMod mod)
public ModLoaderPacketHandler(BaseModProxy mod)
{
this.mod = mod;
}
@@ -22,11 +21,11 @@ public class ModLoaderPacketHandler implements IPacketHandler
{
if (player instanceof EntityPlayerMP)
{
mod.onPacket250Received((EntityPlayer) player, packet);
mod.serverCustomPayload(((EntityPlayerMP)player).field_71135_a, packet);
}
else
{
mod.receiveCustomPacket(packet);
ModLoaderHelper.sidedHelper.sendClientPacket(mod, packet);
}
}
@@ -0,0 +1,23 @@
package cpw.mods.fml.common.modloader;
import net.minecraft.src.EntityItem;
import net.minecraft.src.EntityPlayer;
import cpw.mods.fml.common.IPickupNotifier;
public class ModLoaderPickupNotifier implements IPickupNotifier
{
private BaseModProxy mod;
public ModLoaderPickupNotifier(BaseModProxy mod)
{
this.mod = mod;
}
@Override
public void notifyPickup(EntityItem item, EntityPlayer player)
{
mod.onItemPickup(player, item.field_70294_a);
}
}
@@ -0,0 +1,39 @@
package cpw.mods.fml.common.modloader;
import java.util.List;
import java.util.Random;
import com.google.common.collect.Lists;
import net.minecraft.src.EntityVillager;
import net.minecraft.src.Item;
import net.minecraft.src.MerchantRecipeList;
import net.minecraft.src.TradeEntry;
import cpw.mods.fml.common.registry.VillagerRegistry;
import cpw.mods.fml.common.registry.VillagerRegistry.IVillageTradeHandler;
public class ModLoaderVillageTradeHandler implements IVillageTradeHandler
{
private List<TradeEntry> trades = Lists.newArrayList();
@Override
public void manipulateTradesForVillager(EntityVillager villager, MerchantRecipeList recipeList, Random random)
{
for (TradeEntry ent : trades)
{
if (ent.buying)
{
VillagerRegistry.addEmeraldBuyRecipe(villager, recipeList, random, Item.field_77698_e[ent.id], ent.chance, ent.min, ent.max);
}
else
{
VillagerRegistry.addEmeraldSellRecipe(villager, recipeList, random, Item.field_77698_e[ent.id], ent.chance, ent.min, ent.max);
}
}
}
public void addTrade(TradeEntry entry)
{
trades.add(entry);
}
}
@@ -6,7 +6,6 @@ import net.minecraft.src.ChunkProviderGenerate;
import net.minecraft.src.ChunkProviderHell;
import net.minecraft.src.IChunkProvider;
import net.minecraft.src.World;
import cpw.mods.fml.common.IWorldGenerator;
public class ModLoaderWorldGenerator implements IWorldGenerator
@@ -14,7 +14,6 @@
package cpw.mods.fml.common.modloader;
import java.io.File;
import java.lang.reflect.Field;
import java.util.Map;
@@ -30,12 +29,12 @@ public class ModProperty
private String name;
private Field field;
public ModProperty(Field f, String info, double min, double max, String name)
public ModProperty(Field f, String info, Double min, Double max, String name)
{
this.field = f;
this.info = info;
this.min = min;
this.max = max;
this.min = min != null ? min : Double.MIN_VALUE;
this.max = max != null ? max : Double.MAX_VALUE;
this.name = name;
}
public ModProperty(Field field, Map<String, Object> annotationInfo)
@@ -1,14 +1,14 @@
package cpw.mods.fml.common.network;
import net.minecraft.src.NetHandler;
import net.minecraft.src.NetworkManager;
import com.google.common.io.ByteArrayDataInput;
import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams;
import cpw.mods.fml.common.FMLCommonHandler;
import net.minecraft.src.NetHandler;
import net.minecraft.src.NetworkManager;
public class EntitySpawnAdjustmentPacket extends FMLPacket
{
@@ -8,10 +8,16 @@ import java.io.IOException;
import java.util.List;
import java.util.logging.Level;
import net.minecraft.src.DataWatcher;
import net.minecraft.src.Entity;
import net.minecraft.src.EntityLiving;
import net.minecraft.src.MathHelper;
import net.minecraft.src.NetHandler;
import net.minecraft.src.NetworkManager;
import com.google.common.io.ByteArrayDataInput;
import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams;
import com.google.common.primitives.Bytes;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.FMLLog;
@@ -20,13 +26,6 @@ import cpw.mods.fml.common.registry.EntityRegistry;
import cpw.mods.fml.common.registry.EntityRegistry.EntityRegistration;
import cpw.mods.fml.common.registry.IEntityAdditionalSpawnData;
import cpw.mods.fml.common.registry.IThrowableEntity;
import net.minecraft.src.DataWatcher;
import net.minecraft.src.Entity;
import net.minecraft.src.EntityLiving;
import net.minecraft.src.MathHelper;
import net.minecraft.src.NetHandler;
import net.minecraft.src.NetworkManager;
import net.minecraft.src.World;
public class EntitySpawnPacket extends FMLPacket
{
@@ -76,7 +75,7 @@ public class EntitySpawnPacket extends FMLPacket
// yaw, pitch
dat.writeByte((byte) (ent.field_70177_z * 256.0F / 360.0F));
dat.writeByte((byte) (ent.field_70125_A * 256.0F / 360.0F));
// head yaw
if (ent instanceof EntityLiving)
{
@@ -96,9 +95,9 @@ public class EntitySpawnPacket extends FMLPacket
{
// unpossible
}
dat.write(bos.toByteArray());
if (ent instanceof IThrowableEntity)
{
Entity owner = ((IThrowableEntity)ent).getThrower();
@@ -117,11 +116,14 @@ public class EntitySpawnPacket extends FMLPacket
dat.writeInt((int)(mY * 8000D));
dat.writeInt((int)(mZ * 8000D));
}
else
{
dat.writeInt(0);
}
if (ent instanceof IEntityAdditionalSpawnData)
{
((IEntityAdditionalSpawnData)ent).writeSpawnData(dat);
}
return dat.toByteArray();
}
@@ -152,7 +154,7 @@ public class EntitySpawnPacket extends FMLPacket
{
// Nope
}
dat.skipBytes(data.length - bis.available());
dat.skipBytes(data.length - bis.available() - 27);
throwerId = dat.readInt();
if (throwerId != 0)
{
@@ -160,7 +162,7 @@ public class EntitySpawnPacket extends FMLPacket
speedScaledY = dat.readInt() / 8000D;
speedScaledZ = dat.readInt() / 8000D;
}
this.dataStream = dat;
return this;
}
@@ -170,7 +172,7 @@ public class EntitySpawnPacket extends FMLPacket
{
NetworkModHandler nmh = handler.findNetworkModHandler(networkId);
ModContainer mc = nmh.getContainer();
EntityRegistration registration = EntityRegistry.instance().lookupModSpawn(mc, modEntityId);
Class<? extends Entity> cls = registration.getEntityClass();
if (cls == null)
@@ -179,8 +181,8 @@ public class EntitySpawnPacket extends FMLPacket
return;
}
Entity entity = FMLCommonHandler.instance().spawnEntityIntoClientWorld(cls, this);
Entity entity = FMLCommonHandler.instance().spawnEntityIntoClientWorld(registration, this);
}
}
@@ -2,7 +2,12 @@ package cpw.mods.fml.common.network;
import static cpw.mods.fml.common.network.FMLPacket.Type.MOD_LIST_REQUEST;
import java.io.IOException;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketAddress;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -11,17 +16,21 @@ import net.minecraft.src.Entity;
import net.minecraft.src.EntityPlayer;
import net.minecraft.src.EntityPlayerMP;
import net.minecraft.src.EnumGameType;
import net.minecraft.src.Item;
import net.minecraft.src.NetHandler;
import net.minecraft.src.NetLoginHandler;
import net.minecraft.src.NetServerHandler;
import net.minecraft.src.NetworkManager;
import net.minecraft.src.Packet;
import net.minecraft.src.Packet131MapData;
import net.minecraft.src.Packet1Login;
import net.minecraft.src.Packet250CustomPayload;
import net.minecraft.src.Packet3Chat;
import net.minecraft.src.ServerConfigurationManager;
import net.minecraft.src.World;
import net.minecraft.src.WorldType;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.hash.Hashing;
@@ -32,8 +41,8 @@ import cpw.mods.fml.common.ModContainer;
import cpw.mods.fml.common.discovery.ASMDataTable;
import cpw.mods.fml.common.network.FMLPacket.Type;
import cpw.mods.fml.common.registry.EntityRegistry;
import cpw.mods.fml.common.registry.GameRegistry;
import cpw.mods.fml.common.registry.EntityRegistry.EntityRegistration;
import cpw.mods.fml.relauncher.FMLRelaunchLog;
public class FMLNetworkHandler
{
@@ -41,6 +50,12 @@ public class FMLNetworkHandler
private static final int PROTOCOL_VERSION = 0x1;
private static final FMLNetworkHandler INSTANCE = new FMLNetworkHandler();
// List of states for connections from clients to server
static final int LOGIN_RECEIVED = 1;
static final int CONNECTION_VALID = 2;
static final int FML_OUT_OF_DATE = -1;
static final int MISSING_MODS_OR_VERSIONS = -2;
private Map<NetLoginHandler, Integer> loginStates = Maps.newHashMap();
private Map<ModContainer, NetworkModHandler> networkModHandlers = Maps.newHashMap();
@@ -53,7 +68,6 @@ public class FMLNetworkHandler
if (target.startsWith("MC|"))
{
handler.handleVanilla250Packet(packet);
return;
}
if (target.equals("FML"))
{
@@ -102,15 +116,15 @@ public class FMLNetworkHandler
if (handleVanillaLoginKick(netLoginHandler, server, address, userName))
{
// No FML on the client
FMLRelaunchLog.fine("Connection from %s rejected - no FML packet received from client", userName);
netLoginHandler.completeConnection("You don't have FML installed, or your installation is too old");
FMLLog.fine("Connection from %s rejected - no FML packet received from client", userName);
netLoginHandler.completeConnection("You don't have FML installed, you cannot connect to this server");
return;
}
}
// Are we ready to negotiate with the client?
if (loginStates.get(netLoginHandler) == 1)
switch (loginStates.get(netLoginHandler))
{
case LOGIN_RECEIVED:
// mods can try and kick undesireables here
String modKick = NetworkRegistry.instance().connectionReceived(netLoginHandler, netLoginHandler.field_72538_b);
if (modKick != null)
@@ -125,26 +139,28 @@ public class FMLNetworkHandler
loginStates.remove(netLoginHandler);
return;
}
// Reset the "connection completed" flag so processing can continue
NetLoginHandler.func_72531_a(netLoginHandler, false);
// Send the mod list request packet to the client from the server
netLoginHandler.field_72538_b.func_74429_a(getModListRequestPacket());
loginStates.put(netLoginHandler, 2);
}
// We must be good to go - the ModIdentifiers packet was sent and the
// continuation signal was indicated
else if (loginStates.get(netLoginHandler) == 2)
{
loginStates.put(netLoginHandler, CONNECTION_VALID);
break;
case CONNECTION_VALID:
netLoginHandler.completeConnection(null);
loginStates.remove(netLoginHandler);
}
// We have to abort this connection - there was a negotiation problem
// (most likely missing mods)
else
{
break;
case MISSING_MODS_OR_VERSIONS:
netLoginHandler.completeConnection("The server requires mods that are absent or out of date on your client");
loginStates.remove(netLoginHandler);
break;
case FML_OUT_OF_DATE:
netLoginHandler.completeConnection("Your client is not running a new enough version of FML to connect to this server");
loginStates.remove(netLoginHandler);
break;
default:
netLoginHandler.completeConnection("There was a problem during FML negotiation");
loginStates.remove(netLoginHandler);
break;
}
}
@@ -170,18 +186,31 @@ public class FMLNetworkHandler
public static void handleLoginPacketOnServer(NetLoginHandler handler, Packet1Login login)
{
if (login.field_73561_a == FML_HASH && login.field_73558_e == PROTOCOL_VERSION)
if (login.field_73561_a == FML_HASH)
{
FMLRelaunchLog.finest("Received valid FML login packet from %s", handler.field_72538_b.func_74430_c());
instance().loginStates.put(handler, 1);
if (login.field_73558_e == PROTOCOL_VERSION)
{
FMLLog.finest("Received valid FML login packet from %s", handler.field_72538_b.func_74430_c());
instance().loginStates.put(handler, LOGIN_RECEIVED);
}
else if (login.field_73558_e != PROTOCOL_VERSION)
{
FMLLog.finest("Received incorrect FML (%x) login packet from %s", login.field_73558_e, handler.field_72538_b.func_74430_c());
instance().loginStates.put(handler, FML_OUT_OF_DATE);
}
}
else
{
FMLRelaunchLog.fine("Received invalid FML login packet %d, %d from %s", login.field_73561_a, login.field_73558_e,
FMLLog.fine("Received invalid login packet (%x, %x) from %s", login.field_73561_a, login.field_73558_e,
handler.field_72538_b.func_74430_c());
}
}
static void setHandlerState(NetLoginHandler handler, int state)
{
instance().loginStates.put(handler, state);
}
public static FMLNetworkHandler instance()
{
return INSTANCE;
@@ -189,6 +218,8 @@ public class FMLNetworkHandler
public static Packet1Login getFMLFakeLoginPacket()
{
// Always reset compat to zero before sending our fake packet
FMLCommonHandler.instance().getSidedDelegate().setClientCompatibilityLevel((byte) 0);
Packet1Login fake = new Packet1Login();
// Hash FML using a simple function
fake.field_73561_a = FML_HASH;
@@ -201,11 +232,7 @@ public class FMLNetworkHandler
public Packet250CustomPayload getModListRequestPacket()
{
Packet250CustomPayload pkt = new Packet250CustomPayload();
pkt.field_73630_a = "FML";
pkt.field_73629_c = FMLPacket.makePacket(MOD_LIST_REQUEST);
pkt.field_73628_b = pkt.field_73629_c.length;
return pkt;
return PacketDispatcher.getPacket("FML", FMLPacket.makePacket(MOD_LIST_REQUEST));
}
public void registerNetworkMod(NetworkModHandler handler)
@@ -248,6 +275,7 @@ public class FMLNetworkHandler
public static void handlePlayerLogin(EntityPlayerMP player, NetServerHandler netHandler, NetworkManager manager)
{
NetworkRegistry.instance().playerLoggedIn(player, netHandler, manager);
GameRegistry.onPlayerLogin(player);
}
public Map<Integer, NetworkModHandler> getNetworkIdMap()
@@ -259,8 +287,11 @@ public class FMLNetworkHandler
{
Map<String, ModContainer> mods = Loader.instance().getIndexedModList();
NetworkModHandler handler = findNetworkModHandler(mods.get(key));
handler.setNetworkId(value);
networkIdLookup.put(value, handler);
if (handler != null)
{
handler.setNetworkId(value);
networkIdLookup.put(value, handler);
}
}
public static void onClientConnectionToRemoteServer(NetHandler netClientHandler, String server, int port, NetworkManager networkManager)
@@ -279,10 +310,6 @@ public class FMLNetworkHandler
}
public static void sendPacket(Player player, Packet packet)
{
}
public static void openGui(EntityPlayer player, Object mod, int modGuiId, World world, int x, int y, int z)
{
ModContainer mc = FMLCommonHandler.instance().findContainerFor(mod);
@@ -316,20 +343,80 @@ public class FMLNetworkHandler
{
return null;
}
Packet250CustomPayload pkt = new Packet250CustomPayload();
pkt.field_73630_a = "FML";
pkt.field_73629_c = FMLPacket.makePacket(Type.ENTITYSPAWN, er, entity);
pkt.field_73628_b = pkt.field_73629_c.length;
return pkt;
if (er.usesVanillaSpawning())
{
return null;
}
return PacketDispatcher.getPacket("FML", FMLPacket.makePacket(Type.ENTITYSPAWN, er, entity, instance().findNetworkModHandler(er.getContainer())));
}
public static void makeEntitySpawnAdjustment(int entityId, EntityPlayerMP player, int serverX, int serverY, int serverZ)
{
Packet250CustomPayload pkt = new Packet250CustomPayload();
pkt.field_73630_a = "FML";
pkt.field_73629_c = FMLPacket.makePacket(Type.ENTITYSPAWNADJUSTMENT, entityId, serverX, serverY, serverZ);
pkt.field_73628_b = pkt.field_73629_c.length;
Packet250CustomPayload pkt = PacketDispatcher.getPacket("FML", FMLPacket.makePacket(Type.ENTITYSPAWNADJUSTMENT, entityId, serverX, serverY, serverZ));
player.field_71135_a.func_72567_b(pkt);
}
public static InetAddress computeLocalHost() throws IOException
{
InetAddress add = null;
List<InetAddress> addresses = Lists.newArrayList();
InetAddress localHost = InetAddress.getLocalHost();
for (NetworkInterface ni : Collections.list(NetworkInterface.getNetworkInterfaces()))
{
if (!ni.isLoopback() && ni.isUp())
{
addresses.addAll(Collections.list(ni.getInetAddresses()));
if (addresses.contains(localHost))
{
add = localHost;
break;
}
}
}
if (add == null && !addresses.isEmpty())
{
for (InetAddress addr: addresses)
{
if (addr.getAddress().length == 4)
{
add = addr;
break;
}
}
}
if (add == null)
{
add = localHost;
}
return add;
}
public static Packet3Chat handleChatMessage(NetHandler handler, Packet3Chat chat)
{
return NetworkRegistry.instance().handleChat(handler, chat);
}
public static void handlePacket131Packet(NetHandler handler, Packet131MapData mapData)
{
if (handler instanceof NetServerHandler || mapData.field_73438_a != Item.field_77744_bd.field_77779_bT)
{
// Server side and not "map" packets are always handled by us
NetworkRegistry.instance().handleTinyPacket(handler, mapData);
}
else
{
// Fallback to the net client handler implementation
FMLCommonHandler.instance().handleTinyPacket(handler, mapData);
}
}
public static int getCompatibilityLevel()
{
return PROTOCOL_VERSION;
}
public static boolean vanillaLoginPacketCompatibility()
{
return FMLCommonHandler.instance().getSidedDelegate().getClientCompatibilityLevel() == 0;
}
}
@@ -1,17 +1,13 @@
package cpw.mods.fml.common.network;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import net.minecraft.src.NetHandler;
import net.minecraft.src.NetworkManager;
import com.google.common.base.Throwables;
import com.google.common.io.ByteStreams;
import com.google.common.primitives.Bytes;
import com.google.common.primitives.Primitives;
import com.google.common.primitives.UnsignedBytes;
import cpw.mods.fml.common.FMLLog;
@@ -0,0 +1,24 @@
package cpw.mods.fml.common.network;
import net.minecraft.src.NetHandler;
import net.minecraft.src.NetServerHandler;
import net.minecraft.src.Packet3Chat;
public interface IChatListener
{
/**
* Called when there is a chat message received on the server
* @param handler
* @param message
*/
public Packet3Chat serverChat(NetHandler handler, Packet3Chat message);
/**
* Called when there is a chat message recived on the client
*
* @param handler
* @param message
* @return
*/
public Packet3Chat clientChat(NetHandler handler, Packet3Chat message);
}
@@ -1,11 +1,8 @@
package cpw.mods.fml.common.network;
import net.minecraft.server.MinecraftServer;
import net.minecraft.src.EntityPlayer;
import net.minecraft.src.EntityPlayerMP;
import net.minecraft.src.NetHandler;
import net.minecraft.src.NetLoginHandler;
import net.minecraft.src.NetServerHandler;
import net.minecraft.src.NetworkManager;
import net.minecraft.src.Packet1Login;
@@ -0,0 +1,9 @@
package cpw.mods.fml.common.network;
import net.minecraft.src.NetHandler;
import net.minecraft.src.Packet131MapData;
public interface ITinyPacketHandler
{
void handle(NetHandler handler, Packet131MapData mapData);
}
@@ -1,23 +1,19 @@
package cpw.mods.fml.common.network;
import static cpw.mods.fml.common.network.FMLPacket.Type.*;
import static cpw.mods.fml.common.network.FMLPacket.Type.MOD_IDENTIFIERS;
import java.util.Collection;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import net.minecraft.src.NetHandler;
import net.minecraft.src.NetworkManager;
import com.google.common.collect.Maps;
import com.google.common.io.ByteArrayDataInput;
import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams;
import cpw.mods.fml.common.FMLLog;
import net.minecraft.src.NetHandler;
import net.minecraft.src.NetLoginHandler;
import net.minecraft.src.NetworkManager;
public class ModIdentifiersPacket extends FMLPacket
{
@@ -1,11 +1,12 @@
package cpw.mods.fml.common.network;
import static cpw.mods.fml.common.network.FMLPacket.Type.*;
import static cpw.mods.fml.common.network.FMLPacket.Type.MOD_LIST_REQUEST;
import static cpw.mods.fml.common.network.FMLPacket.Type.MOD_LIST_RESPONSE;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.logging.Level;
import net.minecraft.src.NetHandler;
import net.minecraft.src.NetworkManager;
@@ -17,6 +18,7 @@ import com.google.common.io.ByteArrayDataInput;
import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.FMLLog;
import cpw.mods.fml.common.Loader;
import cpw.mods.fml.common.ModContainer;
@@ -24,6 +26,7 @@ import cpw.mods.fml.common.ModContainer;
public class ModListRequestPacket extends FMLPacket
{
private List<String> sentModList;
private byte compatibilityLevel;
public ModListRequestPacket()
{
@@ -40,6 +43,7 @@ public class ModListRequestPacket extends FMLPacket
{
dat.writeUTF(mc.getModId());
}
dat.writeByte(FMLNetworkHandler.getCompatibilityLevel());
return dat.toByteArray();
}
@@ -53,6 +57,14 @@ public class ModListRequestPacket extends FMLPacket
{
sentModList.add(in.readUTF());
}
try
{
compatibilityLevel = in.readByte();
}
catch (IllegalStateException e)
{
FMLLog.fine("No compatibility byte found - the server is too old");
}
return this;
}
@@ -84,14 +96,23 @@ public class ModListRequestPacket extends FMLPacket
if (indexedModList.size()>0)
{
// TODO : handle client present but server absent mods
for (Entry<String, ModContainer> e : indexedModList.entrySet())
{
if (e.getValue().isNetworkMod())
{
NetworkModHandler missingHandler = FMLNetworkHandler.instance().findNetworkModHandler(e.getValue());
if (missingHandler.requiresServerSide())
{
// TODO : what should we do if a mod is marked "serverSideRequired"? Stop the connection?
FMLLog.warning("The mod %s was not found on the server you connected to, but requested that the server side be present", e.getKey());
}
}
}
}
Packet250CustomPayload pkt = new Packet250CustomPayload();
pkt.field_73630_a = "FML";
pkt.field_73629_c = FMLPacket.makePacket(MOD_LIST_RESPONSE, modVersions, missingMods);
pkt.field_73628_b = pkt.field_73629_c.length;
FMLLog.fine("The server has compatibility level %d", compatibilityLevel);
FMLCommonHandler.instance().getSidedDelegate().setClientCompatibilityLevel(compatibilityLevel);
mgr.func_74429_a(pkt);
mgr.func_74429_a(PacketDispatcher.getPacket("FML", FMLPacket.makePacket(MOD_LIST_RESPONSE, modVersions, missingMods)));
}
}
@@ -1,10 +1,18 @@
package cpw.mods.fml.common.network;
import static cpw.mods.fml.common.network.FMLPacket.Type.*;
import static cpw.mods.fml.common.network.FMLPacket.Type.MOD_IDENTIFIERS;
import static cpw.mods.fml.common.network.FMLPacket.Type.MOD_LIST_RESPONSE;
import static cpw.mods.fml.common.network.FMLPacket.Type.MOD_MISSING;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.logging.Logger;
import net.minecraft.src.NetHandler;
import net.minecraft.src.NetLoginHandler;
import net.minecraft.src.NetworkManager;
import net.minecraft.src.Packet250CustomPayload;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
@@ -16,11 +24,6 @@ import cpw.mods.fml.common.FMLLog;
import cpw.mods.fml.common.Loader;
import cpw.mods.fml.common.ModContainer;
import net.minecraft.src.NetHandler;
import net.minecraft.src.NetLoginHandler;
import net.minecraft.src.NetworkManager;
import net.minecraft.src.Packet250CustomPayload;
public class ModListResponsePacket extends FMLPacket
{
private Map<String,String> modVersions;
@@ -106,12 +109,16 @@ public class ModListResponsePacket extends FMLPacket
if (missingClientMods.size()>0 || versionIncorrectMods.size() > 0)
{
pkt.field_73629_c = FMLPacket.makePacket(MOD_MISSING, missingClientMods, versionIncorrectMods);
FMLLog.fine("User %s connection failed: missing %s, bad versions %s", userName, missingClientMods, versionIncorrectMods);
Logger.getLogger("Minecraft").info(String.format("User %s connection failed: missing %s, bad versions %s", userName, missingClientMods, versionIncorrectMods));
FMLLog.info("User %s connection failed: missing %s, bad versions %s", userName, missingClientMods, versionIncorrectMods);
// Mark this as bad
FMLNetworkHandler.setHandlerState((NetLoginHandler) netHandler, FMLNetworkHandler.MISSING_MODS_OR_VERSIONS);
}
else
{
pkt.field_73629_c = FMLPacket.makePacket(MOD_IDENTIFIERS, netHandler);
FMLLog.fine("User %s connecting with mods %s", userName, modVersions.keySet());
Logger.getLogger("Minecraft").info(String.format("User %s connecting with mods %s", userName, modVersions.keySet()));
FMLLog.info("User %s connecting with mods %s", userName, modVersions.keySet());
}
pkt.field_73628_b = pkt.field_73629_c.length;
@@ -2,12 +2,29 @@ package cpw.mods.fml.common.network;
import java.util.List;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableList.Builder;
import com.google.common.collect.Lists;
import com.google.common.io.ByteArrayDataInput;
import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.Loader;
import cpw.mods.fml.common.ModContainer;
import cpw.mods.fml.common.versioning.ArtifactVersion;
import cpw.mods.fml.common.versioning.DefaultArtifactVersion;
import cpw.mods.fml.common.versioning.VersionRange;
import net.minecraft.src.NetHandler;
import net.minecraft.src.NetworkManager;
public class ModMissingPacket extends FMLPacket
{
private List<ModData> missing;
private List<ModData> badVersion;
public ModMissingPacket()
{
super(Type.MOD_MISSING);
@@ -16,24 +33,76 @@ public class ModMissingPacket extends FMLPacket
@Override
public byte[] generatePacket(Object... data)
{
// TODO
ByteArrayDataOutput dat = ByteStreams.newDataOutput();
List<String> missing = (List<String>) data[0];
List<String> badVersion = (List<String>) data[1];
return new byte[0];
dat.writeInt(missing.size());
for (String missed : missing)
{
ModContainer mc = Loader.instance().getIndexedModList().get(missed);
dat.writeUTF(missed);
dat.writeUTF(mc.getVersion());
}
dat.writeInt(badVersion.size());
for (String bad : badVersion)
{
ModContainer mc = Loader.instance().getIndexedModList().get(bad);
dat.writeUTF(bad);
dat.writeUTF(mc.getVersion());
}
return dat.toByteArray();
}
private static class ModData
{
String modId;
String modVersion;
}
@Override
public FMLPacket consumePacket(byte[] data)
{
// TODO
ByteArrayDataInput dat = ByteStreams.newDataInput(data);
int missingLen = dat.readInt();
missing = Lists.newArrayListWithCapacity(missingLen);
for (int i = 0; i < missingLen; i++)
{
ModData md = new ModData();
md.modId = dat.readUTF();
md.modVersion = dat.readUTF();
missing.add(md);
}
int badVerLength = dat.readInt();
badVersion = Lists.newArrayListWithCapacity(badVerLength);
for (int i = 0; i < badVerLength; i++)
{
ModData md = new ModData();
md.modId = dat.readUTF();
md.modVersion = dat.readUTF();
badVersion.add(md);
}
return this;
}
@Override
public void execute(NetworkManager network, FMLNetworkHandler handler, NetHandler netHandler, String userName)
{
// TODO
FMLCommonHandler.instance().getSidedDelegate().displayMissingMods(this);
}
public List<ArtifactVersion> getModList()
{
Builder<ArtifactVersion> builder = ImmutableList.<ArtifactVersion>builder();
for (ModData md : missing)
{
builder.add(new DefaultArtifactVersion(md.modId, VersionRange.createFromVersion(md.modVersion, null)));
}
for (ModData md : badVersion)
{
builder.add(new DefaultArtifactVersion(md.modId, VersionRange.createFromVersion(md.modVersion, null)));
}
return builder.build();
}
}
@@ -4,9 +4,8 @@ import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.EnumSet;
import cpw.mods.fml.common.Side;
import net.minecraft.src.Packet131MapData;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@@ -24,7 +23,9 @@ public @interface NetworkMod
*/
boolean serverSideRequired() default false;
/**
* A list of Packet250 network channels to register for this mod
* A list of Packet250 network channels to register for this mod - these channels
* will be universal and will require a universal packethandler to handle them
*
* @return
*/
String[] channels() default {};
@@ -36,23 +37,46 @@ public @interface NetworkMod
/**
* A packet handler implementation for channels registered through this annotation
* - this packet handler will be universal and handle both client and server
* requests.
*
* @return
*/
Class<? extends IPacketHandler> packetHandler() default NULL.class;
/**
* A tiny packet handler implementation based on {@link Packet131MapData} for "small"
* data packet loads.
*
* @return
*/
Class<? extends ITinyPacketHandler> tinyPacketHandler() default NULL.class;
/**
* A connection handler implementation for this network mod
*
* @return
*/
Class<? extends IConnectionHandler> connectionHandler() default NULL.class;
/**
* A packet handler and channels to register for the client side
*
* @return
*/
SidedPacketHandler clientPacketHandlerSpec() default @SidedPacketHandler(channels = {}, packetHandler = NULL.class );
/**
* A packet handler and channels to register for the server side
* @return
*/
SidedPacketHandler serverPacketHandlerSpec() default @SidedPacketHandler(channels = {}, packetHandler = NULL.class );
/**
* Special dummy class for handling stupid annotation default values
* @author cpw
*
*/
static interface NULL extends IPacketHandler, IConnectionHandler {};
static interface NULL extends IPacketHandler, IConnectionHandler, ITinyPacketHandler {};
/**
* A marker for a method that will be offered the client's version string
* if more sophisticated version rejection handling is required:
@@ -64,4 +88,15 @@ public @interface NetworkMod
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface VersionCheckHandler { }
/**
* Bundles together a packet handler and it's associated channels for the sided packet handlers
* @author cpw
*
*/
public @interface SidedPacketHandler {
String[] channels();
Class<? extends IPacketHandler> packetHandler();
}
}
@@ -1,21 +1,17 @@
package cpw.mods.fml.common.network;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Set;
import java.util.logging.Level;
import net.minecraft.src.EntityPlayerMP;
import net.minecraft.src.NetServerHandler;
import net.minecraft.src.NetworkManager;
import org.objectweb.asm.Type;
import net.minecraft.src.Item;
import com.google.common.base.Strings;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.FMLLog;
import cpw.mods.fml.common.ModContainer;
import cpw.mods.fml.common.Side;
import cpw.mods.fml.common.discovery.ASMDataTable;
import cpw.mods.fml.common.discovery.ASMDataTable.ASMData;
import cpw.mods.fml.common.versioning.DefaultArtifactVersion;
@@ -24,6 +20,12 @@ import cpw.mods.fml.common.versioning.VersionRange;
public class NetworkModHandler
{
private static Object connectionHandlerDefaultValue;
private static Object packetHandlerDefaultValue;
private static Object clientHandlerDefaultValue;
private static Object serverHandlerDefaultValue;
private static Object tinyPacketHandlerDefaultValue;
private static int assignedIds = 1;
private int localId;
@@ -34,6 +36,7 @@ public class NetworkModHandler
private Method checkHandler;
private VersionRange acceptableRange;
private ITinyPacketHandler tinyPacketHandler;
public NetworkModHandler(ModContainer container, NetworkMod modAnnotation)
{
@@ -41,6 +44,11 @@ public class NetworkModHandler
this.mod = modAnnotation;
this.localId = assignedIds++;
this.networkId = this.localId;
// Skip over the map object because it has special network id meaning
if (Item.field_77744_bd.field_77779_bT == assignedIds)
{
assignedIds++;
}
}
public NetworkModHandler(ModContainer container, Class<?> networkModClass, ASMDataTable table)
{
@@ -92,30 +100,31 @@ public class NetworkModHandler
}
}
if (!mod.packetHandler().getName().equals(NetworkMod.NULL.class.getName()))
FMLLog.finest("Testing mod %s to very it can accept it's own version in a remote connection", container.getModId());
boolean acceptsSelf = acceptVersion(container.getVersion());
if (!acceptsSelf)
{
IPacketHandler instance;
try
{
instance = mod.packetHandler().newInstance();
}
catch (Exception e)
{
FMLLog.log(Level.SEVERE, e, "Unable to create packet handler instance %s", mod.packetHandler().getName());
throw new FMLNetworkException(e);
}
for (String channel : mod.channels())
{
NetworkRegistry.instance().registerChannel(instance, channel);
}
FMLLog.severe("The mod %s appears to reject it's own version number (%s) in it's version handling. This is likely a severe bug in the mod!", container.getModId(), container.getVersion());
}
else if (mod.channels().length > 0)
else
{
FMLLog.warning("The mod id %s attempted to register channels without specifying a valid packet handler", container.getModId());
FMLLog.finest("The mod %s accepts it's own version (%s)", container.getModId(), container.getVersion());
}
if (!mod.connectionHandler().getName().equals(NetworkMod.NULL.class.getName()))
tryCreatingPacketHandler(container, mod.packetHandler(), mod.channels(), null);
if (FMLCommonHandler.instance().getSide().isClient())
{
if (mod.clientPacketHandlerSpec() != getClientHandlerSpecDefaultValue())
{
tryCreatingPacketHandler(container, mod.clientPacketHandlerSpec().packetHandler(), mod.clientPacketHandlerSpec().channels(), Side.CLIENT);
}
}
if (mod.serverPacketHandlerSpec() != getServerHandlerSpecDefaultValue())
{
tryCreatingPacketHandler(container, mod.serverPacketHandlerSpec().packetHandler(), mod.serverPacketHandlerSpec().channels(), Side.SERVER);
}
if (mod.connectionHandler() != getConnectionHandlerDefaultValue())
{
IConnectionHandler instance;
try
@@ -130,8 +139,143 @@ public class NetworkModHandler
NetworkRegistry.instance().registerConnectionHandler(instance);
}
if (mod.tinyPacketHandler()!=getTinyPacketHandlerDefaultValue())
{
try
{
tinyPacketHandler = mod.tinyPacketHandler().newInstance();
}
catch (Exception e)
{
FMLLog.log(Level.SEVERE, e, "Unable to create tiny packet handler instance %s", mod.tinyPacketHandler().getName());
throw new FMLNetworkException(e);
}
}
}
/**
* @param container
*/
private void tryCreatingPacketHandler(ModContainer container, Class<? extends IPacketHandler> clazz, String[] channels, Side side)
{
if (side!=null && side.isClient() && ! FMLCommonHandler.instance().getSide().isClient())
{
return;
}
if (clazz!=getPacketHandlerDefaultValue())
{
if (channels.length==0)
{
FMLLog.log(Level.WARNING, "The mod id %s attempted to register a packet handler without specifying channels for it", container.getModId());
}
else
{
IPacketHandler instance;
try
{
instance = clazz.newInstance();
}
catch (Exception e)
{
FMLLog.log(Level.SEVERE, e, "Unable to create a packet handler instance %s for mod %s", clazz.getName(), container.getModId());
throw new FMLNetworkException(e);
}
for (String channel : channels)
{
NetworkRegistry.instance().registerChannel(instance, channel, side);
}
}
}
else if (channels.length > 0)
{
FMLLog.warning("The mod id %s attempted to register channels without specifying a packet handler", container.getModId());
}
}
/**
* @return
*/
private Object getConnectionHandlerDefaultValue()
{
try {
if (connectionHandlerDefaultValue == null)
{
connectionHandlerDefaultValue = NetworkMod.class.getMethod("connectionHandler").getDefaultValue();
}
return connectionHandlerDefaultValue;
}
catch (NoSuchMethodException e)
{
throw new RuntimeException("Derp?", e);
}
}
/**
* @return
*/
private Object getPacketHandlerDefaultValue()
{
try {
if (packetHandlerDefaultValue == null)
{
packetHandlerDefaultValue = NetworkMod.class.getMethod("packetHandler").getDefaultValue();
}
return packetHandlerDefaultValue;
}
catch (NoSuchMethodException e)
{
throw new RuntimeException("Derp?", e);
}
}
private Object getTinyPacketHandlerDefaultValue()
{
try {
if (tinyPacketHandlerDefaultValue == null)
{
tinyPacketHandlerDefaultValue = NetworkMod.class.getMethod("tinyPacketHandler").getDefaultValue();
}
return tinyPacketHandlerDefaultValue;
}
catch (NoSuchMethodException e)
{
throw new RuntimeException("Derp?", e);
}
}
/**
* @return
*/
private Object getClientHandlerSpecDefaultValue()
{
try {
if (clientHandlerDefaultValue == null)
{
clientHandlerDefaultValue = NetworkMod.class.getMethod("clientPacketHandlerSpec").getDefaultValue();
}
return clientHandlerDefaultValue;
}
catch (NoSuchMethodException e)
{
throw new RuntimeException("Derp?", e);
}
}
/**
* @return
*/
private Object getServerHandlerSpecDefaultValue()
{
try {
if (serverHandlerDefaultValue == null)
{
serverHandlerDefaultValue = NetworkMod.class.getMethod("serverPacketHandlerSpec").getDefaultValue();
}
return serverHandlerDefaultValue;
}
catch (NoSuchMethodException e)
{
throw new RuntimeException("Derp?", e);
}
}
public boolean requiresClientSide()
{
return mod.clientSideRequired();
@@ -194,4 +338,13 @@ public class NetworkModHandler
{
this.networkId = value;
}
public boolean hasTinyPacketHandler()
{
return tinyPacketHandler != null;
}
public ITinyPacketHandler getTinyPacketHandler()
{
return tinyPacketHandler;
}
}
@@ -1,8 +1,6 @@
package cpw.mods.fml.common.network;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -16,9 +14,10 @@ import net.minecraft.src.NetHandler;
import net.minecraft.src.NetLoginHandler;
import net.minecraft.src.NetServerHandler;
import net.minecraft.src.NetworkManager;
import net.minecraft.src.Packet131MapData;
import net.minecraft.src.Packet1Login;
import net.minecraft.src.Packet250CustomPayload;
import net.minecraft.src.TcpConnection;
import net.minecraft.src.Packet3Chat;
import net.minecraft.src.World;
import com.google.common.base.Charsets;
@@ -26,19 +25,23 @@ import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps;
import com.google.common.collect.SetMultimap;
import com.google.common.collect.Sets;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.FMLLog;
import cpw.mods.fml.common.Loader;
import cpw.mods.fml.common.ModContainer;
import cpw.mods.fml.common.Side;
import cpw.mods.fml.common.network.FMLPacket.Type;
/**
* @author cpw
*
*/
public class NetworkRegistry
{
@@ -50,13 +53,16 @@ public class NetworkRegistry
/**
* A map of the packet handlers for packets
*/
private Multimap<String, IPacketHandler> packetHandlers = ArrayListMultimap.create();
private Multimap<String, IPacketHandler> universalPacketHandlers = ArrayListMultimap.create();
private Multimap<String, IPacketHandler> clientPacketHandlers = ArrayListMultimap.create();
private Multimap<String, IPacketHandler> serverPacketHandlers = ArrayListMultimap.create();
/**
* A linked set of registered connection handlers
*/
private Set<IConnectionHandler> connectionHandlers = Sets.newLinkedHashSet();
private Map<ModContainer, IGuiHandler> serverGuiHandlers = Maps.newHashMap();
private Map<ModContainer, IGuiHandler> clientGuiHandlers = Maps.newHashMap();
private List<IChatListener> chatListeners = Lists.newArrayList();
public static NetworkRegistry instance()
{
@@ -66,9 +72,9 @@ public class NetworkRegistry
* Get the packet 250 channel registration string
* @return
*/
byte[] getPacketRegistry()
byte[] getPacketRegistry(Side side)
{
return Joiner.on('\0').join(packetHandlers.keySet()).getBytes(Charsets.UTF_8);
return Joiner.on('\0').join(Iterables.concat(Arrays.asList("FML"),universalPacketHandlers.keySet(), side.isClient() ? clientPacketHandlers.keySet() : serverPacketHandlers.keySet())).getBytes(Charsets.UTF_8);
}
/**
* Is the specified channel active for the player?
@@ -87,7 +93,36 @@ public class NetworkRegistry
*/
public void registerChannel(IPacketHandler handler, String channelName)
{
packetHandlers.put(channelName, handler);
if (Strings.isNullOrEmpty(channelName) || (channelName!=null && channelName.length()>16))
{
FMLLog.severe("Invalid channel name '%s' : %s", channelName, Strings.isNullOrEmpty(channelName) ? "Channel name is empty" : "Channel name is too long (16 chars is maximum)");
throw new RuntimeException("Channel name is invalid");
}
universalPacketHandlers.put(channelName, handler);
}
public void registerChannel(IPacketHandler handler, String channelName, Side side)
{
if (side == null)
{
registerChannel(handler, channelName);
return;
}
if (Strings.isNullOrEmpty(channelName) || (channelName!=null && channelName.length()>16))
{
FMLLog.severe("Invalid channel name '%s' : %s", channelName, Strings.isNullOrEmpty(channelName) ? "Channel name is empty" : "Channel name is too long (16 chars is maximum)");
throw new RuntimeException("Channel name is invalid");
}
if (side.isClient())
{
clientPacketHandlers.put(channelName, handler);
}
else
{
serverPacketHandlers.put(channelName, handler);
}
}
/**
* Activate the channel for the player
@@ -116,13 +151,22 @@ public class NetworkRegistry
connectionHandlers.add(handler);
}
/**
* Register a chat listener
* @param listener
*/
public void registerChatListener(IChatListener listener)
{
chatListeners.add(listener);
}
void playerLoggedIn(EntityPlayerMP player, NetServerHandler netHandler, NetworkManager manager)
{
generateChannelRegistration(player, netHandler, manager);
for (IConnectionHandler handler : connectionHandlers)
{
handler.playerLoggedIn((Player)player, netHandler, manager);
}
generateChannelRegistration(player, netHandler, manager);
}
String connectionReceived(NetLoginHandler netHandler, NetworkManager manager)
@@ -156,6 +200,7 @@ public class NetworkRegistry
void clientLoggedIn(NetHandler clientHandler, NetworkManager manager, Packet1Login login)
{
generateChannelRegistration(clientHandler.getPlayer(), clientHandler, manager);
for (IConnectionHandler handler : connectionHandlers)
{
handler.clientLoggedIn(clientHandler, manager, login);
@@ -174,7 +219,7 @@ public class NetworkRegistry
{
Packet250CustomPayload pkt = new Packet250CustomPayload();
pkt.field_73630_a = "REGISTER";
pkt.field_73629_c = getPacketRegistry();
pkt.field_73629_c = getPacketRegistry(player instanceof EntityPlayerMP ? Side.SERVER : Side.CLIENT);
pkt.field_73628_b = pkt.field_73629_c.length;
manager.func_74429_a(pkt);
}
@@ -198,12 +243,10 @@ public class NetworkRegistry
private void handlePacket(Packet250CustomPayload packet, NetworkManager network, Player player)
{
if (activeChannels.containsEntry(player, packet.field_73630_a))
String channel = packet.field_73630_a;
for (IPacketHandler handler : Iterables.concat(universalPacketHandlers.get(channel), player instanceof EntityPlayerMP ? serverPacketHandlers.get(channel) : clientPacketHandlers.get(channel)))
{
for (IPacketHandler handler : packetHandlers.get(packet.field_73630_a))
{
handler.onPacketData(network, packet, player);
}
handler.onPacketData(network, packet, player);
}
}
@@ -237,6 +280,11 @@ public class NetworkRegistry
public void registerGuiHandler(Object mod, IGuiHandler handler)
{
ModContainer mc = FMLCommonHandler.instance().findContainerFor(mod);
if (mc == null)
{
mc = Loader.instance().activeModContainer();
FMLLog.log(Level.WARNING, "Mod %s attempted to register a gui network handler during a construction phase", mc.getModId());
}
NetworkModHandler nmh = FMLNetworkHandler.instance().findNetworkModHandler(mc);
if (nmh == null)
{
@@ -276,4 +324,35 @@ public class NetworkRegistry
IGuiHandler handler = clientGuiHandlers.get(mc);
FMLCommonHandler.instance().showGuiScreen(handler.getClientGuiElement(modGuiId, player, world, x, y, z));
}
public Packet3Chat handleChat(NetHandler handler, Packet3Chat chat)
{
Side s = Side.CLIENT;
if (handler instanceof NetServerHandler)
{
s = Side.SERVER;
}
for (IChatListener listener : chatListeners)
{
chat = s.isClient() ? listener.clientChat(handler, chat) : listener.serverChat(handler, chat);
}
return chat;
}
public void handleTinyPacket(NetHandler handler, Packet131MapData mapData)
{
NetworkModHandler nmh = FMLNetworkHandler.instance().findNetworkModHandler((int)mapData.field_73438_a);
if (nmh == null)
{
FMLLog.info("Received a tiny packet for network id %d that is not recognised here", mapData.field_73438_a);
return;
}
if (nmh.hasTinyPacketHandler())
{
nmh.getTinyPacketHandler().handle(handler, mapData);
}
else
{
FMLLog.info("Received a tiny packet for a network mod that does not accept tiny packets %s", nmh.getContainer().getModId());
}
}
}
@@ -1,15 +1,13 @@
package cpw.mods.fml.common.network;
import com.google.common.io.ByteArrayDataInput;
import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams;
import cpw.mods.fml.common.FMLCommonHandler;
import net.minecraft.src.EntityPlayer;
import net.minecraft.src.NetHandler;
import net.minecraft.src.NetworkManager;
import com.google.common.io.ByteArrayDataInput;
import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams;
public class OpenGuiPacket extends FMLPacket
{
private int windowId;
@@ -0,0 +1,81 @@
package cpw.mods.fml.common.network;
import net.minecraft.server.MinecraftServer;
import net.minecraft.src.EntityPlayerMP;
import net.minecraft.src.Packet;
import net.minecraft.src.Packet131MapData;
import net.minecraft.src.Packet250CustomPayload;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.FMLLog;
/**
* A simple utility class to send packet 250 packets around the place
*
* @author cpw
*
*/
public class PacketDispatcher
{
public static Packet250CustomPayload getPacket(String type, byte[] data)
{
return new Packet250CustomPayload(type, data);
}
public static void sendPacketToServer(Packet packet)
{
FMLCommonHandler.instance().getSidedDelegate().sendPacket(packet);
}
public static void sendPacketToPlayer(Packet packet, Player player)
{
if (player instanceof EntityPlayerMP)
{
((EntityPlayerMP)player).field_71135_a.func_72567_b(packet);
}
}
public static void sendPacketToAllAround(double X, double Y, double Z, double range, int dimensionId, Packet packet)
{
MinecraftServer server = FMLCommonHandler.instance().getMinecraftServerInstance();
if (server != null)
{
server.func_71203_ab().func_72393_a(X, Y, Z, range, dimensionId, packet);
}
else
{
FMLLog.fine("Attempt to send packet to all around without a server instance available");
}
}
public static void sendPacketToAllInDimension(Packet packet, int dimId)
{
MinecraftServer server = FMLCommonHandler.instance().getMinecraftServerInstance();
if (server != null)
{
server.func_71203_ab().func_72396_a(packet, dimId);
}
else
{
FMLLog.fine("Attempt to send packet to all in dimension without a server instance available");
}
}
public static void sendPacketToAllPlayers(Packet packet)
{
MinecraftServer server = FMLCommonHandler.instance().getMinecraftServerInstance();
if (server != null)
{
server.func_71203_ab().func_72384_a(packet);
}
else
{
FMLLog.fine("Attempt to send packet to all in dimension without a server instance available");
}
}
public static Packet131MapData getTinyPacket(Object mod, short tag, byte[] data)
{
NetworkModHandler nmh = FMLNetworkHandler.instance().findNetworkModHandler(mod);
return new Packet131MapData((short) nmh.getNetworkId(), tag, data);
}
}
@@ -4,40 +4,55 @@ import java.util.BitSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.logging.Level;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Maps;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.FMLLog;
import cpw.mods.fml.common.ModContainer;
import net.minecraft.src.BiomeGenBase;
import net.minecraft.src.Entity;
import net.minecraft.src.EntityList;
import net.minecraft.src.EntityLiving;
import net.minecraft.src.EntityTracker;
import net.minecraft.src.EnumCreatureType;
import net.minecraft.src.SpawnListEntry;
import com.google.common.base.Function;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Maps;
import com.google.common.primitives.UnsignedBytes;
import com.google.common.primitives.UnsignedInteger;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.FMLLog;
import cpw.mods.fml.common.Loader;
import cpw.mods.fml.common.ModContainer;
import cpw.mods.fml.common.network.EntitySpawnPacket;
import cpw.mods.fml.common.registry.EntityRegistry.EntityRegistration;
public class EntityRegistry
{
public class EntityRegistration
{
private Class<? extends Entity> entityClass;
private ModContainer container;
private String entityName;
private int modId;
public EntityRegistration(ModContainer mc, Class<? extends Entity> entityClass, String entityName, int id)
private int trackingRange;
private int updateFrequency;
private boolean sendsVelocityUpdates;
private Function<EntitySpawnPacket, Entity> customSpawnCallback;
private boolean usesVanillaSpawning;
public EntityRegistration(ModContainer mc, Class<? extends Entity> entityClass, String entityName, int id, int trackingRange, int updateFrequency, boolean sendsVelocityUpdates)
{
this.container = mc;
this.entityClass = entityClass;
this.entityName = entityName;
this.modId = id;
this.trackingRange = trackingRange;
this.updateFrequency = updateFrequency;
this.sendsVelocityUpdates = sendsVelocityUpdates;
}
public Class<? extends Entity> getEntityClass()
{
@@ -55,41 +70,94 @@ public class EntityRegistry
{
return modId;
}
public int getTrackingRange()
{
return trackingRange;
}
public int getUpdateFrequency()
{
return updateFrequency;
}
public boolean sendsVelocityUpdates()
{
return sendsVelocityUpdates;
}
public boolean usesVanillaSpawning()
{
return usesVanillaSpawning;
}
public boolean hasCustomSpawning()
{
return customSpawnCallback != null;
}
public Entity doCustomSpawning(EntitySpawnPacket packet) throws Exception
{
return customSpawnCallback.apply(packet);
}
public void setCustomSpawning(Function<EntitySpawnPacket, Entity> callable, boolean usesVanillaSpawning)
{
this.customSpawnCallback = callable;
this.usesVanillaSpawning = usesVanillaSpawning;
}
}
private static final EntityRegistry INSTANCE = new EntityRegistry();
private BitSet availableIndicies;
private ListMultimap<ModContainer, EntityRegistration> entityRegistrations = ArrayListMultimap.create();
private BiMap<String,ModContainer> entityNames = HashBiMap.create();
private Map<String,ModContainer> entityNames = Maps.newHashMap();
private BiMap<Class<? extends Entity>, EntityRegistration> entityClassRegistrations = HashBiMap.create();
public static EntityRegistry instance()
{
return INSTANCE;
}
private EntityRegistry()
{
availableIndicies = new BitSet(256);
availableIndicies.set(0,255);
availableIndicies.set(1,255);
for (Object id : EntityList.field_75623_d.keySet())
{
availableIndicies.clear((Integer)id);
}
}
public static void registerModEntity(Class<? extends Entity> entityClass, String entityName, int id, Object mod)
/**
* Register the mod entity type with FML
* @param entityClass The entity class
* @param entityName A unique name for the entity
* @param id A mod specific ID for the entity
* @param mod The mod
* @param trackingRange The range at which MC will send tracking updates
* @param updateFrequency The frequency of tracking updates
* @param sendsVelocityUpdates Whether to send velocity information packets as well
*/
public static void registerModEntity(Class<? extends Entity> entityClass, String entityName, int id, Object mod, int trackingRange, int updateFrequency, boolean sendsVelocityUpdates)
{
instance().doModEntityRegistration(entityClass, entityName, id, mod);
instance().doModEntityRegistration(entityClass, entityName, id, mod, trackingRange, updateFrequency, sendsVelocityUpdates);
}
private void doModEntityRegistration(Class<? extends Entity> entityClass, String entityName, int id, Object mod)
private void doModEntityRegistration(Class<? extends Entity> entityClass, String entityName, int id, Object mod, int trackingRange, int updateFrequency, boolean sendsVelocityUpdates)
{
ModContainer mc = FMLCommonHandler.instance().findContainerFor(mod);
EntityRegistration er = new EntityRegistration(mc, entityClass, entityName, id);
EntityRegistration er = new EntityRegistration(mc, entityClass, entityName, id, trackingRange, updateFrequency, sendsVelocityUpdates);
try
{
entityClassRegistrations.put(entityClass, er);
entityNames.put(entityName, mc);
if (!EntityList.field_75626_c.containsKey(entityClass))
{
String entityModName = String.format("%s.%s", mc.getModId(), entityName);
EntityList.field_75626_c.put(entityClass, entityModName);
EntityList.field_75625_b.put(entityModName, entityClass);
FMLLog.finest("Automatically registered mod %s entity %s as %s", mc.getModId(), entityName, entityModName);
}
else
{
FMLLog.fine("Skipping automatic mod %s entity registration for already registered class %s", mc.getModId(), entityClass.getName());
}
}
catch (IllegalArgumentException e)
{
@@ -101,21 +169,73 @@ public class EntityRegistry
public static void registerGlobalEntityID(Class <? extends Entity > entityClass, String entityName, int id)
{
instance().validateAndClaimId(id);
if (EntityList.field_75626_c.containsKey(entityClass))
{
ModContainer activeModContainer = Loader.instance().activeModContainer();
String modId = "unknown";
if (activeModContainer != null)
{
modId = activeModContainer.getModId();
}
else
{
FMLLog.severe("There is a rogue mod failing to register entities from outside the context of mod loading. This is incredibly dangerous and should be stopped.");
}
FMLLog.warning("The mod %s tried to register the entity class %s which was already registered - if you wish to override default naming for FML mod entities, register it here first", modId, entityClass);
return;
}
id = instance().validateAndClaimId(id);
EntityList.func_75618_a(entityClass, entityName, id);
}
private void validateAndClaimId(int id)
private int validateAndClaimId(int id)
{
if (!availableIndicies.get(id))
// workaround for broken ML
int realId = id;
if (id < Byte.MIN_VALUE)
{
throw new RuntimeException(String.format("Unable to claim entity id %d", id));
FMLLog.warning("Compensating for modloader out of range compensation by mod : entityId %d for mod %s is now %d", id, Loader.instance().activeModContainer().getModId(), realId);
realId += 3000;
}
availableIndicies.clear(id);
if (realId < 0)
{
realId += Byte.MAX_VALUE;
}
try
{
UnsignedBytes.checkedCast(realId);
}
catch (IllegalArgumentException e)
{
FMLLog.log(Level.SEVERE, "The entity ID %d for mod %s is not an unsigned byte and may not work", id, Loader.instance().activeModContainer().getModId());
}
if (!availableIndicies.get(realId))
{
FMLLog.severe("The mod %s has attempted to register an entity ID %d which is already reserved. This could cause severe problems", Loader.instance().activeModContainer().getModId(), id);
}
availableIndicies.clear(realId);
return realId;
}
public static void registerGlobalEntityID(Class <? extends Entity > entityClass, String entityName, int id, int backgroundEggColour, int foregroundEggColour)
{
if (EntityList.field_75626_c.containsKey(entityClass))
{
ModContainer activeModContainer = Loader.instance().activeModContainer();
String modId = "unknown";
if (activeModContainer != null)
{
modId = activeModContainer.getModId();
}
else
{
FMLLog.severe("There is a rogue mod failing to register entities from outside the context of mod loading. This is incredibly dangerous and should be stopped.");
}
FMLLog.warning("The mod %s tried to register the entity class %s which was already registered - if you wish to override default naming for FML mod entities, register it here first", modId, entityClass);
return;
}
instance().validateAndClaimId(id);
EntityList.func_75614_a(entityClass, entityName, id, backgroundEggColour, foregroundEggColour);
}
@@ -126,7 +246,7 @@ public class EntityRegistry
{
@SuppressWarnings("unchecked")
List<SpawnListEntry> spawns = biome.func_76747_a(typeOfCreature);
for (SpawnListEntry entry : spawns)
{
//Adjusting an existing spawn entry
@@ -138,7 +258,7 @@ public class EntityRegistry
break;
}
}
spawns.add(new SpawnListEntry(entityClass, weightedProb, min, max));
}
}
@@ -146,7 +266,7 @@ public class EntityRegistry
public static void addSpawn(String entityName, int weightedProb, int min, int max, EnumCreatureType spawnList, BiomeGenBase... biomes)
{
Class <? extends Entity > entityClazz = (Class<? extends Entity>) EntityList.field_75625_b.get(entityName);
if (EntityLiving.class.isAssignableFrom(entityClazz))
{
addSpawn((Class <? extends EntityLiving >) entityClazz, weightedProb, min, max, spawnList, biomes);
@@ -159,7 +279,7 @@ public class EntityRegistry
{
@SuppressWarnings("unchecked")
Iterator<SpawnListEntry> spawns = biome.func_76747_a(typeOfCreature).iterator();
while (spawns.hasNext())
{
SpawnListEntry entry = spawns.next();
@@ -174,7 +294,7 @@ public class EntityRegistry
public static void removeSpawn(String entityName, EnumCreatureType spawnList, BiomeGenBase... biomes)
{
Class <? extends Entity > entityClazz = (Class<? extends Entity>) EntityList.field_75625_b.get(entityName);
if (EntityLiving.class.isAssignableFrom(entityClazz))
{
removeSpawn((Class <? extends EntityLiving >) entityClazz, spawnList, biomes);
@@ -194,7 +314,7 @@ public class EntityRegistry
public EntityRegistration lookupModSpawn(Class<? extends Entity> clazz, boolean keepLooking)
{
Class<?> localClazz = clazz;
do
{
EntityRegistration er = entityClassRegistrations.get(localClazz);
@@ -206,7 +326,7 @@ public class EntityRegistry
keepLooking = (!Object.class.equals(localClazz));
}
while (keepLooking);
return null;
}
@@ -222,4 +342,40 @@ public class EntityRegistry
return null;
}
public boolean tryTrackingEntity(EntityTracker entityTracker, Entity entity)
{
EntityRegistration er = lookupModSpawn(entity.getClass(), true);
if (er != null)
{
entityTracker.func_72785_a(entity, er.getTrackingRange(), er.getUpdateFrequency(), er.sendsVelocityUpdates());
return true;
}
return false;
}
/**
*
* DO NOT USE THIS METHOD
*
* @param entityClass
* @param entityTypeId
* @param updateRange
* @param updateInterval
* @param sendVelocityInfo
* @return
*/
@Deprecated
public static EntityRegistration registerModLoaderEntity(Object mod, Class<? extends Entity> entityClass, int entityTypeId, int updateRange, int updateInterval,
boolean sendVelocityInfo)
{
String entityName = (String) EntityList.field_75626_c.get(entityClass);
if (entityName == null)
{
throw new IllegalArgumentException(String.format("The ModLoader mod %s has tried to register an entity tracker for a non-existent entity type %s", Loader.instance().activeModContainer().getModId(), entityClass.getCanonicalName()));
}
instance().doModEntityRegistration(entityClass, entityName, entityTypeId, mod, updateRange, updateInterval, sendVelocityInfo);
return instance().entityClassRegistrations.get(entityClass);
}
}
@@ -1,6 +1,5 @@
package cpw.mods.fml.common.registry;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.Set;
@@ -8,6 +7,7 @@ import java.util.logging.Level;
import net.minecraft.src.BiomeGenBase;
import net.minecraft.src.CraftingManager;
import net.minecraft.src.EntityItem;
import net.minecraft.src.EntityPlayer;
import net.minecraft.src.FurnaceRecipes;
import net.minecraft.src.IChunkProvider;
@@ -27,9 +27,14 @@ import com.google.common.collect.Sets;
import cpw.mods.fml.common.FMLLog;
import cpw.mods.fml.common.ICraftingHandler;
import cpw.mods.fml.common.IDispenseHandler;
import cpw.mods.fml.common.IDispenserHandler;
import cpw.mods.fml.common.IFuelHandler;
import cpw.mods.fml.common.IPickupNotifier;
import cpw.mods.fml.common.IPlayerTracker;
import cpw.mods.fml.common.IWorldGenerator;
import cpw.mods.fml.common.Loader;
import cpw.mods.fml.common.LoaderException;
import cpw.mods.fml.common.LoaderState;
import cpw.mods.fml.common.Mod.Block;
import cpw.mods.fml.common.ModContainer;
@@ -40,13 +45,30 @@ public class GameRegistry
private static Set<IWorldGenerator> worldGenerators = Sets.newHashSet();
private static List<IFuelHandler> fuelHandlers = Lists.newArrayList();
private static List<ICraftingHandler> craftingHandlers = Lists.newArrayList();
private static List<IDispenseHandler> dispenserHandlers = Lists.newArrayList();
private static List<IDispenserHandler> dispenserHandlers = Lists.newArrayList();
private static List<IPickupNotifier> pickupHandlers = Lists.newArrayList();
private static List<IPlayerTracker> playerTrackers = Lists.newArrayList();
/**
* Register a world generator - something that inserts new block types into the world
*
* @param generator
*/
public static void registerWorldGenerator(IWorldGenerator generator)
{
worldGenerators.add(generator);
}
/**
* Callback hook for world gen - if your mod wishes to add extra mod related generation to the world
* call this
*
* @param chunkX
* @param chunkZ
* @param world
* @param chunkGenerator
* @param chunkProvider
*/
public static void generateWorld(int chunkX, int chunkZ, World world, IChunkProvider chunkGenerator, IChunkProvider chunkProvider)
{
long worldSeed = world.func_72905_C();
@@ -61,17 +83,48 @@ public class GameRegistry
}
}
public static void registerDispenserHandler(IDispenseHandler handler)
public static void registerDispenserHandler(IDispenserHandler handler)
{
dispenserHandlers.add(handler);
}
public static int tryDispense(World world, double x, double y, double z, int xVelocity, int zVelocity, ItemStack item)
/**
* Register a handler for dispensers
*
* @param handler
*/
@Deprecated
public static void registerDispenserHandler(final IDispenseHandler handler)
{
for (IDispenseHandler handler : dispenserHandlers)
registerDispenserHandler(new IDispenserHandler()
{
int dispensed = handler.dispense(x, y, z, xVelocity, zVelocity, world, item);
@Override
public int dispense(int x, int y, int z, int xVelocity, int zVelocity, World world, ItemStack item, Random random, double entX, double entY, double entZ)
{
return handler.dispense(x, y, z, xVelocity, zVelocity, world, item, random, entX, entY, entZ);
}
});
}
/**
* Callback hook for dispenser activities - if you add a block and want mods to be able
* to extend their dispenser related activities to it call this
*
* @param world
* @param x
* @param y
* @param z
* @param xVelocity
* @param zVelocity
* @param item
* @return
*/
public static int tryDispense(World world, int x, int y, int z, int xVelocity, int zVelocity, ItemStack item, Random random, double entX, double entY, double entZ)
{
for (IDispenserHandler handler : dispenserHandlers)
{
int dispensed = handler.dispense(x, y, z, xVelocity, zVelocity, world, item, random, entX, entY, entZ);
if (dispensed>-1)
{
return dispensed;
@@ -79,6 +132,14 @@ public class GameRegistry
}
return -1;
}
/**
* Internal method for creating an @Block instance
* @param container
* @param type
* @param annotation
* @return
* @throws Exception
*/
public static Object buildBlock(ModContainer container, Class<?> type, Block annotation) throws Exception
{
Object o = type.getConstructor(int.class).newInstance(findSpareBlockId());
@@ -86,18 +147,37 @@ public class GameRegistry
return o;
}
/**
* Private and not yet working properly
*
* @return
*/
private static int findSpareBlockId()
{
return BlockTracker.nextBlockId();
}
/**
* Register a block with the world
*
*/
public static void registerBlock(net.minecraft.src.Block block)
{
registerBlock(block, ItemBlock.class);
}
/**
* Register a block with the world, with the specified item class
*
* @param block
* @param itemclass
*/
public static void registerBlock(net.minecraft.src.Block block, Class<? extends ItemBlock> itemclass)
{
if (Loader.instance().isInState(LoaderState.CONSTRUCTING))
{
FMLLog.warning("The mod %s is attempting to register a block whilst it it being constructed. This is bad modding practice - please use a proper mod lifecycle event.", Loader.instance().activeModContainer());
}
try
{
assert block != null : "registerBlock: block cannot be null";
@@ -110,7 +190,7 @@ public class GameRegistry
FMLLog.log(Level.SEVERE, e, "Caught an exception during block registration");
throw new LoaderException(e);
}
BlockTracker.reserveBlockId(block.field_71990_ca);
blockRegistry.put(Loader.instance().activeModContainer(), (BlockProxy) block);
}
public static void addRecipe(ItemStack output, Object... params)
@@ -183,4 +263,45 @@ public class GameRegistry
}
}
public static void registerPickupHandler(IPickupNotifier handler)
{
pickupHandlers.add(handler);
}
public static void onPickupNotification(EntityPlayer player, EntityItem item)
{
for (IPickupNotifier notify : pickupHandlers)
{
notify.notifyPickup(item, player);
}
}
public static void registerPlayerTracker(IPlayerTracker tracker)
{
playerTrackers.add(tracker);
}
public static void onPlayerLogin(EntityPlayer player)
{
for(IPlayerTracker tracker : playerTrackers)
tracker.onPlayerLogin(player);
}
public static void onPlayerLogout(EntityPlayer player)
{
for(IPlayerTracker tracker : playerTrackers)
tracker.onPlayerLogout(player);
}
public static void onPlayerChangedDimension(EntityPlayer player)
{
for(IPlayerTracker tracker : playerTrackers)
tracker.onPlayerChangedDimension(player);
}
public static void onPlayerRespawn(EntityPlayer player)
{
for(IPlayerTracker tracker : playerTrackers)
tracker.onPlayerRespawn(player);
}
}
Loaded 100 of 191 files, more files were not shown because too many files have changed in this diff. Show more