Compare commits

...
223 Commits
Author SHA1 Message Date
Dream Master 0ffe3048cb update 2025-07-29 14:31:37 +07:00
Alexdoru 69d1335aea Speedup ClassDiscoverer by using ClassReader.SKIP_CODE 2025-07-27 21:37:55 +02:00
Martin Robertz 850e2b9368 update 2025-05-29 22:09:14 +02:00
FalsePattern 4713f7aebd modern java compat (#31) 2025-05-29 19:26:51 +00:00
Jason Mitchell b999279656 More thread safe, again. (#30) 2025-05-04 08:08:02 +09:00
mts2200 1879ba2071 Improve NPE checks (#26) 2025-01-08 18:51:06 +00:00
Martin Robertz 9d600169ac update 2024-12-22 01:38:26 +01:00
charagarlnad 4e7eb37f3f use ZipFile instead of ZipInputStream in ClassDiscoverer (#25) 2024-12-20 15:18:04 +01:00
glowredman 22dfc1360e Allow colorful Tooltips (#24) 2024-11-13 06:47:10 +00:00
Maya 7bf5935f69 add issue templates 2024-11-11 04:15:39 -06:00
Alexdoru 162de447d5 Change ASM dump folder (#21)
* minor changes to RedirectorTransformer and class dumping

* don't print the stacktrace when failing to write class
2024-10-06 11:49:00 +00:00
Martin Robertz 39ed6607a6 update 2024-10-06 13:35:38 +02:00
Alexdoru 99b815c12e Reduce RAM allocations during rendering (#22)
* edit doc for fluid rendering method + clamp fillRate of the tank between 0 and 1

* init all static fields in the static block

* remove object instantiation that is never used in the following method and assign local variables

* reduce object allocation spam in CCModelLibrary.getRenderMatrix

* fix error in local V value

* remove all object instantiation during rendering to minimize RAM allocation in RenderUtils
2024-10-06 13:33:56 +02:00
Martin Robertz 0f37937ada update 2024-09-01 22:46:57 +02:00
Alexdoru c9d29a5c8e fix logic of the ClassConstantPoolParser (#20) 2024-09-01 22:19:33 +02:00
tth05 ea4f68d163 Add map to provide fast access to all config tags in sub-tree (#18) 2024-07-18 21:37:30 +07:00
Dream Master 549f769747 update 2024-07-17 16:47:04 +07:00
Caedis cba2e0f642 Fix casing 2024-07-04 00:30:22 -07:00
Jason Mitchell 3740253590 Maybe more backwards compatible (#16)
* Maybe more backwards compatible
2024-07-03 11:21:27 -07:00
Jason Mitchell 183e658bb4 merge CCL 2024-07-03 08:40:45 -07:00
Jason Mitchell acf5b9a2e7 Merge in CCL
git-subtree-dir: ccl
git-subtree-mainline: 7f78ceb921
git-subtree-split: ce1830d7b5
2024-07-03 08:22:26 -07:00
Jason Mitchell 7f78ceb921 Bye bye DepLoader 2024-07-01 12:33:39 -07:00
Raven Szewczyk ce1830d7b5 [ci skip] upgraded build system 2024-02-04 19:57:39 +00:00
Raven Szewczyk 4686fe8fa1 [ci skip] upgraded build system 2024-02-04 19:57:37 +00:00
Martin Robertz 4e743ba64b update bs 2024-01-11 23:15:32 +01:00
Martin Robertz c5b8594660 update bs+gitignore 2024-01-11 23:14:18 +01:00
Raven Szewczyk 87168007d7 [ci skip] upgraded build system 2024-01-08 21:24:44 +00:00
Raven Szewczyk 7b0ab21823 [ci skip] upgraded build system 2024-01-08 21:24:42 +00:00
Jason Mitchell dd1abf7ac4 Angelica Compat
Depends on https://github.com/GTNewHorizons/CodeChickenLib/pull/14
2023-12-24 10:31:02 -08:00
Jason Mitchell 14983449e8 Angelica Support - Static -> Instanced (#14)
Static -> Instanced
* Now significantly more thread safe
2023-12-24 10:07:13 -08:00
miozune e8dab57101 Fix incomplete patch for item id packet (#13) 2023-12-01 17:56:58 +09:00
bombcar 20b1e28074 update BS and spotlessApply (#11) 2023-11-29 22:14:41 +01:00
miozune d6e2b946b1 Fix ItemStack packet id limited by short 2023-11-30 00:57:02 +09:00
miozune 52d522f311 Fix wildcard import & spotlessApply 2023-11-30 00:57:02 +09:00
miozune c841d484ee updateBuildScript 2023-11-30 00:57:02 +09:00
unix-supremacist 3145cccd70 null check chunk extensions to not cause errors with chunk pregenerator (#11) 2023-02-08 22:07:50 +01:00
Jason Mitchell cc15e4cec6 Add Curse/Modrinth projects (#10) 2023-02-02 22:07:24 -08:00
Jason Mitchell fcb9063f2f Merge pull request #10 from GTNewHorizons/publish-cf-mn
Publish to CF & MN
2023-02-02 22:07:19 -08:00
Jason Mitchell 16883088a6 Publish to CF & MN 2023-02-02 19:20:03 -08:00
Raven Szewczyk f1034f699e [ci skip] upgraded build system 2023-01-31 09:51:54 +00:00
Raven Szewczyk 83f5eac8d8 [ci skip] upgraded build system 2023-01-31 09:51:52 +00:00
Raven Szewczyk 2cf7226306 Actually fix the broken version/modid this time 2023-01-30 11:50:18 +00:00
Raven Szewczyk 6273a1e71a Use version substitution in CCC mod container 2023-01-30 11:39:47 +00:00
Raven Szewczyk b52d844ed6 Release with RFG 2023-01-30 11:14:43 +00:00
Raven Szewczyk 331a5fcd3f [ci skip] Add git-blame-ignore-revs for spotlessApply 2023-01-30 11:13:51 +00:00
Raven Szewczyk 955a875d42 [ci skip] spotlessApply with the new settings 2023-01-30 11:13:51 +00:00
Raven Szewczyk b45ef7230d [ci skip] Update buildscript to RetroFuturaGradle 2023-01-30 11:13:50 +00:00
Raven Szewczyk de334d86f6 [ci skip] Fix addon.gradle for RFG 2023-01-30 11:13:42 +00:00
Raven Szewczyk 777235b7fb Release with RFG 2023-01-30 11:08:35 +00:00
Raven Szewczyk d183e6d9a9 [ci skip] Add git-blame-ignore-revs for spotlessApply 2023-01-30 10:33:49 +00:00
Raven Szewczyk a4515fbef8 [ci skip] spotlessApply with the new settings 2023-01-30 10:33:49 +00:00
Raven Szewczyk 318c107957 [ci skip] Update buildscript to RetroFuturaGradle 2023-01-30 10:33:45 +00:00
Martin Robertz fabf2af058 Merge pull request #8 from GTNewHorizons/rfg-mapping-path
Add GradleStart-injected property for obf mapping discovery
2023-01-12 06:23:59 +01:00
Raven Szewczyk f6102d56ec Add GradleStart-injected property for obf mapping discovery (for RFG compatibility) 2023-01-11 21:05:45 +00:00
Raven Szewczyk acdf6d754f Update buildscript (#9)
* Update buildscript

* Bump CCL
2023-01-05 12:09:05 +00:00
boubou19 9b42fa756f Merge pull request #7 from GTNewHorizons/buildscript
Update buildscript & apply spotless
2023-01-05 13:00:57 +01:00
Raven Szewczyk fa6fea6843 Apply spotless 2023-01-05 11:49:32 +00:00
Raven Szewczyk 8d95baccb5 Update buildscript 2023-01-05 11:49:10 +00:00
Glease 818b13551b remove @InterfaceDependancyTransformer (#8)
* remove @InterfaceDependancyTransformer

This is no longer used, and I want less class transformer in the LaunchClassLoader

* apply spotless
2022-08-31 16:31:23 +02:00
Martin Robertz 23327451a2 Merge pull request #6 from DrParadox7/master
Fix NPE
2022-08-30 21:58:04 +02:00
TechnoParadox b8a70cb09b Fix NPE
Fix NPE when CodeChhickenLib attempts to unload a chunk that is already null
2022-08-30 20:45:47 +02:00
Jason Mitchell fcd42c8496 [ci skip] Migrate github actions to GTNH-Actions-Workflows 2022-07-16 10:47:29 -07:00
Jason Mitchell cef8a9cbc0 [ci skip] Migrate github actions to GTNH-Actions-Workflows 2022-07-16 10:47:27 -07:00
Martin Robertz c84c6875a1 Merge pull request #5 from GTNewHorizons/no-dump-asm
Does not dump asm by default
2022-04-17 09:11:46 +02:00
MuXiu1997 1908388ce7 Does not dump asm by default 2022-04-16 14:39:07 +08:00
bombcar cd994ecd27 Fix memory check default on (#7)
* fix memory check

* update buildscripts

* spaces

* extra )
2022-02-17 19:11:06 +01:00
bombcar 817438ec82 Remove MCVersion warning (#6)
* buildscript

* fix hammer
2022-02-11 08:09:24 -08:00
bombcar 5423d96eb7 update build script (#4) 2022-02-01 13:47:00 -06:00
Jason Mitchell 1ee3abf0ff update dependencies 2022-01-17 20:23:27 -08:00
Jason Mitchell a37aeac535 maven publish buildscript update 2022-01-17 20:15:32 -08:00
Jason Mitchell 9adf1b6650 maven publish buildscript update 2022-01-17 20:13:53 -08:00
Jason Mitchell cfd00f33c8 maven publish buildscript update 2022-01-17 19:20:12 -08:00
Martin Robertz 883d46d86b Merge pull request #5 from GTNewHorizons/gtnhcheck
add an early low memory error to GTNH
2022-01-01 23:40:11 +01:00
bombcar 0fc1466f9c remove unused import 2022-01-01 01:50:58 -06:00
bombcar 352301c8ea use GB instead of GiB 2022-01-01 01:49:42 -06:00
bombcar 3adeff110f update exit code 2022-01-01 01:37:59 -06:00
bombcar 6aa549db9a typo 2021-12-31 22:41:20 -06:00
bombcar bd177ae0bc add an early low memory error to GTNH 2021-12-31 22:37:18 -06:00
Martin Robertz 6ff72337b7 Merge pull request #3 from GTNewHorizons/fixbuild
update buildscript
2021-12-23 23:23:12 +01:00
Martin Robertz 55ccf763b0 Merge pull request #4 from GTNewHorizons/fixbuild
fixbuild
2021-12-23 23:18:02 +01:00
bombcar 1cca8bba34 another System.out 2021-12-23 11:46:31 -06:00
bombcar 23a1fd9236 logger 2021-12-23 11:38:40 -06:00
bombcar 0d678abc10 developer 2021-12-22 07:46:39 -06:00
bombcar f9d8801644 fixbuild 2021-12-21 09:28:19 -06:00
bombcar 2e1fc1ece0 update buildscript 2021-12-21 08:23:33 -06:00
Glease 8933d4cf78 why main class is now a coremod wtf 2021-12-03 21:12:30 +08:00
Glease 35e8b9a956 this is not a mod but a lib 2021-12-03 13:56:09 +08:00
boubou19 2b7476f2e6 Merge pull request #2 from GTNewHorizons/update-build-script
Update build script and CI
2021-11-30 15:52:56 +01:00
Johann Bernhardt 19dc507599 Update build script and CI 2021-11-30 10:01:34 +01:00
Johann Bernhardt 263864ab82 Remove wrong logo entry 2021-11-23 19:02:11 +01:00
Johann Bernhardt 94630e0b2b Add missing core mod 2021-11-21 13:04:32 +01:00
Martin Robertz 53ac3d0ba7 Merge pull request #1 from SinTh0r4s/unified-build-script
Unified build script
2021-11-20 16:27:27 +01:00
Johann Bernhardt 8fe333ed86 Fix gitignore 2021-11-20 14:05:10 +01:00
Johann Bernhardt 0ac4906338 Updated to unified build script 2021-11-20 13:55:05 +01:00
Chicken-Bones cea80e20a2 Merge pull request #46 from planetguy32/1.7
Fix for 1.7.10 with latest Forge versions.
2015-07-15 14:32:05 +10:00
planetguy 2987b36bad Fix for 1.7.10 with latest Forge versions.
Forge now repeats the Minecraft version in the folder path. This commit
adds another guess that checks that folder for deobfuscation data.
2015-07-14 19:15:48 -07:00
Chicken-Bomes e9f9253875 Moved 1 file too many 2015-05-29 17:44:08 +10:00
Chicken-Bomes 05bd26eb87 Moved ExtendedContainer code from CCC 2015-05-29 17:32:27 +10:00
Chicken-Bomes 42b022af2a Add fontRenderer parameter to drawMultilineTip 2015-04-24 18:47:59 +10:00
Chicken-Bomes 16f0b50920 Fix GuiDraw.getStringWidth with bold formatting 2015-04-24 17:53:39 +10:00
Chicken-Bomes 65a89cc92c Fluid API update 2015-04-17 12:28:56 +10:00
Chicken-Bomes 6b5404f1c0 Add missing icon detection helper method 2015-01-29 10:34:39 +10:00
Chicken-Bomes d92b0a6a31 Potentially breaking change to InventoryRange constructor
Added some new methods to CuboidCoord
Removed unused methods from RayTracer
2015-01-16 18:33:29 +10:00
Chicken-Bomes ccc986f1d7 Fix ConcurrentModificationException in tile chunk load hook 2014-12-19 01:55:31 +10:00
Chicken-Bomes 29e4eda53b Added IChunkLoadTile 2014-12-17 23:39:43 +10:00
Chicken-Bomes feb8bfd028 Workaround some mod interactions not calling the world load event before world tick 2014-11-07 01:04:43 +10:00
Chicken-Bomes 4a40b215d5 Update tool ASM to 5.0.3
Add set(TileEntity) method to BlockCoord
Remove unused imports
2014-11-07 01:04:43 +10:00
Chicken-Bones e570e12e13 Merge pull request #27 from davboecki/master
Set ItemStack in the IInventory again after modifiing it.
2014-10-04 21:41:28 +10:00
davboecki 05d1e187f8 Set ItemStack in the IInventory again after modifiing 2014-10-04 13:00:55 +02:00
Chicken-Bomes 645919daa9 Added FullBlock side masked render function
Fixed bug with Vertex5 constructor not passing tex to UV
2014-08-29 02:29:30 +10:00
Chicken-Bomes f9287f696b Replaced reflective invokation of private super method with copy of mojang code 2014-08-19 00:08:19 +10:00
Chicken-Bomes 38744413af Fixed anisotropic filtering with TextureFX 2014-08-15 19:19:48 +10:00
Chicken-Bomes 71f3c55d9d Add mipmaps to animated TextureFX 2014-08-15 16:40:29 +10:00
Chicken-Bomes f50b326d92 Added lightmap push function to CCRenderState 2014-08-15 14:48:15 +10:00
Chicken-Bomes 3b081ed3cd Keep class references of config package within config so it can be used at the ASM level
Add simple extensible config serialisation
2014-08-05 18:00:41 +10:00
Chicken-Bomes 76a6c9e7d5 Add lang proxy 2014-07-27 22:32:27 +10:00
Chicken-Bomes 0ba1132ff6 Add parameterised mouse point rescaling helper for events 2014-07-25 00:32:36 +10:00
Chicken-Bomes 9411dd0808 Added SimpleBrightnessModel for rendering 'solid' blocks 2014-07-11 15:18:05 +10:00
Chicken-Bomes 4b16ef2776 Fix texture not found exceptions in console when using placeholder texture 2014-07-10 01:17:37 +10:00
Chicken-Bomes 23a58af62a Fix isObfuscated check returning false on obf names as opposed to srg names 2014-07-03 21:11:02 +10:00
Chicken-Bomes f753dcdeb8 Add log4j libs 2014-07-03 01:38:09 +10:00
Chicken-Bomes 18461348e3 Fix crash with tool system when loading ASMHelper 2014-07-03 01:26:02 +10:00
Chicken-Bomes e7c670b1d3 Bound tooltips to screen properly 2014-06-29 14:28:15 +10:00
Chicken-Bomes ba15e4b116 Added informative exception when attempting to register a channel using a modID > 20 characters 2014-06-29 14:27:19 +10:00
Chicken-Bomes 93b1e5dbf0 1.7.10 2014-06-27 15:09:32 +10:00
Chicken-Bones bdb0c8f174 Merge pull request #20 from MrTJP/patch-1
Light attribute should not depend on colour
2014-06-16 10:12:12 +10:00
MrTJP 1680d74d6d Light attribute should not depend on colour
Light attribute makes sure that we have color, but at the time of check, hasColour is false, because nothing has operated yet. We want to check the context flag instead. (We could just not check this color flag at all, and leave the two actually 'separate')
2014-06-15 11:26:19 -04:00
Chicken-Bomes 09bf91715b Seperate colour and lighting a bit. Made baking colours easier and the distinction between dynamic and static rendering easier to manage.
Fixed invalid u coords in generateBlock
2014-06-15 02:07:20 +10:00
Chicken-Bomes 97cb16586a Consistency :L 2014-06-15 00:47:00 +10:00
Chicken-Bomes 29ef6904f0 Fix loophole with model colour attribute in CCRenderState 2014-06-15 00:43:20 +10:00
Chicken-Bomes 0529baaf23 Add setBaseColour function for clarity 2014-06-15 00:27:56 +10:00
Chicken-Bomes 3bde4ab9ee Remove broken render() function in CCModel, made CCRenderState.startDrawing(int) public again 2014-06-15 00:24:18 +10:00
Chicken-Bomes 5c54b184ea Fix inconsistent use of var ints in fluid packets 2014-06-15 00:23:40 +10:00
Chicken-Bomes 307ca81694 Add meaningful exception text to CustomGradient when resource not found 2014-06-15 00:23:00 +10:00
Chicken-Bomes 66015a13c5 Added toString to BlockCoord 2014-06-15 00:21:50 +10:00
Chicken-Bomes 6d19cc0079 Fix colour not being set when a colour multiplier with white was added 2014-06-15 00:21:31 +10:00
Chicken-Bomes 8386a982a2 Fixed IndexOutOfBoundsException with CCRenderState.copyOf 2014-05-23 14:33:17 +10:00
Chicken-Bomes f1153412c1 Remove unused import 2014-05-09 09:25:47 +10:00
Chicken-Bomes 215715f7c5 Added full block model and planar light matrix
Added set function to Rectangle4i
2014-05-09 09:23:58 +10:00
Chicken-Bomes 408e45ef25 Bump patch version 2014-05-08 14:06:12 +10:00
Chicken-Bomes f9fea33b5e Fix encoding inconsistency with writeString between PacketCustom and MCDataOutputStreamWrapper
Refactored -> MCDataOutput -> MCDataOutputStream
2014-05-08 14:04:37 +10:00
Chicken-Bomes 47d7c667de Fix issue with double checking slots for fitting stacks in simulate mode 2014-05-01 00:24:23 +10:00
Chicken-Bomes 66fd8ad103 Reduce classloading remapping to minecraft classes. Everything else should be srg. 2014-04-29 13:15:49 +10:00
Chicken-Bomes 1f03959a99 Fix ClassCircularityError with config package being used by asm package 2014-04-29 11:42:02 +10:00
Chicken-Bomes 52f82017e7 Upgraded ASM lib 2014-04-28 19:40:13 +10:00
Chicken-Bomes 0a14b64e12 Cleaned up directory layout 2014-04-11 08:30:40 +10:00
Chicken-Bomes 32fa471c44 Fix compression crash 2014-04-10 18:37:39 +10:00
Chicken-Bones c3dcc42a65 Merge pull request #16 from progwml6/master
fix issue under linux
2014-04-09 19:21:34 +10:00
Progwml6 12e3060669 fix issue under linux 2014-04-09 00:04:36 -04:00
Chicken-Bomes 2d9f409c7d Organised imports 2014-04-09 13:38:05 +10:00
Chicken-Bomes 41997e15e9 Replace private minecraft accesses with alternatives until transformers are accepted by forge. 2014-04-09 13:20:40 +10:00
Chicken-Bones d910584217 Merge pull request #15 from progwml6/master
fix some issues with 1.7
2014-04-09 11:54:58 +10:00
Progwml6 4e87c9bfe7 make gradle play nice w/ files in the repo root 2014-04-08 03:54:33 -04:00
Soaryn 91c65cf1dc Fixes access to TextureUtil.uploadTextureSub
Since TextureUtil.uploadTextureMipmap is private, I used the next available function which does the same thing with a needless for loop in our case. It, however, is public static
:)
2014-04-08 03:18:16 -04:00
Chicken-Bomes 4699a9e86e Add MCP mapper for ObfMapping in dev environments from a fields/methods.csv conf directory 2014-04-07 23:13:48 +10:00
Chicken-Bones f56ba57d3a Merge pull request #14 from progwml6/master
Add in gradle build system
2014-04-07 17:21:48 +10:00
Progwml6 4babca7004 remove files from old build system, update version #, manifest now via gradle 2014-04-07 02:01:46 -04:00
Progwml6 99865de255 added gradle build script & other things needed to build 2014-04-07 01:57:55 -04:00
Chicken-Bomes 0a5aee875b Update version numbers 2014-04-07 14:04:01 +10:00
Chicken-Bomes ca675b5f31 Initial 1.7 commit 2014-04-07 14:02:47 +10:00
Chicken-Bomes 34154fc011 Add spin parameter to RenderUtils.renderItemUniform 2014-02-23 15:43:35 +10:00
Chicken-Bomes 23b79b7b15 Added a more intuitive renderFluidQuad function with doc 2014-02-13 15:50:23 +10:00
Chicken-Bomes e274d1c512 Added a few methods to CuboidCoord 2014-02-11 19:56:02 +10:00
Chicken-Bomes eac0727165 Strip obfuscated references in tool mode 2014-02-03 11:14:54 +10:00
Chicken-Bomes ae652f51c2 Added command line tool frontend. 2014-02-03 11:02:42 +10:00
Chicken-Bomes 7450370d99 Added support for Qubicle Model files. 2014-01-28 16:54:30 +10:00
Chicken-Bomes 477b77e7e1 Added 9Seg Canvas 2014-01-15 17:41:27 +10:00
Chicken-Bomes 5401f3afb0 Improved ASMReader parsing. Can now handle method/field instructions with spaces in the description
Added equals method to colour
2014-01-09 02:55:11 +10:00
Chicken-Bomes eb6f5e5e7b Fix compile time compatibility with new and old forge 2013-12-21 23:43:28 +10:00
Chicken-Bomes ffc284349e Added some more utility to Cuboid/Rotation 2013-12-21 23:02:51 +10:00
Chicken-Bomes 3c81313a8c Added temporary fix for issues with new mcp system. 2013-12-21 23:01:53 +10:00
Chicken-Bomes 3d64337681 Cleaned, refactored and documented inventory package 2013-12-21 23:01:20 +10:00
Chicken-Bomes 6a8a453496 Added general inventory management classes 2013-12-18 12:25:28 +10:00
Chicken-Bomes 16d43f287d Added a few more set methods to (Block/Cuboid)Coord 2013-12-18 12:25:04 +10:00
Chicken-Bomes 9e6ac47eba Added scala operator overloading to Vector3 and Transformation 2013-12-17 14:51:20 +10:00
Chicken-Bomes 8a777b265e Add intersects method to Rectangle4i
Added compare methods to MathHelper
2013-12-11 17:34:04 +10:00
Chicken-Bomes 699221214c Made a small change to RayTracer to potentially add support for eye-height changing mods. 2013-11-21 12:49:26 +10:00
Chicken-Bones 3e65888097 Merge pull request #4 from Soaryn/patch-1
Accessors for particleMaxAge
2013-10-31 19:11:03 -07:00
Soaryn 6233c2f6ca Accessors for particleMaxAge
Allows access to the maxAge for "copied" layers to behave for the same duration.
2013-10-31 17:13:18 -04:00
Chicken-Bomes dd297d6e42 Fix RayTracer with non EntityPlayerMP instances on server worlds. 2013-10-30 12:23:03 +10:00
Chicken-Bomes a7637ca787 Changed RayTracer.getCorrectedHeadVec to use a sneaking offset relative to getEyeHeight() in SMP. Should fix compatibility with eye-height changing mods. 2013-10-30 11:52:52 +10:00
Chicken-Bones a315c0059e Merge pull request #3 from Soaryn/patch-1
Adds getter and setter for Dig FX particleScale
2013-10-12 18:53:50 -07:00
Soaryn ddadd1f831 Adds getter and setter for Dig FX particleScale
A copy method may be better for this, in the end this will allow for "layered" textures to work properly when breaking a block
2013-10-12 19:18:08 -04:00
Chicken Bones 112c0abc08 Wrapped fluid rendering with safeIcon method. 2013-10-02 12:21:43 +10:00
Chicken Bones 3b762d300f Added setSide function to Cuboid6 2013-10-01 11:58:04 +10:00
Chicken Bones ab0713c129 Added side function to Cuboid6 2013-10-01 11:54:47 +10:00
Chicken Bones b1057544a7 Remove all deprecated content 2013-09-22 14:23:08 +10:00
Chicken Bones 1b71ee5e3d 1.6.4 Update 2013-09-22 13:02:08 +10:00
Chicken Bones bd3234b033 Added missing overload for CCModel.generateBlock 2013-09-20 17:17:39 +10:00
Chicken Bones cdb52bf72a Update to 1.6.3 2013-09-19 12:24:27 +10:00
Chicken Bones d889cf9cbc Added some SideOnly annotations to LangUtil 2013-09-18 23:17:26 +10:00
Chicken Bones f5bbe9d2da Optimised render transformations.
Added documentation to ExtendedMOP.dist
Added expand function to CCModel.
2013-09-10 18:22:44 +10:00
Chicken Bones 6a29a2428f Added easier backface generation. 2013-09-09 08:29:10 +10:00
Chicken Bones ea515682c1 Improved transformation compacting. 2013-09-05 17:41:31 +10:00
Chicken Bones 5c5384f79c Update Forge Mappings. 2013-09-04 13:56:47 +10:00
Chicken Bones c67c731647 Extend MOP for RayTracer depth sorting. 2013-09-04 13:05:24 +10:00
Chicken Bones c545683025 Added a few functions to BlockCoord
Made RedundantTransformation more redundant
2013-09-04 12:51:37 +10:00
Chicken Bones 5ef9f6174d Add transformation compacting. 2013-08-29 11:10:33 +10:00
Chicken Bones 0941845227 Simplify MultiIconTransformation constructor with vaargs 2013-08-27 15:27:10 +10:00
Chicken Bones 9601c27e9d Add some TransformationList compacting. 2013-08-23 17:49:00 +10:00
Chicken Bones a580ca90a9 Add standard planar light model 2013-08-23 17:30:37 +10:00
Chicken Bones 2636721bec Added mask to CCModel.generateBlock
Fixed misleading variable name in MultiIconTransformation.setIconIndex
2013-08-21 23:32:16 +10:00
Chicken Bones 3d4e112552 Refactored generateRotatedPart to apply 2013-08-15 22:02:58 +10:00
Chicken Bones 575ec57050 Added apply methods to some common Vector containers
Added ColourMultiplier vertex modifier.
2013-08-12 13:30:54 +10:00
Chicken Bones 4bd5aab59a Fixed packet compression and splitting on TCP connections. 2013-08-08 19:16:06 +10:00
Chicken Bones 7f42cd94e0 Acquire NetClientHandler for packets sent before the Player and World are established. 2013-08-05 08:23:26 +10:00
Chicken Bones 56776c8149 Fix NPE in RayTracer when tracing a null block. 2013-08-02 12:02:01 +10:00
Chicken Bones 5184abc23c Made alpha a power function of density for gases to produce better visuals for low densities. 2013-08-02 02:04:19 +10:00
Chicken Bones b16ad2115b Added RenderUtils.renderLiquidGauge 2013-08-02 01:21:08 +10:00
Chicken Bones 15d0edcafb Amend typo 2013-07-31 13:30:01 +10:00
Chicken Bones a1433ba4d4 Added set function to Colour 2013-07-31 13:28:35 +10:00
Chicken Bones 57bcf384d1 Fixed uv mappings for some sides in CCModel.generateBlock 2013-07-31 11:10:44 +10:00
Chicken Bones 16704eb601 changed drawOutlinedBoundingBox to drawCuboidOutline accepting Cuboid6
Added expand function to Cuboid6
Renamed transform to apply on Cuboid6
2013-07-30 16:17:40 +10:00
Chicken Bones d6f14e9ab1 Optimised ClassHeirachyManager 2013-07-29 22:53:29 +10:00
Chicken Bones 36e6c64b66 Fixed class heirachy evaluation getting confused with obfuscation. 2013-07-23 16:04:41 +10:00
Chicken Bones a003f2638d Refactored readUnsigned<x> to readU<x> 2013-07-22 19:10:53 +10:00
Chicken Bones fed626df0b Added safeguard to WorldExtensionManager.saveWorld for when someone force closes the client.
Made config files save themselves on tag remove
Removed ' ' -> '_' mapping in config file keys
2013-07-22 15:12:29 +10:00
Chicken Bones 8518ed3bb0 A little cleanup, added glColour to CCRenderState 2013-07-21 22:44:12 +10:00
Chicken Bones a2d3051270 Fix for fields maps without descriptors. 2013-07-19 03:11:36 +10:00
Chicken Bones 9341031e7f Added LangUtil for localisations 2013-07-19 01:00:09 +10:00
Chicken Bones 3c5a61e011 Fixed a few mapping bugs
Added version files
2013-07-17 18:18:57 +10:00
Chicken Bones 0f32dd8620 Initial Commit 2013-07-16 17:58:02 +10:00
Chicken-Bones 397135f687 Initial commit 2013-07-15 21:56:12 -07:00
199 changed files with 17300 additions and 3458 deletions

No files matched your search

+19
View File
@@ -0,0 +1,19 @@
# This is the universal Text Editor Configuration
# for all GTNewHorizons projects
# See: https://editorconfig.org/
root = true
[*]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
[*.{bat,ini}]
end_of_line = crlf
[*.{dtd,json,info,mcmeta,md,sh,svg,xml,xsd,xsl,yaml,yml}]
indent_size = 2
+2
View File
@@ -0,0 +1,2 @@
# Ignore spotlessApply reformat
955a875d42bd8f725d389ef8c4f571824f2ae0c8
+44
View File
@@ -0,0 +1,44 @@
* text eol=lf
*.[jJ][aA][rR] binary
*.[pP][nN][gG] binary
*.[jJ][pP][gG] binary
*.[jJ][pP][eE][gG] binary
*.[gG][iI][fF] binary
*.[tT][iI][fF] binary
*.[tT][iI][fF][fF] binary
*.[iI][cC][oO] binary
*.[sS][vV][gG] text
*.[eE][pP][sS] binary
*.[xX][cC][fF] binary
*.[kK][aA][rR] binary
*.[mM]4[aA] binary
*.[mM][iI][dD] binary
*.[mM][iI][dD][iI] binary
*.[mM][pP]3 binary
*.[oO][gG][gG] binary
*.[rR][aA] binary
*.7[zZ] binary
*.[gG][zZ] binary
*.[tT][aA][rR] binary
*.[tT][gG][zZ] binary
*.[zZ][iI][pP] binary
*.[tT][cC][nN] binary
*.[sS][oO] binary
*.[dD][lL][lL] binary
*.[dD][yY][lL][iI][bB] binary
*.[pP][sS][dD] binary
*.[tT][tT][fF] binary
*.[oO][tT][fF] binary
*.[pP][aA][tT][cC][hH] -text
*.[bB][aA][tT] text eol=crlf
*.[cC][mM][dD] text eol=crlf
*.[pP][sS]1 text eol=crlf
*[aA][uU][tT][oO][gG][eE][nN][eE][rR][aA][tT][eE][dD]* binary
+62
View File
@@ -0,0 +1,62 @@
name: Report Bug
description: "Report a bug."
body:
- type: markdown
attributes:
value: "A bug/crash report with sufficient information and logs to reproduce and track down."
- type: input
id: discord
attributes:
label: Your GTNH Discord Username
description: Leave empty if you don't have one, but this will make it harder to contact you if we need additional info.
placeholder: "Example: Fake#1234"
- type: input
id: version
attributes:
label: Mod Version
description: "What version of the Mod are you using?"
placeholder: "Example: 1.0.0"
validations:
required: true
- type: textarea
id: report
attributes:
label: Bug Report
description: "Relevant information, as well as relevant logs attached such as `logs/fml-client-latest.log."
placeholder: "Example: https://mclo.gs/ OR submit the file to github by dragging it to this textbox."
validations:
required: true
- type: dropdown
id: java
attributes:
label: Java Version
description: What Java version are you using? It's worth mentioning that if you play on Java9+ you should try update to latest minor release (e.g. prefer Java 17.0.6 over 17.0.2) of that version.
options:
- Java 8
- Java 9
- Java 11
- Java 17
- Java 19
- Java 20
- Java 21
- Other (Please Specify)
validations:
required: true
- type: textarea
id: modlist
attributes:
label: Mod List or GTNH Pack Version
description: "List of mods, ideally a minimal reproducible set (can be retrieved from latest.log). If using GTNH please indicate pack version and any changed mods, not the entire modlist."
placeholder: "List of mods or GTNH Pack version goes here"
validations:
required: true
- type: checkboxes
id: final
attributes:
label: Final Checklist
description: Certify that you read things
options:
- label: "I have searched the issues and haven't found a similar issue."
required: true
@@ -0,0 +1,28 @@
name: Feature Request
description: "Request a feature."
body:
- type: markdown
attributes:
value: "Please use this form to request features. We ask you check if it was already requested though"
- type: input
id: discord
attributes:
label: Your GTNH Discord Username
description: Leave empty if you don't have one, but this will make it harder to contact you if we need additional info.
placeholder: "Example: Wumpus#1234"
- type: textarea
id: request
attributes:
label: Feature Request
description: "Relevant information, as well as relevant images"
placeholder: "Example: https://mclo.gs/ OR submit the file to github by dragging it to this textbox."
validations:
required: true
- type: checkboxes
id: final
attributes:
label: Final Checklist
description: Certify that you read things
options:
- label: "I have searched the issues and haven't found a similar issue."
required: true
-9
View File
@@ -1,9 +0,0 @@
directory="run/crash-reports"
if [ -d $directory ]; then
echo "Crash reports detected:"
cat $directory/*
exit 1
else
echo "No crash reports detected"
exit 0
fi
+51
View File
@@ -0,0 +1,51 @@
#!/usr/bin/env bash
# bashsupport disable=BP5006 # Global environment variables
RUNDIR="run" \
CRASH="crash-reports" \
SERVERLOG="server.log"
# enable nullglob to get 0 results when no match rather than the pattern
shopt -s nullglob
# store matches in array
crash_reports=("$RUNDIR/$CRASH/crash"*.txt)
# if array not empty there are crash_reports
if [ "${#crash_reports[@]}" -gt 0 ]; then
# get the latest crash_report from array
latest_crash_report="${crash_reports[-1]}"
{
printf 'Latest crash report detected %s:\n' "${latest_crash_report##*/}"
cat "$latest_crash_report"
} >&2
exit 1
fi
if grep --quiet --fixed-strings 'Fatal errors were detected' "$SERVERLOG"; then
{
printf 'Fatal errors detected:\n'
cat server.log
} >&2
exit 1
fi
if grep --quiet --fixed-strings 'The state engine was in incorrect state ERRORED and forced into state SERVER_STOPPED' \
"$SERVERLOG"; then
{
printf 'Server force stopped:'
cat server.log
} >&2
exit 1
fi
if ! grep --quiet --perl-regexp --only-matching '.+Done \(.+\)\! For help, type "help" or "\?"' "$SERVERLOG"; then
{
printf 'Server did not finish startup:'
cat server.log
} >&2
exit 1
fi
printf 'No crash reports detected'
exit 0
+2 -34
View File
@@ -1,5 +1,3 @@
# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle
name: Build and test
@@ -11,35 +9,5 @@ on:
jobs:
build-and-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Set up JDK 8
uses: actions/setup-java@v2
with:
java-version: '8'
distribution: 'adopt'
cache: gradle
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Setup the workspace
run: ./gradlew setupCIWorkspace
- name: Build the mod
run: ./gradlew build
- name: Run server for 1 minute
run: |
mkdir run
echo "eula=true" > run/eula.txt
timeout 10 ./gradlew runServer || true
- name: Test no crashes happend
run: |
chmod +x .github/scripts/test-no-crash-reports.sh
.github/scripts/test-no-crash-reports.sh
uses: GTNewHorizons/GTNH-Actions-Workflows/.github/workflows/build-and-test.yml@master
secrets: inherit
+7 -38
View File
@@ -1,45 +1,14 @@
# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle
name: Release tagged build
on:
push:
tags:
- '*'
tags: [ '*' ]
permissions:
contents: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Set release version
run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
- name: Set up JDK 8
uses: actions/setup-java@v2
with:
java-version: '8'
distribution: 'adopt'
cache: gradle
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Setup the workspace
run: ./gradlew setupCIWorkspace
- name: Build the mod
run: ./gradlew build
- name: Release under current tag
uses: "marvinpinto/action-automatic-releases@latest"
with:
repo_token: "${{ secrets.GITHUB_TOKEN }}"
automatic_release_tag: "${{ env.RELEASE_VERSION }}"
prerelease: false
title: "${{ env.RELEASE_VERSION }}"
files: build/libs/*.jar
release-tags:
uses: GTNewHorizons/GTNH-Actions-Workflows/.github/workflows/release-tags.yml@master
secrets: inherit
+1
View File
@@ -26,3 +26,4 @@ whitelist.json
*.ipr
*.iws
src/main/resources/mixins.*.json
*.bat
+3
View File
@@ -0,0 +1,3 @@
# Any Github changes require admin approval
/.github/** @GTNewHorizons/admin
+3 -3
View File
@@ -1,8 +1,8 @@
minecraft {
if (replaceGradleTokenInFile) {
replaceIn "CodeChickenCorePlugin.java"
tagReplacementFiles.add "CodeChickenCorePlugin.java"
if(gradleTokenVersion) {
replace gradleTokenVersion, versionDetails().lastTag
injectedTags.put gradleTokenVersion, versionDetails().lastTag
}
}
}
}
+2 -526
View File
@@ -1,529 +1,5 @@
//version: 928ecf7feb33a1149538b0e2cd17e3bc5f281428
/*
DO NOT CHANGE THIS FILE!
Also, you may replace this file at any time if there is an update available.
Please check https://github.com/SinTh0r4s/ExampleMod1.7.10/blob/main/build.gradle for updates.
*/
import com.github.jengelman.gradle.plugins.shadow.tasks.ConfigureShadowRelocation
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import java.util.concurrent.TimeUnit
buildscript {
repositories {
maven {
name = "forge"
url = "https://maven.minecraftforge.net"
}
maven {
name = "sonatype"
url = "https://oss.sonatype.org/content/repositories/snapshots/"
}
maven {
name = "Scala CI dependencies"
url = "https://repo1.maven.org/maven2/"
}
maven {
name = "jitpack"
url = "https://jitpack.io"
}
}
dependencies {
classpath 'com.github.GTNewHorizons:ForgeGradle:1.2.4'
}
}
//version: 1707058017
plugins {
id 'idea'
id 'scala'
id("org.ajoberstar.grgit") version("3.1.1")
id("com.github.johnrengelman.shadow") version("4.0.4")
id("com.palantir.git-version") version("0.12.3")
}
apply plugin: 'forge'
def projectJavaVersion = JavaLanguageVersion.of(8)
java {
toolchain {
languageVersion.set(projectJavaVersion)
}
}
idea {
module {
inheritOutputDirs = true
downloadJavadoc = true
downloadSources = true
}
}
if(JavaVersion.current() != JavaVersion.VERSION_1_8) {
throw new GradleException("This project requires Java 8, but it's running on " + JavaVersion.current())
}
checkPropertyExists("modName")
checkPropertyExists("modId")
checkPropertyExists("modGroup")
checkPropertyExists("autoUpdateBuildScript")
checkPropertyExists("minecraftVersion")
checkPropertyExists("forgeVersion")
checkPropertyExists("replaceGradleTokenInFile")
checkPropertyExists("gradleTokenModId")
checkPropertyExists("gradleTokenModName")
checkPropertyExists("gradleTokenVersion")
checkPropertyExists("gradleTokenGroupName")
checkPropertyExists("apiPackage")
checkPropertyExists("accessTransformersFile")
checkPropertyExists("usesMixins")
checkPropertyExists("mixinPlugin")
checkPropertyExists("mixinsPackage")
checkPropertyExists("coreModClass")
checkPropertyExists("containsMixinsAndOrCoreModOnly")
checkPropertyExists("usesShadowedDependencies")
checkPropertyExists("developmentEnvironmentUserName")
String javaSourceDir = "src/main/java/"
String scalaSourceDir = "src/main/scala/"
String targetPackageJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/")
String targetPackageScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/")
if((getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists()) == false) {
throw new GradleException("Could not resolve \"modGroup\"! Could not find " + targetPackageJava + " or " + targetPackageScala)
}
if(apiPackage) {
targetPackageJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/")
targetPackageScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/")
if((getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists()) == false) {
throw new GradleException("Could not resolve \"apiPackage\"! Could not find " + targetPackageJava + " or " + targetPackageScala)
}
}
if(accessTransformersFile) {
String targetFile = "src/main/resources/META-INF/" + accessTransformersFile
if(getFile(targetFile).exists() == false) {
throw new GradleException("Could not resolve \"accessTransformersFile\"! Could not find " + targetFile)
}
}
if(usesMixins.toBoolean()) {
if(mixinsPackage.isEmpty() || mixinPlugin.isEmpty()) {
throw new GradleException("\"mixinPlugin\" requires \"mixinsPackage\" and \"mixinPlugin\" to be set!")
}
targetPackageJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinsPackage.toString().replaceAll("\\.", "/")
targetPackageScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinsPackage.toString().replaceAll("\\.", "/")
if((getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists()) == false) {
throw new GradleException("Could not resolve \"mixinsPackage\"! Could not find " + targetPackageJava + " or " + targetPackageScala)
}
String targetFileJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".java"
String targetFileScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".scala"
String targetFileScalaJava = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".java"
if((getFile(targetFileJava).exists() || getFile(targetFileScala).exists() || getFile(targetFileScalaJava).exists()) == false) {
throw new GradleException("Could not resolve \"mixinPlugin\"! Could not find " + targetFileJava + " or " + targetFileScala + " or " + targetFileScalaJava)
}
}
if(coreModClass) {
String targetFileJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".java"
String targetFileScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".scala"
String targetFileScalaJava = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".java"
if((getFile(targetFileJava).exists() || getFile(targetFileScala).exists() || getFile(targetFileScalaJava).exists()) == false) {
throw new GradleException("Could not resolve \"coreModClass\"! Could not find " + targetFileJava + " or " + targetFileScala + " or " + targetFileScalaJava)
}
}
configurations.all {
resolutionStrategy.cacheChangingModulesFor(0, TimeUnit.SECONDS)
// Make sure GregTech build won't time out
System.setProperty("org.gradle.internal.http.connectionTimeout", 120000 as String)
System.setProperty("org.gradle.internal.http.socketTimeout", 120000 as String)
}
// Fix Jenkins' Git: chmod a file should not be detected as a change and append a '.dirty' to the version
'git config core.fileMode false'.execute()
// Pulls version from git tag
try {
version = minecraftVersion + "-" + gitVersion()
}
catch (Exception e) {
throw new IllegalStateException("This mod must be version controlled by Git AND the repository must provide at least one tag!");
}
group = modGroup
if(project.hasProperty("customArchiveBaseName") && customArchiveBaseName) {
archivesBaseName = customArchiveBaseName
}
else {
archivesBaseName = modId
}
minecraft {
version = minecraftVersion + "-" + forgeVersion + "-" + minecraftVersion
runDir = "run"
if (replaceGradleTokenInFile) {
replaceIn replaceGradleTokenInFile
if(gradleTokenModId) {
replace gradleTokenModId, modId
}
if(gradleTokenModName) {
replace gradleTokenModName, modName
}
if(gradleTokenVersion) {
replace gradleTokenVersion, versionDetails().lastTag
}
if(gradleTokenGroupName) {
replace gradleTokenGroupName, modGroup
}
}
}
if(file("addon.gradle").exists()) {
apply from: "addon.gradle"
}
apply from: 'repositories.gradle'
configurations {
implementation.extendsFrom(shadowImplementation)
}
repositories {
maven {
name = "Overmind forge repo mirror"
url = "https://gregtech.overminddl1.com/"
}
if(usesMixins.toBoolean()) {
maven {
name = "sponge"
url = "https://repo.spongepowered.org/repository/maven-public"
}
maven {
url = "https://jitpack.io"
}
}
}
dependencies {
if(usesMixins.toBoolean()) {
annotationProcessor("org.ow2.asm:asm-debug-all:5.0.3")
annotationProcessor("com.google.guava:guava:24.1.1-jre")
annotationProcessor("com.google.code.gson:gson:2.8.6")
annotationProcessor("org.spongepowered:mixin:0.8-SNAPSHOT")
// using 0.8 to workaround a issue in 0.7 which fails mixin application
compile("org.spongepowered:mixin:0.7.11-SNAPSHOT") {
// Mixin includes a lot of dependencies that are too up-to-date
exclude module: "launchwrapper"
exclude module: "guava"
exclude module: "gson"
exclude module: "commons-io"
exclude module: "log4j-core"
}
compile("com.github.GTNewHorizons:SpongeMixins:1.3.3:dev")
}
}
apply from: 'dependencies.gradle'
def mixingConfigRefMap = "mixins." + modId + ".refmap.json"
def refMap = "${tasks.compileJava.temporaryDir}" + File.separator + mixingConfigRefMap
def mixinSrg = "${tasks.reobf.temporaryDir}" + File.separator + "mixins.srg"
task generateAssets {
if(usesMixins.toBoolean()) {
getFile("/src/main/resources/mixins." + modId + ".json").text = """{
"required": true,
"minVersion": "0.7.11",
"package": "${modGroup}.${mixinsPackage}",
"plugin": "${modGroup}.${mixinPlugin}",
"refmap": "${mixingConfigRefMap}",
"target": "@env(DEFAULT)",
"compatibilityLevel": "JAVA_8"
}
"""
}
}
task relocateShadowJar(type: ConfigureShadowRelocation) {
target = tasks.shadowJar
prefix = modGroup + ".shadow"
}
shadowJar {
manifest {
attributes(getManifestAttributes())
}
minimize() // This will only allow shading for actually used classes
configurations = [project.configurations.shadowImplementation]
dependsOn(relocateShadowJar)
}
jar {
manifest {
attributes(getManifestAttributes())
}
if(usesShadowedDependencies.toBoolean()) {
dependsOn(shadowJar)
enabled = false
}
}
reobf {
if(usesMixins.toBoolean()) {
addExtraSrgFile mixinSrg
}
}
afterEvaluate {
if(usesMixins.toBoolean()) {
tasks.compileJava {
options.compilerArgs += [
"-AreobfSrgFile=${tasks.reobf.srg}",
"-AoutSrgFile=${mixinSrg}",
"-AoutRefMapFile=${refMap}",
// Elan: from what I understand they are just some linter configs so you get some warning on how to properly code
"-XDenableSunApiLintControl",
"-XDignore.symbol.file"
]
}
}
}
runClient {
def arguments = []
if(usesMixins.toBoolean()) {
arguments += [
"--mods=../build/libs/$modId-${version}.jar",
"--tweakClass org.spongepowered.asm.launch.MixinTweaker"
]
}
if(developmentEnvironmentUserName) {
arguments += [
"--username",
developmentEnvironmentUserName
]
}
args(arguments)
}
runServer {
def arguments = []
if (usesMixins.toBoolean()) {
arguments += [
"--mods=../build/libs/$modId-${version}.jar",
"--tweakClass org.spongepowered.asm.launch.MixinTweaker"
]
}
args(arguments)
}
tasks.withType(JavaExec).configureEach {
javaLauncher.set(
javaToolchains.launcherFor {
languageVersion = projectJavaVersion
}
)
}
processResources
{
// this will ensure that this task is redone when the versions change.
inputs.property "version", project.version
inputs.property "mcversion", project.minecraft.version
// replace stuff in mcmod.info, nothing else
from(sourceSets.main.resources.srcDirs) {
include 'mcmod.info'
// replace version and mcversion
expand "minecraftVersion": project.minecraft.version,
"modVersion": versionDetails().lastTag,
"modId": modId,
"modName": modName
}
if(usesMixins.toBoolean()) {
from refMap
}
// copy everything else, thats not the mcmod.info
from(sourceSets.main.resources.srcDirs) {
exclude 'mcmod.info'
}
}
def getManifestAttributes() {
def manifestAttributes = [:]
if(containsMixinsAndOrCoreModOnly.toBoolean() == false && (usesMixins.toBoolean() || coreModClass)) {
manifestAttributes += ["FMLCorePluginContainsFMLMod": true]
}
if(accessTransformersFile) {
manifestAttributes += ["FMLAT" : accessTransformersFile.toString()]
}
if(coreModClass) {
manifestAttributes += ["FMLCorePlugin": modGroup + "." + coreModClass]
}
if(usesMixins.toBoolean()) {
manifestAttributes += [
"TweakClass" : "org.spongepowered.asm.launch.MixinTweaker",
"MixinConfigs" : "mixins." + modId + ".json",
"ForceLoadAsMod" : containsMixinsAndOrCoreModOnly.toBoolean() == false
]
}
return manifestAttributes
}
task sourcesJar(type: Jar) {
from (sourceSets.main.allJava)
from (file("$projectDir/LICENSE"))
getArchiveClassifier().set('sources')
}
task shadowDevJar(type: ShadowJar) {
from sourceSets.main.output
getArchiveClassifier().set("dev")
manifest {
attributes(getManifestAttributes())
}
minimize() // This will only allow shading for actually used classes
configurations = [project.configurations.shadowImplementation]
}
task relocateShadowDevJar(type: ConfigureShadowRelocation) {
target = tasks.shadowDevJar
prefix = modGroup + ".shadow"
}
task circularResolverJar(type: Jar) {
dependsOn(relocateShadowDevJar)
dependsOn(shadowDevJar)
enabled = false
}
task devJar(type: Jar) {
from sourceSets.main.output
getArchiveClassifier().set("dev")
manifest {
attributes(getManifestAttributes())
}
if(usesShadowedDependencies.toBoolean()) {
dependsOn(circularResolverJar)
enabled = false
}
}
task apiJar(type: Jar) {
from (sourceSets.main.allJava) {
include modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/") + '/**'
}
from (sourceSets.main.output) {
include modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/") + '/**'
}
from (sourceSets.main.resources.srcDirs) {
include("LICENSE")
}
getArchiveClassifier().set('api')
}
artifacts {
archives sourcesJar
archives devJar
if(apiPackage) {
archives apiJar
}
}
// Updating
task updateBuildScript {
doLast {
if (performBuildScriptUpdate(projectDir.toString())) return
print("Build script already up-to-date!")
}
}
if (isNewBuildScriptVersionAvailable(projectDir.toString())) {
if (autoUpdateBuildScript.toBoolean()) {
performBuildScriptUpdate(projectDir.toString())
} else {
println("Build script update available! Run 'gradle updateBuildScript'")
}
}
static URL availableBuildScriptUrl() {
new URL("https://raw.githubusercontent.com/SinTh0r4s/ExampleMod1.7.10/main/build.gradle")
}
boolean performBuildScriptUpdate(String projectDir) {
if (isNewBuildScriptVersionAvailable(projectDir)) {
def buildscriptFile = getFile("build.gradle")
availableBuildScriptUrl().withInputStream { i -> buildscriptFile.withOutputStream { it << i } }
print("Build script updated. Please REIMPORT the project or RESTART your IDE!")
return true
}
return false
}
boolean isNewBuildScriptVersionAvailable(String projectDir) {
Map parameters = ["connectTimeout": 2000, "readTimeout": 2000]
String currentBuildScript = getFile("build.gradle").getText()
String currentBuildScriptHash = getVersionHash(currentBuildScript)
String availableBuildScript = availableBuildScriptUrl().newInputStream(parameters).getText()
String availableBuildScriptHash = getVersionHash(availableBuildScript)
boolean isUpToDate = currentBuildScriptHash.empty || availableBuildScriptHash.empty || currentBuildScriptHash == availableBuildScriptHash
return !isUpToDate
}
static String getVersionHash(String buildScriptContent) {
String versionLine = buildScriptContent.find("^//version: [a-z0-9]*")
if(versionLine != null) {
return versionLine.split(": ").last()
}
return ""
}
configure(updateBuildScript) {
group = 'forgegradle'
description = 'Updates the build script to the latest version'
}
// Helper methods
def checkPropertyExists(String propertyName) {
if (project.hasProperty(propertyName) == false) {
throw new GradleException("This project requires a property \"" + propertyName + "\"! Please add it your \"gradle.properties\". You can find all properties and their description here: https://github.com/SinTh0r4s/ExampleMod1.7.10/blob/main/gradle.properties")
}
}
def getFile(String relativePath) {
return new File(projectDir, relativePath)
id 'com.gtnewhorizons.gtnhconvention'
}
-1
View File
@@ -1,5 +1,4 @@
// Add your dependencies here
dependencies {
compile("com.github.GTNewHorizons:CodeChickenLib:master-SNAPSHOT:dev")
}
+165 -28
View File
@@ -1,60 +1,197 @@
# ExampleMod tag to use as Blowdryer (Spotless, etc.) settings version, leave empty to disable.
# LOCAL to test local config updates.
gtnh.settings.blowdryerTag = 0.2.0
# Human-readable mod name, available for mcmod.info population.
modName = CodeChicken Core
# This is a case-sensitive string to identify your mod. Convention is to use lower case.
# Case-sensitive identifier string, available for mcmod.info population and used for automatic mixin JSON generation.
# Conventionally lowercase.
modId = CodeChickenCore
# Root package of the mod, used to find various classes in other properties,
# mcmod.info substitution, enabling assertions in run tasks, etc.
modGroup = codechicken
# WHY is there no version field?
# The build script relies on git to provide a version via tags. It is super easy and will enable you to always know the
# code base or your binary. Check out this tutorial: https://blog.mattclemente.com/2017/10/13/versioning-with-git-tags/
# Whether to use modGroup as the maven publishing group.
# When false, com.github.GTNewHorizons is used.
useModGroupForPublishing = false
# Will update your build.gradle automatically whenever an update is available
# Updates your build.gradle and settings.gradle automatically whenever an update is available.
autoUpdateBuildScript = false
# Version of Minecraft to target
minecraftVersion = 1.7.10
# Version of Minecraft Forge to target
forgeVersion = 10.13.4.1614
# Select a username for testing your mod with breakpoints. You may leave this empty for a random user name each time you
# restart Minecraft in development. Choose this dependent on your mod:
# Do you need consistent player progressing (for example Thaumcraft)? -> Select a name
# Do you need to test how your custom blocks interacts with a player that is not the owner? -> leave name empty
developmentEnvironmentUserName = "Developer"
# Specify an MCP channel for dependency deobfuscation and the deobfParams task.
channel = stable
# Define a source file of your project with:
# public static final String VERSION = "GRADLETOKEN_VERSION";
# The string's content will be replaced with your mods version when compiled. You should use this to specify your mod's
# version in @Mod([...], version = VERSION, [...])
# Leave these properties empty to skip individual token replacements
replaceGradleTokenInFile = CodeChickenCoreModContainer.java
gradleTokenModId = GRADLETOKEN_MODID
gradleTokenModName = GRADLETOKEN_MODNAME
gradleTokenVersion = GRADLETOKEN_VERSION
# Specify an MCP mappings version for dependency deobfuscation and the deobfParams task.
mappingsVersion = 12
# Defines other MCP mappings for dependency deobfuscation.
remoteMappings = https\://raw.githubusercontent.com/MinecraftForge/FML/1.7.10/conf/
# Select a default username for testing your mod. You can always override this per-run by running
# `./gradlew runClient --username=AnotherPlayer`, or configuring this command in your IDE.
developmentEnvironmentUserName = Developer
# Enables using modern Java syntax (up to version 17) via Jabel, while still targeting JVM 8.
# See https://github.com/bsideup/jabel for details on how this works.
enableModernJavaSyntax = true
# Enables injecting missing generics into the decompiled source code for a better coding experience.
# Turns most publicly visible List, Map, etc. into proper List<E>, Map<K, V> types.
enableGenericInjection = true
# Generate a class with a String field for the mod version named as defined below.
# If generateGradleTokenClass is empty or not missing, no such class will be generated.
# If gradleTokenVersion is empty or missing, the field will not be present in the class.
generateGradleTokenClass = codechicken.core.asm.Tags
# Name of the token containing the project's current version to generate/replace.
gradleTokenVersion = VERSION
# [DEPRECATED] Mod Group replacement token.
gradleTokenGroupName =
# In case your mod provides an API for other mods to implement you may declare its package here. Otherwise you can
# [DEPRECATED]
# Multiple source files can be defined here by providing a comma-separated list: Class1.java,Class2.java,Class3.java
# public static final String VERSION = "GRADLETOKEN_VERSION";
# The string's content will be replaced with your mod's version when compiled. You should use this to specify your mod's
# version in @Mod([...], version = VERSION, [...]).
# Leave these properties empty to skip individual token replacements.
replaceGradleTokenInFile =
# In case your mod provides an API for other mods to implement you may declare its package here. Otherwise, you can
# leave this property empty.
# Example value: apiPackage = api + modGroup = com.myname.mymodid -> com.myname.mymodid.api
# Example value: (apiPackage = api) + (modGroup = com.myname.mymodid) -> com.myname.mymodid.api
apiPackage =
# Specify the configuration file for Forge's access transformers here. I must be placed into /src/main/resources/META-INF/
# Example value: mymodid_at.cfg
# Specify the configuration file for Forge's access transformers here. It must be placed into /src/main/resources/META-INF/
# There can be multiple files in a space-separated list.
# Example value: mymodid_at.cfg nei_at.cfg
accessTransformersFile =
# Provides setup for Mixins if enabled. If you don't know what mixins are: Keep it disabled!
usesMixins = false
# Specify the location of your implementation of IMixinPlugin. Leave it empty otherwise.
# Set to a non-empty string to configure mixins in a separate source set under src/VALUE, instead of src/main.
# This can speed up compile times thanks to not running the mixin annotation processor on all input sources.
# Mixin classes will have access to "main" classes, but not the other way around.
separateMixinSourceSet =
# Adds some debug arguments like verbose output and class export.
usesMixinDebug = false
# Specify the location of your implementation of IMixinConfigPlugin. Leave it empty otherwise.
mixinPlugin =
# Specify the package that contains all of your Mixins. You may only place Mixins in this package or the build will fail!
mixinsPackage =
# Specify the core mod entry class if you use a core mod. This class must implement IFMLLoadingPlugin!
# This parameter is for legacy compatability only
# Example value: coreModClass = asm.FMLPlugin + modGroup = com.myname.mymodid -> com.myname.mymodid.asm.FMLPlugin
# This parameter is for legacy compatibility only
# Example value: (coreModClass = asm.FMLPlugin) + (modGroup = com.myname.mymodid) -> com.myname.mymodid.asm.FMLPlugin
coreModClass = core.launch.CodeChickenCorePlugin
# If your project is only a consolidation of mixins or a core mod and does NOT contain a 'normal' mod ( = some class
# that is annotated with @Mod) you want this to be true. When in doubt: leave it on false!
containsMixinsAndOrCoreModOnly = true
# If enabled, you may use 'shadowImplementation' for dependencies. They will be integrated in your jar. It is your
# responsibility check the licence and request permission for distribution, if required.
# Enables Mixins even if this mod doesn't use them, useful if one of the dependencies uses mixins.
forceEnableMixins = false
# If enabled, you may use 'shadowCompile' for dependencies. They will be integrated into your jar. It is your
# responsibility to check the license and request permission for distribution if required.
usesShadowedDependencies = false
# If disabled, won't remove unused classes from shadowed dependencies. Some libraries use reflection to access
# their own classes, making the minimization unreliable.
minimizeShadowedDependencies = true
# If disabled, won't rename the shadowed classes.
relocateShadowedDependencies = true
# Adds CurseMaven, Modrinth, and some more well-known 1.7.10 repositories.
includeWellKnownRepositories = true
# A list of repositories to exclude from the includeWellKnownRepositories setting. Should be a space separated
# list of strings, with the acceptable keys being(case does not matter):
# cursemaven
# modrinth
excludeWellKnownRepositories =
# Change these to your Maven coordinates if you want to publish to a custom Maven repository instead of the default GTNH Maven.
# Authenticate with the MAVEN_USER and MAVEN_PASSWORD environment variables.
# If you need a more complex setup disable maven publishing here and add a publishing repository to addon.gradle.
usesMavenPublishing = true
# Maven repository to publish the mod to.
# mavenPublishUrl = https\://nexus.gtnewhorizons.com/repository/releases/
# Publishing to Modrinth requires you to set the MODRINTH_TOKEN environment variable to your current Modrinth API token.
#
# The project's ID on Modrinth. Can be either the slug or the ID.
# Leave this empty if you don't want to publish to Modrinth.
modrinthProjectId = codechickencore-unofficial
# The project's relations on Modrinth. You can use this to refer to other projects on Modrinth.
# Syntax: scope1-type1:name1;scope2-type2:name2;...
# Where scope can be one of [required, optional, incompatible, embedded],
# type can be one of [project, version],
# and the name is the Modrinth project or version slug/id of the other mod.
# Example: required-project:fplib;optional-project:gasstation;incompatible-project:gregtech
# Note: UniMixins is automatically set as a required dependency if usesMixins = true.
modrinthRelations =
# Publishing to CurseForge requires you to set the CURSEFORGE_TOKEN environment variable to one of your CurseForge API tokens.
#
# The project's numeric ID on CurseForge. You can find this in the About Project box.
# Leave this empty if you don't want to publish on CurseForge.
curseForgeProjectId = 746279
# The project's relations on CurseForge. You can use this to refer to other projects on CurseForge.
# Syntax: type1:name1;type2:name2;...
# Where type can be one of [requiredDependency, embeddedLibrary, optionalDependency, tool, incompatible],
# and the name is the CurseForge project slug of the other mod.
# Example: requiredDependency:railcraft;embeddedLibrary:cofhlib;incompatible:buildcraft
# Note: UniMixins is automatically set as a required dependency if usesMixins = true.
curseForgeRelations =
# Optional parameter to customize the produced artifacts. Use this to preserve artifact naming when migrating older
# projects. New projects should not use this parameter.
# customArchiveBaseName =
# Optional parameter to have the build automatically fail if an illegal version is used.
# This can be useful if you e.g. only want to allow versions in the form of '1.1.xxx'.
# The check is ONLY performed if the version is a git tag.
# Note: the specified string must be escaped, so e.g. 1\\.1\\.\\d+ instead of 1\.1\.\d+
# versionPattern =
# Uncomment to prevent the source code from being published.
# noPublishedSources = true
# Uncomment this to disable Spotless checks.
# This should only be uncommented to keep it easier to sync with upstream/other forks.
# That is, if there is no other active fork/upstream, NEVER change this.
# disableSpotless = true
# Uncomment this to disable Checkstyle checks (currently wildcard import check).
# disableCheckstyle = true
# Override the IDEA build type. Valid values are: "" (leave blank, do not override), "idea" (force use native IDEA build), "gradle"
# (force use delegated build).
# This is meant to be set in $HOME/.gradle/gradle.properties.
# e.g. add "systemProp.org.gradle.project.ideaOverrideBuildType=idea" will override the build type to be native build.
# WARNING: If you do use this option, it will overwrite whatever you have in your existing projects. This might not be what you want!
# Usually there is no need to uncomment this here as other developers do not necessarily use the same build type as you.
# ideaOverrideBuildType = idea
# Whether IDEA should run spotless checks when pressing the Build button.
# This is meant to be set in $HOME/.gradle/gradle.properties.
# ideaCheckSpotlessOnBuild = true
Binary file not shown.
+3 -1
View File
@@ -1,5 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.9.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Vendored Regular → Executable
+180 -117
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env sh
#!/bin/sh
#
# Copyright 2015 the original author or authors.
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -15,80 +15,115 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
#
##############################################################################
##
## Gradle start up script for UN*X
##
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
MAX_FD=maximum
warn () {
echo "$*"
}
} >&2
die () {
echo
echo "$*"
echo
exit 1
}
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD="$JAVA_HOME/bin/java"
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
@@ -97,92 +132,120 @@ Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
JAVACMD=java
if ! command -v java >/dev/null 2>&1
then
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"
Vendored
+27 -33
View File
@@ -13,8 +13,10 @@
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@rem SPDX-License-Identifier: Apache-2.0
@rem
@if "%DEBUG%" == "" @echo off
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@@ -25,10 +27,14 @@
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@@ -37,13 +43,13 @@ if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
if %ERRORLEVEL% equ 0 goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
echo. 1>&2
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
@@ -51,48 +57,36 @@ goto fail
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
echo. 1>&2
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
+1 -3
View File
@@ -1,7 +1,5 @@
// Add any additional repositiroes for your dependencies here
repositories {
maven {
url = "https://jitpack.io"
}
mavenLocal()
}
+23
View File
@@ -0,0 +1,23 @@
pluginManagement {
repositories {
maven {
// RetroFuturaGradle
name "GTNH Maven"
url "https://nexus.gtnewhorizons.com/repository/public/"
mavenContent {
includeGroup("com.gtnewhorizons")
includeGroupByRegex("com\\.gtnewhorizons\\..+")
}
}
gradlePluginPortal()
mavenCentral()
mavenLocal()
}
}
plugins {
id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.41'
}
@@ -1,111 +1,22 @@
package codechicken.core;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.ArrayList;
import codechicken.core.launch.CodeChickenCorePlugin;
import com.google.common.base.Function;
import cpw.mods.fml.common.Loader;
import cpw.mods.fml.common.versioning.ComparableVersion;
import cpw.mods.fml.relauncher.FMLInjectionData;
import net.minecraft.client.Minecraft;
import net.minecraft.util.ChatComponentText;
import net.minecraft.util.StatCollector;
public class CCUpdateChecker {
public class CCUpdateChecker
{
private static final ArrayList<String> updates = new ArrayList<String>();
public static void tick() {}
private static class ThreadUpdateCheck extends Thread
{
private final URL url;
private final Function<String, Void> handler;
public ThreadUpdateCheck(URL url, Function<String, Void> handler) {
this.url = url;
this.handler = handler;
setName("CodeChicken Update Checker");
}
@Override
public void run() {
try {
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(5000);
conn.setReadTimeout(5000);
BufferedReader read = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String ret = read.readLine();
read.close();
if(ret == null) ret = "";
handler.apply(ret);
} catch (SocketTimeoutException ignored) {}
catch (UnknownHostException ignored) {}
catch (IOException iox) {
iox.printStackTrace();
}
}
}
public static void tick() {
Minecraft mc = Minecraft.getMinecraft();
if (!mc.inGameHasFocus)
return;
synchronized (updates) {
for (String s : updates)
mc.thePlayer.addChatMessage(new ChatComponentText(s));
updates.clear();
}
}
public static void addUpdateMessage(String s) {
synchronized (updates) {
updates.add(s);
}
}
public static void addUpdateMessage(String s) {}
public static String mcVersion() {
return (String) FMLInjectionData.data()[4];
}
public static void updateCheck(final String mod, final String version) {
updateCheck("http://www.chickenbones.net/Files/notification/version.php?" +
"version=" + mcVersion() + "&" +
"file=" + mod,
new Function<String, Void>()
{
@Override public Void apply(String ret) {
if (!ret.startsWith("Ret: ")) {
CodeChickenCorePlugin.logger.error("Failed to check update for " + mod + " returned: " + ret);
return null;
}
ComparableVersion newversion = new ComparableVersion(ret.substring(5));
if (newversion.compareTo(new ComparableVersion(version)) > 0)
addUpdateMessage(StatCollector.translateToLocalFormatted("codechickencore.update", newversion, mod));
return null;
}
});
}
public static void updateCheck(final String mod, final String version) {}
public static void updateCheck(String mod) {
updateCheck(mod, Loader.instance().getIndexedModList().get(mod).getVersion());
}
public static void updateCheck(String mod) {}
public static void updateCheck(String url, Function<String, Void> handler) {
try {
new ThreadUpdateCheck(new URL(url), handler).start();
} catch (MalformedURLException e) {
CodeChickenCorePlugin.logger.error("Malformed URL: "+url, e);
}
}
public static void updateCheck(String url, Function<String, Void> handler) {}
}
@@ -1,29 +1,31 @@
package codechicken.core;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipFile;
import net.minecraft.launchwrapper.Launch;
import org.objectweb.asm.tree.ClassNode;
import codechicken.core.launch.CodeChickenCorePlugin;
import codechicken.lib.asm.ASMHelper;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.tree.ClassNode;
import com.google.common.collect.ImmutableList;
import codechicken.core.launch.CodeChickenCorePlugin;
import codechicken.lib.asm.ASMHelper;
import cpw.mods.fml.common.FMLLog;
import cpw.mods.fml.common.Loader;
import cpw.mods.fml.common.ModClassLoader;
import cpw.mods.fml.relauncher.CoreModManager;
public class ClassDiscoverer
{
@SuppressWarnings("unused")
public class ClassDiscoverer {
public IStringMatcher matcher;
public String[] superclasses;
public ArrayList<Class<?>> classes;
@@ -35,15 +37,12 @@ public class ClassDiscoverer
for (int i = 0; i < superclasses.length; i++)
this.superclasses[i] = superclasses[i].getName().replace('.', '/');
classes = new ArrayList<Class<?>>();
classes = new ArrayList<>();
modClassLoader = (ModClassLoader) Loader.instance().getModClassLoader();
}
public ClassDiscoverer(Class<?>... superclasses) {
this(new IStringMatcher()
{
public boolean matches(String test) {return true;}
}, superclasses);
this(test -> true, superclasses);
}
public ArrayList<Class<?>> findClasses() {
@@ -59,13 +58,11 @@ public class ClassDiscoverer
try {
String classname = resource.replace(".class", "").replace("\\", ".").replace("/", ".");
byte[] bytes = Launch.classLoader.getClassBytes(classname);
if (bytes == null)
return;
if (bytes == null) return;
ClassNode cnode = ASMHelper.createClassNode(bytes);
ClassNode cnode = ASMHelper.createClassNode(bytes, ClassReader.SKIP_CODE);
for (String superclass : superclasses)
if (!cnode.interfaces.contains(superclass) && !cnode.superName.equals(superclass))
return;
if (!cnode.interfaces.contains(superclass) && !cnode.superName.equals(superclass)) return;
addClass(classname);
} catch (IOException e) {
@@ -83,49 +80,49 @@ public class ClassDiscoverer
}
private void findClasspathMods() {
List<String> knownLibraries = ImmutableList.<String>builder()
.addAll(modClassLoader.getDefaultLibraries())
List<String> knownLibraries = ImmutableList.<String>builder().addAll(modClassLoader.getDefaultLibraries())
.addAll(CoreModManager.getLoadedCoremods()).build();
File[] minecraftSources = modClassLoader.getParentSources();
HashSet<String> searchedSources = new HashSet<String>();
HashSet<String> searchedSources = new HashSet<>();
for (File minecraftSource : minecraftSources) {
if (searchedSources.contains(minecraftSource.getAbsolutePath()))
continue;
if (searchedSources.contains(minecraftSource.getAbsolutePath())) continue;
searchedSources.add(minecraftSource.getAbsolutePath());
if (minecraftSource.isFile()) {
if (!knownLibraries.contains(minecraftSource.getName())) {
FMLLog.fine("Found a minecraft related file at %s, examining for codechicken classes", minecraftSource.getAbsolutePath());
FMLLog.fine(
"Found a minecraft related file at %s, examining for codechicken classes",
minecraftSource.getAbsolutePath());
try {
readFromZipFile(minecraftSource);
} catch (Exception e) {
CodeChickenCorePlugin.logger.error("Failed to scan " + minecraftSource.getAbsolutePath() + ", the zip file is invalid", e);
CodeChickenCorePlugin.logger.error(
"Failed to scan " + minecraftSource.getAbsolutePath() + ", the zip file is invalid",
e);
}
}
} else if (minecraftSource.isDirectory()) {
FMLLog.fine("Found a minecraft related directory at %s, examining for codechicken classes", minecraftSource.getAbsolutePath());
FMLLog.fine(
"Found a minecraft related directory at %s, examining for codechicken classes",
minecraftSource.getAbsolutePath());
readFromDirectory(minecraftSource, minecraftSource);
}
}
}
private void readFromZipFile(File file) throws IOException {
FileInputStream fileinputstream = new FileInputStream(file);
ZipInputStream zipinputstream = new ZipInputStream(fileinputstream);
do {
ZipEntry zipentry = zipinputstream.getNextEntry();
if (zipentry == null) {
break;
}
String fullname = zipentry.getName().replace('\\', '/');
int pos = fullname.lastIndexOf('/');
String name = pos == -1 ? fullname : fullname.substring(pos + 1);
if (!zipentry.isDirectory() && matcher.matches(name)) {
checkAddClass(fullname);
try (ZipFile zipFile = new ZipFile(file)) {
Enumeration<? extends ZipEntry> zipEntries = zipFile.entries();
while (zipEntries.hasMoreElements()) {
ZipEntry zipentry = zipEntries.nextElement();
String fullname = zipentry.getName().replace('\\', '/');
int pos = fullname.lastIndexOf('/');
String name = pos == -1 ? fullname : fullname.substring(pos + 1);
if (!zipentry.isDirectory() && matcher.matches(name)) {
checkAddClass(fullname);
}
}
}
while (true);
fileinputstream.close();
}
private void readFromDirectory(File directory, File basedirectory) {
+12 -13
View File
@@ -1,12 +1,5 @@
package codechicken.core;
import codechicken.core.internal.CCCEventHandler;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.ModContainer;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.network.NetworkManager;
@@ -14,8 +7,14 @@ import net.minecraft.server.MinecraftServer;
import net.minecraft.util.EnumChatFormatting;
import net.minecraft.world.World;
public class ClientUtils extends CommonUtils
{
import codechicken.core.internal.CCCEventHandler;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.ModContainer;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
public class ClientUtils extends CommonUtils {
private static Minecraft mc() {
return Minecraft.getMinecraft();
}
@@ -24,15 +23,14 @@ public class ClientUtils extends CommonUtils
return mc().theWorld;
}
public static boolean inWorld()//TODO unused
public static boolean inWorld() // TODO unused
{
return mc().getNetHandler() != null;
}
public static void openSMPGui(int windowId, GuiScreen gui) {
mc().displayGuiScreen(gui);
if (windowId != 0)
mc().thePlayer.openContainer.windowId = windowId;
if (windowId != 0) mc().thePlayer.openContainer.windowId = windowId;
}
public static float getRenderFrame() {
@@ -63,7 +61,8 @@ public class ClientUtils extends CommonUtils
public static void enhanceSupportersList(Object mod) {
ModContainer mc = FMLCommonHandler.instance().findContainerFor(mod);
mc.getMetadata().description = mc.getMetadata().description.replace("Supporters:", EnumChatFormatting.AQUA+"Supporters:");
mc.getMetadata().description = mc.getMetadata().description
.replace("Supporters:", EnumChatFormatting.AQUA + "Supporters:");
GuiModListScroll.register(mod);
}
}
@@ -2,15 +2,16 @@ package codechicken.core;
import java.io.File;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.relauncher.FMLInjectionData;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityList;
import net.minecraft.world.World;
import net.minecraftforge.common.DimensionManager;
public class CommonUtils
{
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.relauncher.FMLInjectionData;
public class CommonUtils {
public static boolean isClient() {
return FMLCommonHandler.instance().getSide().isClient();
}
@@ -37,14 +38,12 @@ public class CommonUtils
}
public static String getRelativePath(File parent, File child) {
if (parent.isFile() || !child.getPath().startsWith(parent.getPath()))
return null;
if (parent.isFile() || !child.getPath().startsWith(parent.getPath())) return null;
return child.getPath().substring(parent.getPath().length() + 1);
}
public static void registerHandledEntity(Class<? extends Entity> entityClass, String identifier)
{
public static void registerHandledEntity(Class<? extends Entity> entityClass, String identifier) {
EntityList.classToStringMapping.put(entityClass, identifier);
EntityList.stringToClassMapping.put(identifier, entityClass);
}
@@ -1,5 +1,40 @@
package codechicken.core;
import static org.lwjgl.opengl.GL11.GL_ALWAYS;
import static org.lwjgl.opengl.GL11.GL_EQUAL;
import static org.lwjgl.opengl.GL11.GL_KEEP;
import static org.lwjgl.opengl.GL11.GL_PACK_ALIGNMENT;
import static org.lwjgl.opengl.GL11.GL_REPLACE;
import static org.lwjgl.opengl.GL11.GL_STENCIL_INDEX;
import static org.lwjgl.opengl.GL11.GL_STENCIL_TEST;
import static org.lwjgl.opengl.GL11.GL_UNPACK_ALIGNMENT;
import static org.lwjgl.opengl.GL11.GL_UNSIGNED_BYTE;
import static org.lwjgl.opengl.GL11.GL_ZERO;
import static org.lwjgl.opengl.GL11.glColorMask;
import static org.lwjgl.opengl.GL11.glDisable;
import static org.lwjgl.opengl.GL11.glEnable;
import static org.lwjgl.opengl.GL11.glPixelStorei;
import static org.lwjgl.opengl.GL11.glReadPixels;
import static org.lwjgl.opengl.GL11.glStencilFunc;
import static org.lwjgl.opengl.GL11.glStencilOp;
import java.awt.Dimension;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.LinkedList;
import java.util.List;
import javax.imageio.ImageIO;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.MinecraftForgeClient;
import org.lwjgl.BufferUtils;
import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.GL11;
import codechicken.core.launch.CodeChickenCorePlugin;
import codechicken.lib.gui.GuiDraw;
import codechicken.lib.vec.Rectangle4i;
@@ -7,27 +42,9 @@ import cpw.mods.fml.client.GuiModList;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.ModContainer;
import cpw.mods.fml.common.ModMetadata;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.MinecraftForgeClient;
import org.lwjgl.BufferUtils;
import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.GL11;
import javax.imageio.ImageIO;
public class GuiModListScroll {
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL11.glReadPixels;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.LinkedList;
import java.util.List;
public class GuiModListScroll
{
private static List<ModContainer> scrollMods = new LinkedList<ModContainer>();
public static void register(Object mod) {
@@ -37,8 +54,7 @@ public class GuiModListScroll
private static void register(ModContainer mod) {
if (MinecraftForgeClient.getStencilBits() == 0)
CodeChickenCorePlugin.logger.error("Unable to do mod description scrolling due to lack of stencil buffer");
else
scrollMods.add(mod);
else scrollMods.add(mod);
}
private static void screenshotStencil(int x) {
@@ -49,11 +65,10 @@ public class GuiModListScroll
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glReadPixels(0, 0, d.width, d.height, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, buf);
for(int i = 0; i < d.width; i++)
for(int j = 0; j < d.height; j++)
img.setRGB(i, d.height-j-1, buf.get(j * d.width + i) == 0 ? 0 : 0xFFFFFF);
for (int i = 0; i < d.width; i++) for (int j = 0; j < d.height; j++)
img.setRGB(i, d.height - j - 1, buf.get(j * d.width + i) == 0 ? 0 : 0xFFFFFF);
try {
ImageIO.write(img, "png", new File("stencil"+x+".png"));
ImageIO.write(img, "png", new File("stencil" + x + ".png"));
} catch (IOException e) {
e.printStackTrace();
}
@@ -63,36 +78,35 @@ public class GuiModListScroll
private static double scroll;
private static double lastFrameTime;
private static double timeStart;
public static void draw(GuiModList gui, int mouseX, int mouseY) {
ModContainer selectedMod = ReflectionManager.getField(GuiModList.class, ModContainer.class, gui, "selectedMod");
if(selectedMod != lastMod) {
if (selectedMod != lastMod) {
lastMod = selectedMod;
scroll = 0;
timeStart = ClientUtils.getRenderTime();
}
if(!scrollMods.contains(selectedMod) || selectedMod.getMetadata().autogenerated)
return;
if (!scrollMods.contains(selectedMod) || selectedMod.getMetadata().autogenerated) return;
int y1 = calcDescY(gui, selectedMod);
int y1draw = y1 + 10;
int y2 = gui.height-38;
int y2 = gui.height - 38;
int x1 = ReflectionManager.getField(GuiModList.class, Integer.class, gui, "listWidth") + 20;
int x2 = gui.width - 20;
if(x2 - x1 <= 20)
return;
if (x2 - x1 <= 20) return;
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_ALWAYS, 1, 1);
glColorMask(false, false, false, false);
glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO);
GuiDraw.drawRect(0, 0, gui.width, gui.height, -1);//clear stencil buffer
GuiDraw.drawRect(0, 0, gui.width, gui.height, -1); // clear stencil buffer
screenshotStencil(1);
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
GuiDraw.drawRect(x1, y1, gui.width - x1, gui.height - y1, -1);//add description area (even below button)
GuiDraw.drawRect(x1, y1, gui.width - x1, gui.height - y1, -1); // add description area (even below button)
glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO);
GuiDraw.drawRect(gui.width / 2 - 75, y2, 200, 20, -1);//subtract done button
GuiDraw.drawRect(gui.width / 2 - 75, y2, 200, 20, -1); // subtract done button
screenshotStencil(2);
@@ -100,13 +114,13 @@ public class GuiModListScroll
glStencilFunc(GL_EQUAL, 1, 1);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
gui.drawDefaultBackground();//fill stencil with background
gui.drawDefaultBackground(); // fill stencil with background
glColorMask(false, false, false, false);
glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO);
GuiDraw.drawRect(0, 0, gui.width, gui.height, -1);
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
GuiDraw.drawRect(x1, y1draw, x2-x1, y2-y1draw, -1);
GuiDraw.drawRect(x1, y1draw, x2 - x1, y2 - y1draw, -1);
screenshotStencil(3);
@@ -114,10 +128,11 @@ public class GuiModListScroll
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
String description = selectedMod.getMetadata().description;
int height = GuiDraw.fontRenderer.listFormattedStringToWidth(description, x2-x1).size()*GuiDraw.fontRenderer.FONT_HEIGHT;
int height = GuiDraw.fontRenderer.listFormattedStringToWidth(description, x2 - x1).size()
* GuiDraw.fontRenderer.FONT_HEIGHT;
boolean needsScroll = height > y2-y1draw;
if((ClientUtils.getRenderTime() - timeStart) > 40 && needsScroll) {
boolean needsScroll = height > y2 - y1draw;
if ((ClientUtils.getRenderTime() - timeStart) > 40 && needsScroll) {
double dt = ClientUtils.getRenderTime() - lastFrameTime;
if (new Rectangle4i(x1, y1draw, x2 - x1, y2 - y1draw).contains(mouseX, mouseY)) {
double d = Keyboard.isKeyDown(Keyboard.KEY_UP) ? -1 : Keyboard.isKeyDown(Keyboard.KEY_DOWN) ? 1 : 0;
@@ -128,36 +143,35 @@ public class GuiModListScroll
}
lastFrameTime = ClientUtils.getRenderTime();
//draw description
// draw description
double dy = scroll % (height + 20);
GL11.glPushMatrix();
GL11.glTranslated(0, -dy, 0);
GuiDraw.fontRenderer.drawSplitString(description, x1, y1draw, x2-x1, 0xDDDDDD);
if(needsScroll) {
GL11.glTranslated(0, height + 20, 0);
GuiDraw.fontRenderer.drawSplitString(description, x1, y1draw, x2 - x1, 0xDDDDDD);
}
GL11.glTranslated(0, -dy, 0);
GuiDraw.fontRenderer.drawSplitString(description, x1, y1draw, x2 - x1, 0xDDDDDD);
if (needsScroll) {
GL11.glTranslated(0, height + 20, 0);
GuiDraw.fontRenderer.drawSplitString(description, x1, y1draw, x2 - x1, 0xDDDDDD);
}
GL11.glPopMatrix();
glDisable(GL_STENCIL_TEST);
}
/**
* Does not add the last 10 px space before the description normally starts
* Ignores empty child mods expecting a background draw overwrite
* Does not add the last 10 px space before the description normally starts Ignores empty child mods expecting a
* background draw overwrite
*/
private static int calcDescY(GuiModList gui, ModContainer mod) {
ModMetadata meta = mod.getMetadata();
int y = 35;
if(!!meta.logoFile.isEmpty() && ReflectionManager.getField(GuiModList.class, ResourceLocation.class, gui, "cachedLogo") != null)
if (!!meta.logoFile.isEmpty()
&& ReflectionManager.getField(GuiModList.class, ResourceLocation.class, gui, "cachedLogo") != null)
y += 65;
y += 12; // title
y += 40; // necessary lines
if(!meta.credits.isEmpty())
y += 10;
if(!meta.childMods.isEmpty())
y += 10;
if (!meta.credits.isEmpty()) y += 10;
if (!meta.childMods.isEmpty()) y += 10;
return y;
}
}
@@ -2,7 +2,7 @@ package codechicken.core;
import net.minecraft.entity.player.EntityPlayerMP;
public interface IGuiPacketSender
{
public interface IGuiPacketSender {
void sendPacket(EntityPlayerMP player, int windowId);
}
@@ -1,6 +1,6 @@
package codechicken.core;
public interface IStringMatcher
{
public interface IStringMatcher {
public boolean matches(String test);
}
@@ -1,7 +1,9 @@
package codechicken.core;
public class ProfileTimer
{
import codechicken.core.launch.CodeChickenCorePlugin;
public class ProfileTimer {
public double decay;
public long startTime;
public long nanoTime;
@@ -28,12 +30,11 @@ public class ProfileTimer
}
public void end() {
long t = System.nanoTime()-startTime;
nanoTime = (long)(nanoTime*decay+t*(1-decay));
long t = System.nanoTime() - startTime;
nanoTime = (long) (nanoTime * decay + t * (1 - decay));
scanCount++;
if(logScans > 0 && scanCount % logScans == 0)
System.out.println("Profiled " + logName + " " + nanoTime + "ns");
if (logScans > 0 && scanCount % logScans == 0)
CodeChickenCorePlugin.logger.info("Profiled " + logName + " " + nanoTime + "ns");
}
}
@@ -8,12 +8,11 @@ import java.util.HashMap;
import codechicken.lib.asm.ObfMapping;
public class ReflectionManager
{
public class ReflectionManager {
public static HashMap<Class<?>, Class<?>> primitiveWrappers = new HashMap<Class<?>, Class<?>>();
static
{
static {
primitiveWrappers.put(Integer.TYPE, Integer.class);
primitiveWrappers.put(Short.TYPE, Short.class);
primitiveWrappers.put(Byte.TYPE, Byte.class);
@@ -23,293 +22,238 @@ public class ReflectionManager
primitiveWrappers.put(Boolean.TYPE, Boolean.class);
primitiveWrappers.put(Character.TYPE, Character.class);
}
public static boolean isInstance(Class<?> class1, Object obj)
{
public static boolean isInstance(Class<?> class1, Object obj) {
Class<?> primitive = primitiveWrappers.get(class1);
if(primitive != null)
{
if(primitive == Long.class && Long.class.isInstance(obj))
if (primitive != null) {
if (primitive == Long.class && Long.class.isInstance(obj)) return true;
if ((primitive == Long.class || primitive == Integer.class) && Integer.class.isInstance(obj)) return true;
if ((primitive == Long.class || primitive == Integer.class || primitive == Short.class)
&& Short.class.isInstance(obj))
return true;
if((primitive == Long.class || primitive == Integer.class) && Integer.class.isInstance(obj))
if ((primitive == Long.class || primitive == Integer.class
|| primitive == Short.class
|| primitive == Byte.class) && Integer.class.isInstance(obj))
return true;
if((primitive == Long.class || primitive == Integer.class || primitive == Short.class) && Short.class.isInstance(obj))
return true;
if((primitive == Long.class || primitive == Integer.class || primitive == Short.class || primitive == Byte.class) && Integer.class.isInstance(obj))
return true;
if(primitive == Double.class && Double.class.isInstance(obj))
return true;
if((primitive == Double.class || primitive == Float.class) && Float.class.isInstance(obj))
return true;
if (primitive == Double.class && Double.class.isInstance(obj)) return true;
if ((primitive == Double.class || primitive == Float.class) && Float.class.isInstance(obj)) return true;
return primitive.isInstance(obj);
}
return class1.isInstance(obj);
}
public static Class<?> findClass(String name)
{
public static Class<?> findClass(String name) {
return findClass(name, true);
}
public static boolean classExists(String name)
{
public static boolean classExists(String name) {
return findClass(name, false) != null;
}
public static Class<?> findClass(String name, boolean init)
{
try
{
public static Class<?> findClass(String name, boolean init) {
try {
return Class.forName(name, init, ReflectionManager.class.getClassLoader());
}
catch (ClassNotFoundException cnfe)
{
try
{
return Class.forName("net.minecraft.src."+name, init, ReflectionManager.class.getClassLoader());
}
catch (ClassNotFoundException cnfe2)
{
} catch (ClassNotFoundException cnfe) {
try {
return Class.forName("net.minecraft.src." + name, init, ReflectionManager.class.getClassLoader());
} catch (ClassNotFoundException cnfe2) {
return null;
}
}
}
public static void setField(Class<?> class1, Object instance, String name, Object value) throws IllegalArgumentException, IllegalAccessException
{
setField(class1, instance, new String[]{name}, value);
public static void setField(Class<?> class1, Object instance, String name, Object value)
throws IllegalArgumentException, IllegalAccessException {
setField(class1, instance, new String[] { name }, value);
}
public static void setField(Class<?> class1, Object instance, String[] names, Object value) throws IllegalArgumentException, IllegalAccessException
{
for(Field field : class1.getDeclaredFields())
{
public static void setField(Class<?> class1, Object instance, String[] names, Object value)
throws IllegalArgumentException, IllegalAccessException {
for (Field field : class1.getDeclaredFields()) {
boolean match = false;
for(String name : names)
{
if(field.getName().equals(name))
{
for (String name : names) {
if (field.getName().equals(name)) {
match = true;
break;
}
}
if(!match)
{
if (!match) {
continue;
}
}
field.setAccessible(true);
field.set(instance, value);
return;
}
}
public static void setField(Class<?> class1, Object instance, int fieldindex, Object value) throws IllegalArgumentException, IllegalAccessException
{
public static void setField(Class<?> class1, Object instance, int fieldindex, Object value)
throws IllegalArgumentException, IllegalAccessException {
Field field = class1.getDeclaredFields()[fieldindex];
field.setAccessible(true);
field.set(instance, value);
}
/**
* Static function
* void return type
* single name
* Static function void return type single name
*/
public static void callMethod(Class<?> class1, String name, Object... params) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException
{
callMethod(class1, null, new String[]{name}, params);
public static void callMethod(Class<?> class1, String name, Object... params)
throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
callMethod(class1, null, new String[] { name }, params);
}
/**
* Static function
* void return type
* single name
* Static function void return type single name
*/
public static void callMethod(Class<?> class1, String[] names, Object... params) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException
{
public static void callMethod(Class<?> class1, String[] names, Object... params)
throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
callMethod(class1, null, names, params);
}
/**
* void return type
* single name
* void return type single name
*/
public static void callMethod(Class<?> class1, Object instance, String name, Object... params) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException
{
callMethod(class1, null, instance, new String[]{name}, params);
public static void callMethod(Class<?> class1, Object instance, String name, Object... params)
throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
callMethod(class1, null, instance, new String[] { name }, params);
}
/**
* void return type
*/
public static void callMethod(Class<?> class1, Object instance, String[] names, Object... params) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException
{
public static void callMethod(Class<?> class1, Object instance, String[] names, Object... params)
throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
callMethod(class1, null, instance, names, params);
}
/**
* Static method
* single name
* Static method single name
*/
public static <R> R callMethod(Class<?> class1, Class<R> returntype, String name, Object... params) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException
{
return callMethod(class1, returntype, null, new String[]{name}, params);
public static <R> R callMethod(Class<?> class1, Class<R> returntype, String name, Object... params)
throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
return callMethod(class1, returntype, null, new String[] { name }, params);
}
/**
* Static method
*/
public static <R> R callMethod(Class<?> class1, Class<R> returntype, String[] names, Object... params) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException
{
public static <R> R callMethod(Class<?> class1, Class<R> returntype, String[] names, Object... params)
throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
return callMethod(class1, returntype, null, names, params);
}
/**
* sinlge name
*/
public static <R> R callMethod(Class<?> class1, Class<R> returntype, Object instance, String name, Object... params) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException
{
return callMethod(class1, returntype, instance, new String[]{name}, params);
public static <R> R callMethod(Class<?> class1, Class<R> returntype, Object instance, String name, Object... params)
throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
return callMethod(class1, returntype, instance, new String[] { name }, params);
}
public static <R> R callMethod(Class<?> class1, Class<R> returntype, Object instance, String[] names, Object... params) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException
{
nextMethod: for(Method method : class1.getDeclaredMethods())
{
public static <R> R callMethod(Class<?> class1, Class<R> returntype, Object instance, String[] names,
Object... params) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
nextMethod: for (Method method : class1.getDeclaredMethods()) {
boolean match = false;
for(String name : names)
{
if(method.getName().equals(name))
{
for (String name : names) {
if (method.getName().equals(name)) {
match = true;
break;
}
}
if(!match)
{
if (!match) {
continue;
}
Class<?>[] paramtypes = method.getParameterTypes();
if(paramtypes.length != params.length)
continue;
for(int i = 0; i < params.length; i++)
{
if(!isInstance(paramtypes[i], params[i]))
continue nextMethod;
if (paramtypes.length != params.length) continue;
for (int i = 0; i < params.length; i++) {
if (!isInstance(paramtypes[i], params[i])) continue nextMethod;
}
method.setAccessible(true);
return (R)method.invoke(instance, params);
return (R) method.invoke(instance, params);
}
return null;
}
public static <T> T getField(Class<?> class1, Class<T> fieldType, Object instance, int fieldIndex) throws IllegalArgumentException, IllegalAccessException
{
public static <T> T getField(Class<?> class1, Class<T> fieldType, Object instance, int fieldIndex)
throws IllegalArgumentException, IllegalAccessException {
Field field = class1.getDeclaredFields()[fieldIndex];
field.setAccessible(true);
return (T) field.get(instance);
}
public static <T> T getField(Class<?> class1, Class<T> fieldType, Object instance, String fieldName)
{
try
{
public static <T> T getField(Class<?> class1, Class<T> fieldType, Object instance, String fieldName) {
try {
Field field = class1.getDeclaredField(fieldName);
field.setAccessible(true);
return (T) field.get(instance);
}
catch(Exception e)
{
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static <T> T newInstance(Class<T> class1, Object... params) throws IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException
{
nextMethod: for(Constructor<?> constructor : class1.getDeclaredConstructors())
{
public static <T> T newInstance(Class<T> class1, Object... params)
throws IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException {
nextMethod: for (Constructor<?> constructor : class1.getDeclaredConstructors()) {
Class<?>[] paramtypes = constructor.getParameterTypes();
if(paramtypes.length != params.length)
continue;
for(int i = 0; i < params.length; i++)
{
if(!isInstance(paramtypes[i], params[i]))
continue nextMethod;
if (paramtypes.length != params.length) continue;
for (int i = 0; i < params.length; i++) {
if (!isInstance(paramtypes[i], params[i])) continue nextMethod;
}
constructor.setAccessible(true);
return (T)constructor.newInstance(params);
return (T) constructor.newInstance(params);
}
return null;
}
public static boolean hasField(Class<?> class1, String fieldName)
{
try
{
public static boolean hasField(Class<?> class1, String fieldName) {
try {
class1.getDeclaredField(fieldName);
return true;
}
catch(NoSuchFieldException nfe)
{
} catch (NoSuchFieldException nfe) {
return false;
}
}
public static <T> T get(Field field, Class<T> class1)
{
public static <T> T get(Field field, Class<T> class1) {
return get(field, class1, null);
}
public static <T> T get(Field field, Class<T> class1, Object instance)
{
try
{
return (T)field.get(instance);
}
catch(Exception e)
{
throw new RuntimeException(e);
}
}
public static void set(Field field, Object value)
{
set(field, null, value);
}
public static void set(Field field, Object instance, Object value)
{
try
{
field.set(instance, value);
}
catch(Exception e)
{
public static <T> T get(Field field, Class<T> class1, Object instance) {
try {
return (T) field.get(instance);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static Field getField(ObfMapping mapping)
{
public static void set(Field field, Object value) {
set(field, null, value);
}
public static void set(Field field, Object instance, Object value) {
try {
field.set(instance, value);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static Field getField(ObfMapping mapping) {
mapping.toRuntime();
try
{
try {
Class<?> clazz = ReflectionManager.class.getClassLoader().loadClass(mapping.javaClass());
Field field = clazz.getDeclaredField(mapping.s_name);
field.setAccessible(true);
return field;
}
catch(Exception e)
{
} catch (Exception e) {
throw new RuntimeException(e);
}
}
+25 -20
View File
@@ -7,16 +7,18 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import codechicken.lib.asm.ObfMapping;
import com.mojang.authlib.GameProfile;
import net.minecraft.server.MinecraftServer;
import net.minecraft.inventory.Container;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.inventory.Container;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.IChatComponent;
public class ServerUtils extends CommonUtils
{
import com.mojang.authlib.GameProfile;
import codechicken.lib.asm.ObfMapping;
public class ServerUtils extends CommonUtils {
public static MinecraftServer mc() {
return MinecraftServer.getServer();
}
@@ -31,9 +33,7 @@ public class ServerUtils extends CommonUtils
public static ArrayList<EntityPlayer> getPlayersInDimension(int dimension) {
ArrayList<EntityPlayer> players = new ArrayList<EntityPlayer>();
for (EntityPlayer p : getPlayers())
if(p.dimension == dimension)
players.add(p);
for (EntityPlayer p : getPlayers()) if (p.dimension == dimension) players.add(p);
return players;
}
@@ -50,13 +50,21 @@ public class ServerUtils extends CommonUtils
private static Field field_152661_c;
private static Class<?> c_ProfileEntry;
private static Method func_152668_a;
static {
try {
field_152661_c = ReflectionManager.getField(new ObfMapping("net/minecraft/server/management/PlayerProfileCache", "field_152661_c", "[Ljava/util/Map;"));
c_ProfileEntry = ServerUtils.class.getClassLoader().loadClass("net.minecraft.server.management.PlayerProfileCache$ProfileEntry");
field_152661_c = ReflectionManager.getField(
new ObfMapping(
"net/minecraft/server/management/PlayerProfileCache",
"field_152661_c",
"[Ljava/util/Map;"));
c_ProfileEntry = ServerUtils.class.getClassLoader()
.loadClass("net.minecraft.server.management.PlayerProfileCache$ProfileEntry");
func_152668_a = c_ProfileEntry.getDeclaredMethod(
new ObfMapping("net/minecraft/server/management/PlayerProfileCache$ProfileEntry",
"func_152668_a", "()Lcom/mojang/authlib/GameProfile;").toRuntime().s_name);
new ObfMapping(
"net/minecraft/server/management/PlayerProfileCache$ProfileEntry",
"func_152668_a",
"()Lcom/mojang/authlib/GameProfile;").toRuntime().s_name);
func_152668_a.setAccessible(true);
} catch (Exception e) {
@@ -66,14 +74,12 @@ public class ServerUtils extends CommonUtils
public static GameProfile getGameProfile(String username) {
EntityPlayer player = getPlayer(username);
if(player != null)
return player.getGameProfile();
if (player != null) return player.getGameProfile();
username = username.toLowerCase(Locale.ROOT);
try {//use reflection to bypass saving the game profiles every time we ask the cache for one
try { // use reflection to bypass saving the game profiles every time we ask the cache for one
Object cacheEntry = ((Map) field_152661_c.get(mc().func_152358_ax())).get(username);
if(cacheEntry != null)
return (GameProfile) func_152668_a.invoke(cacheEntry);
if (cacheEntry != null) return (GameProfile) func_152668_a.invoke(cacheEntry);
} catch (Exception e) {
throw new RuntimeException(e);
}
@@ -90,7 +96,6 @@ public class ServerUtils extends CommonUtils
}
public static void sendChatToAll(IChatComponent msg) {
for(EntityPlayer p : getPlayers())
p.addChatComponentMessage(msg);
for (EntityPlayer p : getPlayers()) p.addChatComponentMessage(msg);
}
}
@@ -5,61 +5,53 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map.Entry;
public class TaskProfiler
{
public static class ProfilerResult
{
public class TaskProfiler {
public static class ProfilerResult {
public final String name;
public final long time;
public final double fraction;
public ProfilerResult(String name, long time, long totalTime)
{
public ProfilerResult(String name, long time, long totalTime) {
this.name = name;
this.time = time;
fraction = time/(double)totalTime;
fraction = time / (double) totalTime;
}
}
public HashMap<String, Long> times = new HashMap<String, Long>();
public String currentSection;
private long startTime;
private long totalTime;
public void start(String section)
{
if(currentSection != null)
end();
public void start(String section) {
if (currentSection != null) end();
currentSection = section;
startTime = System.nanoTime();
}
public void end()
{
long time = System.nanoTime()-startTime;
totalTime+=time;
public void end() {
long time = System.nanoTime() - startTime;
totalTime += time;
Long prev = times.get(currentSection);
if(prev == null)
prev = 0L;
times.put(currentSection, prev+time);
if (prev == null) prev = 0L;
times.put(currentSection, prev + time);
currentSection = null;
}
public List<ProfilerResult> getResults()
{
public List<ProfilerResult> getResults() {
ArrayList<ProfilerResult> results = new ArrayList<ProfilerResult>(times.size());
for(Entry<String, Long> e : times.entrySet())
for (Entry<String, Long> e : times.entrySet())
results.add(new ProfilerResult(e.getKey(), e.getValue(), totalTime));
return results;
}
public void clear()
{
if(currentSection != null)
end();
public void clear() {
if (currentSection != null) end();
times.clear();
totalTime = 0;
}
@@ -6,12 +6,11 @@ import java.lang.reflect.Field;
import com.google.common.collect.ImmutableBiMap;
import codechicken.lib.asm.ObfMapping;
import cpw.mods.fml.common.asm.transformers.AccessTransformer;
import cpw.mods.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper;
public class CodeChickenAccessTransformer extends AccessTransformer
{
public class CodeChickenAccessTransformer extends AccessTransformer {
private static boolean makeAllPublic;
private static Field f_classNameBiMap;
private static Object emptyMap = ImmutableBiMap.of();
@@ -22,17 +21,15 @@ public class CodeChickenAccessTransformer extends AccessTransformer
}
private void loadPublicConfig() {
if (ObfMapping.obfuscated)
return;
if (ObfMapping.obfuscated) return;
makeAllPublic = CodeChickenCoreModContainer.config.getTag("dev.runtimePublic")
.setComment("Enabling this setting will make all minecraft classes public at runtime in MCP just as they are in modloader." +
"\nYou should ONLY use this when you are testing with a mod that relies on runtime publicity and doesn't include access transformers." +
"\nSuch mods are doing the wrong thing and should be fixed.")
makeAllPublic = CodeChickenCoreModContainer.config.getTag("dev.runtimePublic").setComment(
"Enabling this setting will make all minecraft classes public at runtime in MCP just as they are in modloader."
+ "\nYou should ONLY use this when you are testing with a mod that relies on runtime publicity and doesn't include access transformers."
+ "\nSuch mods are doing the wrong thing and should be fixed.")
.getBooleanValue(false);
if (!makeAllPublic)
return;
if (!makeAllPublic) return;
try {
f_classNameBiMap = FMLDeobfuscatingRemapper.class.getDeclaredField("classNameBiMap");
@@ -45,11 +42,9 @@ public class CodeChickenAccessTransformer extends AccessTransformer
@Override
public byte[] transform(String name, String transformedName, byte[] bytes) {
boolean setPublic = makeAllPublic && name.startsWith("net.minecraft.");
if (setPublic)
setClassMap(name);
if (setPublic) setClassMap(name);
bytes = super.transform(name, transformedName, bytes);
if (setPublic)
restoreClassMap();
if (setPublic) restoreClassMap();
return bytes;
}
@@ -4,31 +4,34 @@ import java.io.File;
import java.util.LinkedList;
import java.util.List;
import codechicken.core.CCUpdateChecker;
import net.minecraftforge.common.MinecraftForge;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;
import codechicken.core.ClientUtils;
import codechicken.core.featurehack.LiquidTextures;
import codechicken.core.internal.CCCEventHandler;
import codechicken.core.launch.CodeChickenCorePlugin;
import codechicken.lib.config.ConfigFile;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;
import cpw.mods.fml.common.*;
import cpw.mods.fml.common.DummyModContainer;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.LoadController;
import cpw.mods.fml.common.ModMetadata;
import cpw.mods.fml.common.event.FMLInitializationEvent;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import cpw.mods.fml.common.versioning.ArtifactVersion;
import cpw.mods.fml.common.versioning.VersionParser;
import cpw.mods.fml.common.versioning.VersionRange;
import net.minecraftforge.common.MinecraftForge;
public class CodeChickenCoreModContainer extends DummyModContainer
{
public class CodeChickenCoreModContainer extends DummyModContainer {
public static ConfigFile config;
public static void loadConfig() {
if(config == null)
config = new ConfigFile(new File(CodeChickenCorePlugin.minecraftDir, "config/CodeChickenCore.cfg")).setComment("CodeChickenCore configuration file.");
if (config == null)
config = new ConfigFile(new File(CodeChickenCorePlugin.minecraftDir, "config/CodeChickenCore.cfg"))
.setComment("CodeChickenCore configuration file.");
}
public CodeChickenCoreModContainer() {
@@ -37,16 +40,16 @@ public class CodeChickenCoreModContainer extends DummyModContainer
private static ModMetadata getModMetadata() {
final ModMetadata modMetadata = new ModMetadata();
modMetadata.name = "GRADLETOKEN_MODNAME";
modMetadata.modId = "GRADLETOKEN_MODID";
modMetadata.version = "GRADLETOKEN_VERSION";
modMetadata.name = "CodeChicken Core";
modMetadata.modId = "CodeChickenCore";
modMetadata.version = Tags.VERSION;
return modMetadata;
}
@Override
public List<ArtifactVersion> getDependants() {
LinkedList<ArtifactVersion> deps = new LinkedList<ArtifactVersion>();
if(!getVersion().contains("$")) {
if (!getVersion().contains("$")) {
deps.add(VersionParser.parseVersionReference("Forge@[10.13.3,)"));
deps.add(VersionParser.parseVersionReference("NotEnoughItems@[1.0.5,)"));
deps.add(VersionParser.parseVersionReference("EnderStorage@[1.4.7,)"));
@@ -65,16 +68,12 @@ public class CodeChickenCoreModContainer extends DummyModContainer
@Subscribe
public void preInit(FMLPreInitializationEvent event) {
if (event.getSide().isClient())
LiquidTextures.init();
if (event.getSide().isClient()) LiquidTextures.init();
}
@Subscribe
public void init(FMLInitializationEvent event) {
if (event.getSide().isClient()) {
if (config.getTag("checkUpdates").getBooleanValue(true))
CCUpdateChecker.updateCheck(getModId());
ClientUtils.enhanceSupportersList("CodeChickenCore");
FMLCommonHandler.instance().bus().register(new CCCEventHandler());
@@ -6,6 +6,9 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import net.minecraft.launchwrapper.IClassTransformer;
import net.minecraft.launchwrapper.LaunchClassLoader;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.MethodNode;
@@ -13,82 +16,78 @@ import codechicken.lib.asm.ASMHelper;
import codechicken.lib.asm.ClassHeirachyManager;
import codechicken.lib.asm.ObfMapping;
import net.minecraft.launchwrapper.IClassTransformer;
import net.minecraft.launchwrapper.LaunchClassLoader;
public class DefaultImplementationTransformer implements IClassTransformer {
private static LaunchClassLoader cl = (LaunchClassLoader) ClassHeirachyManager.class.getClassLoader();
public class DefaultImplementationTransformer implements IClassTransformer
{
private static LaunchClassLoader cl = (LaunchClassLoader)ClassHeirachyManager.class.getClassLoader();
private static ClassNode getClassNode(String name) {
try {
return ASMHelper.createClassNode(cl.getClassBytes(name.replace('/', '.')));
} catch (IOException e) {
throw new RuntimeException(e);
}
try {
return ASMHelper.createClassNode(cl.getClassBytes(name.replace('/', '.')));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
static class InterfaceImpl
{
public final String iname;
public ArrayList<MethodNode> impls = new ArrayList<MethodNode>();
public InterfaceImpl(String iname, String cname)
{
this.iname = iname;
HashSet<String> names = new HashSet<String>();
ClassNode inode = getClassNode(iname);
for(MethodNode method : inode.methods)
names.add(method.name+method.desc);
ClassNode cnode = getClassNode(cname);
for(MethodNode method : cnode.methods)
if(names.contains(method.name+method.desc)) {
impls.add(method);
method.desc = new ObfMapping(cnode.name, method.name, method.desc).toRuntime().s_desc;
}
}
public boolean patch(ClassNode cnode) {
LinkedList<String> names = new LinkedList<String>();
for(MethodNode method : cnode.methods) {
ObfMapping m = new ObfMapping(cnode.name, method.name, method.desc).toRuntime();
names.add(m.s_name+m.s_desc);
}
static class InterfaceImpl {
boolean changed = false;
for(MethodNode impl : impls) {
if(names.contains(impl.name+impl.desc))
continue;
MethodNode copy = new MethodNode(impl.access, impl.name, impl.desc,
impl.signature, impl.exceptions == null ? null : impl.exceptions.toArray(new String[0]));
ASMHelper.copy(impl, copy);
cnode.methods.add(impl);
changed = true;
}
return changed;
}
}
private static HashMap<String, InterfaceImpl> impls = new HashMap<String, InterfaceImpl>();
public static void registerDefaultImpl(String iname, String cname) {
impls.put(iname.replace('.', '/'), new InterfaceImpl(iname, cname));
}
@Override
public byte[] transform(String name, String transformedName, byte[] bytes) {
if(transformedName.startsWith("net.minecraft") || impls.isEmpty())
return bytes;
ClassNode cnode = ASMHelper.createClassNode(bytes);
boolean changed = false;
for(String iname : cnode.interfaces) {
InterfaceImpl impl = impls.get(iname);
if(impl != null)
changed |= impl.patch(cnode);
}
return changed ? ASMHelper.createBytes(cnode, 0) : bytes;
}
public final String iname;
public ArrayList<MethodNode> impls = new ArrayList<MethodNode>();
public InterfaceImpl(String iname, String cname) {
this.iname = iname;
HashSet<String> names = new HashSet<String>();
ClassNode inode = getClassNode(iname);
for (MethodNode method : inode.methods) names.add(method.name + method.desc);
ClassNode cnode = getClassNode(cname);
for (MethodNode method : cnode.methods) if (names.contains(method.name + method.desc)) {
impls.add(method);
method.desc = new ObfMapping(cnode.name, method.name, method.desc).toRuntime().s_desc;
}
}
public boolean patch(ClassNode cnode) {
LinkedList<String> names = new LinkedList<String>();
for (MethodNode method : cnode.methods) {
ObfMapping m = new ObfMapping(cnode.name, method.name, method.desc).toRuntime();
names.add(m.s_name + m.s_desc);
}
boolean changed = false;
for (MethodNode impl : impls) {
if (names.contains(impl.name + impl.desc)) continue;
MethodNode copy = new MethodNode(
impl.access,
impl.name,
impl.desc,
impl.signature,
impl.exceptions == null ? null : impl.exceptions.toArray(new String[0]));
ASMHelper.copy(impl, copy);
cnode.methods.add(impl);
changed = true;
}
return changed;
}
}
private static HashMap<String, InterfaceImpl> impls = new HashMap<String, InterfaceImpl>();
public static void registerDefaultImpl(String iname, String cname) {
impls.put(iname.replace('.', '/'), new InterfaceImpl(iname, cname));
}
@Override
public byte[] transform(String name, String transformedName, byte[] bytes) {
if (transformedName.startsWith("net.minecraft") || impls.isEmpty()) return bytes;
ClassNode cnode = ASMHelper.createClassNode(bytes);
boolean changed = false;
for (String iname : cnode.interfaces) {
InterfaceImpl impl = impls.get(iname);
if (impl != null) changed |= impl.patch(cnode);
}
return changed ? ASMHelper.createBytes(cnode, 0) : bytes;
}
}
@@ -1,5 +1,7 @@
package codechicken.core.asm;
import static codechicken.core.launch.CodeChickenCorePlugin.logger;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
@@ -12,140 +14,118 @@ import java.util.Stack;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
import net.minecraft.launchwrapper.IClassTransformer;
import net.minecraft.launchwrapper.Launch;
import net.minecraft.launchwrapper.LaunchClassLoader;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.Opcodes;
import net.minecraft.launchwrapper.IClassTransformer;
import net.minecraft.launchwrapper.LaunchClassLoader;
public class DelegatedTransformer implements IClassTransformer {
import static codechicken.core.launch.CodeChickenCorePlugin.logger;
public class DelegatedTransformer implements IClassTransformer
{
private static ArrayList<IClassTransformer> delegatedTransformers;
private static Method m_defineClass;
private static Field f_cachedClasses;
public DelegatedTransformer()
{
public DelegatedTransformer() {
delegatedTransformers = new ArrayList<IClassTransformer>();
try
{
m_defineClass = ClassLoader.class.getDeclaredMethod("defineClass", String.class, byte[].class, Integer.TYPE, Integer.TYPE);
try {
m_defineClass = ClassLoader.class
.getDeclaredMethod("defineClass", String.class, byte[].class, Integer.TYPE, Integer.TYPE);
m_defineClass.setAccessible(true);
f_cachedClasses = LaunchClassLoader.class.getDeclaredField("cachedClasses");
f_cachedClasses.setAccessible(true);
}
catch(Exception e)
{
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
public byte[] transform(String name, String tname, byte[] bytes)
{
public byte[] transform(String name, String tname, byte[] bytes) {
if (bytes == null) return null;
for(IClassTransformer trans : delegatedTransformers)
bytes = trans.transform(name, tname, bytes);
for (IClassTransformer trans : delegatedTransformers) bytes = trans.transform(name, tname, bytes);
return bytes;
}
public static void addTransformer(String transformer, JarFile jar, File jarFile)
{
public static void addTransformer(String transformer, JarFile jar, File jarFile) {
logger.debug("Adding CCTransformer: " + transformer);
try
{
try {
byte[] bytes;
bytes = Launch.classLoader.getClassBytes(transformer);
if(bytes == null)
{
String resourceName = transformer.replace('.', '/')+".class";
if (bytes == null) {
String resourceName = transformer.replace('.', '/') + ".class";
ZipEntry entry = jar.getEntry(resourceName);
if(entry == null)
throw new Exception("Failed to add transformer: "+transformer+". Entry not found in jar file "+jarFile.getName());
if (entry == null) throw new Exception(
"Failed to add transformer: " + transformer
+ ". Entry not found in jar file "
+ jarFile.getName());
bytes = readFully(jar.getInputStream(entry));
}
defineDependancies(bytes, jar, jarFile);
Class<?> clazz = defineClass(transformer, bytes);
if(!IClassTransformer.class.isAssignableFrom(clazz))
throw new Exception("Failed to add transformer: "+transformer+" is not an instance of IClassTransformer");
if (!IClassTransformer.class.isAssignableFrom(clazz)) throw new Exception(
"Failed to add transformer: " + transformer + " is not an instance of IClassTransformer");
IClassTransformer classTransformer;
try
{
try {
classTransformer = (IClassTransformer) clazz.getDeclaredConstructor(File.class).newInstance(jarFile);
}
catch(NoSuchMethodException nsme)
{
} catch (NoSuchMethodException nsme) {
classTransformer = (IClassTransformer) clazz.newInstance();
}
delegatedTransformers.add(classTransformer);
}
catch(Exception e)
{
} catch (Exception e) {
e.printStackTrace();
}
}
}
private static void defineDependancies(byte[] bytes, JarFile jar, File jarFile) throws Exception
{
private static void defineDependancies(byte[] bytes, JarFile jar, File jarFile) throws Exception {
defineDependancies(bytes, jar, jarFile, new Stack<String>());
}
private static void defineDependancies(byte[] bytes, JarFile jar, File jarFile, Stack<String> depStack) throws Exception
{
private static void defineDependancies(byte[] bytes, JarFile jar, File jarFile, Stack<String> depStack)
throws Exception {
ClassReader reader = new ClassReader(bytes);
DependancyLister lister = new DependancyLister(Opcodes.ASM4);
reader.accept(lister, 0);
depStack.push(reader.getClassName());
for(String dependancy : lister.getDependancies())
{
if(depStack.contains(dependancy))
continue;
try
{
for (String dependancy : lister.getDependancies()) {
if (depStack.contains(dependancy)) continue;
try {
Launch.classLoader.loadClass(dependancy.replace('/', '.'));
}
catch(ClassNotFoundException cnfe)
{
ZipEntry entry = jar.getEntry(dependancy+".class");
if(entry == null)
throw new Exception("Dependency "+dependancy+" not found in jar file "+jarFile.getName());
} catch (ClassNotFoundException cnfe) {
ZipEntry entry = jar.getEntry(dependancy + ".class");
if (entry == null)
throw new Exception("Dependency " + dependancy + " not found in jar file " + jarFile.getName());
byte[] depbytes = readFully(jar.getInputStream(entry));
defineDependancies(depbytes, jar, jarFile, depStack);
logger.debug("Defining dependancy: "+dependancy);
logger.debug("Defining dependancy: " + dependancy);
defineClass(dependancy.replace('/', '.'), depbytes);
}
}
depStack.pop();
}
private static Class<?> defineClass(String classname, byte[] bytes) throws Exception
{
private static Class<?> defineClass(String classname, byte[] bytes) throws Exception {
Class<?> clazz = (Class<?>) m_defineClass.invoke(Launch.classLoader, classname, bytes, 0, bytes.length);
((Map<String, Class<?>>)f_cachedClasses.get(Launch.classLoader)).put(classname, clazz);
((Map<String, Class<?>>) f_cachedClasses.get(Launch.classLoader)).put(classname, clazz);
return clazz;
}
public static byte[] readFully(InputStream stream) throws IOException
{
public static byte[] readFully(InputStream stream) throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream(stream.available());
int r;
while ((r = stream.read()) != -1)
{
while ((r = stream.read()) != -1) {
bos.write(r);
}
@@ -12,84 +12,70 @@ import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
public class DependancyLister extends ClassVisitor
{
public class DependancyLister extends ClassVisitor {
private static Pattern classdesc = Pattern.compile("L(.+?);");
private class DependancyMethodLister extends MethodVisitor
{
public DependancyMethodLister(int api)
{
private class DependancyMethodLister extends MethodVisitor {
public DependancyMethodLister(int api) {
super(api);
}
@Override
public void visitFieldInsn(int opcode, String owner, String name, String desc)
{
public void visitFieldInsn(int opcode, String owner, String name, String desc) {
dependDesc(desc);
}
@Override
public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index)
{
public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) {
dependDesc(desc);
}
@Override
public void visitMethodInsn(int opcode, String owner, String name, String desc)
{
public void visitMethodInsn(int opcode, String owner, String name, String desc) {
depend(owner);
dependDesc(desc);
}
}
private HashSet<String> dependancies = new HashSet<String>();
public DependancyLister(int api)
{
public DependancyLister(int api) {
super(api);
}
@Override
public FieldVisitor visitField(int access, String name, String desc, String signature, Object value)
{
public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
dependDesc(desc);
return null;
}
private void dependDesc(String desc)
{
private void dependDesc(String desc) {
Matcher match = classdesc.matcher(desc);
while(match.find())
{
while (match.find()) {
String s = match.group();
depend(s.substring(1, s.length()-1));
depend(s.substring(1, s.length() - 1));
}
}
private void depend(String classname)
{
private void depend(String classname) {
dependancies.add(classname);
}
@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions)
{
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
dependDesc(desc);
return new DependancyMethodLister(Opcodes.ASM4);
}
@Override
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces)
{
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
depend(superName);
if(interfaces != null)
for(String interfacename : interfaces)
depend(interfacename);
if (interfaces != null) for (String interfacename : interfaces) depend(interfacename);
}
public List<String> getDependancies()
{
public List<String> getDependancies() {
return new ArrayList<String>(dependancies);
}
}
@@ -5,10 +5,6 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface InterfaceDependancies
{
}
@Target({ ElementType.TYPE })
public @interface InterfaceDependancies {}
@@ -1,53 +0,0 @@
package codechicken.core.asm;
import java.util.Iterator;
import codechicken.lib.asm.ASMInit;
import net.minecraft.launchwrapper.Launch;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.AnnotationNode;
import org.objectweb.asm.tree.ClassNode;
import codechicken.lib.asm.ASMHelper;
import codechicken.lib.asm.ObfMapping;
import net.minecraft.launchwrapper.IClassTransformer;
public class InterfaceDependancyTransformer implements IClassTransformer
{
static {
ASMInit.init();
}
@Override
public byte[] transform(String name, String tname, byte[] bytes) {
if (bytes == null) return null;
ClassNode cnode = ASMHelper.createClassNode(bytes);
boolean hasDependancyInterfaces = false;
if (cnode.visibleAnnotations != null)
for (AnnotationNode ann : cnode.visibleAnnotations)
if (ann.desc.equals(Type.getDescriptor(InterfaceDependancies.class))) {
hasDependancyInterfaces = true;
break;
}
if (!hasDependancyInterfaces)
return bytes;
hasDependancyInterfaces = false;
for (Iterator<String> iterator = cnode.interfaces.iterator(); iterator.hasNext(); ) {
try {
Launch.classLoader.findClass(new ObfMapping(iterator.next()).toRuntime().javaClass());
} catch (ClassNotFoundException cnfe) {
iterator.remove();
hasDependancyInterfaces = true;
}
}
if (!hasDependancyInterfaces)
return bytes;
return ASMHelper.createBytes(cnode, 0);
}
}
@@ -2,12 +2,17 @@ package codechicken.core.asm;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.*;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import codechicken.lib.asm.ASMInit;
import cpw.mods.fml.relauncher.IFMLLoadingPlugin;
import net.minecraft.launchwrapper.IClassTransformer;
import net.minecraft.launchwrapper.Launch;
import net.minecraft.launchwrapper.LaunchClassLoader;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;
@@ -19,24 +24,23 @@ import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import codechicken.lib.asm.ASMHelper;
import codechicken.lib.asm.ASMInit;
import codechicken.lib.asm.CC_ClassWriter;
import codechicken.lib.asm.ObfMapping;
import codechicken.obfuscator.IHeirachyEvaluator;
import codechicken.obfuscator.ObfuscationRun;
import codechicken.obfuscator.ObfuscationMap.ObfuscationEntry;
import codechicken.obfuscator.ObfuscationRun;
import cpw.mods.fml.common.asm.transformers.AccessTransformer;
import cpw.mods.fml.relauncher.IFMLLoadingPlugin;
import net.minecraft.launchwrapper.IClassTransformer;
import net.minecraft.launchwrapper.LaunchClassLoader;
public class MCPDeobfuscationTransformer implements IClassTransformer, Opcodes, IHeirachyEvaluator {
public class MCPDeobfuscationTransformer implements IClassTransformer, Opcodes, IHeirachyEvaluator
{
static {
ASMInit.init();
}
public static class LoadPlugin implements IFMLLoadingPlugin
{
public static class LoadPlugin implements IFMLLoadingPlugin {
@Override
public String[] getASMTransformerClass() {
return new String[0];
@@ -78,7 +82,8 @@ public class MCPDeobfuscationTransformer implements IClassTransformer, Opcodes,
try {
f_transformers = LaunchClassLoader.class.getDeclaredField("transformers");
f_modifiers = AccessTransformer.class.getDeclaredField("modifiers");
Class<?> c_Modifier = Class.forName(AccessTransformer.class.getName() + "$Modifier", false, Launch.classLoader);
Class<?> c_Modifier = Class
.forName(AccessTransformer.class.getName() + "$Modifier", false, Launch.classLoader);
f_Modifier_name = c_Modifier.getDeclaredField("name");
f_Modifier_desc = c_Modifier.getDeclaredField("desc");
@@ -118,7 +123,9 @@ public class MCPDeobfuscationTransformer implements IClassTransformer, Opcodes,
if (CodeChickenCoreModContainer.config.getTag("dev.deobfuscate")
.setComment("set to true to completely deobfuscate mcp names")
.getBooleanValue(!ObfMapping.obfuscated)) {
run = new ObfuscationRun(false, ObfMapping.MCPRemapper.getConfFiles(),
run = new ObfuscationRun(
false,
ObfMapping.MCPRemapper.getConfFiles(),
ObfuscationRun.fillDefaults(new HashMap<String, String>()));
run.obf.setHeirachyEvaluator(instance);
run.setQuiet().parseMappings();
@@ -129,7 +136,7 @@ public class MCPDeobfuscationTransformer implements IClassTransformer, Opcodes,
run.setSeargeConstants();
getTransformers().add(instance);
} else {
getTransformers().add(0, instance);//insert transformer as first.
getTransformers().add(0, instance); // insert transformer as first.
}
}
}
@@ -141,8 +148,7 @@ public class MCPDeobfuscationTransformer implements IClassTransformer, Opcodes,
activated = true;
}
if (!activated || bytes == null)
return bytes;
if (!activated || bytes == null) return bytes;
ClassNode cnode = ASMHelper.createClassNode(bytes, ClassReader.EXPAND_FRAMES);
ClassWriter cw = new CC_ClassWriter(0, true);
@@ -153,21 +159,24 @@ public class MCPDeobfuscationTransformer implements IClassTransformer, Opcodes,
private byte[] injectCallback(byte[] bytes) {
ClassNode cnode = ASMHelper.createClassNode(bytes);
MethodNode mnode = ASMHelper.findMethod(new ObfMapping(cnode.name, "<clinit>", "()V"), cnode);
mnode.instructions.insert(new MethodInsnNode(INVOKESTATIC, "codechicken/core/asm/MCPDeobfuscationTransformer", "loadCallback", "()V"));
mnode.instructions.insert(
new MethodInsnNode(
INVOKESTATIC,
"codechicken/core/asm/MCPDeobfuscationTransformer",
"loadCallback",
"()V"));
return ASMHelper.createBytes(cnode, 0);
}
public static void loadCallback() {
if (ObfMapping.obfuscated) {
//move ourselves to the end
// move ourselves to the end
List<IClassTransformer> transformers = getTransformers();
transformers.remove(instance);
transformers.add(instance);
} else {
//remap access transformers
for (IClassTransformer t : getTransformers())
if (t instanceof AccessTransformer)
remapAccessTransformer(t);
// remap access transformers
for (IClassTransformer t : getTransformers()) if (t instanceof AccessTransformer) remapAccessTransformer(t);
}
}
@@ -207,10 +216,9 @@ public class MCPDeobfuscationTransformer implements IClassTransformer, Opcodes,
name = name.replace('/', '.');
try {
byte[] bytes = Launch.classLoader.getClassBytes(name);
if (bytes != null)
return ObfuscationRun.getParents(ASMHelper.createClassNode(bytes));
if (bytes != null) return ObfuscationRun.getParents(ASMHelper.createClassNode(bytes));
} catch (IOException ignored) {}
//clear the miss cache because the library containing it might be loaded later
// clear the miss cache because the library containing it might be loaded later
Launch.classLoader.clearNegativeEntries(Collections.singleton(name));
return null;
}
@@ -218,19 +226,15 @@ public class MCPDeobfuscationTransformer implements IClassTransformer, Opcodes,
@Override
public boolean isLibClass(ObfuscationEntry desc) {
String name = desc.srg.s_owner;
for (String p : excludedPackages)
if (name.startsWith(p))
return true;
for (String p : excludedPackages) if (name.startsWith(p)) return true;
return false;
}
public static String unmap(String name) {
if (run == null)
return null;
if (run == null) return null;
ObfuscationEntry e = run.obf.lookupMcpClass(name);
if (e == null)
return null;
if (e == null) return null;
return e.obf.s_owner;
}
@@ -1,22 +1,22 @@
package codechicken.core.asm;
import static org.objectweb.asm.Opcodes.ASM4;
import java.io.File;
import java.io.PrintWriter;
import net.minecraft.launchwrapper.Launch;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.util.Printer;
import org.objectweb.asm.util.TraceMethodVisitor;
import codechicken.core.launch.CodeChickenCorePlugin;
import codechicken.lib.asm.ObfMapping;
import static org.objectweb.asm.Opcodes.*;
public class MethodASMifier extends ClassVisitor {
public class MethodASMifier extends ClassVisitor
{
PrintWriter printWriter;
ObfMapping method;
Printer asmifier;
@@ -55,10 +55,8 @@ public class MethodASMifier extends ClassVisitor
public static void printMethod(ObfMapping method, byte[] bytes, Printer printer, File toFile) {
try {
if (!toFile.getParentFile().exists())
toFile.getParentFile().mkdirs();
if (!toFile.exists())
toFile.createNewFile();
if (!toFile.getParentFile().exists()) toFile.getParentFile().mkdirs();
if (!toFile.exists()) toFile.createNewFile();
PrintWriter printWriter = new PrintWriter(toFile);
@@ -1,23 +1,28 @@
package codechicken.core.asm;
import codechicken.lib.asm.*;
import codechicken.lib.asm.ModularASMTransformer.MethodReplacer;
import codechicken.lib.asm.ModularASMTransformer.MethodTransformer;
import codechicken.lib.asm.ModularASMTransformer.MethodWriter;
import static codechicken.lib.asm.InsnComparator.findOnce;
import java.util.Map;
import net.minecraft.launchwrapper.IClassTransformer;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.JumpInsnNode;
import org.objectweb.asm.tree.LabelNode;
import org.objectweb.asm.tree.MethodNode;
import codechicken.lib.asm.ASMBlock;
import codechicken.lib.asm.ASMInit;
import codechicken.lib.asm.ASMReader;
import codechicken.lib.asm.ModularASMTransformer;
import codechicken.lib.asm.ModularASMTransformer.MethodReplacer;
import codechicken.lib.asm.ModularASMTransformer.MethodTransformer;
import codechicken.lib.asm.ModularASMTransformer.MethodWriter;
import codechicken.lib.asm.ObfMapping;
import codechicken.lib.config.ConfigTag;
import net.minecraft.launchwrapper.IClassTransformer;
import java.util.Map;
public class TweakTransformer implements IClassTransformer, Opcodes {
import static codechicken.lib.asm.InsnComparator.*;
public class TweakTransformer implements IClassTransformer, Opcodes
{
static {
ASMInit.init();
}
@@ -32,49 +37,68 @@ public class TweakTransformer implements IClassTransformer, Opcodes
.setComment("Various tweaks that can be applied to game mechanics.").useBraces();
tweaks.removeTag("persistantLava");
if (tweaks.getTag("environmentallyFriendlyCreepers")
.setComment("If set to true, creepers will not destroy landscape. (A version of mobGriefing setting just for creepers)")
if (tweaks.getTag("environmentallyFriendlyCreepers").setComment(
"If set to true, creepers will not destroy landscape. (A version of mobGriefing setting just for creepers)")
.getBooleanValue(false)) {
transformer.add(new MethodReplacer(new ObfMapping("net/minecraft/entity/monster/EntityCreeper", "func_146077_cc", "()V"),
blocks.get("d_environmentallyFriendlyCreepers"), blocks.get("environmentallyFriendlyCreepers")));
transformer.add(
new MethodReplacer(
new ObfMapping("net/minecraft/entity/monster/EntityCreeper", "func_146077_cc", "()V"),
blocks.get("d_environmentallyFriendlyCreepers"),
blocks.get("environmentallyFriendlyCreepers")));
}
if (!tweaks.getTag("softLeafReplace")
.setComment("If set to false, leaves will only replace air when growing")
if (!tweaks.getTag("softLeafReplace").setComment("If set to false, leaves will only replace air when growing")
.getBooleanValue(false)) {
transformer.add(new MethodWriter(ACC_PUBLIC, new ObfMapping("net/minecraft/block/Block", "canBeReplacedByLeaves", "(Lnet/minecraft/world/IBlockAccess;III)Z"), blocks.get("softLeafReplace")));
transformer.add(
new MethodWriter(
ACC_PUBLIC,
new ObfMapping(
"net/minecraft/block/Block",
"canBeReplacedByLeaves",
"(Lnet/minecraft/world/IBlockAccess;III)Z"),
blocks.get("softLeafReplace")));
}
if (tweaks.getTag("doFireTickOut")
.setComment("If set to true and doFireTick is disabled in the game rules, fire will still dissipate if it's not over a fire source")
if (tweaks.getTag("doFireTickOut").setComment(
"If set to true and doFireTick is disabled in the game rules, fire will still dissipate if it's not over a fire source")
.getBooleanValue(true)) {
transformer.add(new MethodTransformer(new ObfMapping("net/minecraft/block/BlockFire", "func_149674_a", "(Lnet/minecraft/world/World;IIILjava/util/Random;)V"))
{
@Override
public void transform(MethodNode mv) {
ASMBlock needle = blocks.get("n_doFireTick");
ASMBlock inject = blocks.get("doFireTick");
transformer.add(
new MethodTransformer(
new ObfMapping(
"net/minecraft/block/BlockFire",
"func_149674_a",
"(Lnet/minecraft/world/World;IIILjava/util/Random;)V")) {
ASMBlock key = needle.applyLabels(findOnce(mv.instructions, needle.list));
LabelNode jlabel = key.get("LRET");
mv.instructions.insertBefore(jlabel, new JumpInsnNode(GOTO, inject.get("LSKIP")));
mv.instructions.insert(jlabel, inject.list.list);
}
});
@Override
public void transform(MethodNode mv) {
ASMBlock needle = blocks.get("n_doFireTick");
ASMBlock inject = blocks.get("doFireTick");
ASMBlock key = needle.applyLabels(findOnce(mv.instructions, needle.list));
LabelNode jlabel = key.get("LRET");
mv.instructions.insertBefore(jlabel, new JumpInsnNode(GOTO, inject.get("LSKIP")));
mv.instructions.insert(jlabel, inject.list.list);
}
});
}
if (tweaks.getTag("finiteWater")
.setComment("If set to true two adjacent water source blocks will not generate a third.")
.getBooleanValue(false)) {
transformer.add(new MethodTransformer(new ObfMapping("net/minecraft/block/BlockDynamicLiquid", "func_149674_a", "(Lnet/minecraft/world/World;IIILjava/util/Random;)V"))
{
@Override
public void transform(MethodNode mv) {
ASMBlock needle = blocks.get("finiteWater");
ASMBlock key = needle.applyLabels(findOnce(mv.instructions, needle.list));
mv.instructions.insertBefore(key.list.getFirst(), new JumpInsnNode(GOTO, key.get("LEND")));
}
});
transformer.add(
new MethodTransformer(
new ObfMapping(
"net/minecraft/block/BlockDynamicLiquid",
"func_149674_a",
"(Lnet/minecraft/world/World;IIILjava/util/Random;)V")) {
@Override
public void transform(MethodNode mv) {
ASMBlock needle = blocks.get("finiteWater");
ASMBlock key = needle.applyLabels(findOnce(mv.instructions, needle.list));
mv.instructions.insertBefore(key.list.getFirst(), new JumpInsnNode(GOTO, key.get("LEND")));
}
});
}
}
@@ -2,24 +2,25 @@ package codechicken.core.commands;
import java.util.List;
import codechicken.core.ServerUtils;
import net.minecraft.command.ICommand;
import net.minecraft.command.ICommandSender;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.ChatComponentText;
import net.minecraft.util.ChatComponentTranslation;
import net.minecraft.util.ChunkCoordinates;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.command.ICommand;
import net.minecraft.command.ICommandSender;
import net.minecraft.util.IChatComponent;
import net.minecraft.world.World;
import net.minecraft.world.WorldServer;
import net.minecraftforge.common.DimensionManager;
public abstract class CoreCommand implements ICommand
{
public class WCommandSender implements ICommandSender
{
import codechicken.core.ServerUtils;
public abstract class CoreCommand implements ICommand {
public class WCommandSender implements ICommandSender {
public ICommandSender wrapped;
public WCommandSender(ICommandSender sender) {
@@ -78,15 +79,13 @@ public abstract class CoreCommand implements ICommand
public void processCommand(ICommandSender listener, String[] args) {
WCommandSender wsender = new WCommandSender(listener);
if (args.length < minimumParameters() ||
args.length == 1 && args[0].equals("help")) {
if (args.length < minimumParameters() || args.length == 1 && args[0].equals("help")) {
printHelp(wsender);
return;
}
String command = getCommandName();
for (String arg : args)
command += " " + arg;
for (String arg : args) command += " " + arg;
handleCommand(command, wsender.getCommandSenderName(), args, wsender);
}
@@ -113,12 +112,12 @@ public abstract class CoreCommand implements ICommand
}
@Override
public List<?> getCommandAliases() {
public List<String> getCommandAliases() {
return null;
}
@Override
public List<?> addTabCompletionOptions(ICommandSender var1, String[] var2) {
public List<String> addTabCompletionOptions(ICommandSender var1, String[] var2) {
return null;
}
@@ -130,16 +129,13 @@ public abstract class CoreCommand implements ICommand
@Override
public boolean canCommandSenderUseCommand(ICommandSender var1) {
if (OPOnly()) {
if (var1 instanceof EntityPlayer)
return MinecraftServer.getServer().getConfigurationManager().func_152596_g(((EntityPlayer) var1).getGameProfile());
else if (var1 instanceof MinecraftServer)
return true;
else
return false;
if (var1 instanceof EntityPlayer) return MinecraftServer.getServer().getConfigurationManager()
.func_152596_g(((EntityPlayer) var1).getGameProfile());
else if (var1 instanceof MinecraftServer) return true;
else return false;
}
return true;
}
public abstract int minimumParameters();
}
@@ -1,60 +1,54 @@
package codechicken.core.commands;
import net.minecraft.util.MovingObjectPosition.MovingObjectType;
import net.minecraft.world.ChunkPosition;
import net.minecraft.command.ICommandSender;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.command.ICommandSender;
import net.minecraft.util.MovingObjectPosition;
import net.minecraft.util.MovingObjectPosition.MovingObjectType;
import net.minecraft.util.Vec3;
import net.minecraft.world.ChunkPosition;
import net.minecraft.world.WorldServer;
public abstract class PlayerCommand extends CoreCommand
{
public abstract class PlayerCommand extends CoreCommand {
@Override
public boolean canCommandSenderUseCommand(ICommandSender var1)
{
if(!super.canCommandSenderUseCommand(var1))
return false;
public boolean canCommandSenderUseCommand(ICommandSender var1) {
if (!super.canCommandSenderUseCommand(var1)) return false;
return var1 instanceof EntityPlayer;
}
@Override
public void handleCommand(String command, String playername, String[] args, WCommandSender listener)
{
EntityPlayerMP player = (EntityPlayerMP)listener.wrapped;
public void handleCommand(String command, String playername, String[] args, WCommandSender listener) {
EntityPlayerMP player = (EntityPlayerMP) listener.wrapped;
handleCommand(getWorld(player), player, args);
}
public abstract void handleCommand(WorldServer world, EntityPlayerMP player, String[] args);
public ChunkPosition getPlayerLookingAtBlock(EntityPlayerMP player, float reach)
{
Vec3 vec3d = Vec3.createVectorHelper(player.posX, (player.posY + 1.6200000000000001D) - player.yOffset, player.posZ);
public ChunkPosition getPlayerLookingAtBlock(EntityPlayerMP player, float reach) {
Vec3 vec3d = Vec3
.createVectorHelper(player.posX, (player.posY + 1.6200000000000001D) - player.yOffset, player.posZ);
Vec3 vec3d1 = player.getLook(1.0F);
Vec3 vec3d2 = vec3d.addVector(vec3d1.xCoord * reach, vec3d1.yCoord * reach, vec3d1.zCoord * reach);
MovingObjectPosition hit = player.worldObj.rayTraceBlocks(vec3d, vec3d2);
if(hit == null || hit.typeOfHit != MovingObjectType.BLOCK)
{
if (hit == null || hit.typeOfHit != MovingObjectType.BLOCK) {
return null;
}
return new ChunkPosition(hit.blockX, hit.blockY, hit.blockZ);
}
public Entity getPlayerLookingAtEntity(EntityPlayerMP player, float reach)
{
Vec3 vec3d = Vec3.createVectorHelper(player.posX, (player.posY + 1.6200000000000001D) - player.yOffset, player.posZ);
public Entity getPlayerLookingAtEntity(EntityPlayerMP player, float reach) {
Vec3 vec3d = Vec3
.createVectorHelper(player.posX, (player.posY + 1.6200000000000001D) - player.yOffset, player.posZ);
Vec3 vec3d1 = player.getLook(1.0F);
Vec3 vec3d2 = vec3d.addVector(vec3d1.xCoord * reach, vec3d1.yCoord * reach, vec3d1.zCoord * reach);
MovingObjectPosition hit = player.worldObj.rayTraceBlocks(vec3d, vec3d2);
if(hit == null || hit.typeOfHit != MovingObjectType.ENTITY)
{
if (hit == null || hit.typeOfHit != MovingObjectType.ENTITY) {
return null;
}
return hit.entityHit;
}
}
@@ -1,28 +1,24 @@
package codechicken.core.commands;
import net.minecraft.server.MinecraftServer;
import net.minecraft.command.ICommandSender;
import net.minecraft.server.MinecraftServer;
public abstract class ServerCommand extends CoreCommand {
public abstract class ServerCommand extends CoreCommand
{
@Override
public void processCommand(ICommandSender var1, String[] var2)
{
handleCommand(var2, (MinecraftServer)var1);
public void processCommand(ICommandSender var1, String[] var2) {
handleCommand(var2, (MinecraftServer) var1);
}
@Override
public boolean canCommandSenderUseCommand(ICommandSender var1)
{
if(!super.canCommandSenderUseCommand(var1))
return false;
public boolean canCommandSenderUseCommand(ICommandSender var1) {
if (!super.canCommandSenderUseCommand(var1)) return false;
return var1 instanceof MinecraftServer;
}
public abstract void handleCommand(String[] args, MinecraftServer listener);
public final boolean OPOnly()
{
public final boolean OPOnly() {
return false;
}
}
}
@@ -4,10 +4,10 @@ import net.minecraft.entity.Entity;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.world.World;
public class EntityRenderHook extends Entity
{
public static interface IRenderCallback
{
public class EntityRenderHook extends Entity {
public static interface IRenderCallback {
public void render(float frame, int pass);
public boolean shouldRenderInPass(int pass);
@@ -26,21 +26,17 @@ public class EntityRenderHook extends Entity
@Override
public void onUpdate() {
if (!callback.isValid())
setDead();
if (!callback.isValid()) setDead();
}
@Override
protected void entityInit() {
}
protected void entityInit() {}
@Override
protected void readEntityFromNBT(NBTTagCompound var1) {
}
protected void readEntityFromNBT(NBTTagCompound var1) {}
@Override
protected void writeEntityToNBT(NBTTagCompound var1) {
}
protected void writeEntityToNBT(NBTTagCompound var1) {}
@Override
public boolean shouldRenderInPass(int pass) {
@@ -4,44 +4,35 @@ import net.minecraft.entity.Entity;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.world.World;
public class EntityUpdateHook extends Entity
{
public static interface IUpdateCallback
{
public class EntityUpdateHook extends Entity {
public static interface IUpdateCallback {
public void onUpdate();
public boolean isValid();
}
public final IUpdateCallback callback;
public EntityUpdateHook(World world, int x, int y, int z, IUpdateCallback callback)
{
public EntityUpdateHook(World world, int x, int y, int z, IUpdateCallback callback) {
super(world);
setPosition(x, y, z);
this.callback = callback;
}
@Override
public void onUpdate()
{
if(!callback.isValid())
setDead();
else
callback.onUpdate();
public void onUpdate() {
if (!callback.isValid()) setDead();
else callback.onUpdate();
}
@Override
protected void entityInit()
{
}
protected void entityInit() {}
@Override
protected void readEntityFromNBT(NBTTagCompound var1)
{
}
protected void readEntityFromNBT(NBTTagCompound var1) {}
@Override
protected void writeEntityToNBT(NBTTagCompound var1)
{
}
protected void writeEntityToNBT(NBTTagCompound var1) {}
}
@@ -5,34 +5,28 @@ import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
public class FeatureHack
{
public class FeatureHack {
private static boolean updateHookEnabled = false;
private static boolean renderHookEnabled = false;
public static void enableUpdateHook()
{
if(updateHookEnabled)
return;
public static void enableUpdateHook() {
if (updateHookEnabled) return;
updateHookEnabled = true;
if(FMLCommonHandler.instance().getSide().isClient())
enableClientUpdateHook();
if (FMLCommonHandler.instance().getSide().isClient()) enableClientUpdateHook();
}
@SideOnly(Side.CLIENT)
public static void enableRenderHook()
{
if(renderHookEnabled)
return;
public static void enableRenderHook() {
if (renderHookEnabled) return;
renderHookEnabled = true;
RenderingRegistry.registerEntityRenderingHandler(EntityUpdateHook.class, new RenderNull());
}
@SideOnly(Side.CLIENT)
private static void enableClientUpdateHook()
{
private static void enableClientUpdateHook() {
RenderingRegistry.registerEntityRenderingHandler(EntityRenderHook.class, new RenderEntityRenderHook());
}
}
@@ -1,27 +1,31 @@
package codechicken.core.featurehack;
import codechicken.lib.asm.ObfMapping;
import java.lang.reflect.Field;
import java.util.Map;
import net.minecraft.item.Item;
import net.minecraft.util.ObjectIntIdentityMap;
import net.minecraft.util.RegistryNamespaced;
import net.minecraft.util.RegistrySimple;
import java.lang.reflect.Field;
import java.util.Map;
import codechicken.lib.asm.ObfMapping;
public class GameDataManipulator {
public class GameDataManipulator
{
public static Field f_registryObjects;
public static Field f_underlyingIntegerMap;
static
{
static {
try {
f_registryObjects = RegistrySimple.class.getDeclaredField(
new ObfMapping("net/minecraft/util/RegistrySimple", "field_82596_a", "Ljava/util/Map;").toRuntime().s_name);
new ObfMapping("net/minecraft/util/RegistrySimple", "field_82596_a", "Ljava/util/Map;")
.toRuntime().s_name);
f_registryObjects.setAccessible(true);
f_underlyingIntegerMap = RegistryNamespaced.class.getDeclaredField(
new ObfMapping("net/minecraft/util/RegistryNamespaced", "field_148759_a", "Lnet/minecraft/util/ObjectIntIdentityMap;").toRuntime().s_name);
new ObfMapping(
"net/minecraft/util/RegistryNamespaced",
"field_148759_a",
"Lnet/minecraft/util/ObjectIntIdentityMap;").toRuntime().s_name);
f_underlyingIntegerMap.setAccessible(true);
} catch (Exception e) {
throw new RuntimeException(e);
@@ -31,8 +35,8 @@ public class GameDataManipulator
public static void replaceItem(int id, Item item) {
try {
String name = Item.itemRegistry.getNameForObject(Item.getItemById(id));
((Map)f_registryObjects.get(Item.itemRegistry)).put(name, item);
((ObjectIntIdentityMap)f_underlyingIntegerMap.get(Item.itemRegistry)).func_148746_a(item, id);
((Map) f_registryObjects.get(Item.itemRegistry)).put(name, item);
((ObjectIntIdentityMap) f_underlyingIntegerMap.get(Item.itemRegistry)).func_148746_a(item, id);
} catch (Exception e) {
throw new RuntimeException(e);
}
@@ -1,58 +1,55 @@
package codechicken.core.featurehack;
import java.lang.reflect.Field;
import codechicken.core.ReflectionManager;
import codechicken.core.featurehack.mc.TextureLavaFX;
import codechicken.core.featurehack.mc.TextureLavaFlowFX;
import codechicken.core.featurehack.mc.TextureWaterFX;
import codechicken.core.featurehack.mc.TextureWaterFlowFX;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import net.minecraft.block.Block;
import net.minecraft.init.Blocks;
import net.minecraft.util.IIcon;
import net.minecraftforge.client.event.TextureStitchEvent;
import net.minecraftforge.common.MinecraftForge;
import codechicken.core.ReflectionManager;
import codechicken.core.asm.TweakTransformer;
import codechicken.core.featurehack.mc.TextureLavaFX;
import codechicken.core.featurehack.mc.TextureLavaFlowFX;
import codechicken.core.featurehack.mc.TextureWaterFX;
import codechicken.core.featurehack.mc.TextureWaterFlowFX;
import codechicken.lib.asm.ObfMapping;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
public class LiquidTextures {
public class LiquidTextures
{
public static IIcon[] newTextures = new IIcon[4];
public static boolean replaceLava;
public static boolean replaceWater;
private static Field field_tex;
public static void init()
{
replaceWater = TweakTransformer.tweaks.getTag("replaceWaterFX").setComment("Set this to true to use the pre1.5 water textures").getBooleanValue(false);
replaceLava = TweakTransformer.tweaks.getTag("replaceLavaFX").setComment("Set this to true to use the pre1.5 lava textures").getBooleanValue(false);
if(replaceWater)
{
public static void init() {
replaceWater = TweakTransformer.tweaks.getTag("replaceWaterFX")
.setComment("Set this to true to use the pre1.5 water textures").getBooleanValue(false);
replaceLava = TweakTransformer.tweaks.getTag("replaceLavaFX")
.setComment("Set this to true to use the pre1.5 lava textures").getBooleanValue(false);
if (replaceWater) {
newTextures[0] = new TextureWaterFX().texture;
newTextures[1] = new TextureWaterFlowFX().texture;
}
if(replaceLava)
{
if (replaceLava) {
newTextures[2] = new TextureLavaFX().texture;
newTextures[3] = new TextureLavaFlowFX().texture;
}
if(replaceWater || replaceLava)
{
if (replaceWater || replaceLava) {
MinecraftForge.EVENT_BUS.register(new LiquidTextures());
field_tex = ReflectionManager.getField(new ObfMapping("net/minecraft/block/BlockLiquid", "field_149806_a", "[Lnet/minecraft/util/IIcon;"));
field_tex = ReflectionManager.getField(
new ObfMapping("net/minecraft/block/BlockLiquid", "field_149806_a", "[Lnet/minecraft/util/IIcon;"));
}
}
@SubscribeEvent
public void postStitch(TextureStitchEvent.Post event)
{
public void postStitch(TextureStitchEvent.Post event) {
IIcon[] icons;
if(replaceLava)
{
if (replaceLava) {
icons = ReflectionManager.get(field_tex, IIcon[].class, Blocks.flowing_lava);
icons[0] = newTextures[2];
icons[1] = newTextures[3];
@@ -60,8 +57,7 @@ public class LiquidTextures
icons[0] = newTextures[2];
icons[1] = newTextures[3];
}
if(replaceWater)
{
if (replaceWater) {
icons = ReflectionManager.get(field_tex, IIcon[].class, Blocks.flowing_water);
icons[0] = newTextures[0];
icons[1] = newTextures[1];
@@ -1,26 +1,24 @@
package codechicken.core.featurehack;
import net.minecraft.client.renderer.entity.Render;
import net.minecraft.entity.Entity;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.MinecraftForgeClient;
import org.lwjgl.opengl.GL11;
import net.minecraft.entity.Entity;
import net.minecraft.util.ResourceLocation;
import net.minecraft.client.renderer.entity.Render;
import net.minecraftforge.client.MinecraftForgeClient;
public class RenderEntityRenderHook extends Render {
public class RenderEntityRenderHook extends Render
{
@Override
public void doRender(Entity entity, double x, double y, double z, float f, float frame)
{
EntityRenderHook hook = (EntityRenderHook)entity;
GL11.glTranslated(x-hook.posX, y-hook.posY, z-hook.posZ);
((EntityRenderHook)entity).callback.render(frame, MinecraftForgeClient.getRenderPass());
GL11.glTranslated(hook.posX-x, hook.posY-y, hook.posZ-z);
public void doRender(Entity entity, double x, double y, double z, float f, float frame) {
EntityRenderHook hook = (EntityRenderHook) entity;
GL11.glTranslated(x - hook.posX, y - hook.posY, z - hook.posZ);
((EntityRenderHook) entity).callback.render(frame, MinecraftForgeClient.getRenderPass());
GL11.glTranslated(hook.posX - x, hook.posY - y, hook.posZ - z);
}
@Override
protected ResourceLocation getEntityTexture(Entity entity)
{
protected ResourceLocation getEntityTexture(Entity entity) {
return null;
}
}
@@ -4,16 +4,13 @@ import net.minecraft.client.renderer.entity.Render;
import net.minecraft.entity.Entity;
import net.minecraft.util.ResourceLocation;
public class RenderNull extends Render
{
public class RenderNull extends Render {
@Override
public void doRender(Entity var1, double var2, double var4, double var6, float var8, float var9)
{
}
public void doRender(Entity var1, double var2, double var4, double var6, float var8, float var9) {}
@Override
protected ResourceLocation getEntityTexture(Entity entity)
{
protected ResourceLocation getEntityTexture(Entity entity) {
return null;
}
}
@@ -1,38 +1,37 @@
package codechicken.core.featurehack;
import static net.minecraftforge.common.util.ForgeDirection.UP;
import java.util.Random;
import net.minecraft.block.Block;
import net.minecraft.init.Blocks;
import net.minecraft.world.World;
import static net.minecraftforge.common.util.ForgeDirection.UP;
public class TweakTransformerHelper {
public class TweakTransformerHelper
{
public static void quenchFireTick(World world, int x, int y, int z, Random rand)
{
public static void quenchFireTick(World world, int x, int y, int z, Random rand) {
Block base = world.getBlock(x, y - 1, z);
boolean supported = (base != null && base.isFireSource(world, x, y - 1, z, UP));
if (!Blocks.fire.canPlaceBlockAt(world, x, y, z) ||
!supported && world.isRaining() && (world.canLightningStrikeAt(x, y, z) || world.canLightningStrikeAt(x - 1, y, z) || world.canLightningStrikeAt(x + 1, y, z) || world.canLightningStrikeAt(x, y, z - 1) || world.canLightningStrikeAt(x, y, z + 1)))
if (!Blocks.fire.canPlaceBlockAt(world, x, y, z) || !supported && world.isRaining()
&& (world.canLightningStrikeAt(x, y, z) || world.canLightningStrikeAt(x - 1, y, z)
|| world.canLightningStrikeAt(x + 1, y, z)
|| world.canLightningStrikeAt(x, y, z - 1)
|| world.canLightningStrikeAt(x, y, z + 1)))
world.setBlockToAir(x, y, z);
else
{
else {
int meta = world.getBlockMetadata(x, y, z);
if(meta < 15)
world.setBlockMetadataWithNotify(x, y, z, meta+rand.nextInt(3)/2, 0);
if (meta < 15) world.setBlockMetadataWithNotify(x, y, z, meta + rand.nextInt(3) / 2, 0);
world.scheduleBlockUpdate(x, y, z, Blocks.fire, Blocks.fire.tickRate(world) + rand.nextInt(10));
if(!supported && !Blocks.fire.canCatchFire(world, x, y - 1, z, UP) && meta == 15 && rand.nextInt(4) == 0)
if (!supported && !Blocks.fire.canCatchFire(world, x, y - 1, z, UP) && meta == 15 && rand.nextInt(4) == 0)
world.setBlockToAir(x, y, z);
}
}
public static boolean canPlaceBlockAt(World world, int x, int y, int z)
{
public static boolean canPlaceBlockAt(World world, int x, int y, int z) {
Block block = world.getBlock(x, y, z);
return block.isAir(world, x, y, z) || block.isReplaceable(world, x, y, z);
}
@@ -1,28 +1,27 @@
package codechicken.core.featurehack.mc;
import net.minecraft.util.MathHelper;
import codechicken.lib.colour.ColourRGBA;
import codechicken.lib.render.TextureFX;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.util.MathHelper;
@SideOnly(Side.CLIENT)
public class TextureLavaFX extends TextureFX
{
public class TextureLavaFX extends TextureFX {
protected float[] field_76876_g = new float[256];
protected float[] field_76878_h = new float[256];
protected float[] field_76879_i = new float[256];
protected float[] field_76877_j = new float[256];
public TextureLavaFX()
{
public TextureLavaFX() {
super(16, "lava_still_fx");
setup();
}
@Override
public void setup()
{
public void setup() {
super.setup();
field_76876_g = new float[tileSizeSquare];
field_76878_h = new float[tileSizeSquare];
@@ -30,8 +29,7 @@ public class TextureLavaFX extends TextureFX
field_76877_j = new float[tileSizeSquare];
}
public void onTick()
{
public void onTick() {
int var2;
float var3;
int var5;
@@ -40,36 +38,40 @@ public class TextureLavaFX extends TextureFX
int var8;
int var9;
for (int var1 = 0; var1 < tileSizeBase; ++var1)
{
for (var2 = 0; var2 < tileSizeBase; ++var2)
{
for (int var1 = 0; var1 < tileSizeBase; ++var1) {
for (var2 = 0; var2 < tileSizeBase; ++var2) {
var3 = 0.0F;
int var4 = (int)(MathHelper.sin(var2 * (float)Math.PI * 2.0F / 16.0F) * 1.2F);
var5 = (int)(MathHelper.sin(var1 * (float)Math.PI * 2.0F / 16.0F) * 1.2F);
int var4 = (int) (MathHelper.sin(var2 * (float) Math.PI * 2.0F / 16.0F) * 1.2F);
var5 = (int) (MathHelper.sin(var1 * (float) Math.PI * 2.0F / 16.0F) * 1.2F);
for (var6 = var1 - 1; var6 <= var1 + 1; ++var6)
{
for (var7 = var2 - 1; var7 <= var2 + 1; ++var7)
{
for (var6 = var1 - 1; var6 <= var1 + 1; ++var6) {
for (var7 = var2 - 1; var7 <= var2 + 1; ++var7) {
var8 = var6 + var4 & tileSizeMask;
var9 = var7 + var5 & tileSizeMask;
var3 += this.field_76876_g[var8 + var9 * tileSizeBase];
}
}
this.field_76878_h[var1 + var2 * tileSizeBase] = var3 / 10.0F + (this.field_76879_i[(var1 + 0 & tileSizeMask) + (var2 + 0 & tileSizeMask) * tileSizeBase] + this.field_76879_i[(var1 + 1 & tileSizeMask) + (var2 + 0 & tileSizeMask) * tileSizeBase] + this.field_76879_i[(var1 + 1 & tileSizeMask) + (var2 + 1 & tileSizeMask) * tileSizeBase] + this.field_76879_i[(var1 + 0 & tileSizeMask) + (var2 + 1 & tileSizeMask) * tileSizeBase]) / 4.0F * 0.8F;
this.field_76879_i[var1 + var2 * tileSizeBase] += this.field_76877_j[var1 + var2 * tileSizeBase] * 0.01F;
this.field_76878_h[var1 + var2 * tileSizeBase] = var3 / 10.0F
+ (this.field_76879_i[(var1 + 0 & tileSizeMask) + (var2 + 0 & tileSizeMask) * tileSizeBase]
+ this.field_76879_i[(var1 + 1 & tileSizeMask)
+ (var2 + 0 & tileSizeMask) * tileSizeBase]
+ this.field_76879_i[(var1 + 1 & tileSizeMask)
+ (var2 + 1 & tileSizeMask) * tileSizeBase]
+ this.field_76879_i[(var1 + 0 & tileSizeMask)
+ (var2 + 1 & tileSizeMask) * tileSizeBase])
/ 4.0F
* 0.8F;
this.field_76879_i[var1 + var2 * tileSizeBase] += this.field_76877_j[var1 + var2 * tileSizeBase]
* 0.01F;
if (this.field_76879_i[var1 + var2 * tileSizeBase] < 0.0F)
{
if (this.field_76879_i[var1 + var2 * tileSizeBase] < 0.0F) {
this.field_76879_i[var1 + var2 * tileSizeBase] = 0.0F;
}
this.field_76877_j[var1 + var2 * tileSizeBase] -= 0.06F;
if (Math.random() < 0.005D)
{
if (Math.random() < 0.005D) {
this.field_76877_j[var1 + var2 * tileSizeBase] = 1.5F;
}
}
@@ -79,26 +81,22 @@ public class TextureLavaFX extends TextureFX
this.field_76878_h = this.field_76876_g;
this.field_76876_g = var11;
for (var2 = 0; var2 < tileSizeSquare; ++var2)
{
for (var2 = 0; var2 < tileSizeSquare; ++var2) {
var3 = this.field_76876_g[var2] * 2.0F;
if (var3 > 1.0F)
{
if (var3 > 1.0F) {
var3 = 1.0F;
}
if (var3 < 0.0F)
{
if (var3 < 0.0F) {
var3 = 0.0F;
}
var5 = (int)(var3 * 100.0F + 155.0F);
var6 = (int)(var3 * var3 * 255.0F);
var7 = (int)(var3 * var3 * var3 * var3 * 128.0F);
var5 = (int) (var3 * 100.0F + 155.0F);
var6 = (int) (var3 * var3 * 255.0F);
var7 = (int) (var3 * var3 * var3 * var3 * 128.0F);
if (this.anaglyphEnabled)
{
if (this.anaglyphEnabled) {
var8 = (var5 * 30 + var6 * 59 + var7 * 11) / 100;
var9 = (var5 * 30 + var6 * 70) / 100;
int var10 = (var5 * 30 + var7 * 70) / 100;
@@ -1,34 +1,33 @@
package codechicken.core.featurehack.mc;
import net.minecraft.util.MathHelper;
import codechicken.lib.colour.ColourRGBA;
import codechicken.lib.render.TextureFX;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.util.MathHelper;
@SideOnly(Side.CLIENT)
public class TextureLavaFlowFX extends TextureFX
{
public class TextureLavaFlowFX extends TextureFX {
protected float[] field_76871_g = new float[256];
protected float[] field_76874_h = new float[256];
protected float[] field_76875_i = new float[256];
protected float[] field_76872_j = new float[256];
int field_76873_k = 0;
//shadow
// shadow
public int tileSizeBase = 16;
public int tileSizeSquare = 256;
public int tileSizeMask = 15;
public int tileSizeSquareMask = 255;
public TextureLavaFlowFX()
{
public TextureLavaFlowFX() {
super(32, "lava_flow_fx");
}
@Override
public void setup()
{
public void setup() {
super.setup();
field_76871_g = new float[tileSizeSquare];
field_76874_h = new float[tileSizeSquare];
@@ -37,8 +36,7 @@ public class TextureLavaFlowFX extends TextureFX
field_76873_k = 0;
}
public void onTick()
{
public void onTick() {
++this.field_76873_k;
int var2;
float var3;
@@ -48,36 +46,40 @@ public class TextureLavaFlowFX extends TextureFX
int var8;
int var9;
for (int var1 = 0; var1 < tileSizeBase; ++var1)
{
for (var2 = 0; var2 < tileSizeBase; ++var2)
{
for (int var1 = 0; var1 < tileSizeBase; ++var1) {
for (var2 = 0; var2 < tileSizeBase; ++var2) {
var3 = 0.0F;
int var4 = (int)(MathHelper.sin(var2 * (float)Math.PI * 2.0F / 16.0F) * 1.2F);
var5 = (int)(MathHelper.sin(var1 * (float)Math.PI * 2.0F / 16.0F) * 1.2F);
int var4 = (int) (MathHelper.sin(var2 * (float) Math.PI * 2.0F / 16.0F) * 1.2F);
var5 = (int) (MathHelper.sin(var1 * (float) Math.PI * 2.0F / 16.0F) * 1.2F);
for (var6 = var1 - 1; var6 <= var1 + 1; ++var6)
{
for (var7 = var2 - 1; var7 <= var2 + 1; ++var7)
{
for (var6 = var1 - 1; var6 <= var1 + 1; ++var6) {
for (var7 = var2 - 1; var7 <= var2 + 1; ++var7) {
var8 = var6 + var4 & tileSizeMask;
var9 = var7 + var5 & tileSizeMask;
var3 += this.field_76871_g[var8 + var9 * tileSizeBase];
}
}
this.field_76874_h[var1 + var2 * tileSizeBase] = var3 / 10.0F + (this.field_76875_i[(var1 + 0 & tileSizeMask) + (var2 + 0 & tileSizeMask) * tileSizeBase] + this.field_76875_i[(var1 + 1 & tileSizeMask) + (var2 + 0 & tileSizeMask) * tileSizeBase] + this.field_76875_i[(var1 + 1 & tileSizeMask) + (var2 + 1 & tileSizeMask) * tileSizeBase] + this.field_76875_i[(var1 + 0 & tileSizeMask) + (var2 + 1 & tileSizeMask) * tileSizeBase]) / 4.0F * 0.8F;
this.field_76875_i[var1 + var2 * tileSizeBase] += this.field_76872_j[var1 + var2 * tileSizeBase] * 0.01F;
this.field_76874_h[var1 + var2 * tileSizeBase] = var3 / 10.0F
+ (this.field_76875_i[(var1 + 0 & tileSizeMask) + (var2 + 0 & tileSizeMask) * tileSizeBase]
+ this.field_76875_i[(var1 + 1 & tileSizeMask)
+ (var2 + 0 & tileSizeMask) * tileSizeBase]
+ this.field_76875_i[(var1 + 1 & tileSizeMask)
+ (var2 + 1 & tileSizeMask) * tileSizeBase]
+ this.field_76875_i[(var1 + 0 & tileSizeMask)
+ (var2 + 1 & tileSizeMask) * tileSizeBase])
/ 4.0F
* 0.8F;
this.field_76875_i[var1 + var2 * tileSizeBase] += this.field_76872_j[var1 + var2 * tileSizeBase]
* 0.01F;
if (this.field_76875_i[var1 + var2 * tileSizeBase] < 0.0F)
{
if (this.field_76875_i[var1 + var2 * tileSizeBase] < 0.0F) {
this.field_76875_i[var1 + var2 * tileSizeBase] = 0.0F;
}
this.field_76872_j[var1 + var2 * tileSizeBase] -= 0.06F;
if (Math.random() < 0.005D)
{
if (Math.random() < 0.005D) {
this.field_76872_j[var1 + var2 * tileSizeBase] = 1.5F;
}
}
@@ -87,26 +89,22 @@ public class TextureLavaFlowFX extends TextureFX
this.field_76874_h = this.field_76871_g;
this.field_76871_g = var11;
for (var2 = 0; var2 < tileSizeSquare; ++var2)
{
for (var2 = 0; var2 < tileSizeSquare; ++var2) {
var3 = this.field_76871_g[(var2 - this.field_76873_k / 3 * tileSizeBase) & tileSizeSquareMask] * 2.0F;
if (var3 > 1.0F)
{
if (var3 > 1.0F) {
var3 = 1.0F;
}
if (var3 < 0.0F)
{
if (var3 < 0.0F) {
var3 = 0.0F;
}
var5 = (int)(var3 * 100.0F + 155.0F);
var6 = (int)(var3 * var3 * 255.0F);
var7 = (int)(var3 * var3 * var3 * var3 * 128.0F);
var5 = (int) (var3 * 100.0F + 155.0F);
var6 = (int) (var3 * var3 * 255.0F);
var7 = (int) (var3 * var3 * var3 * var3 * 128.0F);
if (this.anaglyphEnabled)
{
if (this.anaglyphEnabled) {
var8 = (var5 * 30 + var6 * 59 + var7 * 11) / 100;
var9 = (var5 * 30 + var6 * 70) / 100;
int var10 = (var5 * 30 + var7 * 70) / 100;
@@ -115,17 +113,16 @@ public class TextureLavaFlowFX extends TextureFX
var7 = var10;
}
int px = var2&tileSizeMask;
int py = var2/tileSizeBase;
int px = var2 & tileSizeMask;
int py = var2 / tileSizeBase;
writeColour(px, py, var5, var6, var7, -1);
writeColour(px+16, py, var5, var6, var7, -1);
writeColour(px, py+16, var5, var6, var7, -1);
writeColour(px+16, py+16, var5, var6, var7, -1);
writeColour(px + 16, py, var5, var6, var7, -1);
writeColour(px, py + 16, var5, var6, var7, -1);
writeColour(px + 16, py + 16, var5, var6, var7, -1);
}
}
private void writeColour(int px, int py, int var5, int var6, int var7, int var8)
{
imageData[py*32+px] = new ColourRGBA(var5, var6, var7, var8).argb();
private void writeColour(int px, int py, int var5, int var6, int var7, int var8) {
imageData[py * 32 + px] = new ColourRGBA(var5, var6, var7, var8).argb();
}
}
@@ -6,8 +6,8 @@ import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
@SideOnly(Side.CLIENT)
public class TextureWaterFX extends TextureFX
{
public class TextureWaterFX extends TextureFX {
/** red RGB value for water texture */
protected float[] red = new float[256];
@@ -19,15 +19,14 @@ public class TextureWaterFX extends TextureFX
/** alpha RGB value for water texture */
protected float[] alpha = new float[256];
public TextureWaterFX()
{
public TextureWaterFX() {
super(16, "water_still_fx");
setup();
}
@Override
public void setup()
{
public void setup() {
super.setup();
red = new float[tileSizeSquare];
green = new float[tileSizeSquare];
@@ -35,22 +34,18 @@ public class TextureWaterFX extends TextureFX
alpha = new float[tileSizeSquare];
}
public void onTick()
{
public void onTick() {
int var1;
int var2;
float var3;
int var5;
int var6;
for (var1 = 0; var1 < tileSizeBase; ++var1)
{
for (var2 = 0; var2 < tileSizeBase; ++var2)
{
for (var1 = 0; var1 < tileSizeBase; ++var1) {
for (var2 = 0; var2 < tileSizeBase; ++var2) {
var3 = 0.0F;
for (int var4 = var1 - 1; var4 <= var1 + 1; ++var4)
{
for (int var4 = var1 - 1; var4 <= var1 + 1; ++var4) {
var5 = var4 & tileSizeMask;
var6 = var2 & tileSizeMask;
var3 += this.red[var5 + var6 * tileSizeBase];
@@ -60,21 +55,17 @@ public class TextureWaterFX extends TextureFX
}
}
for (var1 = 0; var1 < tileSizeBase; ++var1)
{
for (var2 = 0; var2 < tileSizeBase; ++var2)
{
for (var1 = 0; var1 < tileSizeBase; ++var1) {
for (var2 = 0; var2 < tileSizeBase; ++var2) {
this.blue[var1 + var2 * tileSizeBase] += this.alpha[var1 + var2 * tileSizeBase] * 0.05F;
if (this.blue[var1 + var2 * tileSizeBase] < 0.0F)
{
if (this.blue[var1 + var2 * tileSizeBase] < 0.0F) {
this.blue[var1 + var2 * tileSizeBase] = 0.0F;
}
this.alpha[var1 + var2 * tileSizeBase] -= 0.1F;
if (Math.random() < 0.05D)
{
if (Math.random() < 0.05D) {
this.alpha[var1 + var2 * tileSizeBase] = 0.5F;
}
}
@@ -84,28 +75,24 @@ public class TextureWaterFX extends TextureFX
this.green = this.red;
this.red = var12;
for (var2 = 0; var2 < tileSizeSquare; ++var2)
{
for (var2 = 0; var2 < tileSizeSquare; ++var2) {
var3 = this.red[var2];
if (var3 > 1.0F)
{
if (var3 > 1.0F) {
var3 = 1.0F;
}
if (var3 < 0.0F)
{
if (var3 < 0.0F) {
var3 = 0.0F;
}
float var13 = var3 * var3;
var5 = (int)(32.0F + var13 * 32.0F);
var6 = (int)(50.0F + var13 * 64.0F);
var5 = (int) (32.0F + var13 * 32.0F);
var6 = (int) (50.0F + var13 * 64.0F);
int var7 = 255;
int var8 = (int)(146.0F + var13 * 50.0F);
int var8 = (int) (146.0F + var13 * 50.0F);
if (this.anaglyphEnabled)
{
if (this.anaglyphEnabled) {
int var9 = (var5 * 30 + var6 * 59 + var7 * 11) / 100;
int var10 = (var5 * 30 + var6 * 70) / 100;
int var11 = (var5 * 30 + var7 * 70) / 100;
@@ -6,28 +6,26 @@ import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
@SideOnly(Side.CLIENT)
public class TextureWaterFlowFX extends TextureFX
{
public class TextureWaterFlowFX extends TextureFX {
protected float[] field_76880_g = new float[256];
protected float[] field_76883_h = new float[256];
protected float[] field_76884_i = new float[256];
protected float[] field_76881_j = new float[256];
private int tickCounter = 0;
//shadow
// shadow
public int tileSizeBase = 16;
public int tileSizeSquare = 256;
public int tileSizeMask = 15;
public int tileSizeSquareMask = 255;
public TextureWaterFlowFX()
{
public TextureWaterFlowFX() {
super(32, "water_flow_fx");
}
@Override
public void setup()
{
public void setup() {
super.setup();
field_76880_g = new float[tileSizeSquare];
field_76883_h = new float[tileSizeSquare];
@@ -36,8 +34,7 @@ public class TextureWaterFlowFX extends TextureFX
tickCounter = 0;
}
public void onTick()
{
public void onTick() {
++this.tickCounter;
int var1;
int var2;
@@ -45,38 +42,33 @@ public class TextureWaterFlowFX extends TextureFX
int var5;
int var6;
for (var1 = 0; var1 < tileSizeBase; ++var1)
{
for (var2 = 0; var2 < tileSizeBase; ++var2)
{
for (var1 = 0; var1 < tileSizeBase; ++var1) {
for (var2 = 0; var2 < tileSizeBase; ++var2) {
var3 = 0.0F;
for (int var4 = var2 - 2; var4 <= var2; ++var4)
{
for (int var4 = var2 - 2; var4 <= var2; ++var4) {
var5 = var1 & tileSizeMask;
var6 = var4 & tileSizeMask;
var3 += this.field_76880_g[var5 + var6 * tileSizeBase];
}
this.field_76883_h[var1 + var2 * tileSizeBase] = var3 / 3.2F + this.field_76884_i[var1 + var2 * tileSizeBase] * 0.8F;
this.field_76883_h[var1 + var2 * tileSizeBase] = var3 / 3.2F
+ this.field_76884_i[var1 + var2 * tileSizeBase] * 0.8F;
}
}
for (var1 = 0; var1 < tileSizeBase; ++var1)
{
for (var2 = 0; var2 < tileSizeBase; ++var2)
{
this.field_76884_i[var1 + var2 * tileSizeBase] += this.field_76881_j[var1 + var2 * tileSizeBase] * 0.05F;
for (var1 = 0; var1 < tileSizeBase; ++var1) {
for (var2 = 0; var2 < tileSizeBase; ++var2) {
this.field_76884_i[var1 + var2 * tileSizeBase] += this.field_76881_j[var1 + var2 * tileSizeBase]
* 0.05F;
if (this.field_76884_i[var1 + var2 * tileSizeBase] < 0.0F)
{
if (this.field_76884_i[var1 + var2 * tileSizeBase] < 0.0F) {
this.field_76884_i[var1 + var2 * tileSizeBase] = 0.0F;
}
this.field_76881_j[var1 + var2 * tileSizeBase] -= 0.3F;
if (Math.random() < 0.2D)
{
if (Math.random() < 0.2D) {
this.field_76881_j[var1 + var2 * tileSizeBase] = 0.5F;
}
}
@@ -86,28 +78,24 @@ public class TextureWaterFlowFX extends TextureFX
this.field_76883_h = this.field_76880_g;
this.field_76880_g = var12;
for (var2 = 0; var2 < tileSizeSquare; ++var2)
{
for (var2 = 0; var2 < tileSizeSquare; ++var2) {
var3 = this.field_76880_g[var2 - this.tickCounter * tileSizeBase & tileSizeSquareMask];
if (var3 > 1.0F)
{
if (var3 > 1.0F) {
var3 = 1.0F;
}
if (var3 < 0.0F)
{
if (var3 < 0.0F) {
var3 = 0.0F;
}
float var13 = var3 * var3;
var5 = (int)(32.0F + var13 * 32.0F);
var6 = (int)(50.0F + var13 * 64.0F);
var5 = (int) (32.0F + var13 * 32.0F);
var6 = (int) (50.0F + var13 * 64.0F);
int var7 = 255;
int var8 = (int)(146.0F + var13 * 50.0F);
int var8 = (int) (146.0F + var13 * 50.0F);
if (this.anaglyphEnabled)
{
if (this.anaglyphEnabled) {
int var9 = (var5 * 30 + var6 * 59 + var7 * 11) / 100;
int var10 = (var5 * 30 + var6 * 70) / 100;
int var11 = (var5 * 30 + var7 * 70) / 100;
@@ -116,18 +104,16 @@ public class TextureWaterFlowFX extends TextureFX
var7 = var11;
}
int px = var2&tileSizeMask;
int py = var2/tileSizeBase;
int px = var2 & tileSizeMask;
int py = var2 / tileSizeBase;
writeColour(px, py, var5, var6, var7, var8);
writeColour(px+16, py, var5, var6, var7, var8);
writeColour(px, py+16, var5, var6, var7, var8);
writeColour(px+16, py+16, var5, var6, var7, var8);
writeColour(px + 16, py, var5, var6, var7, var8);
writeColour(px, py + 16, var5, var6, var7, var8);
writeColour(px + 16, py + 16, var5, var6, var7, var8);
}
}
private void writeColour(int px, int py, int var5, int var6, int var7, int var8)
{
imageData[py*32+px] = new ColourRGBA(var5, var6, var7, var8).argb();
private void writeColour(int px, int py, int var5, int var6, int var7, int var8) {
imageData[py * 32 + px] = new ColourRGBA(var5, var6, var7, var8).argb();
}
}
@@ -5,15 +5,14 @@ import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.FluidTankInfo;
import net.minecraftforge.fluids.IFluidTank;
public class ExtendedFluidTank implements IFluidTank
{
public class ExtendedFluidTank implements IFluidTank {
private FluidStack fluid;
private boolean changeType;
private int capacity;
public ExtendedFluidTank(FluidStack type, int capacity)
{
if(type == null) {
public ExtendedFluidTank(FluidStack type, int capacity) {
if (type == null) {
type = FluidUtils.water;
changeType = true;
}
@@ -21,97 +20,76 @@ public class ExtendedFluidTank implements IFluidTank
fluid = FluidUtils.copy(type, 0);
this.capacity = capacity;
}
public ExtendedFluidTank(int capacity)
{
public ExtendedFluidTank(int capacity) {
this(null, capacity);
}
@Override
public FluidStack getFluid()
{
public FluidStack getFluid() {
return fluid.copy();
}
@Override
public int getCapacity()
{
public int getCapacity() {
return capacity;
}
public boolean canAccept(FluidStack type)
{
public boolean canAccept(FluidStack type) {
return type == null || (fluid.amount == 0 && changeType) || fluid.isFluidEqual(type);
}
@Override
public int fill(FluidStack resource, boolean doFill)
{
if(resource == null)
return 0;
public int fill(FluidStack resource, boolean doFill) {
if (resource == null) return 0;
if(!canAccept(resource))
return 0;
int tofill = Math.min(getCapacity()-fluid.amount, resource.amount);
if(doFill && tofill > 0)
{
if(!fluid.isFluidEqual(resource))
fluid = FluidUtils.copy(resource, fluid.amount+tofill);
else
fluid.amount+=tofill;
if (!canAccept(resource)) return 0;
int tofill = Math.min(getCapacity() - fluid.amount, resource.amount);
if (doFill && tofill > 0) {
if (!fluid.isFluidEqual(resource)) fluid = FluidUtils.copy(resource, fluid.amount + tofill);
else fluid.amount += tofill;
onLiquidChanged();
}
return tofill;
}
@Override
public FluidStack drain(int maxDrain, boolean doDrain)
{
if(fluid.amount == 0 || maxDrain <= 0)
return null;
public FluidStack drain(int maxDrain, boolean doDrain) {
if (fluid.amount == 0 || maxDrain <= 0) return null;
int todrain = Math.min(maxDrain, fluid.amount);
if(doDrain && todrain > 0)
{
fluid.amount-=todrain;
if (doDrain && todrain > 0) {
fluid.amount -= todrain;
onLiquidChanged();
}
return FluidUtils.copy(fluid, todrain);
}
public FluidStack drain(FluidStack resource, boolean doDrain)
{
if (resource == null || !resource.isFluidEqual(fluid))
return null;
public FluidStack drain(FluidStack resource, boolean doDrain) {
if (resource == null || !resource.isFluidEqual(fluid)) return null;
return drain(resource.amount, doDrain);
}
public void onLiquidChanged()
{
}
public void onLiquidChanged() {}
public void fromTag(NBTTagCompound tag)
{
public void fromTag(NBTTagCompound tag) {
fluid = FluidUtils.read(tag);
}
public NBTTagCompound toTag()
{
public NBTTagCompound toTag() {
return FluidUtils.write(fluid, new NBTTagCompound());
}
@Override
public int getFluidAmount()
{
public int getFluidAmount() {
return fluid.amount;
}
@Override
public FluidTankInfo getInfo()
{
public FluidTankInfo getInfo() {
return new FluidTankInfo(this);
}
}
@@ -1,6 +1,5 @@
package codechicken.core.fluid;
import codechicken.lib.inventory.InventoryUtils;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
@@ -11,87 +10,75 @@ import net.minecraftforge.fluids.FluidRegistry;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.IFluidHandler;
public class FluidUtils
{
import codechicken.lib.inventory.InventoryUtils;
public class FluidUtils {
public static int B = FluidContainerRegistry.BUCKET_VOLUME;
public static FluidStack water = new FluidStack(FluidRegistry.WATER, 1000);
public static FluidStack lava = new FluidStack(FluidRegistry.LAVA, 1000);
public static boolean fillTankWithContainer(IFluidHandler tank, EntityPlayer player)
{
public static boolean fillTankWithContainer(IFluidHandler tank, EntityPlayer player) {
ItemStack stack = player.getCurrentEquippedItem();
FluidStack liquid = FluidContainerRegistry.getFluidForFilledItem(stack);
if(liquid == null)
if (liquid == null) return false;
if (tank.fill(ForgeDirection.UNKNOWN, liquid, false) != liquid.amount && !player.capabilities.isCreativeMode)
return false;
if(tank.fill(ForgeDirection.UNKNOWN, liquid, false) != liquid.amount && !player.capabilities.isCreativeMode)
return false;
tank.fill(ForgeDirection.UNKNOWN, liquid, true);
if(!player.capabilities.isCreativeMode)
if (!player.capabilities.isCreativeMode)
InventoryUtils.consumeItem(player.inventory, player.inventory.currentItem);
player.inventoryContainer.detectAndSendChanges();
return true;
}
public static boolean emptyTankIntoContainer(IFluidHandler tank, EntityPlayer player, FluidStack tankLiquid)
{
public static boolean emptyTankIntoContainer(IFluidHandler tank, EntityPlayer player, FluidStack tankLiquid) {
ItemStack stack = player.getCurrentEquippedItem();
if(!FluidContainerRegistry.isEmptyContainer(stack))
return false;
if (!FluidContainerRegistry.isEmptyContainer(stack)) return false;
ItemStack filled = FluidContainerRegistry.fillFluidContainer(tankLiquid, stack);
FluidStack liquid = FluidContainerRegistry.getFluidForFilledItem(filled);
if(liquid == null || filled == null)
return false;
if (liquid == null || filled == null) return false;
tank.drain(ForgeDirection.UNKNOWN, liquid.amount, true);
if(!player.capabilities.isCreativeMode)
{
if(stack.stackSize == 1)
player.inventory.setInventorySlotContents(player.inventory.currentItem, filled);
else if(player.inventory.addItemStackToInventory(filled))
stack.stackSize--;
else
return false;
if (!player.capabilities.isCreativeMode) {
if (stack.stackSize == 1) player.inventory.setInventorySlotContents(player.inventory.currentItem, filled);
else if (player.inventory.addItemStackToInventory(filled)) stack.stackSize--;
else return false;
}
player.inventoryContainer.detectAndSendChanges();
player.inventoryContainer.detectAndSendChanges();
return true;
}
public static FluidStack copy(FluidStack liquid, int quantity)
{
public static FluidStack copy(FluidStack liquid, int quantity) {
liquid = liquid.copy();
liquid.amount = quantity;
return liquid;
}
public static FluidStack read(NBTTagCompound tag)
{
public static FluidStack read(NBTTagCompound tag) {
FluidStack stack = FluidStack.loadFluidStackFromNBT(tag);
return stack != null ? stack : FluidUtils.emptyFluid();
}
public static NBTTagCompound write(FluidStack fluid, NBTTagCompound tag)
{
return fluid == null || fluid.getFluid() == null ? new NBTTagCompound() : fluid.writeToNBT(new NBTTagCompound());
public static NBTTagCompound write(FluidStack fluid, NBTTagCompound tag) {
return fluid == null || fluid.getFluid() == null ? new NBTTagCompound()
: fluid.writeToNBT(new NBTTagCompound());
}
public static int getLuminosity(FluidStack stack, double density)
{
public static int getLuminosity(FluidStack stack, double density) {
Fluid fluid = stack.getFluid();
if(fluid == null)
return 0;
if (fluid == null) return 0;
int light = fluid.getLuminosity(stack);
if(fluid.isGaseous())
light=(int)(light*density);
if (fluid.isGaseous()) light = (int) (light * density);
return light;
}
@@ -4,29 +4,25 @@ import net.minecraftforge.common.util.ForgeDirection;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.IFluidHandler;
public class TankAccess
{
public class TankAccess {
public IFluidHandler tank;
public ForgeDirection side;
public TankAccess(IFluidHandler tank, ForgeDirection side)
{
public TankAccess(IFluidHandler tank, ForgeDirection side) {
this.tank = tank;
this.side = side;
}
public TankAccess(IFluidHandler tank, int side)
{
public TankAccess(IFluidHandler tank, int side) {
this(tank, ForgeDirection.getOrientation(side));
}
public int fill(FluidStack resource, boolean doFill)
{
public int fill(FluidStack resource, boolean doFill) {
return tank.fill(side, resource, doFill);
}
public FluidStack drain(int maxDrain, boolean doDrain)
{
public FluidStack drain(int maxDrain, boolean doDrain) {
return tank.drain(side, maxDrain, doDrain);
}
}
@@ -1,20 +1,20 @@
package codechicken.core.gui;
import com.google.common.base.Objects;
import java.util.Map;
import java.util.TreeMap;
public class ClickCounter<T>
{
public class ClickCount
{
import com.google.common.base.Objects;
public class ClickCounter<T> {
public class ClickCount {
public T clicked;
public long time;
public int count;
public boolean update(T clicked) {
if(!Objects.equal(this.clicked, clicked)) {
if (!Objects.equal(this.clicked, clicked)) {
this.clicked = clicked;
count = 0;
time = Long.MIN_VALUE;
@@ -28,8 +28,7 @@ public class ClickCounter<T>
public ClickCount getCount(int button) {
ClickCount c = buttons.get(button);
if(c == null)
buttons.put(button, c = new ClickCount());
if (c == null) buttons.put(button, c = new ClickCount());
return c;
}
@@ -40,14 +39,11 @@ public class ClickCounter<T>
public int mouseUp(T clicked, int button) {
ClickCount c = getCount(button);
if(!c.update(clicked))
return 0;
if (!c.update(clicked)) return 0;
long time = System.currentTimeMillis();
if(time-c.time < 500)
c.count++;
else
c.count = 1;
if (time - c.time < 500) c.count++;
else c.count = 1;
c.time = time;
return c.count;
}
@@ -1,13 +1,13 @@
package codechicken.core.gui;
import net.minecraft.client.Minecraft;
import net.minecraft.client.audio.PositionedSoundRecord;
import net.minecraft.util.ResourceLocation;
import org.lwjgl.opengl.GL11;
public class GuiCCButton extends GuiWidget
{
public class GuiCCButton extends GuiWidget {
public String text;
public String actionCommand;
private boolean isEnabled = true;
@@ -34,28 +34,34 @@ public class GuiCCButton extends GuiWidget
public void mouseClicked(int x, int y, int button) {
if (isEnabled && pointInside(x, y) && actionCommand != null) {
sendAction(actionCommand, button);
Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.func_147674_a(new ResourceLocation("gui.button.press"), 1.0F));
Minecraft.getMinecraft().getSoundHandler()
.playSound(PositionedSoundRecord.func_147674_a(new ResourceLocation("gui.button.press"), 1.0F));
}
}
@Override
public void draw(int mousex, int mousey, float frame) {
if (!visible)
return;
if (!visible) return;
drawButtonTex(mousex, mousey);
if(text != null)
drawText(mousex, mousey);
if (text != null) drawText(mousex, mousey);
}
public void drawButtonTex(int mousex, int mousey) {
GL11.glColor4f(1, 1, 1, 1);
renderEngine.bindTexture(guiTex);
int state = getButtonTex(mousex, mousey);
drawTexturedModalRect(x, y, 0, 46 + state * 20, width / 2, height / 2);//top left
drawTexturedModalRect(x + width / 2, y, 200 - width / 2, 46 + state * 20, width / 2, height / 2);//top right
drawTexturedModalRect(x, y + height / 2, 0, 46 + state * 20 + 20 - height / 2, width / 2, height / 2);//bottom left
drawTexturedModalRect(x + width / 2, y + height / 2, 200 - width / 2, 46 + state * 20 + 20 - height / 2, width / 2, height / 2);//bottom right
drawTexturedModalRect(x, y, 0, 46 + state * 20, width / 2, height / 2); // top left
drawTexturedModalRect(x + width / 2, y, 200 - width / 2, 46 + state * 20, width / 2, height / 2); // top right
drawTexturedModalRect(x, y + height / 2, 0, 46 + state * 20 + 20 - height / 2, width / 2, height / 2); // bottom
// left
drawTexturedModalRect(
x + width / 2,
y + height / 2,
200 - width / 2,
46 + state * 20 + 20 - height / 2,
width / 2,
height / 2); // bottom right
}
public int getButtonTex(int mousex, int mousey) {
@@ -5,184 +5,145 @@ import net.minecraft.util.ChatAllowedCharacters;
import org.lwjgl.input.Keyboard;
public class GuiCCTextField extends GuiWidget
{
public class GuiCCTextField extends GuiWidget {
private String text;
private boolean isFocused;
private boolean isEnabled;
public int maxStringLength;
public int cursorCounter;
public String actionCommand;
private String allowedCharacters;
public GuiCCTextField(int x, int y, int width, int height, String text)
{
public GuiCCTextField(int x, int y, int width, int height, String text) {
super(x, y, width, height);
isFocused = false;
isEnabled = true;
this.text = text;
}
public GuiCCTextField setActionCommand(String s)
{
public GuiCCTextField setActionCommand(String s) {
actionCommand = s;
return this;
}
public void setText(String s)
{
if(s.equals(text))
return;
public void setText(String s) {
if (s.equals(text)) return;
String oldText = text;
text = s;
onTextChanged(oldText);
}
public void onTextChanged(String oldText)
{
}
public void onTextChanged(String oldText) {}
public final String getText()
{
public final String getText() {
return text;
}
public final boolean isEnabled()
{
public final boolean isEnabled() {
return isEnabled;
}
public void setEnabled(boolean b)
{
public void setEnabled(boolean b) {
isEnabled = b;
if(!isEnabled && isFocused)
setFocused(false);
if (!isEnabled && isFocused) setFocused(false);
}
public final boolean isFocused()
{
public final boolean isFocused() {
return isFocused;
}
@Override
public void update()
{
public void update() {
cursorCounter++;
}
@Override
public void keyTyped(char c, int keycode)
{
if(!isEnabled || !isFocused)
return;
public void keyTyped(char c, int keycode) {
if (!isEnabled || !isFocused) return;
/*if(c == '\t')//tab
{
parentGuiScreen.selectNextField();
}*/
if(c == '\026')//paste
/*
* if(c == '\t')//tab { parentGuiScreen.selectNextField(); }
*/
if (c == '\026') // paste
{
String s = GuiScreen.getClipboardString();
if(s == null || s.equals(""))
return;
if (s == null || s.equals("")) return;
for(int i = 0; i < s.length(); i++)
{
if(text.length() == maxStringLength)
return;
for (int i = 0; i < s.length(); i++) {
if (text.length() == maxStringLength) return;
char tc = s.charAt(i);
if(canAddChar(tc))
setText(text + tc);
if (canAddChar(tc)) setText(text + tc);
}
}
if(keycode == Keyboard.KEY_RETURN)
{
if (keycode == Keyboard.KEY_RETURN) {
setFocused(false);
sendAction(actionCommand, getText());
}
if(keycode == Keyboard.KEY_BACK && text.length() > 0)
setText(text.substring(0, text.length() - 1));
if (keycode == Keyboard.KEY_BACK && text.length() > 0) setText(text.substring(0, text.length() - 1));
if((text.length() < maxStringLength || maxStringLength == 0) && canAddChar(c))
setText(text + c);
if ((text.length() < maxStringLength || maxStringLength == 0) && canAddChar(c)) setText(text + c);
}
public boolean canAddChar(char c)
{
return allowedCharacters == null ? ChatAllowedCharacters.isAllowedCharacter(c) : allowedCharacters.indexOf(c) >= 0;
public boolean canAddChar(char c) {
return allowedCharacters == null ? ChatAllowedCharacters.isAllowedCharacter(c)
: allowedCharacters.indexOf(c) >= 0;
}
@Override
public void mouseClicked(int x, int y, int button)
{
if(isEnabled && pointInside(x, y))
{
public void mouseClicked(int x, int y, int button) {
if (isEnabled && pointInside(x, y)) {
setFocused(true);
if(button == 1)
setText("");
}
else
setFocused(false);
if (button == 1) setText("");
} else setFocused(false);
}
public void setFocused(boolean focus)
{
if(focus == isFocused)
return;
public void setFocused(boolean focus) {
if (focus == isFocused) return;
isFocused = focus;
onFocusChanged();
}
public void onFocusChanged()
{
if(isFocused)
cursorCounter = 0;
public void onFocusChanged() {
if (isFocused) cursorCounter = 0;
}
@Override
public void draw(int i, int j, float f)
{
public void draw(int i, int j, float f) {
drawBackground();
drawText();
}
public void drawBackground()
{
public void drawBackground() {
drawRect(x - 1, y - 1, x + width + 1, y + height + 1, 0xffa0a0a0);
drawRect(x, y, x + width, y + height, 0xff000000);
}
public String getDrawText()
{
public String getDrawText() {
String s = getText();
if(isEnabled && isFocused && (cursorCounter / 6) % 2 == 0)
s+="_";
if (isEnabled && isFocused && (cursorCounter / 6) % 2 == 0) s += "_";
return s;
}
public void drawText()
{
drawString(fontRenderer, getDrawText(), x + 4, y + height/2 - 4, getTextColour());
public void drawText() {
drawString(fontRenderer, getDrawText(), x + 4, y + height / 2 - 4, getTextColour());
}
public int getTextColour()
{
public int getTextColour() {
return isEnabled ? 0xe0e0e0 : 0x707070;
}
public GuiCCTextField setMaxStringLength(int i)
{
public GuiCCTextField setMaxStringLength(int i) {
maxStringLength = i;
return this;
}
public GuiCCTextField setAllowedCharacters(String s)
{
public GuiCCTextField setAllowedCharacters(String s) {
allowedCharacters = s;
return this;
}
@@ -3,41 +3,37 @@ package codechicken.core.gui;
import java.awt.Point;
import java.util.ArrayList;
import codechicken.lib.gui.GuiDraw;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.GL11;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiScreen;
public class GuiScreenWidget extends GuiScreen implements IGuiActionListener
{
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.GL11;
import codechicken.lib.gui.GuiDraw;
public class GuiScreenWidget extends GuiScreen implements IGuiActionListener {
public ArrayList<GuiWidget> widgets = new ArrayList<GuiWidget>();
public int xSize, ySize, guiTop, guiLeft;
public GuiScreenWidget()
{
public GuiScreenWidget() {
this(176, 166);
}
public GuiScreenWidget(int xSize, int ySize)
{
public GuiScreenWidget(int xSize, int ySize) {
super();
this.xSize = xSize;
this.ySize = ySize;
}
@Override
public void initGui()
{
public void initGui() {
guiTop = (height - ySize) / 2;
guiLeft = (width - xSize) / 2;
if(!widgets.isEmpty())
resize();
if (!widgets.isEmpty()) resize();
}
public void reset()
{
public void reset() {
widgets.clear();
initGui();
addWidgets();
@@ -45,106 +41,78 @@ public class GuiScreenWidget extends GuiScreen implements IGuiActionListener
}
@Override
public void setWorldAndResolution(Minecraft mc, int i, int j)
{
public void setWorldAndResolution(Minecraft mc, int i, int j) {
boolean init = this.mc == null;
super.setWorldAndResolution(mc, i, j);
if(init) {
if (init) {
addWidgets();
resize();
}
}
public void add(GuiWidget widget)
{
public void add(GuiWidget widget) {
widgets.add(widget);
widget.onAdded(this);
}
@Override
public void drawScreen(int mousex, int mousey, float f)
{
public void drawScreen(int mousex, int mousey, float f) {
GL11.glTranslated(guiLeft, guiTop, 0);
drawBackground();
for(GuiWidget widget : widgets)
widget.draw(mousex-guiLeft, mousey-guiTop, f);
for (GuiWidget widget : widgets) widget.draw(mousex - guiLeft, mousey - guiTop, f);
drawForeground();
GL11.glTranslated(-guiLeft, -guiTop, 0);
}
public void drawBackground()
{
}
public void drawBackground() {}
public void drawForeground()
{
}
public void drawForeground() {}
@Override
protected void mouseClicked(int x, int y, int button)
{
protected void mouseClicked(int x, int y, int button) {
super.mouseClicked(x, y, button);
for(GuiWidget widget : widgets)
widget.mouseClicked(x-guiLeft, y-guiTop, button);
for (GuiWidget widget : widgets) widget.mouseClicked(x - guiLeft, y - guiTop, button);
}
@Override
protected void mouseMovedOrUp(int x, int y, int button)
{
protected void mouseMovedOrUp(int x, int y, int button) {
super.mouseMovedOrUp(x, y, button);
for(GuiWidget widget : widgets)
widget.mouseMovedOrUp(x-guiLeft, y-guiTop, button);
for (GuiWidget widget : widgets) widget.mouseMovedOrUp(x - guiLeft, y - guiTop, button);
}
@Override
protected void mouseClickMove(int x, int y, int button, long time)
{
protected void mouseClickMove(int x, int y, int button, long time) {
super.mouseClickMove(x, y, button, time);
for(GuiWidget widget : widgets)
widget.mouseDragged(x-guiLeft, y-guiTop, button, time);
for (GuiWidget widget : widgets) widget.mouseDragged(x - guiLeft, y - guiTop, button, time);
}
@Override
public void updateScreen()
{
public void updateScreen() {
super.updateScreen();
if(mc.currentScreen == this)
for(GuiWidget widget : widgets)
widget.update();
if (mc.currentScreen == this) for (GuiWidget widget : widgets) widget.update();
}
@Override
public void keyTyped(char c, int keycode)
{
public void keyTyped(char c, int keycode) {
super.keyTyped(c, keycode);
for(GuiWidget widget : widgets)
widget.keyTyped(c, keycode);
for (GuiWidget widget : widgets) widget.keyTyped(c, keycode);
}
@Override
public void handleMouseInput()
{
public void handleMouseInput() {
super.handleMouseInput();
int i = Mouse.getEventDWheel();
if(i != 0)
{
if (i != 0) {
Point p = GuiDraw.getMousePosition();
int scroll = i > 0 ? 1 : -1;
for(GuiWidget widget : widgets)
widget.mouseScrolled(p.x, p.y, scroll);
for (GuiWidget widget : widgets) widget.mouseScrolled(p.x, p.y, scroll);
}
}
@Override
public void actionPerformed(String ident, Object... params)
{
}
public void actionPerformed(String ident, Object... params) {}
public void resize()
{
}
public void resize() {}
public void addWidgets()
{
}
public void addWidgets() {}
}
@@ -1,12 +1,13 @@
package codechicken.core.gui;
import java.awt.Dimension;
import java.awt.Rectangle;
import codechicken.lib.math.MathHelper;
import codechicken.lib.vec.Rectangle4i;
import java.awt.*;
public abstract class GuiScrollPane extends GuiWidget {
public abstract class GuiScrollPane extends GuiWidget
{
protected int scrollclicky = -1;
protected float scrollpercent;
protected int scrollmousey;
@@ -29,7 +30,11 @@ public abstract class GuiScrollPane extends GuiWidget
}
public Rectangle windowBounds() {
return new Rectangle(x+marginleft, y+margintop, width-marginleft-marginright, height-margintop-marginbottom);
return new Rectangle(
x + marginleft,
y + margintop,
width - marginleft - marginright,
height - margintop - marginbottom);
}
public abstract int contentHeight();
@@ -42,8 +47,10 @@ public abstract class GuiScrollPane extends GuiWidget
public Rectangle scrollbarBounds() {
Dimension dim = scrollbarDim();
return new Rectangle(
x + width - dim.width, y + (int) ((height - dim.height) * percentscrolled + 0.4999),
dim.width, dim.height);
x + width - dim.width,
y + (int) ((height - dim.height) * percentscrolled + 0.4999),
dim.width,
dim.height);
}
public void scrollUp() {
@@ -55,7 +62,7 @@ public abstract class GuiScrollPane extends GuiWidget
}
public void scroll(int i) {
percentscrolled += i * height / (float)(2*contentHeight());
percentscrolled += i * height / (float) (2 * contentHeight());
calculatePercentScrolled();
}
@@ -102,15 +109,13 @@ public abstract class GuiScrollPane extends GuiWidget
Rectangle w = windowBounds();
int barempty = height - sbar.height;
if (button == 0 &&
sbar.height < height && //the scroll bar can move (not full length)
mx >= sbar.x && mx <= sbar.x + sbar.width &&
my >= y && my <= y + height)//in the scroll pane
if (button == 0 && sbar.height < height && // the scroll bar can move (not full length)
mx >= sbar.x && mx <= sbar.x + sbar.width && my >= y && my <= y + height) // in the scroll pane
{
if (my < sbar.y) {
percentscrolled = (my - y) / (float) barempty;
calculatePercentScrolled();
} else if (my > sbar.y+sbar.height) {
} else if (my > sbar.y + sbar.height) {
percentscrolled = (my - y - sbar.height + 1) / (float) barempty;
calculatePercentScrolled();
} else {
@@ -118,29 +123,25 @@ public abstract class GuiScrollPane extends GuiWidget
scrollpercent = percentscrolled;
scrollmousey = my;
}
} else if (w.contains(mx, my))
slotDown(mx - w.x, my - w.y + scrolledPixels(), button);
} else if (w.contains(mx, my)) slotDown(mx - w.x, my - w.y + scrolledPixels(), button);
}
/**
* Mouse down on slot area
* Coordinates relative to slot content area
* Mouse down on slot area Coordinates relative to slot content area
*/
public void slotDown(int mx, int my, int button) {}
/**
* Mouse up on slot area
* Coordinates relative to slot content area
* Mouse up on slot area Coordinates relative to slot content area
*/
public void slotUp(int mx, int my, int button) {}
@Override
public void mouseMovedOrUp(int mx, int my, int button) {
Rectangle w = windowBounds();
if (isScrolling() && button == 0)//we were scrolling and we released mouse
if (isScrolling() && button == 0) // we were scrolling and we released mouse
scrollclicky = -1;
else if (w.contains(mx, my))
slotUp(mx - w.x, my - w.y + scrolledPixels(), button);
else if (w.contains(mx, my)) slotUp(mx - w.x, my - w.y + scrolledPixels(), button);
}
@Override
@@ -151,12 +152,9 @@ public abstract class GuiScrollPane extends GuiWidget
int barupallowed = (int) ((height - sbarh) * scrollpercent + 0.5);
int bardownallowed = (height - sbarh) - barupallowed;
if (-scrolldiff > barupallowed)
scrollmousey = scrollclicky - barupallowed;
else if (scrolldiff > bardownallowed)
scrollmousey = scrollclicky + bardownallowed;
else
scrollmousey = mousey;
if (-scrolldiff > barupallowed) scrollmousey = scrollclicky - barupallowed;
else if (scrolldiff > bardownallowed) scrollmousey = scrollclicky + bardownallowed;
else scrollmousey = mousey;
calculatePercentScrolled();
}
@@ -180,7 +178,7 @@ public abstract class GuiScrollPane extends GuiWidget
public void draw(int mx, int my, float frame) {
Rectangle w = windowBounds();
drawBackground(frame);
drawContent(mx-w.x, my+scrolledPixels()-w.y, frame);
drawContent(mx - w.x, my + scrolledPixels() - w.y, frame);
drawOverlay(frame);
drawScrollbar(frame);
}
@@ -192,24 +190,22 @@ public abstract class GuiScrollPane extends GuiWidget
public abstract void drawContent(int mx, int my, float frame);
public void drawOverlay(float frame) {
//outlines
drawRect(x, y - 1, x + width, y, 0xffa0a0a0);//top
drawRect(x, y + height, x + width, y + height + 1, 0xffa0a0a0);//bottom
drawRect(x - 1, y - 1, x, y + height + 1, 0xffa0a0a0);//left
drawRect(x + width, y - 1, x + width + 1, y + height + 1, 0xffa0a0a0);//right
// outlines
drawRect(x, y - 1, x + width, y, 0xffa0a0a0); // top
drawRect(x, y + height, x + width, y + height + 1, 0xffa0a0a0); // bottom
drawRect(x - 1, y - 1, x, y + height + 1, 0xffa0a0a0); // left
drawRect(x + width, y - 1, x + width + 1, y + height + 1, 0xffa0a0a0); // right
}
public void drawScrollbar(float frame) {
Rectangle r = scrollbarBounds();
drawRect(r.x, r.y, r.x + r.width, r.y + r.height, 0xFF8B8B8B);//corners
drawRect(r.x, r.y, r.x + r.width - 1, r.y + r.height - 1, 0xFFF0F0F0);//topleft up
drawRect(r.x + 1, r.y + 1, r.x + r.width, r.y + r.height, 0xFF555555);//bottom right down
drawRect(r.x + 1, r.y + 1, r.x + r.width - 1, r.y + r.height - 1, 0xFFC6C6C6);//scrollbar
drawRect(r.x, r.y, r.x + r.width, r.y + r.height, 0xFF8B8B8B); // corners
drawRect(r.x, r.y, r.x + r.width - 1, r.y + r.height - 1, 0xFFF0F0F0); // topleft up
drawRect(r.x + 1, r.y + 1, r.x + r.width, r.y + r.height, 0xFF555555); // bottom right down
drawRect(r.x + 1, r.y + 1, r.x + r.width - 1, r.y + r.height - 1, 0xFFC6C6C6); // scrollbar
int algn = scrollbarGuideAlignment();
if (algn != 0)
drawRect(algn > 0 ? r.x + r.width : r.x - 1, y, r.x, y + height, 0xFF808080);//lineguide
if (algn != 0) drawRect(algn > 0 ? r.x + r.width : r.x - 1, y, r.x, y + height, 0xFF808080); // lineguide
}
}
@@ -1,11 +1,11 @@
package codechicken.core.gui;
import java.awt.Rectangle;
import org.lwjgl.input.Keyboard;
import java.awt.*;
public abstract class GuiScrollSlot extends GuiScrollPane {
public abstract class GuiScrollSlot extends GuiScrollPane
{
protected String actionCommand;
public boolean focused;
protected ClickCounter<Integer> click = new ClickCounter<Integer>();
@@ -40,13 +40,11 @@ public abstract class GuiScrollSlot extends GuiScrollPane
protected abstract void drawSlot(int slot, int x, int y, int mx, int my, float frame);
protected void unfocus() {
}
protected void unfocus() {}
public void setFocused(boolean focus) {
focused = focus;
if (!focused)
unfocus();
if (!focused) unfocus();
}
@Override
@@ -56,37 +54,34 @@ public abstract class GuiScrollSlot extends GuiScrollPane
public int getSlotY(int slot) {
int h = 0;
for(int i = 0; i < slot; i++)
h+=getSlotHeight(i);
for (int i = 0; i < slot; i++) h += getSlotHeight(i);
return h;
}
public int getSlot(int my) {
if (my < 0)
return -1;
if (my < 0) return -1;
int y = 0;
for(int i = 0; i < getNumSlots(); i++) {
for (int i = 0; i < getNumSlots(); i++) {
int h = getSlotHeight(i);
if(my >= y && my < y+h)
return i;
y+=h;
if (my >= y && my < y + h) return i;
y += h;
}
return -1;
}
public int getClickedSlot(int my) {
return getSlot(my-windowBounds().y+scrolledPixels());
return getSlot(my - windowBounds().y + scrolledPixels());
}
@Override
public int scrolledPixels() {
int scrolled = super.scrolledPixels();
if(!smoothScroll) {
if (!smoothScroll) {
int slot = getSlot(scrolled);
int sloty = getSlotY(slot);
int sloth = getSlotHeight(slot);
scrolled = sloty+(int)((scrolled-sloty)/(double)sloth+0.5)*sloth;
scrolled = sloty + (int) ((scrolled - sloty) / (double) sloth + 0.5) * sloth;
}
return scrolled;
}
@@ -106,8 +101,7 @@ public abstract class GuiScrollSlot extends GuiScrollPane
@Override
public Rectangle scrollbarBounds() {
Rectangle r = super.scrollbarBounds();
if(scrollbarAlignment() == -1)
r.x = x;
if (scrollbarAlignment() == -1) r.x = x;
return r;
}
@@ -125,21 +119,16 @@ public abstract class GuiScrollSlot extends GuiScrollPane
public void slotUp(int mx, int my, int button) {
int slot = getSlot(my);
int c = click.mouseUp(slot >= 0 ? slot : null, button);
if(c > 0 && slot >= 0)
slotClicked(slot, button, mx, my-getSlotY(slot), c);
if (c > 0 && slot >= 0) slotClicked(slot, button, mx, my - getSlotY(slot), c);
}
@Override
public void keyTyped(char c, int keycode) {
if (!focused)
return;
if (!focused) return;
if (keycode == Keyboard.KEY_UP)
selectPrev();
if (keycode == Keyboard.KEY_DOWN)
selectNext();
if (keycode == Keyboard.KEY_RETURN && actionCommand != null)
sendAction(actionCommand);
if (keycode == Keyboard.KEY_UP) selectPrev();
if (keycode == Keyboard.KEY_DOWN) selectNext();
if (keycode == Keyboard.KEY_RETURN && actionCommand != null) sendAction(actionCommand);
}
@Override
@@ -149,9 +138,9 @@ public abstract class GuiScrollSlot extends GuiScrollPane
int y = 0;
for (int slot = 0; slot < getNumSlots(); slot++) {
int h = getSlotHeight(slot);
if (y+h > scrolled && y < scrolled+w.height)
drawSlot(slot, w.x, w.y+y-scrolledPixels(), mx, my-y, frame);
y+=h;
if (y + h > scrolled && y < scrolled + w.height)
drawSlot(slot, w.x, w.y + y - scrolledPixels(), mx, my - y, frame);
y += h;
}
}
}
@@ -7,78 +7,58 @@ import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.renderer.texture.TextureManager;
import net.minecraft.util.ResourceLocation;
public class GuiWidget extends Gui
{
public class GuiWidget extends Gui {
protected static final ResourceLocation guiTex = new ResourceLocation("textures/gui/widgets.png");
public GuiScreen parentScreen;
public TextureManager renderEngine;
public FontRenderer fontRenderer;
public int x;
public int y;
public int width;
public int height;
public GuiWidget(int x, int y, int width, int height)
{
public GuiWidget(int x, int y, int width, int height) {
setSize(x, y, width, height);
}
public void setSize(int x, int y, int width, int height)
{
public void setSize(int x, int y, int width, int height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
public boolean pointInside(int px, int py)
{
public boolean pointInside(int px, int py) {
return px >= x && px < x + width && py >= y && py < y + height;
}
public void sendAction(String actionCommand, Object... params)
{
public void sendAction(String actionCommand, Object... params) {
sendAction(parentScreen, actionCommand, params);
}
public static void sendAction(GuiScreen screen, String actionCommand, Object... params)
{
if(actionCommand != null && screen instanceof IGuiActionListener)
public static void sendAction(GuiScreen screen, String actionCommand, Object... params) {
if (actionCommand != null && screen instanceof IGuiActionListener)
((IGuiActionListener) screen).actionPerformed(actionCommand, params);
}
public void mouseClicked(int x, int y, int button)
{
}
public void mouseClicked(int x, int y, int button) {}
public void mouseMovedOrUp(int x, int y, int button)
{
}
public void mouseDragged(int x, int y, int button, long time)
{
}
public void update()
{
}
public void mouseMovedOrUp(int x, int y, int button) {}
public void draw(int mousex, int mousey, float frame)
{
}
public void mouseDragged(int x, int y, int button, long time) {}
public void keyTyped(char c, int keycode)
{
}
public void update() {}
public void mouseScrolled(int x, int y, int scroll)
{
}
public void onAdded(GuiScreen s)
{
public void draw(int mousex, int mousey, float frame) {}
public void keyTyped(char c, int keycode) {}
public void mouseScrolled(int x, int y, int scroll) {}
public void onAdded(GuiScreen s) {
Minecraft mc = Minecraft.getMinecraft();
parentScreen = s;
renderEngine = mc.renderEngine;
@@ -1,6 +1,6 @@
package codechicken.core.gui;
public interface IGuiActionListener
{
public interface IGuiActionListener {
public void actionPerformed(String actionCommand, Object... params);
}
}
@@ -1,6 +1,6 @@
package codechicken.core.internal;
import codechicken.core.CCUpdateChecker;
import net.minecraftforge.client.event.GuiScreenEvent;
import codechicken.core.GuiModListScroll;
import cpw.mods.fml.client.GuiModList;
@@ -9,31 +9,27 @@ import cpw.mods.fml.common.gameevent.TickEvent;
import cpw.mods.fml.common.gameevent.TickEvent.Phase;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraftforge.client.event.GuiScreenEvent;
public class CCCEventHandler
{
public class CCCEventHandler {
public static int renderTime;
public static float renderFrame;
@SubscribeEvent
public void clientTick(TickEvent.ClientTickEvent event) {
if(event.phase == Phase.END) {
CCUpdateChecker.tick();
if (event.phase == Phase.END) {
renderTime++;
}
}
@SubscribeEvent
public void renderTick(TickEvent.RenderTickEvent event) {
if(event.phase == Phase.START)
renderFrame = event.renderTickTime;
if (event.phase == Phase.START) renderFrame = event.renderTickTime;
}
@SubscribeEvent
@SideOnly(Side.CLIENT)
public void posGuiRender(GuiScreenEvent.DrawScreenEvent.Post event) {
if(event.gui instanceof GuiModList)
GuiModListScroll.draw((GuiModList)event.gui, event.mouseX, event.mouseY);
if (event.gui instanceof GuiModList) GuiModListScroll.draw((GuiModList) event.gui, event.mouseX, event.mouseY);
}
}
@@ -3,125 +3,98 @@ package codechicken.core.inventory;
import java.awt.Point;
import java.util.ArrayList;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.GL11;
import codechicken.lib.gui.GuiDraw;
import codechicken.core.gui.GuiWidget;
import codechicken.core.gui.IGuiActionListener;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.inventory.Container;
public class GuiContainerWidget extends GuiContainer implements IGuiActionListener
{
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.GL11;
import codechicken.core.gui.GuiWidget;
import codechicken.core.gui.IGuiActionListener;
import codechicken.lib.gui.GuiDraw;
public class GuiContainerWidget extends GuiContainer implements IGuiActionListener {
public ArrayList<GuiWidget> widgets = new ArrayList<GuiWidget>();
public GuiContainerWidget(Container inventorySlots)
{
public GuiContainerWidget(Container inventorySlots) {
this(inventorySlots, 176, 166);
}
public GuiContainerWidget(Container inventorySlots, int xSize, int ySize)
{
public GuiContainerWidget(Container inventorySlots, int xSize, int ySize) {
super(inventorySlots);
this.xSize = xSize;
this.ySize = ySize;
}
@Override
public void setWorldAndResolution(Minecraft mc, int i, int j)
{
public void setWorldAndResolution(Minecraft mc, int i, int j) {
super.setWorldAndResolution(mc, i, j);
if(widgets.isEmpty())
addWidgets();
if (widgets.isEmpty()) addWidgets();
}
public void add(GuiWidget widget)
{
public void add(GuiWidget widget) {
widgets.add(widget);
widget.onAdded(this);
}
@Override
protected void drawGuiContainerBackgroundLayer(float f, int mousex, int mousey)
{
protected void drawGuiContainerBackgroundLayer(float f, int mousex, int mousey) {
GL11.glTranslated(guiLeft, guiTop, 0);
drawBackground();
for(GuiWidget widget : widgets)
widget.draw(mousex-guiLeft, mousey-guiTop, f);
for (GuiWidget widget : widgets) widget.draw(mousex - guiLeft, mousey - guiTop, f);
GL11.glTranslated(-guiLeft, -guiTop, 0);
}
public void drawBackground()
{
}
public void drawBackground() {}
@Override
protected void mouseClicked(int x, int y, int button)
{
protected void mouseClicked(int x, int y, int button) {
super.mouseClicked(x, y, button);
for(GuiWidget widget : widgets)
widget.mouseClicked(x-guiLeft, y-guiTop, button);
}
@Override
protected void mouseMovedOrUp(int x, int y, int button)
{
super.mouseMovedOrUp(x, y, button);
for(GuiWidget widget : widgets)
widget.mouseMovedOrUp(x-guiLeft, y-guiTop, button);
}
@Override
protected void mouseClickMove(int x, int y, int button, long time)
{
super.mouseClickMove(x, y, button, time);
for(GuiWidget widget : widgets)
widget.mouseDragged(x-guiLeft, y-guiTop, button, time);
}
@Override
public void updateScreen()
{
super.updateScreen();
if(mc.currentScreen == this)
for(GuiWidget widget : widgets)
widget.update();
}
@Override
public void keyTyped(char c, int keycode)
{
super.keyTyped(c, keycode);
for(GuiWidget widget : widgets)
widget.keyTyped(c, keycode);
for (GuiWidget widget : widgets) widget.mouseClicked(x - guiLeft, y - guiTop, button);
}
@Override
public void handleMouseInput()
{
protected void mouseMovedOrUp(int x, int y, int button) {
super.mouseMovedOrUp(x, y, button);
for (GuiWidget widget : widgets) widget.mouseMovedOrUp(x - guiLeft, y - guiTop, button);
}
@Override
protected void mouseClickMove(int x, int y, int button, long time) {
super.mouseClickMove(x, y, button, time);
for (GuiWidget widget : widgets) widget.mouseDragged(x - guiLeft, y - guiTop, button, time);
}
@Override
public void updateScreen() {
super.updateScreen();
if (mc.currentScreen == this) for (GuiWidget widget : widgets) widget.update();
}
@Override
public void keyTyped(char c, int keycode) {
super.keyTyped(c, keycode);
for (GuiWidget widget : widgets) widget.keyTyped(c, keycode);
}
@Override
public void handleMouseInput() {
super.handleMouseInput();
int i = Mouse.getEventDWheel();
if(i != 0)
{
if (i != 0) {
Point p = GuiDraw.getMousePosition();
int scroll = i > 0 ? 1 : -1;
for(GuiWidget widget : widgets)
widget.mouseScrolled(p.x, p.y, scroll);
for (GuiWidget widget : widgets) widget.mouseScrolled(p.x, p.y, scroll);
}
}
@Override
public void actionPerformed(String ident, Object... params)
{
}
public void actionPerformed(String ident, Object... params) {}
public void addWidgets()
{
}
public void addWidgets() {}
@Override
public void onGuiClosed() {
@@ -1,9 +1,12 @@
package codechicken.core.launch;
import java.awt.Desktop;
import java.awt.GraphicsEnvironment;
import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.text.CharacterIterator;
import java.text.StringCharacterIterator;
import java.util.List;
import java.util.Map;
import java.util.jar.Attributes;
@@ -15,47 +18,63 @@ import javax.swing.JOptionPane;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import codechicken.core.asm.*;
import cpw.mods.fml.relauncher.CoreModManager;
import cpw.mods.fml.common.versioning.DefaultArtifactVersion;
import cpw.mods.fml.common.versioning.VersionParser;
import cpw.mods.fml.relauncher.FMLInjectionData;
import cpw.mods.fml.relauncher.IFMLCallHook;
import cpw.mods.fml.relauncher.IFMLLoadingPlugin;
import cpw.mods.fml.relauncher.IFMLLoadingPlugin.TransformerExclusions;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@TransformerExclusions(value = {"codechicken.core.asm", "codechicken.obfuscator"})
public class CodeChickenCorePlugin implements IFMLLoadingPlugin, IFMLCallHook
{
import codechicken.core.asm.CodeChickenCoreModContainer;
import codechicken.core.asm.DelegatedTransformer;
import codechicken.core.asm.MCPDeobfuscationTransformer;
import codechicken.core.asm.Tags;
import codechicken.core.asm.TweakTransformer;
import codechicken.lib.config.ConfigTag;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.versioning.DefaultArtifactVersion;
import cpw.mods.fml.common.versioning.VersionParser;
import cpw.mods.fml.relauncher.CoreModManager;
import cpw.mods.fml.relauncher.FMLInjectionData;
import cpw.mods.fml.relauncher.IFMLCallHook;
import cpw.mods.fml.relauncher.IFMLLoadingPlugin;
import cpw.mods.fml.relauncher.IFMLLoadingPlugin.MCVersion;
import cpw.mods.fml.relauncher.IFMLLoadingPlugin.TransformerExclusions;
@TransformerExclusions(value = { "codechicken.core.asm", "codechicken.obfuscator" })
@MCVersion("1.7.10")
public class CodeChickenCorePlugin implements IFMLLoadingPlugin, IFMLCallHook {
public static final String mcVersion = "[1.7.10]";
public static final String version = "GRADLETOKEN_VERSION";
@Deprecated
public static final String version = Tags.VERSION;
public static File minecraftDir;
public static String currentMcVersion;
public static Logger logger = LogManager.getLogger("CodeChickenCore");
public CodeChickenCorePlugin() {
if (minecraftDir != null)
return;//get called twice, once for IFMLCallHook
if (minecraftDir != null) return; // get called twice, once for IFMLCallHook
minecraftDir = (File) FMLInjectionData.data()[6];
currentMcVersion = (String) FMLInjectionData.data()[4];
DepLoader.load();
injectDeobfPlugin();
}
private void injectDeobfPlugin() {
try {
Class<?> wrapperClass = Class.forName("cpw.mods.fml.relauncher.CoreModManager$FMLPluginWrapper");
Constructor wrapperConstructor = wrapperClass.getConstructor(String.class, IFMLLoadingPlugin.class, File.class, Integer.TYPE, String[].class);
Constructor wrapperConstructor = wrapperClass
.getConstructor(String.class, IFMLLoadingPlugin.class, File.class, Integer.TYPE, String[].class);
Field f_loadPlugins = CoreModManager.class.getDeclaredField("loadPlugins");
wrapperConstructor.setAccessible(true);
f_loadPlugins.setAccessible(true);
((List)f_loadPlugins.get(null)).add(2, wrapperConstructor.newInstance("CCCDeobfPlugin", new MCPDeobfuscationTransformer.LoadPlugin(), null, 0, new String[0]));
((List) f_loadPlugins.get(null)).add(
2,
wrapperConstructor.newInstance(
"CCCDeobfPlugin",
new MCPDeobfuscationTransformer.LoadPlugin(),
null,
0,
new String[0]));
} catch (Exception e) {
logger.error("Failed to inject MCPDeobfuscation Transformer", e);
}
@@ -67,16 +86,16 @@ public class CodeChickenCorePlugin implements IFMLLoadingPlugin, IFMLCallHook
String err = "This version of " + mod + " does not support minecraft version " + mcVersion;
logger.error(err);
JEditorPane ep = new JEditorPane("text/html",
"<html>" +
err +
"<br>Remove it from your coremods folder and check <a href=\"http://www.minecraftforum.net/topic/909223-\">here</a> for updates" +
"</html>");
JEditorPane ep = new JEditorPane(
"text/html",
"<html>" + err
+ "<br>Remove it from your coremods folder and check <a href=\"http://www.minecraftforum.net/topic/909223-\">here</a> for updates"
+ "</html>");
ep.setEditable(false);
ep.setOpaque(false);
ep.addHyperlinkListener(new HyperlinkListener()
{
ep.addHyperlinkListener(new HyperlinkListener() {
@Override
public void hyperlinkUpdate(HyperlinkEvent event) {
try {
@@ -91,15 +110,89 @@ public class CodeChickenCorePlugin implements IFMLLoadingPlugin, IFMLCallHook
}
}
public static long parseSize(String text) {
double d = Double.parseDouble(text.replaceAll("[GMK]B?$", ""));
long l = Math.round(d * 1024 * 1024 * 1024L);
switch (text.replaceAll("\\d?", "").toUpperCase().charAt(0)) {
default:
l /= 1024;
case 'K':
l /= 1024;
case 'M':
l /= 1024;
case 'G':
return l;
}
}
public static String humanReadableByteCountBin(long bytes) {
long absB = bytes == Long.MIN_VALUE ? Long.MAX_VALUE : Math.abs(bytes);
if (absB < 1024) {
return bytes + " B";
}
long value = absB;
CharacterIterator ci = new StringCharacterIterator("KMGTPE");
for (int i = 40; i >= 0 && absB > 0xfffccccccccccccL >> i; i -= 10) {
value >>= 10;
ci.next();
}
value *= Long.signum(bytes);
return String.format("%.1f %cB", value / 1024.0, ci.current());
}
public static void systemCheck(ConfigTag checkRAM) {
long minBytes = parseSize(
checkRAM.getTag("minRAM").setComment("Amount of RAM minimum this modpack needs to load")
.getValue("3GB"));
if (Runtime.getRuntime().maxMemory() < minBytes) {
String err = "You should have at least " + humanReadableByteCountBin(minBytes)
+ " of RAM but you have only allocated "
+ humanReadableByteCountBin(Runtime.getRuntime().maxMemory())
+ ".";
logger.error(err);
JEditorPane ep = new JEditorPane(
"text/html",
"<html>" + err
+ "<br>"
+ checkRAM.getTag("modPack").setComment("Name of the modpack")
.getValue("Unidentified ModPack")
+ " seriously won't run without enough RAM. "
+ checkRAM.getTag("wiki").setComment("Webpage describing RAM settings").getValue(
"See <a href=\"https://downloadmoreram.com\">DownloadMoreRam.com</a> for details.")
+ "<br>Recommended values are between "
+ checkRAM.getTag("recRAM").setComment("Lower bound of recommended RAM").getValue("4GB")
+ " and "
+ checkRAM.getTag("recRAMUpper").setComment("Upper bound of recommended RAM")
.getValue("6GB")
+ ". Check your launcher's JVM arguments."
+ "</html>");
ep.setEditable(false);
ep.setOpaque(false);
ep.addHyperlinkListener(new HyperlinkListener() {
@Override
public void hyperlinkUpdate(HyperlinkEvent event) {
try {
if (event.getEventType().equals(HyperlinkEvent.EventType.ACTIVATED))
Desktop.getDesktop().browse(event.getURL().toURI());
} catch (Exception ignored) {}
}
});
if (!GraphicsEnvironment.isHeadless())
JOptionPane.showMessageDialog(null, ep, "lol nope", JOptionPane.ERROR_MESSAGE);
FMLCommonHandler.instance().exitJava(-98, true);
}
}
@Override
public String[] getASMTransformerClass() {
versionCheck(mcVersion, "CodeChickenCore");
return new String[]{
"codechicken.lib.asm.ClassHeirachyManager",
"codechicken.core.asm.InterfaceDependancyTransformer",
"codechicken.core.asm.TweakTransformer",
"codechicken.core.asm.DelegatedTransformer",
"codechicken.core.asm.DefaultImplementationTransformer"};
return new String[] { "codechicken.lib.asm.ClassHeirachyManager", "codechicken.core.asm.TweakTransformer",
"codechicken.core.asm.DelegatedTransformer", "codechicken.core.asm.DefaultImplementationTransformer",
"codechicken.lib.asm.RedirectorTransformer" };
}
@Override
@@ -118,12 +211,18 @@ public class CodeChickenCorePlugin implements IFMLLoadingPlugin, IFMLCallHook
}
@Override
public void injectData(Map<String, Object> data) {
}
public void injectData(Map<String, Object> data) {}
@Override
public Void call() {
CodeChickenCoreModContainer.loadConfig();
ConfigTag checkRAM;
checkRAM = CodeChickenCoreModContainer.config.getTag("checks")
.setComment("Configuration options for checking various requirements for a modpack.").useBraces();
if (checkRAM.getTag("checkRAM")
.setComment("If set to true, check RAM available for Minecraft before continuing to load")
.getBooleanValue(false))
systemCheck(checkRAM);
TweakTransformer.load();
scanCodeChickenMods();
@@ -132,31 +231,24 @@ public class CodeChickenCorePlugin implements IFMLLoadingPlugin, IFMLCallHook
private void scanCodeChickenMods() {
File modsDir = new File(minecraftDir, "mods");
for (File file : modsDir.listFiles())
scanMod(file);
for (File file : modsDir.listFiles()) scanMod(file);
File versionModsDir = new File(minecraftDir, "mods/" + currentMcVersion);
if (versionModsDir.exists())
for (File file : versionModsDir.listFiles())
scanMod(file);
if (versionModsDir.exists()) for (File file : versionModsDir.listFiles()) scanMod(file);
}
private void scanMod(File file) {
if (!file.getName().endsWith(".jar") && !file.getName().endsWith(".zip"))
return;
if (!file.getName().endsWith(".jar") && !file.getName().endsWith(".zip")) return;
try {
JarFile jar = new JarFile(file);
try {
Manifest manifest = jar.getManifest();
if (manifest == null)
return;
if (manifest == null) return;
Attributes attr = manifest.getMainAttributes();
if (attr == null)
return;
if (attr == null) return;
String transformer = attr.getValue("CCTransformer");
if (transformer != null)
DelegatedTransformer.addTransformer(transformer, jar, file);
if (transformer != null) DelegatedTransformer.addTransformer(transformer, jar, file);
} finally {
jar.close();
}
@@ -1,51 +1,26 @@
package codechicken.core.launch;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import cpw.mods.fml.common.versioning.ComparableVersion;
import cpw.mods.fml.relauncher.FMLInjectionData;
import cpw.mods.fml.relauncher.FMLLaunchHandler;
import cpw.mods.fml.relauncher.IFMLCallHook;
import cpw.mods.fml.relauncher.IFMLLoadingPlugin;
import net.minecraft.launchwrapper.LaunchClassLoader;
import sun.misc.URLClassPath;
import sun.net.util.URLUtil;
import javax.swing.*;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import java.awt.*;
import java.awt.Dialog.ModalityType;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.*;
import java.lang.reflect.Field;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLConnection;
import java.nio.ByteBuffer;
import java.util.*;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import javax.swing.Box;
import javax.swing.JDialog;
import javax.swing.JOptionPane;
import cpw.mods.fml.common.versioning.ComparableVersion;
import cpw.mods.fml.relauncher.IFMLCallHook;
import cpw.mods.fml.relauncher.IFMLLoadingPlugin;
import cpw.mods.fml.relauncher.IFMLLoadingPlugin.MCVersion;
/**
* For autodownloading stuff.
* This is really unoriginal, mostly ripped off FML, credits to cpw.
* For autodownloading stuff. This is really unoriginal, mostly ripped off FML, credits to cpw.
*/
@MCVersion("1.7.10")
public class DepLoader implements IFMLLoadingPlugin, IFMLCallHook {
private static ByteBuffer downloadBuffer = ByteBuffer.allocateDirect(1 << 23);
private static final String owner = "CB's DepLoader";
private static DepLoadInst inst;
public interface IDownloadDisplay {
void resetProgress(int sizeGuess);
void setPokeThread(Thread currentThread);
@@ -63,143 +38,52 @@ public class DepLoader implements IFMLLoadingPlugin, IFMLCallHook {
@SuppressWarnings("serial")
public static class Downloader extends JOptionPane implements IDownloadDisplay {
private JDialog container;
private JLabel currentActivity;
private JProgressBar progress;
boolean stopIt;
Thread pokeThread;
private Box makeProgressPanel() {
Box box = Box.createVerticalBox();
box.add(Box.createRigidArea(new Dimension(0, 10)));
JLabel welcomeLabel = new JLabel("<html><b><font size='+1'>" + owner + " is setting up your minecraft environment</font></b></html>");
box.add(welcomeLabel);
welcomeLabel.setAlignmentY(LEFT_ALIGNMENT);
welcomeLabel = new JLabel("<html>Please wait, " + owner + " has some tasks to do before you can play</html>");
welcomeLabel.setAlignmentY(LEFT_ALIGNMENT);
box.add(welcomeLabel);
box.add(Box.createRigidArea(new Dimension(0, 10)));
currentActivity = new JLabel("Currently doing ...");
box.add(currentActivity);
box.add(Box.createRigidArea(new Dimension(0, 10)));
progress = new JProgressBar(0, 100);
progress.setStringPainted(true);
box.add(progress);
box.add(Box.createRigidArea(new Dimension(0, 30)));
return box;
return null;
}
@Override
public JDialog makeDialog() {
if (container != null)
return container;
setMessageType(JOptionPane.INFORMATION_MESSAGE);
setMessage(makeProgressPanel());
setOptions(new Object[]{"Stop"});
addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getSource() == Downloader.this && evt.getPropertyName() == VALUE_PROPERTY) {
requestClose("This will stop minecraft from launching\nAre you sure you want to do this?");
}
}
});
container = new JDialog(null, "Hello", ModalityType.MODELESS);
container.setResizable(false);
container.setLocationRelativeTo(null);
container.add(this);
this.updateUI();
container.pack();
container.setMinimumSize(container.getPreferredSize());
container.setVisible(true);
container.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
container.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
requestClose("Closing this window will stop minecraft from launching\nAre you sure you wish to do this?");
}
});
return container;
return null;
}
protected void requestClose(String message) {
int shouldClose = JOptionPane.showConfirmDialog(container, message, "Are you sure you want to stop?", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
if (shouldClose == JOptionPane.YES_OPTION)
container.dispose();
stopIt = true;
if (pokeThread != null)
pokeThread.interrupt();
}
protected void requestClose(String message) {}
@Override
public void updateProgressString(String progressUpdate, Object... data) {
//FMLLog.finest(progressUpdate, data);
if (currentActivity != null)
currentActivity.setText(String.format(progressUpdate, data));
}
public void updateProgressString(String progressUpdate, Object... data) {}
@Override
public void resetProgress(int sizeGuess) {
if (progress != null)
progress.getModel().setRangeProperties(0, 0, 0, sizeGuess, false);
}
public void resetProgress(int sizeGuess) {}
@Override
public void updateProgress(int fullLength) {
if (progress != null)
progress.getModel().setValue(fullLength);
}
public void updateProgress(int fullLength) {}
@Override
public void setPokeThread(Thread currentThread) {
this.pokeThread = currentThread;
}
public void setPokeThread(Thread currentThread) {}
@Override
public boolean shouldStopIt() {
return stopIt;
return true;
}
@Override
public void showErrorDialog(String name, String url) {
JEditorPane ep = new JEditorPane("text/html",
"<html>" +
owner + " was unable to download required library " + name +
"<br>Check your internet connection and try restarting or download it manually from" +
"<br><a href=\"" + url + "\">" + url + "</a> and put it in your mods folder" +
"</html>");
ep.setEditable(false);
ep.setOpaque(false);
ep.addHyperlinkListener(new HyperlinkListener() {
@Override
public void hyperlinkUpdate(HyperlinkEvent event) {
try {
if (event.getEventType().equals(HyperlinkEvent.EventType.ACTIVATED))
Desktop.getDesktop().browse(event.getURL().toURI());
} catch (Exception e) {
}
}
});
JOptionPane.showMessageDialog(null, ep, "A download error has occured", JOptionPane.ERROR_MESSAGE);
}
public void showErrorDialog(String name, String url) {}
}
public static class DummyDownloader implements IDownloadDisplay {
@Override
public void resetProgress(int sizeGuess) {
}
@Override
public void setPokeThread(Thread currentThread) {
}
public void resetProgress(int sizeGuess) {}
@Override
public void updateProgress(int fullLength) {
}
public void setPokeThread(Thread currentThread) {}
@Override
public void updateProgress(int fullLength) {}
@Override
public boolean shouldStopIt() {
@@ -207,8 +91,7 @@ public class DepLoader implements IFMLLoadingPlugin, IFMLCallHook {
}
@Override
public void updateProgressString(String string, Object... data) {
}
public void updateProgressString(String string, Object... data) {}
@Override
public Object makeDialog() {
@@ -216,12 +99,11 @@ public class DepLoader implements IFMLLoadingPlugin, IFMLCallHook {
}
@Override
public void showErrorDialog(String name, String url) {
}
public void showErrorDialog(String name, String url) {}
}
public static class VersionedFile
{
public static class VersionedFile {
public final Pattern pattern;
public final String filename;
public final ComparableVersion version;
@@ -231,11 +113,10 @@ public class DepLoader implements IFMLLoadingPlugin, IFMLCallHook {
this.pattern = pattern;
this.filename = filename;
Matcher m = pattern.matcher(filename);
if(m.matches()) {
if (m.matches()) {
name = m.group(1);
version = new ComparableVersion(m.group(2));
}
else {
} else {
name = null;
version = null;
}
@@ -246,8 +127,8 @@ public class DepLoader implements IFMLLoadingPlugin, IFMLCallHook {
}
}
public static class Dependency
{
public static class Dependency {
public String url;
public VersionedFile file;
@@ -265,325 +146,13 @@ public class DepLoader implements IFMLLoadingPlugin, IFMLCallHook {
}
public static class DepLoadInst {
private File modsDir;
private File v_modsDir;
private IDownloadDisplay downloadMonitor;
private JDialog popupWindow;
private Map<String, Dependency> depMap = new HashMap<String, Dependency>();
private HashSet<String> depSet = new HashSet<String>();
public DepLoadInst() {}
public DepLoadInst() {
String mcVer = (String) FMLInjectionData.data()[4];
File mcDir = (File) FMLInjectionData.data()[6];
modsDir = new File(mcDir, "mods");
v_modsDir = new File(mcDir, "mods/" + mcVer);
if (!v_modsDir.exists())
v_modsDir.mkdirs();
}
private void addClasspath(String name) {
try {
((LaunchClassLoader) DepLoader.class.getClassLoader()).addURL(new File(v_modsDir, name).toURI().toURL());
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
private void deleteMod(File mod) {
if (mod.delete())
return;
try {
ClassLoader cl = DepLoader.class.getClassLoader();
URL url = mod.toURI().toURL();
Field f_ucp = URLClassLoader.class.getDeclaredField("ucp");
Field f_loaders = URLClassPath.class.getDeclaredField("loaders");
Field f_lmap = URLClassPath.class.getDeclaredField("lmap");
f_ucp.setAccessible(true);
f_loaders.setAccessible(true);
f_lmap.setAccessible(true);
URLClassPath ucp = (URLClassPath) f_ucp.get(cl);
Closeable loader = ((Map<String, Closeable>) f_lmap.get(ucp)).remove(URLUtil.urlNoFragString(url));
if (loader != null) {
loader.close();
((List<?>) f_loaders.get(ucp)).remove(loader);
}
} catch (Exception e) {
e.printStackTrace();
}
if (!mod.delete()) {
mod.deleteOnExit();
String msg = owner + " was unable to delete file " + mod.getPath() + " the game will now try to delete it on exit. If this dialog appears again, delete it manually.";
System.err.println(msg);
if (!GraphicsEnvironment.isHeadless())
JOptionPane.showMessageDialog(null, msg, "An update error has occured", JOptionPane.ERROR_MESSAGE);
System.exit(1);
}
}
private void download(Dependency dep) {
popupWindow = (JDialog) downloadMonitor.makeDialog();
File libFile = new File(v_modsDir, dep.file.filename);
try {
URL libDownload = new URL(dep.url + '/' + dep.file.filename);
downloadMonitor.updateProgressString("Downloading file %s", libDownload.toString());
System.out.format("Downloading file %s\n", libDownload.toString());
URLConnection connection = libDownload.openConnection();
connection.setConnectTimeout(5000);
connection.setReadTimeout(5000);
connection.setRequestProperty("User-Agent", "" + owner + " Downloader");
int sizeGuess = connection.getContentLength();
download(connection.getInputStream(), sizeGuess, libFile);
downloadMonitor.updateProgressString("Download complete");
System.out.println("Download complete");
scanDepInfo(libFile);
} catch (Exception e) {
libFile.delete();
if (downloadMonitor.shouldStopIt()) {
System.err.println("You have stopped the downloading operation before it could complete");
System.exit(1);
return;
}
downloadMonitor.showErrorDialog(dep.file.filename, dep.url + '/' + dep.file.filename);
throw new RuntimeException("A download error occured", e);
}
}
private void download(InputStream is, int sizeGuess, File target) throws Exception {
if (sizeGuess > downloadBuffer.capacity())
throw new Exception(String.format("The file %s is too large to be downloaded by " + owner + " - the download is invalid", target.getName()));
downloadBuffer.clear();
int bytesRead, fullLength = 0;
downloadMonitor.resetProgress(sizeGuess);
try {
downloadMonitor.setPokeThread(Thread.currentThread());
byte[] smallBuffer = new byte[1024];
while ((bytesRead = is.read(smallBuffer)) >= 0) {
downloadBuffer.put(smallBuffer, 0, bytesRead);
fullLength += bytesRead;
if (downloadMonitor.shouldStopIt()) {
break;
}
downloadMonitor.updateProgress(fullLength);
}
is.close();
downloadMonitor.setPokeThread(null);
downloadBuffer.limit(fullLength);
downloadBuffer.position(0);
} catch (InterruptedIOException e) {
// We were interrupted by the stop button. We're stopping now.. clear interruption flag.
Thread.interrupted();
throw new Exception("Stop");
} catch (IOException e) {
throw e;
}
try {
/*String cksum = generateChecksum(downloadBuffer);
if (cksum.equals(validationHash))
{*/
if (!target.exists())
target.createNewFile();
downloadBuffer.position(0);
FileOutputStream fos = new FileOutputStream(target);
fos.getChannel().write(downloadBuffer);
fos.close();
/*}
else
{
throw new RuntimeException(String.format("The downloaded file %s has an invalid checksum %s (expecting %s). The download did not succeed correctly and the file has been deleted. Please try launching again.", target.getName(), cksum, validationHash));
}*/
} catch (Exception e) {
throw e;
}
}
private String checkExisting(Dependency dep) {
for (File f : modsDir.listFiles()) {
VersionedFile vfile = new VersionedFile(f.getName(), dep.file.pattern);
if (!vfile.matches() || !vfile.name.equals(dep.file.name))
continue;
if (f.renameTo(new File(v_modsDir, f.getName())))
continue;
deleteMod(f);
}
for (File f : v_modsDir.listFiles()) {
VersionedFile vfile = new VersionedFile(f.getName(), dep.file.pattern);
if (!vfile.matches() || !vfile.name.equals(dep.file.name))
continue;
int cmp = vfile.version.compareTo(dep.file.version);
if (cmp < 0) {
System.out.println("Deleted old version " + f.getName());
deleteMod(f);
return null;
}
if (cmp > 0) {
System.err.println("Warning: version of " + dep.file.name + ", " + vfile.version + " is newer than request " + dep.file.version);
return f.getName();
}
return f.getName();//found dependency
}
return null;
}
public void load() {
scanDepInfos();
if (depMap.isEmpty())
return;
loadDeps();
activateDeps();
}
private void activateDeps() {
for (Dependency dep : depMap.values())
if (dep.coreLib)
addClasspath(dep.existing);
}
private void loadDeps() {
downloadMonitor = FMLLaunchHandler.side().isClient() ? new Downloader() : new DummyDownloader();
try {
while (!depSet.isEmpty()) {
Iterator<String> it = depSet.iterator();
Dependency dep = depMap.get(it.next());
it.remove();
load(dep);
}
} finally {
if (popupWindow != null) {
popupWindow.setVisible(false);
popupWindow.dispose();
}
}
}
private void load(Dependency dep) {
dep.existing = checkExisting(dep);
if (dep.existing == null)//download dep
{
download(dep);
dep.existing = dep.file.filename;
}
}
private List<File> modFiles() {
List<File> list = new LinkedList<File>();
list.addAll(Arrays.asList(modsDir.listFiles()));
list.addAll(Arrays.asList(v_modsDir.listFiles()));
return list;
}
private void scanDepInfos() {
for (File file : modFiles()) {
if (!file.getName().endsWith(".jar") && !file.getName().endsWith(".zip"))
continue;
scanDepInfo(file);
}
}
private void scanDepInfo(File file) {
try {
ZipFile zip = new ZipFile(file);
ZipEntry e = zip.getEntry("dependancies.info");
if (e == null) e = zip.getEntry("dependencies.info");
if (e != null)
loadJSon(zip.getInputStream(e));
zip.close();
} catch (Exception e) {
System.err.println("Failed to load dependencies.info from " + file.getName() + " as JSON");
e.printStackTrace();
}
}
private void loadJSon(InputStream input) throws IOException {
InputStreamReader reader = new InputStreamReader(input);
JsonElement root = new JsonParser().parse(reader);
if (root.isJsonArray())
loadJSonArr(root);
else
loadJson(root.getAsJsonObject());
reader.close();
}
private void loadJSonArr(JsonElement root) throws IOException {
for (JsonElement node : root.getAsJsonArray())
loadJson(node.getAsJsonObject());
}
private void loadJson(JsonObject node) throws IOException {
boolean obfuscated = ((LaunchClassLoader) DepLoader.class.getClassLoader())
.getClassBytes("net.minecraft.world.World") == null;
String testClass = node.get("class").getAsString();
if (DepLoader.class.getResource("/" + testClass.replace('.', '/') + ".class") != null)
return;
String repo = node.get("repo").getAsString();
String filename = node.get("file").getAsString();
if (!obfuscated && node.has("dev"))
filename = node.get("dev").getAsString();
boolean coreLib = node.has("coreLib") && node.get("coreLib").getAsBoolean();
Pattern pattern = null;
try {
if(node.has("pattern"))
pattern = Pattern.compile(node.get("pattern").getAsString());
} catch (PatternSyntaxException e) {
System.err.println("Invalid filename pattern: "+node.get("pattern"));
e.printStackTrace();
}
if(pattern == null)
pattern = Pattern.compile("(\\w+).*?([\\d\\.]+)[-\\w]*\\.[^\\d]+");
VersionedFile file = new VersionedFile(filename, pattern);
if (!file.matches())
throw new RuntimeException("Invalid filename format for dependency: " + filename);
addDep(new Dependency(repo, file, coreLib));
}
private void addDep(Dependency newDep) {
if (mergeNew(depMap.get(newDep.file.name), newDep)) {
depMap.put(newDep.file.name, newDep);
depSet.add(newDep.file.name);
}
}
private boolean mergeNew(Dependency oldDep, Dependency newDep) {
if (oldDep == null)
return true;
Dependency newest = newDep.file.version.compareTo(oldDep.file.version) > 0 ? newDep : oldDep;
newest.coreLib = newDep.coreLib || oldDep.coreLib;
return newest == newDep;
}
public void load() {}
}
public static void load() {
if (inst == null) {
inst = new DepLoadInst();
inst.load();
}
}
public static void load() {}
@Override
public String[] getASMTransformerClass() {
@@ -601,8 +170,7 @@ public class DepLoader implements IFMLLoadingPlugin, IFMLCallHook {
}
@Override
public void injectData(Map<String, Object> data) {
}
public void injectData(Map<String, Object> data) {}
@Override
public Void call() {
@@ -0,0 +1,177 @@
package codechicken.lib.asm;
import static org.objectweb.asm.tree.AbstractInsnNode.FRAME;
import static org.objectweb.asm.tree.AbstractInsnNode.JUMP_INSN;
import static org.objectweb.asm.tree.AbstractInsnNode.LABEL;
import static org.objectweb.asm.tree.AbstractInsnNode.LOOKUPSWITCH_INSN;
import static org.objectweb.asm.tree.AbstractInsnNode.TABLESWITCH_INSN;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.JumpInsnNode;
import org.objectweb.asm.tree.LabelNode;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.google.common.collect.ImmutableMap;
public class ASMBlock {
public InsnListSection list;
private BiMap<String, LabelNode> labels;
public ASMBlock(InsnListSection list, BiMap<String, LabelNode> labels) {
this.list = list;
this.labels = labels;
}
public ASMBlock(InsnListSection list) {
this(list, HashBiMap.<String, LabelNode>create());
}
public ASMBlock(InsnList list) {
this(new InsnListSection(list));
}
public ASMBlock() {
this(new InsnListSection());
}
public LabelNode getOrAdd(String s) {
LabelNode l = get(s);
if (l == null) labels.put(s, l = new LabelNode());
return l;
}
public LabelNode get(String s) {
return labels.get(s);
}
public void replaceLabels(Map<LabelNode, LabelNode> labelMap, Set<LabelNode> usedLabels) {
for (AbstractInsnNode insn : list) switch (insn.getType()) {
case LABEL:
AbstractInsnNode insn2 = insn.clone(labelMap);
if (insn2 == insn) // identity mapping
continue;
if (usedLabels.contains(insn2))
throw new IllegalStateException("LabelNode cannot be a part of two InsnLists");
list.replace(insn, insn2);
break;
case JUMP_INSN:
case FRAME:
case LOOKUPSWITCH_INSN:
case TABLESWITCH_INSN:
list.replace(insn, insn.clone(labelMap));
}
for (Entry<LabelNode, LabelNode> entry : labelMap.entrySet()) {
String key = labels.inverse().get(entry.getKey());
if (key != null) labels.put(key, entry.getValue());
}
}
public void replaceLabels(Map<LabelNode, LabelNode> labelMap) {
replaceLabels(labelMap, Collections.EMPTY_SET);
}
public void replaceLabel(String s, LabelNode l) {
LabelNode old = get(s);
if (old != null) replaceLabels(ImmutableMap.of(old, l));
}
/**
* Pulls all common labels from other into this
*
* @return this
*/
public ASMBlock mergeLabels(ASMBlock other) {
if (labels.isEmpty() || other.labels.isEmpty()) return this;
// common labels, give them our nodes
HashMap<LabelNode, LabelNode> labelMap = list.identityLabelMap();
for (Entry<String, LabelNode> entry : other.labels.entrySet()) {
LabelNode old = labels.get(entry.getKey());
if (old != null) labelMap.put(old, entry.getValue());
}
HashSet<LabelNode> usedLabels = new HashSet<LabelNode>();
for (AbstractInsnNode insn = other.list.list.getFirst(); insn != null; insn = insn.getNext())
if (insn.getType() == LABEL) usedLabels.add((LabelNode) insn);
replaceLabels(labelMap, usedLabels);
return this;
}
/**
* Like mergeLabels but pulls insns from other list into this so LabelNodes can be transferred
*
* @return this
*/
public ASMBlock pullLabels(ASMBlock other) {
other.list.remove();
return mergeLabels(other);
}
public ASMBlock copy() {
BiMap<String, LabelNode> labels = HashBiMap.create();
Map<LabelNode, LabelNode> labelMap = list.cloneLabels();
for (Entry<String, LabelNode> entry : this.labels.entrySet())
labels.put(entry.getKey(), labelMap.get(entry.getValue()));
return new ASMBlock(list.copy(labelMap), labels);
}
public ASMBlock applyLabels(InsnListSection list2) {
if (labels.isEmpty()) return new ASMBlock(list2);
Set<LabelNode> cFlowLabels1 = labels.values();
Set<LabelNode> cFlowLabels2 = InsnComparator.getControlFlowLabels(list2);
ASMBlock block = new ASMBlock(list2);
HashMap<LabelNode, LabelNode> labelMap = new HashMap<LabelNode, LabelNode>();
for (int i = 0, k = 0; i < list.size() && k < list2.size();) {
AbstractInsnNode insn1 = list.get(i);
if (!InsnComparator.insnImportant(insn1, cFlowLabels1)) {
i++;
continue;
}
AbstractInsnNode insn2 = list2.get(k);
if (!InsnComparator.insnImportant(insn2, cFlowLabels2)) {
k++;
continue;
}
if (insn1.getOpcode() != insn2.getOpcode())
throw new IllegalArgumentException("Lists do not match:\n" + list + "\n\n" + list2);
switch (insn1.getType()) {
case LABEL:
labelMap.put((LabelNode) insn1, (LabelNode) insn2);
break;
case JUMP_INSN:
labelMap.put(((JumpInsnNode) insn1).label, ((JumpInsnNode) insn2).label);
break;
}
i++;
k++;
}
for (Entry<String, LabelNode> entry : labels.entrySet())
block.labels.put(entry.getKey(), labelMap.get(entry.getValue()));
return block;
}
public InsnList rawListCopy() {
return list.copy().list;
}
}
@@ -0,0 +1,203 @@
package codechicken.lib.asm;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.FieldNode;
import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.LabelNode;
import org.objectweb.asm.tree.LocalVariableNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.TryCatchBlockNode;
import org.objectweb.asm.util.ASMifier;
import org.objectweb.asm.util.Textifier;
import org.objectweb.asm.util.TraceClassVisitor;
import codechicken.lib.config.ConfigFile;
import codechicken.lib.config.DefaultingConfigFile;
public class ASMHelper {
public static ConfigFile config = loadConfig();
public static Logger logger = LogManager.getLogger("CCL ASM");
private static ConfigFile loadConfig() {
try { // weak reference for environments without FML
File mcDir = (File) ((Object[]) Class.forName("cpw.mods.fml.relauncher.FMLInjectionData").getMethod("data")
.invoke(null))[6];
File file = new File(mcDir, "config/CodeChickenLib.cfg");
if (ObfMapping.obfuscated) return new DefaultingConfigFile(file);
else return new ConfigFile(file).setComment("CodeChickenLib development configuration file.");
} catch (Exception ignored) {
return null; // no config for these systems
}
}
public static interface Acceptor {
public void accept(ClassVisitor cv) throws IOException;
}
public static MethodNode findMethod(ObfMapping methodmap, ClassNode cnode) {
for (MethodNode mnode : cnode.methods) if (methodmap.matches(mnode)) return mnode;
return null;
}
public static FieldNode findField(ObfMapping fieldmap, ClassNode cnode) {
for (FieldNode fnode : cnode.fields) if (fieldmap.matches(fnode)) return fnode;
return null;
}
public static ClassNode createClassNode(byte[] bytes) {
return createClassNode(bytes, 0);
}
public static ClassNode createClassNode(byte[] bytes, int flags) {
ClassNode cnode = new ClassNode();
ClassReader reader = new ClassReader(bytes);
reader.accept(cnode, flags);
return cnode;
}
public static byte[] createBytes(ClassNode cnode, int flags) {
ClassWriter cw = new CC_ClassWriter(flags);
cnode.accept(cw);
return cw.toByteArray();
}
public static Map<LabelNode, LabelNode> cloneLabels(InsnList list) {
return new InsnListSection(list).cloneLabels();
}
public static InsnList cloneInsnList(InsnList list) {
return new InsnListSection(list).copy().list;
}
public static InsnList cloneInsnList(Map<LabelNode, LabelNode> labelMap, InsnList list) {
return new InsnListSection(list).copy(labelMap).list;
}
public static List<TryCatchBlockNode> cloneTryCatchBlocks(Map<LabelNode, LabelNode> labelMap,
List<TryCatchBlockNode> tcblocks) {
ArrayList<TryCatchBlockNode> clone = new ArrayList<TryCatchBlockNode>();
for (TryCatchBlockNode node : tcblocks) clone.add(
new TryCatchBlockNode(
labelMap.get(node.start),
labelMap.get(node.end),
labelMap.get(node.handler),
node.type));
return clone;
}
public static List<LocalVariableNode> cloneLocals(Map<LabelNode, LabelNode> labelMap,
List<LocalVariableNode> locals) {
ArrayList<LocalVariableNode> clone = new ArrayList<LocalVariableNode>(locals.size());
for (LocalVariableNode node : locals) clone.add(
new LocalVariableNode(
node.name,
node.desc,
node.signature,
labelMap.get(node.start),
labelMap.get(node.end),
node.index));
return clone;
}
public static void copy(MethodNode src, MethodNode dst) {
Map<LabelNode, LabelNode> labelMap = cloneLabels(src.instructions);
dst.instructions = cloneInsnList(labelMap, src.instructions);
dst.tryCatchBlocks = cloneTryCatchBlocks(labelMap, src.tryCatchBlocks);
if (src.localVariables != null) dst.localVariables = cloneLocals(labelMap, src.localVariables);
dst.visibleAnnotations = src.visibleAnnotations;
dst.invisibleAnnotations = src.invisibleAnnotations;
dst.visitMaxs(src.maxStack, src.maxLocals);
}
public static String toString(InsnList list) {
return new InsnListSection(list).toString();
}
public static int getLocal(List<LocalVariableNode> list, String name) {
int found = -1;
for (LocalVariableNode node : list) {
if (node.name.equals(name)) {
if (found >= 0) throw new RuntimeException(
"Duplicate local variable: " + name + " not coded to handle this scenario.");
found = node.index;
}
}
return found;
}
public static void replaceMethod(MethodNode original, MethodNode replacement) {
original.instructions.clear();
if (original.localVariables != null) original.localVariables.clear();
if (original.tryCatchBlocks != null) original.tryCatchBlocks.clear();
replacement.accept(original);
}
public static void dump(Acceptor acceptor, File file, boolean filterImportant, boolean sortLocals,
boolean textify) {
try {
if (!file.getParentFile().exists()) file.getParentFile().mkdirs();
if (!file.exists()) file.createNewFile();
PrintWriter pout = new PrintWriter(file);
ClassVisitor cv = new TraceClassVisitor(null, textify ? new Textifier() : new ASMifier(), pout);
if (filterImportant) cv = new ImportantInsnVisitor(cv);
if (sortLocals) cv = new LocalVariablesSorterVisitor(cv);
acceptor.accept(cv);
pout.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static void dump(Acceptor acceptor, File file, boolean filterImportant, boolean sortLocals) {
dump(acceptor, file, filterImportant, sortLocals, config.getTag("textify").getBooleanValue(true));
}
public static void dump(final byte[] bytes, File file, boolean filterImportant, boolean sortLocals) {
dump(new Acceptor() {
@Override
public void accept(ClassVisitor cv) {
new ClassReader(bytes).accept(cv, ClassReader.EXPAND_FRAMES);
}
}, file, filterImportant, sortLocals);
}
public static void dump(final InputStream is, File file, boolean filterImportant, boolean sortLocals) {
dump(new Acceptor() {
@Override
public void accept(ClassVisitor cv) throws IOException {
new ClassReader(is).accept(cv, ClassReader.EXPAND_FRAMES);
}
}, file, filterImportant, sortLocals);
}
public static void dump(final ClassNode cnode, File file, boolean filterImportant, boolean sortLocals) {
dump(new Acceptor() {
@Override
public void accept(ClassVisitor cv) {
cnode.accept(cv);
}
}, file, filterImportant, sortLocals);
}
}
@@ -0,0 +1,19 @@
package codechicken.lib.asm;
import net.minecraft.launchwrapper.Launch;
/**
* Initialisation class for using this package. Call this on coremod load
*/
public class ASMInit {
private static boolean initialised = false;
public static void init() {
if (!initialised) {
Launch.classLoader.addTransformerExclusion("codechicken.lib.asm");
Launch.classLoader.addTransformerExclusion("codechicken.lib.config");
initialised = true;
}
}
}
@@ -0,0 +1,469 @@
package codechicken.lib.asm;
import static org.objectweb.asm.Opcodes.AALOAD;
import static org.objectweb.asm.Opcodes.AASTORE;
import static org.objectweb.asm.Opcodes.ACONST_NULL;
import static org.objectweb.asm.Opcodes.ALOAD;
import static org.objectweb.asm.Opcodes.ANEWARRAY;
import static org.objectweb.asm.Opcodes.ARETURN;
import static org.objectweb.asm.Opcodes.ARRAYLENGTH;
import static org.objectweb.asm.Opcodes.ASTORE;
import static org.objectweb.asm.Opcodes.ATHROW;
import static org.objectweb.asm.Opcodes.BALOAD;
import static org.objectweb.asm.Opcodes.BASTORE;
import static org.objectweb.asm.Opcodes.BIPUSH;
import static org.objectweb.asm.Opcodes.CALOAD;
import static org.objectweb.asm.Opcodes.CASTORE;
import static org.objectweb.asm.Opcodes.CHECKCAST;
import static org.objectweb.asm.Opcodes.D2F;
import static org.objectweb.asm.Opcodes.D2I;
import static org.objectweb.asm.Opcodes.D2L;
import static org.objectweb.asm.Opcodes.DADD;
import static org.objectweb.asm.Opcodes.DALOAD;
import static org.objectweb.asm.Opcodes.DASTORE;
import static org.objectweb.asm.Opcodes.DCMPG;
import static org.objectweb.asm.Opcodes.DCMPL;
import static org.objectweb.asm.Opcodes.DCONST_0;
import static org.objectweb.asm.Opcodes.DCONST_1;
import static org.objectweb.asm.Opcodes.DDIV;
import static org.objectweb.asm.Opcodes.DLOAD;
import static org.objectweb.asm.Opcodes.DMUL;
import static org.objectweb.asm.Opcodes.DNEG;
import static org.objectweb.asm.Opcodes.DREM;
import static org.objectweb.asm.Opcodes.DRETURN;
import static org.objectweb.asm.Opcodes.DSTORE;
import static org.objectweb.asm.Opcodes.DSUB;
import static org.objectweb.asm.Opcodes.DUP;
import static org.objectweb.asm.Opcodes.DUP2;
import static org.objectweb.asm.Opcodes.DUP2_X1;
import static org.objectweb.asm.Opcodes.DUP2_X2;
import static org.objectweb.asm.Opcodes.DUP_X1;
import static org.objectweb.asm.Opcodes.DUP_X2;
import static org.objectweb.asm.Opcodes.F2D;
import static org.objectweb.asm.Opcodes.F2I;
import static org.objectweb.asm.Opcodes.F2L;
import static org.objectweb.asm.Opcodes.FADD;
import static org.objectweb.asm.Opcodes.FALOAD;
import static org.objectweb.asm.Opcodes.FASTORE;
import static org.objectweb.asm.Opcodes.FCMPG;
import static org.objectweb.asm.Opcodes.FCMPL;
import static org.objectweb.asm.Opcodes.FCONST_0;
import static org.objectweb.asm.Opcodes.FCONST_1;
import static org.objectweb.asm.Opcodes.FCONST_2;
import static org.objectweb.asm.Opcodes.FDIV;
import static org.objectweb.asm.Opcodes.FLOAD;
import static org.objectweb.asm.Opcodes.FMUL;
import static org.objectweb.asm.Opcodes.FNEG;
import static org.objectweb.asm.Opcodes.FREM;
import static org.objectweb.asm.Opcodes.FRETURN;
import static org.objectweb.asm.Opcodes.FSTORE;
import static org.objectweb.asm.Opcodes.FSUB;
import static org.objectweb.asm.Opcodes.GETFIELD;
import static org.objectweb.asm.Opcodes.GETSTATIC;
import static org.objectweb.asm.Opcodes.GOTO;
import static org.objectweb.asm.Opcodes.I2B;
import static org.objectweb.asm.Opcodes.I2C;
import static org.objectweb.asm.Opcodes.I2D;
import static org.objectweb.asm.Opcodes.I2F;
import static org.objectweb.asm.Opcodes.I2L;
import static org.objectweb.asm.Opcodes.I2S;
import static org.objectweb.asm.Opcodes.IADD;
import static org.objectweb.asm.Opcodes.IALOAD;
import static org.objectweb.asm.Opcodes.IAND;
import static org.objectweb.asm.Opcodes.IASTORE;
import static org.objectweb.asm.Opcodes.ICONST_0;
import static org.objectweb.asm.Opcodes.ICONST_1;
import static org.objectweb.asm.Opcodes.ICONST_2;
import static org.objectweb.asm.Opcodes.ICONST_3;
import static org.objectweb.asm.Opcodes.ICONST_4;
import static org.objectweb.asm.Opcodes.ICONST_5;
import static org.objectweb.asm.Opcodes.ICONST_M1;
import static org.objectweb.asm.Opcodes.IDIV;
import static org.objectweb.asm.Opcodes.IFEQ;
import static org.objectweb.asm.Opcodes.IFGE;
import static org.objectweb.asm.Opcodes.IFGT;
import static org.objectweb.asm.Opcodes.IFLE;
import static org.objectweb.asm.Opcodes.IFLT;
import static org.objectweb.asm.Opcodes.IFNE;
import static org.objectweb.asm.Opcodes.IFNONNULL;
import static org.objectweb.asm.Opcodes.IFNULL;
import static org.objectweb.asm.Opcodes.IF_ACMPEQ;
import static org.objectweb.asm.Opcodes.IF_ACMPNE;
import static org.objectweb.asm.Opcodes.IF_ICMPEQ;
import static org.objectweb.asm.Opcodes.IF_ICMPGE;
import static org.objectweb.asm.Opcodes.IF_ICMPGT;
import static org.objectweb.asm.Opcodes.IF_ICMPLE;
import static org.objectweb.asm.Opcodes.IF_ICMPLT;
import static org.objectweb.asm.Opcodes.IF_ICMPNE;
import static org.objectweb.asm.Opcodes.IINC;
import static org.objectweb.asm.Opcodes.ILOAD;
import static org.objectweb.asm.Opcodes.IMUL;
import static org.objectweb.asm.Opcodes.INEG;
import static org.objectweb.asm.Opcodes.INSTANCEOF;
import static org.objectweb.asm.Opcodes.INVOKEDYNAMIC;
import static org.objectweb.asm.Opcodes.INVOKEINTERFACE;
import static org.objectweb.asm.Opcodes.INVOKESPECIAL;
import static org.objectweb.asm.Opcodes.INVOKESTATIC;
import static org.objectweb.asm.Opcodes.INVOKEVIRTUAL;
import static org.objectweb.asm.Opcodes.IOR;
import static org.objectweb.asm.Opcodes.IREM;
import static org.objectweb.asm.Opcodes.IRETURN;
import static org.objectweb.asm.Opcodes.ISHL;
import static org.objectweb.asm.Opcodes.ISHR;
import static org.objectweb.asm.Opcodes.ISTORE;
import static org.objectweb.asm.Opcodes.ISUB;
import static org.objectweb.asm.Opcodes.IUSHR;
import static org.objectweb.asm.Opcodes.IXOR;
import static org.objectweb.asm.Opcodes.JSR;
import static org.objectweb.asm.Opcodes.L2D;
import static org.objectweb.asm.Opcodes.L2F;
import static org.objectweb.asm.Opcodes.L2I;
import static org.objectweb.asm.Opcodes.LADD;
import static org.objectweb.asm.Opcodes.LALOAD;
import static org.objectweb.asm.Opcodes.LAND;
import static org.objectweb.asm.Opcodes.LASTORE;
import static org.objectweb.asm.Opcodes.LCMP;
import static org.objectweb.asm.Opcodes.LCONST_0;
import static org.objectweb.asm.Opcodes.LCONST_1;
import static org.objectweb.asm.Opcodes.LDC;
import static org.objectweb.asm.Opcodes.LDIV;
import static org.objectweb.asm.Opcodes.LLOAD;
import static org.objectweb.asm.Opcodes.LMUL;
import static org.objectweb.asm.Opcodes.LNEG;
import static org.objectweb.asm.Opcodes.LOOKUPSWITCH;
import static org.objectweb.asm.Opcodes.LOR;
import static org.objectweb.asm.Opcodes.LREM;
import static org.objectweb.asm.Opcodes.LRETURN;
import static org.objectweb.asm.Opcodes.LSHL;
import static org.objectweb.asm.Opcodes.LSHR;
import static org.objectweb.asm.Opcodes.LSTORE;
import static org.objectweb.asm.Opcodes.LSUB;
import static org.objectweb.asm.Opcodes.LUSHR;
import static org.objectweb.asm.Opcodes.LXOR;
import static org.objectweb.asm.Opcodes.MONITORENTER;
import static org.objectweb.asm.Opcodes.MONITOREXIT;
import static org.objectweb.asm.Opcodes.MULTIANEWARRAY;
import static org.objectweb.asm.Opcodes.NEW;
import static org.objectweb.asm.Opcodes.NEWARRAY;
import static org.objectweb.asm.Opcodes.NOP;
import static org.objectweb.asm.Opcodes.POP;
import static org.objectweb.asm.Opcodes.POP2;
import static org.objectweb.asm.Opcodes.PUTFIELD;
import static org.objectweb.asm.Opcodes.PUTSTATIC;
import static org.objectweb.asm.Opcodes.RET;
import static org.objectweb.asm.Opcodes.RETURN;
import static org.objectweb.asm.Opcodes.SALOAD;
import static org.objectweb.asm.Opcodes.SASTORE;
import static org.objectweb.asm.Opcodes.SIPUSH;
import static org.objectweb.asm.Opcodes.SWAP;
import static org.objectweb.asm.Opcodes.TABLESWITCH;
import static org.objectweb.asm.tree.AbstractInsnNode.FIELD_INSN;
import static org.objectweb.asm.tree.AbstractInsnNode.FRAME;
import static org.objectweb.asm.tree.AbstractInsnNode.IINC_INSN;
import static org.objectweb.asm.tree.AbstractInsnNode.INSN;
import static org.objectweb.asm.tree.AbstractInsnNode.INT_INSN;
import static org.objectweb.asm.tree.AbstractInsnNode.INVOKE_DYNAMIC_INSN;
import static org.objectweb.asm.tree.AbstractInsnNode.JUMP_INSN;
import static org.objectweb.asm.tree.AbstractInsnNode.LABEL;
import static org.objectweb.asm.tree.AbstractInsnNode.LDC_INSN;
import static org.objectweb.asm.tree.AbstractInsnNode.LOOKUPSWITCH_INSN;
import static org.objectweb.asm.tree.AbstractInsnNode.METHOD_INSN;
import static org.objectweb.asm.tree.AbstractInsnNode.MULTIANEWARRAY_INSN;
import static org.objectweb.asm.tree.AbstractInsnNode.TABLESWITCH_INSN;
import static org.objectweb.asm.tree.AbstractInsnNode.TYPE_INSN;
import static org.objectweb.asm.tree.AbstractInsnNode.VAR_INSN;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.IincInsnNode;
import org.objectweb.asm.tree.InsnNode;
import org.objectweb.asm.tree.IntInsnNode;
import org.objectweb.asm.tree.JumpInsnNode;
import org.objectweb.asm.tree.LdcInsnNode;
import org.objectweb.asm.tree.LineNumberNode;
import org.objectweb.asm.tree.MultiANewArrayInsnNode;
import org.objectweb.asm.tree.VarInsnNode;
public class ASMReader {
public static Map<String, Integer> opCodes = new HashMap<String, Integer>();
public static byte[] TYPE;
static {
opCodes.put("NOP", NOP);
opCodes.put("ACONST_NULL", ACONST_NULL);
opCodes.put("ICONST_M1", ICONST_M1);
opCodes.put("ICONST_0", ICONST_0);
opCodes.put("ICONST_1", ICONST_1);
opCodes.put("ICONST_2", ICONST_2);
opCodes.put("ICONST_3", ICONST_3);
opCodes.put("ICONST_4", ICONST_4);
opCodes.put("ICONST_5", ICONST_5);
opCodes.put("LCONST_0", LCONST_0);
opCodes.put("LCONST_1", LCONST_1);
opCodes.put("FCONST_0", FCONST_0);
opCodes.put("FCONST_1", FCONST_1);
opCodes.put("FCONST_2", FCONST_2);
opCodes.put("DCONST_0", DCONST_0);
opCodes.put("DCONST_1", DCONST_1);
opCodes.put("BIPUSH", BIPUSH);
opCodes.put("SIPUSH", SIPUSH);
opCodes.put("LDC", LDC);
opCodes.put("ILOAD", ILOAD);
opCodes.put("LLOAD", LLOAD);
opCodes.put("FLOAD", FLOAD);
opCodes.put("DLOAD", DLOAD);
opCodes.put("ALOAD", ALOAD);
opCodes.put("IALOAD", IALOAD);
opCodes.put("LALOAD", LALOAD);
opCodes.put("FALOAD", FALOAD);
opCodes.put("DALOAD", DALOAD);
opCodes.put("AALOAD", AALOAD);
opCodes.put("BALOAD", BALOAD);
opCodes.put("CALOAD", CALOAD);
opCodes.put("SALOAD", SALOAD);
opCodes.put("ISTORE", ISTORE);
opCodes.put("LSTORE", LSTORE);
opCodes.put("FSTORE", FSTORE);
opCodes.put("DSTORE", DSTORE);
opCodes.put("ASTORE", ASTORE);
opCodes.put("IASTORE", IASTORE);
opCodes.put("LASTORE", LASTORE);
opCodes.put("FASTORE", FASTORE);
opCodes.put("DASTORE", DASTORE);
opCodes.put("AASTORE", AASTORE);
opCodes.put("BASTORE", BASTORE);
opCodes.put("CASTORE", CASTORE);
opCodes.put("SASTORE", SASTORE);
opCodes.put("POP", POP);
opCodes.put("POP2", POP2);
opCodes.put("DUP", DUP);
opCodes.put("DUP_X1", DUP_X1);
opCodes.put("DUP_X2", DUP_X2);
opCodes.put("DUP2", DUP2);
opCodes.put("DUP2_X1", DUP2_X1);
opCodes.put("DUP2_X2", DUP2_X2);
opCodes.put("SWAP", SWAP);
opCodes.put("IADD", IADD);
opCodes.put("LADD", LADD);
opCodes.put("FADD", FADD);
opCodes.put("DADD", DADD);
opCodes.put("ISUB", ISUB);
opCodes.put("LSUB", LSUB);
opCodes.put("FSUB", FSUB);
opCodes.put("DSUB", DSUB);
opCodes.put("IMUL", IMUL);
opCodes.put("LMUL", LMUL);
opCodes.put("FMUL", FMUL);
opCodes.put("DMUL", DMUL);
opCodes.put("IDIV", IDIV);
opCodes.put("LDIV", LDIV);
opCodes.put("FDIV", FDIV);
opCodes.put("DDIV", DDIV);
opCodes.put("IREM", IREM);
opCodes.put("LREM", LREM);
opCodes.put("FREM", FREM);
opCodes.put("DREM", DREM);
opCodes.put("INEG", INEG);
opCodes.put("LNEG", LNEG);
opCodes.put("FNEG", FNEG);
opCodes.put("DNEG", DNEG);
opCodes.put("ISHL", ISHL);
opCodes.put("LSHL", LSHL);
opCodes.put("ISHR", ISHR);
opCodes.put("LSHR", LSHR);
opCodes.put("IUSHR", IUSHR);
opCodes.put("LUSHR", LUSHR);
opCodes.put("IAND", IAND);
opCodes.put("LAND", LAND);
opCodes.put("IOR", IOR);
opCodes.put("LOR", LOR);
opCodes.put("IXOR", IXOR);
opCodes.put("LXOR", LXOR);
opCodes.put("IINC", IINC);
opCodes.put("I2L", I2L);
opCodes.put("I2F", I2F);
opCodes.put("I2D", I2D);
opCodes.put("L2I", L2I);
opCodes.put("L2F", L2F);
opCodes.put("L2D", L2D);
opCodes.put("F2I", F2I);
opCodes.put("F2L", F2L);
opCodes.put("F2D", F2D);
opCodes.put("D2I", D2I);
opCodes.put("D2L", D2L);
opCodes.put("D2F", D2F);
opCodes.put("I2B", I2B);
opCodes.put("I2C", I2C);
opCodes.put("I2S", I2S);
opCodes.put("LCMP", LCMP);
opCodes.put("FCMPL", FCMPL);
opCodes.put("FCMPG", FCMPG);
opCodes.put("DCMPL", DCMPL);
opCodes.put("DCMPG", DCMPG);
opCodes.put("IFEQ", IFEQ);
opCodes.put("IFNE", IFNE);
opCodes.put("IFLT", IFLT);
opCodes.put("IFGE", IFGE);
opCodes.put("IFGT", IFGT);
opCodes.put("IFLE", IFLE);
opCodes.put("IF_ICMPEQ", IF_ICMPEQ);
opCodes.put("IF_ICMPNE", IF_ICMPNE);
opCodes.put("IF_ICMPLT", IF_ICMPLT);
opCodes.put("IF_ICMPGE", IF_ICMPGE);
opCodes.put("IF_ICMPGT", IF_ICMPGT);
opCodes.put("IF_ICMPLE", IF_ICMPLE);
opCodes.put("IF_ACMPEQ", IF_ACMPEQ);
opCodes.put("IF_ACMPNE", IF_ACMPNE);
opCodes.put("GOTO", GOTO);
opCodes.put("JSR", JSR);
opCodes.put("RET", RET);
opCodes.put("TABLESWITCH", TABLESWITCH);
opCodes.put("LOOKUPSWITCH", LOOKUPSWITCH);
opCodes.put("IRETURN", IRETURN);
opCodes.put("LRETURN", LRETURN);
opCodes.put("FRETURN", FRETURN);
opCodes.put("DRETURN", DRETURN);
opCodes.put("ARETURN", ARETURN);
opCodes.put("RETURN", RETURN);
opCodes.put("GETSTATIC", GETSTATIC);
opCodes.put("PUTSTATIC", PUTSTATIC);
opCodes.put("GETFIELD", GETFIELD);
opCodes.put("PUTFIELD", PUTFIELD);
opCodes.put("INVOKEVIRTUAL", INVOKEVIRTUAL);
opCodes.put("INVOKESPECIAL", INVOKESPECIAL);
opCodes.put("INVOKESTATIC", INVOKESTATIC);
opCodes.put("INVOKEINTERFACE", INVOKEINTERFACE);
opCodes.put("INVOKEDYNAMIC", INVOKEDYNAMIC);
opCodes.put("NEW", NEW);
opCodes.put("NEWARRAY", NEWARRAY);
opCodes.put("ANEWARRAY", ANEWARRAY);
opCodes.put("ARRAYLENGTH", ARRAYLENGTH);
opCodes.put("ATHROW", ATHROW);
opCodes.put("CHECKCAST", CHECKCAST);
opCodes.put("INSTANCEOF", INSTANCEOF);
opCodes.put("MONITORENTER", MONITORENTER);
opCodes.put("MONITOREXIT", MONITOREXIT);
opCodes.put("MULTIANEWARRAY", MULTIANEWARRAY);
opCodes.put("IFNULL", IFNULL);
opCodes.put("IFNONNULL", IFNONNULL);
// derived from classWriter, mapped to AbstractInsnNode
TYPE = new byte[200];
String s = "AAAAAAAAAAAAAAAABBJ__CCCCC____________________AAAAAAAACC"
+ "CCC____________________AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ "AAAAAAAAAAAAAAAAAKAAAAAAAAAAAAAAAAAAAAHHHHHHHHHHHHHHHHCLMAA"
+ "AAAAEEEEFFFFGDBDAADDAA_NHH";
for (int i = 0; i < s.length(); i++) TYPE[i] = (byte) (s.charAt(i) - 'A');
}
public static Map<String, ASMBlock> loadResource(String res) {
return loadResource(ASMHelper.class.getResourceAsStream(res), res);
}
public static Map<String, ASMBlock> loadResource(InputStream in, String res) {
HashMap<String, ASMBlock> blocks = new HashMap<String, ASMBlock>();
String current = "unnamed";
ASMBlock block = new ASMBlock();
try {
BufferedReader r = new BufferedReader(new InputStreamReader(in));
String line;
while ((line = r.readLine()) != null) {
{
int hpos = line.indexOf('#');
if (hpos >= 0) line = line.substring(0, hpos);
}
line = line.trim();
if (line.length() == 0) continue;
if (line.startsWith("list ")) {
if (block.list.size() > 0) blocks.put(current, block);
current = line.substring(5);
block = new ASMBlock();
continue;
}
try {
AbstractInsnNode insn = null;
String[] split = line.replace(" : ", ":").split(" ");
Integer i_opcode = opCodes.get(split[0]);
if (i_opcode == null) {
if (split[0].equals("LINENUMBER"))
insn = new LineNumberNode(Integer.parseInt(split[1]), block.getOrAdd(split[2]));
else if (split[0].startsWith("L")) insn = block.getOrAdd(split[0]);
else throw new Exception("Unknown opcode " + split[0]);
} else {
int opcode = i_opcode;
switch (TYPE[opcode]) {
case INSN:
insn = new InsnNode(opcode);
break;
case INT_INSN:
insn = new IntInsnNode(opcode, Integer.parseInt(split[1]));
break;
case VAR_INSN:
insn = new VarInsnNode(opcode, Integer.parseInt(split[1]));
break;
case TYPE_INSN:
insn = new ObfMapping(split[1]).toClassloading().toInsn(opcode);
break;
case FIELD_INSN:
case METHOD_INSN:
StringBuilder sb = new StringBuilder();
for (int i = 1; i < split.length; i++) sb.append(split[i]);
insn = ObfMapping.fromDesc(sb.toString()).toClassloading().toInsn(opcode);
break;
case INVOKE_DYNAMIC_INSN:
throw new Exception("Found INVOKEDYNAMIC while reading");
case JUMP_INSN:
insn = new JumpInsnNode(opcode, block.getOrAdd(split[1]));
break;
case LDC_INSN:
String cst = split[1];
if (cst.equals("*")) insn = new LdcInsnNode(null);
else if (cst.endsWith("\"")) insn = new LdcInsnNode(cst.substring(1, cst.length() - 1));
else if (cst.endsWith("L"))
insn = new LdcInsnNode(Long.valueOf(cst.substring(0, cst.length() - 1)));
else if (cst.endsWith("F"))
insn = new LdcInsnNode(Float.valueOf(cst.substring(0, cst.length() - 1)));
else if (cst.endsWith("D"))
insn = new LdcInsnNode(Double.valueOf(cst.substring(0, cst.length() - 1)));
else if (cst.contains(".")) insn = new LdcInsnNode(Double.valueOf(cst));
else insn = new LdcInsnNode(Integer.valueOf(cst));
break;
case IINC_INSN:
insn = new IincInsnNode(opcode, Integer.parseInt(split[1]));
break;
case LABEL:
throw new Exception("Use L# for labels");
case TABLESWITCH_INSN:
case LOOKUPSWITCH_INSN:
throw new Exception("I don't know how to deal with this insn type");
case MULTIANEWARRAY_INSN:
insn = new MultiANewArrayInsnNode(split[1], Integer.parseInt(split[2]));
break;
case FRAME:
throw new Exception("Use ClassWriter.COMPUTE_FRAMES");
}
}
if (insn != null) block.list.add(insn);
} catch (Exception e) {
System.err.println("Error while reading ASM Block " + current + " from " + res + ", line: " + line);
e.printStackTrace();
}
}
r.close();
if (block.list.size() > 0) blocks.put(current, block);
} catch (IOException e) {
throw new RuntimeException("Failed to read ASM resource: " + res, e);
}
return blocks;
}
}
@@ -0,0 +1,29 @@
package codechicken.lib.asm;
import org.objectweb.asm.ClassWriter;
public class CC_ClassWriter extends ClassWriter {
private final boolean runtime;
public CC_ClassWriter(int flags) {
this(flags, false);
}
public CC_ClassWriter(int flags, boolean runtime) {
super(flags);
this.runtime = runtime;
}
@Override
protected String getCommonSuperClass(String type1, String type2) {
String c = type1.replace('/', '.');
String d = type2.replace('/', '.');
if (ClassHeirachyManager.classExtends(d, c)) return type1;
if (ClassHeirachyManager.classExtends(c, d)) return type2;
do {
c = ClassHeirachyManager.getSuperClass(c, runtime);
} while (!ClassHeirachyManager.classExtends(d, c));
return c.replace('.', '/');
}
}
@@ -0,0 +1,109 @@
package codechicken.lib.asm;
/***
* This Class is derived from the ASM ClassReader
* <p>
* ASM: a very small and fast Java bytecode manipulation framework Copyright (c) 2000-2011 INRIA, France Telecom All
* rights reserved.
* <p>
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or other materials provided with the
* distribution. 3. Neither the name of the copyright holders nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior written permission.
* <p>
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import java.nio.charset.StandardCharsets;
import org.objectweb.asm.Opcodes;
/**
* Using this class to search for a (single) String reference is > 40 times faster than parsing a class with a
* ClassReader + ClassNode while using way less RAM
*/
public class ClassConstantPoolParser {
private static final int UTF8 = 1;
private static final int INT = 3;
private static final int FLOAT = 4;
private static final int LONG = 5;
private static final int DOUBLE = 6;
private static final int FIELD = 9;
private static final int METH = 10;
private static final int IMETH = 11;
private static final int NAME_TYPE = 12;
private static final int HANDLE = 15;
private static final int INDY = 18;
private final byte[][] BYTES_TO_SEARCH;
public ClassConstantPoolParser(String... strings) {
BYTES_TO_SEARCH = new byte[strings.length][];
for (int i = 0; i < BYTES_TO_SEARCH.length; i++) {
BYTES_TO_SEARCH[i] = strings[i].getBytes(StandardCharsets.UTF_8);
}
}
/**
* Returns true if the constant pool of the class represented by this byte array contains one of the Strings we are
* looking for
*/
public boolean find(byte[] basicClass) {
if (basicClass == null || basicClass.length == 0) {
return false;
}
// checks the class version
if (readShort(6, basicClass) > Opcodes.V1_8) {
return false;
}
// parses the constant pool
int n = readUnsignedShort(8, basicClass);
int index = 10;
for (int i = 1; i < n; ++i) {
int size;
switch (basicClass[index]) {
case FIELD, METH, IMETH, INT, FLOAT, NAME_TYPE, INDY -> size = 5;
case LONG, DOUBLE -> {
size = 9;
++i;
}
case UTF8 -> {
final int strLen = readUnsignedShort(index + 1, basicClass);
size = 3 + strLen;
label: for (byte[] bytes : BYTES_TO_SEARCH) {
if (strLen == bytes.length) {
for (int j = index + 3; j < index + 3 + strLen; j++) {
if (basicClass[j] != bytes[j - (index + 3)]) {
continue label;
}
}
return true;
}
}
}
case HANDLE -> size = 4;
default -> size = 3;
}
index += size;
}
return false;
}
private static short readShort(final int index, byte[] basicClass) {
return (short) (((basicClass[index] & 0xFF) << 8) | (basicClass[index + 1] & 0xFF));
}
private static int readUnsignedShort(final int index, byte[] basicClass) {
return ((basicClass[index] & 0xFF) << 8) | (basicClass[index + 1] & 0xFF);
}
}
@@ -0,0 +1,154 @@
package codechicken.lib.asm;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import net.minecraft.launchwrapper.IClassTransformer;
import net.minecraft.launchwrapper.Launch;
import net.minecraft.launchwrapper.LaunchClassLoader;
import org.objectweb.asm.tree.ClassNode;
import cpw.mods.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper;
/**
* This is added as a class transformer if CodeChickenCore is installed. Adding it as a class transformer will speed
* evaluation up slightly by automatically caching superclasses when they are first loaded.
*/
public class ClassHeirachyManager implements IClassTransformer {
static {
ASMInit.init();
}
public static class SuperCache {
String superclass;
public HashSet<String> parents = new HashSet<String>();
private boolean flattened;
public void add(String parent) {
parents.add(parent);
}
public void flatten() {
if (flattened) return;
for (String s : new ArrayList<String>(parents)) {
SuperCache c = declareClass(s);
if (c != null) {
c.flatten();
parents.addAll(c.parents);
}
}
flattened = true;
}
}
public static HashMap<String, SuperCache> superclasses = new HashMap<String, SuperCache>();
private static LaunchClassLoader cl = Launch.classLoader;
public static String toKey(String name) {
if (ObfMapping.obfuscated)
name = FMLDeobfuscatingRemapper.INSTANCE.map(name.replace('.', '/')).replace('/', '.');
return name;
}
public static String unKey(String name) {
if (ObfMapping.obfuscated)
name = FMLDeobfuscatingRemapper.INSTANCE.unmap(name.replace('.', '/')).replace('/', '.');
return name;
}
/**
* @param name The class in question
* @param superclass The class being extended
* @return true if clazz extends, either directly or indirectly, superclass.
*/
public static boolean classExtends(String name, String superclass) {
name = toKey(name);
superclass = toKey(superclass);
if (name.equals(superclass)) return true;
SuperCache cache = declareClass(name);
if (cache == null) // just can't handle this
return false;
cache.flatten();
return cache.parents.contains(superclass);
}
private static SuperCache declareClass(String name) {
name = toKey(name);
SuperCache cache = superclasses.get(name);
if (cache != null) return cache;
try {
byte[] bytes = cl.getClassBytes(unKey(name));
if (bytes != null) cache = declareASM(bytes);
} catch (Exception e) {}
if (cache != null) return cache;
try {
cache = declareReflection(name);
} catch (ClassNotFoundException e) {}
return cache;
}
private static SuperCache declareReflection(String name) throws ClassNotFoundException {
Class<?> aclass = Class.forName(name);
SuperCache cache = getOrCreateCache(name);
if (aclass.isInterface()) cache.superclass = "java.lang.Object";
else if (name.equals("java.lang.Object")) return cache;
else cache.superclass = toKey(aclass.getSuperclass().getName());
cache.add(cache.superclass);
for (Class<?> iclass : aclass.getInterfaces()) cache.add(toKey(iclass.getName()));
return cache;
}
private static SuperCache declareASM(byte[] bytes) {
ClassNode node = ASMHelper.createClassNode(bytes);
String name = toKey(node.name);
SuperCache cache = getOrCreateCache(name);
cache.superclass = toKey(node.superName.replace('/', '.'));
cache.add(cache.superclass);
for (String iclass : node.interfaces) cache.add(toKey(iclass.replace('/', '.')));
return cache;
}
@Override
public byte[] transform(String name, String tname, byte[] bytes) {
if (bytes == null) return null;
if (!superclasses.containsKey(tname)) declareASM(bytes);
return bytes;
}
public static SuperCache getOrCreateCache(String name) {
SuperCache cache = superclasses.get(name);
if (cache == null) superclasses.put(name, cache = new SuperCache());
return cache;
}
public static String getSuperClass(String name, boolean runtime) {
name = toKey(name);
SuperCache cache = declareClass(name);
if (cache == null) return "java.lang.Object";
cache.flatten();
String s = cache.superclass;
if (!runtime) s = FMLDeobfuscatingRemapper.INSTANCE.unmap(s);
return s;
}
}
@@ -0,0 +1,36 @@
package codechicken.lib.asm;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.MethodNode;
public class ImportantInsnVisitor extends ClassVisitor {
public class ImportantInsnMethodVisitor extends MethodVisitor {
MethodVisitor delegate;
public ImportantInsnMethodVisitor(int access, String name, String desc, String signature, String[] exceptions) {
super(Opcodes.ASM4, new MethodNode(access, name, desc, signature, exceptions));
delegate = cv.visitMethod(access, name, desc, signature, exceptions);
}
@Override
public void visitEnd() {
super.visitEnd();
MethodNode mnode = (MethodNode) mv;
mnode.instructions = InsnComparator.getImportantList(mnode.instructions);
mnode.accept(delegate);
}
}
public ImportantInsnVisitor(ClassVisitor cv) {
super(Opcodes.ASM4, cv);
}
@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
return new ImportantInsnMethodVisitor(access, name, desc, signature, exceptions);
}
}
@@ -0,0 +1,210 @@
package codechicken.lib.asm;
import static org.objectweb.asm.tree.AbstractInsnNode.FIELD_INSN;
import static org.objectweb.asm.tree.AbstractInsnNode.FRAME;
import static org.objectweb.asm.tree.AbstractInsnNode.IINC_INSN;
import static org.objectweb.asm.tree.AbstractInsnNode.INT_INSN;
import static org.objectweb.asm.tree.AbstractInsnNode.JUMP_INSN;
import static org.objectweb.asm.tree.AbstractInsnNode.LABEL;
import static org.objectweb.asm.tree.AbstractInsnNode.LDC_INSN;
import static org.objectweb.asm.tree.AbstractInsnNode.LINE;
import static org.objectweb.asm.tree.AbstractInsnNode.LOOKUPSWITCH_INSN;
import static org.objectweb.asm.tree.AbstractInsnNode.METHOD_INSN;
import static org.objectweb.asm.tree.AbstractInsnNode.TABLESWITCH_INSN;
import static org.objectweb.asm.tree.AbstractInsnNode.TYPE_INSN;
import static org.objectweb.asm.tree.AbstractInsnNode.VAR_INSN;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.FieldInsnNode;
import org.objectweb.asm.tree.IincInsnNode;
import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.IntInsnNode;
import org.objectweb.asm.tree.JumpInsnNode;
import org.objectweb.asm.tree.LabelNode;
import org.objectweb.asm.tree.LdcInsnNode;
import org.objectweb.asm.tree.LookupSwitchInsnNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.TableSwitchInsnNode;
import org.objectweb.asm.tree.TypeInsnNode;
import org.objectweb.asm.tree.VarInsnNode;
import com.google.common.base.Function;
import com.google.common.collect.Maps;
public class InsnComparator {
public static boolean varInsnEqual(VarInsnNode insn1, VarInsnNode insn2) {
return insn1.var == -1 || insn2.var == -1 || insn1.var == insn2.var;
}
public static boolean methodInsnEqual(MethodInsnNode insn1, MethodInsnNode insn2) {
return insn1.owner.equals(insn2.owner) && insn1.name.equals(insn2.name) && insn1.desc.equals(insn2.desc);
}
public static boolean fieldInsnEqual(FieldInsnNode insn1, FieldInsnNode insn2) {
return insn1.owner.equals(insn2.owner) && insn1.name.equals(insn2.name) && insn1.desc.equals(insn2.desc);
}
public static boolean ldcInsnEqual(LdcInsnNode insn1, LdcInsnNode insn2) {
return insn1.cst == null || insn2.cst == null || insn1.cst.equals(insn2.cst);
}
public static boolean typeInsnEqual(TypeInsnNode insn1, TypeInsnNode insn2) {
return insn1.desc.equals("*") || insn2.desc.equals("*") || insn1.desc.equals(insn2.desc);
}
public static boolean iincInsnEqual(IincInsnNode node1, IincInsnNode node2) {
return node1.var == node2.var && node1.incr == node2.incr;
}
public static boolean intInsnEqual(IntInsnNode node1, IntInsnNode node2) {
return node1.operand == -1 || node2.operand == -1 || node1.operand == node2.operand;
}
public static boolean insnEqual(AbstractInsnNode node1, AbstractInsnNode node2) {
if (node1.getOpcode() != node2.getOpcode()) return false;
switch (node2.getType()) {
case VAR_INSN:
return varInsnEqual((VarInsnNode) node1, (VarInsnNode) node2);
case TYPE_INSN:
return typeInsnEqual((TypeInsnNode) node1, (TypeInsnNode) node2);
case FIELD_INSN:
return fieldInsnEqual((FieldInsnNode) node1, (FieldInsnNode) node2);
case METHOD_INSN:
return methodInsnEqual((MethodInsnNode) node1, (MethodInsnNode) node2);
case LDC_INSN:
return ldcInsnEqual((LdcInsnNode) node1, (LdcInsnNode) node2);
case IINC_INSN:
return iincInsnEqual((IincInsnNode) node1, (IincInsnNode) node2);
case INT_INSN:
return intInsnEqual((IntInsnNode) node1, (IntInsnNode) node2);
default:
return true;
}
}
public static boolean insnImportant(AbstractInsnNode insn, Set<LabelNode> controlFlowLabels) {
switch (insn.getType()) {
case LINE:
case FRAME:
return false;
case LABEL:
return controlFlowLabels.contains(insn);
default:
return true;
}
}
public static Set<LabelNode> getControlFlowLabels(InsnListSection list) {
return getControlFlowLabels(list.list);
}
public static Set<LabelNode> getControlFlowLabels(InsnList list) {
HashSet<LabelNode> controlFlowLabels = new HashSet<LabelNode>();
for (AbstractInsnNode insn = list.getFirst(); insn != null; insn = insn.getNext()) {
switch (insn.getType()) {
case JUMP_INSN:
JumpInsnNode jinsn = (JumpInsnNode) insn;
controlFlowLabels.add(jinsn.label);
break;
case TABLESWITCH_INSN:
TableSwitchInsnNode tsinsn = (TableSwitchInsnNode) insn;
controlFlowLabels.add(tsinsn.dflt);
for (LabelNode label : tsinsn.labels) controlFlowLabels.add(label);
break;
case LOOKUPSWITCH_INSN:
LookupSwitchInsnNode lsinsn = (LookupSwitchInsnNode) insn;
controlFlowLabels.add(lsinsn.dflt);
for (LabelNode label : lsinsn.labels) controlFlowLabels.add(label);
break;
}
}
return controlFlowLabels;
}
public static InsnList getImportantList(InsnList list) {
return getImportantList(new InsnListSection(list)).list;
}
public static InsnListSection getImportantList(InsnListSection list) {
if (list.size() == 0) return list;
Set<LabelNode> controlFlowLabels = getControlFlowLabels(list);
Map<LabelNode, LabelNode> labelMap = Maps.asMap(controlFlowLabels, new Function<LabelNode, LabelNode>() {
@Override
public LabelNode apply(LabelNode input) {
return input;
}
});
InsnListSection importantNodeList = new InsnListSection();
for (AbstractInsnNode insn : list)
if (insnImportant(insn, controlFlowLabels)) importantNodeList.add(insn.clone(labelMap));
return importantNodeList;
}
public static List<InsnListSection> find(InsnListSection haystack, InsnListSection needle) {
Set<LabelNode> controlFlowLabels = getControlFlowLabels(haystack);
LinkedList<InsnListSection> list = new LinkedList<InsnListSection>();
for (int start = 0; start <= haystack.size() - needle.size(); start++) {
InsnListSection section = matches(haystack.drop(start), needle, controlFlowLabels);
if (section != null) {
list.add(section);
start = section.end - 1;
}
}
return list;
}
public static List<InsnListSection> find(InsnList haystack, InsnListSection needle) {
return find(new InsnListSection(haystack), needle);
}
public static InsnListSection matches(InsnListSection haystack, InsnListSection needle,
Set<LabelNode> controlFlowLabels) {
int h = 0, n = 0;
for (; h < haystack.size() && n < needle.size(); h++) {
AbstractInsnNode insn = haystack.get(h);
if (!insnImportant(insn, controlFlowLabels)) continue;
if (!insnEqual(haystack.get(h), needle.get(n))) return null;
n++;
}
if (n != needle.size()) return null;
return haystack.take(h);
}
public static InsnListSection findOnce(InsnListSection haystack, InsnListSection needle) {
List<InsnListSection> list = find(haystack, needle);
if (list.size() != 1) throw new RuntimeException(
"Needle found " + list.size() + " times in Haystack:\n" + haystack + "\n\n" + needle);
return list.get(0);
}
public static InsnListSection findOnce(InsnList haystack, InsnListSection needle) {
return findOnce(new InsnListSection(haystack), needle);
}
public static List<InsnListSection> findN(InsnListSection haystack, InsnListSection needle) {
List<InsnListSection> list = find(haystack, needle);
if (list.isEmpty()) throw new RuntimeException("Needle not found in Haystack:\n" + haystack + "\n\n" + needle);
return list;
}
public static List<InsnListSection> findN(InsnList haystack, InsnListSection needle) {
return findN(new InsnListSection(haystack), needle);
}
}
@@ -0,0 +1,235 @@
package codechicken.lib.asm;
import static org.objectweb.asm.tree.AbstractInsnNode.FRAME;
import static org.objectweb.asm.tree.AbstractInsnNode.JUMP_INSN;
import static org.objectweb.asm.tree.AbstractInsnNode.LABEL;
import static org.objectweb.asm.tree.AbstractInsnNode.LOOKUPSWITCH_INSN;
import static org.objectweb.asm.tree.AbstractInsnNode.TABLESWITCH_INSN;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.FrameNode;
import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.JumpInsnNode;
import org.objectweb.asm.tree.LabelNode;
import org.objectweb.asm.tree.LookupSwitchInsnNode;
import org.objectweb.asm.tree.TableSwitchInsnNode;
import org.objectweb.asm.util.Textifier;
import org.objectweb.asm.util.TraceMethodVisitor;
/**
* A section of an InsnList, may become invalid if the insn list is modified
*/
public class InsnListSection implements Iterable<AbstractInsnNode> {
private class InsnListSectionIterator implements Iterator<AbstractInsnNode> {
int i = 0;
@Override
public boolean hasNext() {
return i < size();
}
@Override
public AbstractInsnNode next() {
return get(i++);
}
@Override
public void remove() {
InsnListSection.this.remove(--i);
}
}
public InsnList list;
public int start;
public int end;
public InsnListSection(InsnList list, int start, int end) {
this.list = list;
this.start = start;
this.end = end;
}
public InsnListSection(InsnList list, AbstractInsnNode first, AbstractInsnNode last) {
this(list, list.indexOf(first), list.indexOf(last) + 1);
}
public InsnListSection(InsnList list) {
this(list, 0, list.size());
}
public InsnListSection() {
this(new InsnList());
}
public void accept(MethodVisitor mv) {
for (AbstractInsnNode insn : this) insn.accept(mv);
}
public AbstractInsnNode getFirst() {
return size() == 0 ? null : list.get(start);
}
public AbstractInsnNode getLast() {
return size() == 0 ? null : list.get(end - 1);
}
public int size() {
return end - start;
}
public AbstractInsnNode get(int i) {
return list.get(start + i);
}
public void set(int i, AbstractInsnNode insn) {
list.set(get(i), insn);
}
public void remove(int i) {
list.remove(get(i));
end--;
}
public void replace(AbstractInsnNode location, AbstractInsnNode insn) {
list.set(location, insn);
}
public void add(AbstractInsnNode insn) {
list.add(insn);
end++;
}
public void insertBefore(InsnList insns) {
int s = insns.size();
if (this.list.size() == 0) list.insert(insns);
else list.insertBefore(list.get(start), insns);
start += s;
end += s;
}
public void insert(InsnList insns) {
if (end == 0) list.insert(insns);
else list.insert(list.get(end - 1), insns);
}
public void replace(InsnList insns) {
int s = insns.size();
remove();
insert(insns);
end = start + s;
}
public void remove() {
while (end != start) remove(0);
}
public void setLast(AbstractInsnNode last) {
end = list.indexOf(last) + 1;
}
public void setFirst(AbstractInsnNode first) {
start = list.indexOf(first);
}
public InsnListSection drop(int n) {
return slice(n, size());
}
public InsnListSection take(int n) {
return slice(0, n);
}
public InsnListSection slice(int start, int end) {
return new InsnListSection(list, this.start + start, this.start + end);
}
/**
* Removes leading and trailing labels and line number nodes that don't affect control flow
*
* @return this
*/
public InsnListSection trim(Set<LabelNode> controlFlowLabels) {
while (start < end && !InsnComparator.insnImportant(getFirst(), controlFlowLabels)) start++;
while (start < end && !InsnComparator.insnImportant(getLast(), controlFlowLabels)) end--;
return this;
}
public String toString() {
Textifier t = new Textifier();
accept(new TraceMethodVisitor(t));
StringWriter sw = new StringWriter();
t.print(new PrintWriter(sw));
return sw.toString();
}
public void println() {
System.out.println(toString());
}
public HashMap<LabelNode, LabelNode> identityLabelMap() {
HashMap<LabelNode, LabelNode> labelMap = new HashMap<LabelNode, LabelNode>();
for (AbstractInsnNode insn : this) switch (insn.getType()) {
case LABEL:
labelMap.put((LabelNode) insn, (LabelNode) insn);
break;
case JUMP_INSN:
labelMap.put(((JumpInsnNode) insn).label, ((JumpInsnNode) insn).label);
break;
case LOOKUPSWITCH_INSN:
LookupSwitchInsnNode linsn = (LookupSwitchInsnNode) insn;
labelMap.put(linsn.dflt, linsn.dflt);
for (LabelNode label : linsn.labels) labelMap.put(label, label);
break;
case TABLESWITCH_INSN:
TableSwitchInsnNode tinsn = (TableSwitchInsnNode) insn;
labelMap.put(tinsn.dflt, tinsn.dflt);
for (LabelNode label : tinsn.labels) labelMap.put(label, label);
break;
case FRAME:
FrameNode fnode = (FrameNode) insn;
if (fnode.local != null)
for (Object o : fnode.local) if (o instanceof LabelNode) labelMap.put((LabelNode) o, (LabelNode) o);
if (fnode.stack != null)
for (Object o : fnode.stack) if (o instanceof LabelNode) labelMap.put((LabelNode) o, (LabelNode) o);
break;
}
return labelMap;
}
public Map<LabelNode, LabelNode> cloneLabels() {
Map<LabelNode, LabelNode> labelMap = identityLabelMap();
for (Entry<LabelNode, LabelNode> entry : labelMap.entrySet()) entry.setValue(new LabelNode());
return labelMap;
}
public InsnListSection copy() {
return copy(cloneLabels());
}
public InsnListSection copy(Map<LabelNode, LabelNode> labelMap) {
InsnListSection copy = new InsnListSection();
for (AbstractInsnNode insn : this) copy.add(insn.clone(labelMap));
return copy;
}
@Override
public Iterator<AbstractInsnNode> iterator() {
return new InsnListSectionIterator();
}
}
@@ -0,0 +1,37 @@
package codechicken.lib.asm;
import java.util.Set;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.commons.LocalVariablesSorter;
public class LocalVariablesSorterVisitor extends ClassVisitor {
public Set<ObfMapping> methods;
public String owner;
public LocalVariablesSorterVisitor(Set<ObfMapping> methods, ClassVisitor cv) {
super(Opcodes.ASM4, cv);
this.methods = methods;
}
public LocalVariablesSorterVisitor(ClassVisitor cv) {
this(null, cv);
}
@Override
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
super.visit(version, access, name, signature, superName, interfaces);
owner = name;
}
@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
MethodVisitor mv = cv.visitMethod(access, name, desc, signature, exceptions);
return methods == null || methods.contains(new ObfMapping(owner, name, desc))
? new LocalVariablesSorter(access, desc, mv)
: mv;
}
}
@@ -0,0 +1,292 @@
package codechicken.lib.asm;
import static codechicken.lib.asm.ASMHelper.config;
import static codechicken.lib.asm.ASMHelper.createBytes;
import static codechicken.lib.asm.ASMHelper.dump;
import static codechicken.lib.asm.ASMHelper.findMethod;
import static codechicken.lib.asm.ASMHelper.logger;
import java.io.File;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.MethodNode;
public class ModularASMTransformer {
public static class ClassNodeTransformerList {
List<ClassNodeTransformer> transformers = new LinkedList<ClassNodeTransformer>();
HashSet<ObfMapping> methodsToSort = new HashSet<ObfMapping>();
public void add(ClassNodeTransformer t) {
transformers.add(t);
t.addMethodsToSort(methodsToSort);
}
public byte[] transform(byte[] bytes) {
ClassNode cnode = new ClassNode();
ClassReader reader = new ClassReader(bytes);
ClassVisitor cv = cnode;
if (!methodsToSort.isEmpty()) cv = new LocalVariablesSorterVisitor(methodsToSort, cv);
reader.accept(cv, ClassReader.EXPAND_FRAMES);
try {
int writeFlags = 0;
for (ClassNodeTransformer t : transformers) {
t.transform(cnode);
writeFlags |= t.writeFlags;
}
bytes = createBytes(cnode, writeFlags);
if (config.getTag("dump_asm").getBooleanValue(false))
dump(bytes, new File("asm/ccl_modular/" + cnode.name.replace('/', '#') + ".txt"), false, false);
return bytes;
} catch (RuntimeException e) {
dump(bytes, new File("asm/ccl_modular/" + cnode.name.replace('/', '#') + ".txt"), false, false);
throw e;
}
}
}
public abstract static class ClassNodeTransformer {
public int writeFlags;
public ClassNodeTransformer(int writeFlags) {
this.writeFlags = writeFlags;
}
public ClassNodeTransformer() {
this(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
}
public abstract String className();
public abstract void transform(ClassNode cnode);
public void addMethodsToSort(Set<ObfMapping> set) {}
}
public abstract static class MethodTransformer extends ClassNodeTransformer {
public final ObfMapping method;
public MethodTransformer(ObfMapping method) {
this.method = method.toClassloading();
}
@Override
public String className() {
return method.javaClass();
}
@Override
public void transform(ClassNode cnode) {
MethodNode mv = findMethod(method, cnode);
if (mv == null) throw new RuntimeException("Method not found: " + method);
try {
transform(mv);
} catch (Exception e) {
throw new RuntimeException("Error transforming method: " + method, e);
}
}
public abstract void transform(MethodNode mv);
}
public static class MethodWriter extends ClassNodeTransformer {
public final int access;
public final ObfMapping method;
public final String[] exceptions;
public InsnList list;
public MethodWriter(int access, ObfMapping method) {
this(access, method, null, (InsnList) null);
}
public MethodWriter(int access, ObfMapping method, InsnList list) {
this(access, method, null, list);
}
public MethodWriter(int access, ObfMapping method, ASMBlock block) {
this(access, method, null, block);
}
public MethodWriter(int access, ObfMapping method, String[] exceptions) {
this(access, method, exceptions, (InsnList) null);
}
public MethodWriter(int access, ObfMapping method, String[] exceptions, InsnList list) {
this.access = access;
this.method = method.toClassloading();
this.exceptions = exceptions;
this.list = list;
}
public MethodWriter(int access, ObfMapping method, String[] exceptions, ASMBlock block) {
this(access, method, exceptions, block.rawListCopy());
}
@Override
public String className() {
return method.javaClass();
}
@Override
public void transform(ClassNode cnode) {
MethodNode mv = findMethod(method, cnode);
if (mv == null) mv = (MethodNode) method.visitMethod(cnode, access, exceptions);
else {
mv.access = access;
mv.instructions.clear();
if (mv.localVariables != null) mv.localVariables.clear();
if (mv.tryCatchBlocks != null) mv.tryCatchBlocks.clear();
}
write(mv);
}
public void write(MethodNode mv) {
logger.debug("Writing method " + method);
list.accept(mv);
}
}
public static class MethodInjector extends MethodTransformer {
public ASMBlock needle;
public ASMBlock injection;
public boolean before;
public MethodInjector(ObfMapping method, ASMBlock needle, ASMBlock injection, boolean before) {
super(method);
this.needle = needle;
this.injection = injection;
this.before = before;
}
public MethodInjector(ObfMapping method, ASMBlock injection, boolean before) {
this(method, null, injection, before);
}
public MethodInjector(ObfMapping method, InsnList needle, InsnList injection, boolean before) {
this(method, new ASMBlock(needle), new ASMBlock(injection), before);
}
public MethodInjector(ObfMapping method, InsnList injection, boolean before) {
this(method, null, new ASMBlock(injection), before);
}
@Override
public void addMethodsToSort(Set<ObfMapping> set) {
set.add(method);
}
@Override
public void transform(MethodNode mv) {
if (needle == null) {
logger.debug("Injecting " + (before ? "before" : "after") + " method " + method);
if (before) mv.instructions.insert(injection.rawListCopy());
else mv.instructions.add(injection.rawListCopy());
} else {
for (InsnListSection key : InsnComparator.findN(mv.instructions, needle.list)) {
logger.debug(
"Injecting " + (before ? "before" : "after")
+ " method "
+ method
+ " @ "
+ key.start
+ " - "
+ key.end);
ASMBlock injectBlock = injection.copy().mergeLabels(needle.applyLabels(key));
if (before) key.insertBefore(injectBlock.list.list);
else key.insert(injectBlock.list.list);
}
}
}
}
public static class MethodReplacer extends MethodTransformer {
public ASMBlock needle;
public ASMBlock replacement;
public MethodReplacer(ObfMapping method, ASMBlock needle, ASMBlock replacement) {
super(method);
this.needle = needle;
this.replacement = replacement;
}
public MethodReplacer(ObfMapping method, InsnList needle, InsnList replacement) {
this(method, new ASMBlock(needle), new ASMBlock(replacement));
}
@Override
public void addMethodsToSort(Set<ObfMapping> set) {
set.add(method);
}
@Override
public void transform(MethodNode mv) {
for (InsnListSection key : InsnComparator.findN(mv.instructions, needle.list)) {
logger.debug("Replacing method " + method + " @ " + key.start + " - " + key.end);
ASMBlock replaceBlock = replacement.copy().pullLabels(needle.applyLabels(key));
key.insert(replaceBlock.list.list);
}
}
}
public static class FieldWriter extends ClassNodeTransformer {
public final ObfMapping field;
public final int access;
public final Object value;
public FieldWriter(int access, ObfMapping field, Object value) {
this.field = field.toClassloading();
this.access = access;
this.value = value;
}
public FieldWriter(int access, ObfMapping field) {
this(access, field, null);
}
@Override
public String className() {
return field.javaClass();
}
@Override
public void transform(ClassNode cnode) {
field.visitField(cnode, access, value);
}
}
public HashMap<String, ClassNodeTransformerList> transformers = new HashMap<String, ClassNodeTransformerList>();
public void add(ClassNodeTransformer t) {
ClassNodeTransformerList list = transformers.get(t.className());
if (list == null) transformers.put(t.className(), list = new ClassNodeTransformerList());
list.add(t);
}
public byte[] transform(String name, byte[] bytes) {
if (bytes == null) return null;
ClassNodeTransformerList list = transformers.get(name);
return list == null ? bytes : list.transform(bytes);
}
}
@@ -0,0 +1,401 @@
package codechicken.lib.asm;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import javax.swing.JFileChooser;
import net.minecraft.launchwrapper.Launch;
import net.minecraftforge.common.ForgeVersion;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.commons.Remapper;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.FieldInsnNode;
import org.objectweb.asm.tree.FieldNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.TypeInsnNode;
import com.google.common.base.Charsets;
import com.google.common.base.Objects;
import com.google.common.io.LineProcessor;
import com.google.common.io.Resources;
import codechicken.lib.config.ConfigTag;
import cpw.mods.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper;
import cpw.mods.fml.relauncher.FMLInjectionData;
public class ObfMapping {
public static class ObfRemapper extends Remapper {
private final HashMap<String, String> fields = new HashMap<>();
private final HashMap<String, String> funcs = new HashMap<>();
public ObfRemapper() {
try {
Field rawFieldMapsField = FMLDeobfuscatingRemapper.class.getDeclaredField("rawFieldMaps");
Field rawMethodMapsField = FMLDeobfuscatingRemapper.class.getDeclaredField("rawMethodMaps");
rawFieldMapsField.setAccessible(true);
rawMethodMapsField.setAccessible(true);
Map<String, Map<String, String>> rawFieldMaps = (Map<String, Map<String, String>>) rawFieldMapsField
.get(FMLDeobfuscatingRemapper.INSTANCE);
Map<String, Map<String, String>> rawMethodMaps = (Map<String, Map<String, String>>) rawMethodMapsField
.get(FMLDeobfuscatingRemapper.INSTANCE);
if (rawFieldMaps == null) throw new IllegalStateException(
"codechicken.lib.asm.ObfMapping loaded too early. Make sure all references are in or after the asm transformer load stage");
for (Map<String, String> map : rawFieldMaps.values())
for (Entry<String, String> entry : map.entrySet()) if (entry.getValue().startsWith("field"))
fields.put(entry.getValue(), entry.getKey().substring(0, entry.getKey().indexOf(':')));
for (Map<String, String> map : rawMethodMaps.values())
for (Entry<String, String> entry : map.entrySet()) if (entry.getValue().startsWith("func"))
funcs.put(entry.getValue(), entry.getKey().substring(0, entry.getKey().indexOf('(')));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
public String mapMethodName(String owner, String name, String desc) {
String s = funcs.get(name);
return s == null ? name : s;
}
@Override
public String mapFieldName(String owner, String name, String desc) {
String s = fields.get(name);
return s == null ? name : s;
}
@Override
public String map(String typeName) {
return FMLDeobfuscatingRemapper.INSTANCE.unmap(typeName);
}
public String unmap(String typeName) {
return FMLDeobfuscatingRemapper.INSTANCE.map(typeName);
}
public boolean isObf(String typeName) {
return !map(typeName).equals(typeName) || !unmap(typeName).equals(typeName);
}
}
public static class MCPRemapper extends Remapper implements LineProcessor<Void> {
public static File[] getConfFiles() {
ConfigTag tag = ASMHelper.config.getTag("mappingDir")
.setComment("Path to directory holding packaged.srg, fields.csv and methods.csv for mcp remapping");
for (int i = 0; i < DIR_GUESSES + DIR_ASKS; i++) {
File dir = confDirectoryGuess(i, tag);
if (dir == null || dir.isFile()) continue;
File[] mappings;
try {
mappings = parseConfDir(dir);
} catch (Exception e) {
if (i >= DIR_GUESSES) e.printStackTrace();
continue;
}
tag.setValue(dir.getPath());
return mappings;
}
throw new RuntimeException("Failed to select mappings directory, set it manually in the config");
}
private static final int DIR_GUESSES = 6;
private static final int DIR_ASKS = 3;
public static File confDirectoryGuess(int i, ConfigTag tag) {
File mcDir = (File) FMLInjectionData.data()[6];
switch (i) {
case 0:
return tag.value != null ? new File(tag.getValue()) : null;
case 1:
return new File(mcDir, "../conf");
case 2:
return new File(mcDir, "../build/unpacked/conf");
case 3:
return new File(
System.getProperty("user.home"),
".gradle/caches/minecraft/net/minecraftforge/forge/" + FMLInjectionData.data()[4]
+ "-"
+ ForgeVersion.getVersion()
+ "/unpacked/conf");
case 4:
return new File(
System.getProperty("user.home"),
".gradle/caches/minecraft/net/minecraftforge/forge/" + FMLInjectionData.data()[4]
+ "-"
+ ForgeVersion.getVersion()
+ "-"
+ FMLInjectionData.data()[4]
+ "/unpacked/conf");
case 5:
final String gradleCsvDir = System.getProperty("net.minecraftforge.gradle.GradleStart.csvDir");
return gradleCsvDir != null ? new File(gradleCsvDir) : null;
default:
JFileChooser fc = new JFileChooser(mcDir);
fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
fc.setDialogTitle("Select an mcp conf dir for the deobfuscator.");
int ret = fc.showDialog(null, "Select");
return ret == JFileChooser.APPROVE_OPTION ? fc.getSelectedFile() : null;
}
}
public static File[] parseConfDir(File confDir) {
File srgDir = new File(confDir, "conf");
if (!srgDir.exists()) srgDir = confDir;
File srgs = new File(srgDir, "packaged.srg");
if (!srgs.exists()) srgs = new File(srgDir, "joined.srg");
if (!srgs.exists()) throw new RuntimeException("Could not find packaged.srg or joined.srg");
File mapDir = new File(confDir, "mappings");
if (!mapDir.exists()) mapDir = confDir;
File methods = new File(mapDir, "methods.csv");
if (!methods.exists()) throw new RuntimeException("Could not find methods.csv");
File fields = new File(mapDir, "fields.csv");
if (!fields.exists()) throw new RuntimeException("Could not find fields.csv");
return new File[] { srgs, methods, fields };
}
private final HashMap<String, String> fields = new HashMap<>();
private final HashMap<String, String> funcs = new HashMap<>();
public MCPRemapper() {
File[] mappings = getConfFiles();
try {
Resources.readLines(mappings[1].toURI().toURL(), Charsets.UTF_8, this);
Resources.readLines(mappings[2].toURI().toURL(), Charsets.UTF_8, this);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public String mapMethodName(String owner, String name, String desc) {
String s = funcs.get(name);
return s == null ? name : s;
}
@Override
public String mapFieldName(String owner, String name, String desc) {
String s = fields.get(name);
return s == null ? name : s;
}
@Override
public boolean processLine(String line) throws IOException {
int i = line.indexOf(',');
String srg = line.substring(0, i);
int i2 = i + 1;
i = line.indexOf(',', i2);
String mcp = line.substring(i2, i);
(srg.startsWith("func") ? funcs : fields).put(srg, mcp);
return true;
}
@Override
public Void getResult() {
return null;
}
}
public static ObfRemapper obfMapper = new ObfRemapper();
public static Remapper mcpMapper = null;
public static void loadMCPRemapper() {
if (mcpMapper == null) mcpMapper = new MCPRemapper();
}
public static final boolean obfuscated;
static {
boolean obf = true;
try {
obf = Launch.classLoader.getClassBytes("net.minecraft.world.World") == null;
} catch (IOException ignored) {}
obfuscated = obf;
if (!obf) loadMCPRemapper();
}
public String s_owner;
public String s_name;
public String s_desc;
public ObfMapping(String owner) {
this(owner, "", "");
}
public ObfMapping(String owner, String name, String desc) {
this.s_owner = owner;
this.s_name = name;
this.s_desc = desc;
if (s_owner.contains(".")) throw new IllegalArgumentException(s_owner);
}
public ObfMapping(ObfMapping descmap, String subclass) {
this(subclass, descmap.s_name, descmap.s_desc);
}
public static ObfMapping fromDesc(String s) {
int lastDot = s.lastIndexOf('.');
if (lastDot < 0) return new ObfMapping(s, "", "");
int sep = s.indexOf('('); // methods
int sep_end = sep;
if (sep < 0) {
sep = s.indexOf(' '); // some stuffs
sep_end = sep + 1;
}
if (sep < 0) {
sep = s.indexOf(':'); // fields
sep_end = sep + 1;
}
if (sep < 0) return new ObfMapping(s.substring(0, lastDot), s.substring(lastDot + 1), "");
return new ObfMapping(s.substring(0, lastDot), s.substring(lastDot + 1, sep), s.substring(sep_end));
}
public ObfMapping subclass(String subclass) {
return new ObfMapping(this, subclass);
}
public boolean matches(MethodNode node) {
return s_name.equals(node.name) && s_desc.equals(node.desc);
}
public boolean matches(MethodInsnNode node) {
return s_owner.equals(node.owner) && s_name.equals(node.name) && s_desc.equals(node.desc);
}
public AbstractInsnNode toInsn(int opcode) {
if (isClass()) return new TypeInsnNode(opcode, s_owner);
else if (isMethod()) return new MethodInsnNode(opcode, s_owner, s_name, s_desc);
else return new FieldInsnNode(opcode, s_owner, s_name, s_desc);
}
public void visitTypeInsn(MethodVisitor mv, int opcode) {
mv.visitTypeInsn(opcode, s_owner);
}
public void visitMethodInsn(MethodVisitor mv, int opcode) {
mv.visitMethodInsn(opcode, s_owner, s_name, s_desc);
}
public void visitFieldInsn(MethodVisitor mv, int opcode) {
mv.visitFieldInsn(opcode, s_owner, s_name, s_desc);
}
public MethodVisitor visitMethod(ClassVisitor visitor, int access, String[] exceptions) {
return visitor.visitMethod(access, s_name, s_desc, null, exceptions);
}
public FieldVisitor visitField(ClassVisitor visitor, int access, Object value) {
return visitor.visitField(access, s_name, s_desc, null, value);
}
public boolean isClass(String name) {
return name.replace('.', '/').equals(s_owner);
}
public boolean matches(String name, String desc) {
return s_name.equals(name) && s_desc.equals(desc);
}
public boolean matches(FieldNode node) {
return s_name.equals(node.name) && s_desc.equals(node.desc);
}
public boolean matches(FieldInsnNode node) {
return s_owner.equals(node.owner) && s_name.equals(node.name) && s_desc.equals(node.desc);
}
public String javaClass() {
return s_owner.replace('/', '.');
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof ObfMapping)) return false;
ObfMapping desc = (ObfMapping) obj;
return s_owner.equals(desc.s_owner) && s_name.equals(desc.s_name) && s_desc.equals(desc.s_desc);
}
@Override
public int hashCode() {
return Objects.hashCode(s_desc, s_name, s_owner);
}
@Override
public String toString() {
if (s_name.length() == 0) return "[" + s_owner + "]";
if (s_desc.length() == 0) return "[" + s_owner + "." + s_name + "]";
return "[" + (isMethod() ? methodDesc() : fieldDesc()) + "]";
}
public String methodDesc() {
return s_owner + "." + s_name + s_desc;
}
public String fieldDesc() {
return s_owner + "." + s_name + ":" + s_desc;
}
public boolean isClass() {
return s_name.length() == 0;
}
public boolean isMethod() {
return s_desc.contains("(");
}
public boolean isField() {
return !isClass() && !isMethod();
}
public ObfMapping map(Remapper mapper) {
if (mapper == null) return this;
if (isMethod()) s_name = mapper.mapMethodName(s_owner, s_name, s_desc);
else if (isField()) s_name = mapper.mapFieldName(s_owner, s_name, s_desc);
s_owner = mapper.mapType(s_owner);
if (isMethod()) s_desc = mapper.mapMethodDesc(s_desc);
else if (s_desc.length() > 0) s_desc = mapper.mapDesc(s_desc);
return this;
}
public ObfMapping toRuntime() {
map(mcpMapper);
return this;
}
public ObfMapping toClassloading() {
if (!obfuscated) map(mcpMapper);
else if (obfMapper.isObf(s_owner)) map(obfMapper);
return this;
}
public ObfMapping copy() {
return new ObfMapping(s_owner, s_name, s_desc);
}
}
@@ -0,0 +1,205 @@
package codechicken.lib.asm;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.nio.file.Files;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import net.minecraft.launchwrapper.IClassTransformer;
import net.minecraft.launchwrapper.Launch;
import org.apache.commons.io.FileUtils;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.FieldInsnNode;
import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.InsnNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.util.Textifier;
import org.objectweb.asm.util.TraceClassVisitor;
import codechicken.core.launch.CodeChickenCorePlugin;
public class RedirectorTransformer implements IClassTransformer, Opcodes {
private static final boolean DUMP_CLASSES = Boolean.parseBoolean(System.getProperty("ccl.dumpClass", "false"));
private static final String RenderStateClass = "codechicken/lib/render/CCRenderState";
private static final Set<String> redirectedFields = new HashSet<>();
private static final Set<String> redirectedSimpleMethods = new HashSet<>();
private static final Set<String> redirectedMethods = new HashSet<>();
private static final ClassConstantPoolParser cstPoolParser;
static {
Collections.addAll(
redirectedFields,
"pipeline",
"model",
"firstVertexIndex",
"lastVertexIndex",
"vertexIndex",
"baseColour",
"alphaOverride",
"useNormals",
"computeLighting",
"useColour",
"lightMatrix",
"vert",
"hasNormal",
"normal",
"hasColour",
"colour",
"hasBrightness",
"brightness",
"side",
"lc",
"normalAttrib",
"colourAttrib",
"lightCoordAttrib",
"sideAttrib",
"lightingAttrib"
);
Collections.addAll(redirectedSimpleMethods, "reset", "pullLightmap", "pushLightmap", "setDynamic", "draw");
Collections.addAll(
redirectedMethods,
"setPipeline",
"bindModel",
"setModel",
"setVertexRange",
"render",
"runPipeline",
"writeVert",
"setNormal",
"setColour",
"setBrightness",
"startDrawing");
cstPoolParser = new ClassConstantPoolParser(RenderStateClass);
}
@Override
public byte[] transform(String name, String transformedName, byte[] basicClass) {
if (!cstPoolParser.find(basicClass)) {
return basicClass;
}
final ClassReader cr = new ClassReader(basicClass);
final ClassNode cn = new ClassNode();
cr.accept(cn, 0);
boolean changed = false;
// spotless:off
for (MethodNode mn : cn.methods) {
for (AbstractInsnNode node : mn.instructions.toArray()) {
if (node instanceof FieldInsnNode fNode) {
if (node.getOpcode() == GETSTATIC && RenderStateClass.equals(fNode.owner) && redirectedFields.contains(fNode.name)) {
mn.instructions.insertBefore(fNode,
new MethodInsnNode(
INVOKESTATIC,
fNode.owner,
"instance",
"()Lcodechicken/lib/render/CCRenderState;",
false));
fNode.setOpcode(GETFIELD);
changed = true;
} else if (node.getOpcode() == PUTSTATIC && RenderStateClass.equals(fNode.owner) && redirectedFields.contains(fNode.name)) {
InsnList list = new InsnList();
list.add(new MethodInsnNode(
INVOKESTATIC,
fNode.owner,
"instance",
"()Lcodechicken/lib/render/CCRenderState;",
false));
list.add(new InsnNode(SWAP));
mn.instructions.insertBefore(fNode, list);
fNode.setOpcode(PUTFIELD);
changed = true;
}
} else if (node instanceof MethodInsnNode mNode) {
if (node.getOpcode() == INVOKESTATIC && RenderStateClass.equals(mNode.owner) && redirectedSimpleMethods.contains(mNode.name)) {
mn.instructions.insertBefore(mNode,
new MethodInsnNode(
INVOKESTATIC,
mNode.owner,
"instance",
"()Lcodechicken/lib/render/CCRenderState;",
false));
mNode.setOpcode(INVOKEVIRTUAL);
mNode.name = mNode.name + "Instance";
changed = true;
} else if (node.getOpcode() == INVOKEVIRTUAL && RenderStateClass.equals(mNode.owner)
&& (redirectedSimpleMethods.contains(mNode.name) || redirectedMethods.contains(mNode.name))) {
// Handle mods that updated to previously new API
mNode.name = mNode.name + "Instance";
changed = true;
}
}
}
}
// spotless:on
if (changed) {
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
cn.accept(cw);
final byte[] bytes = cw.toByteArray();
if (DUMP_CLASSES) {
saveTransformedClass(basicClass, transformedName + "_PRE");
saveTransformedClass(bytes, transformedName + "_POST");
}
return bytes;
}
return basicClass;
}
private File outputDir = null;
private void saveTransformedClass(final byte[] data, final String classname) {
if (outputDir == null) {
outputDir = new File(Launch.minecraftHome, "ASM_CCL" + File.separatorChar + "REDIRECTOR");
try {
FileUtils.deleteDirectory(outputDir);
} catch (IOException ignored) {}
if (!outputDir.exists()) {
// noinspection ResultOfMethodCallIgnored
outputDir.mkdirs();
}
}
final String fileName = classname.replace('.', File.separatorChar);
final File classFile = new File(outputDir, fileName + ".class");
final File bytecodeFile = new File(outputDir, fileName + "_BYTE.txt");
final File outDir = classFile.getParentFile();
if (!outDir.exists()) {
// noinspection ResultOfMethodCallIgnored
outDir.mkdirs();
}
if (classFile.exists()) {
// noinspection ResultOfMethodCallIgnored
classFile.delete();
}
try (final OutputStream output = Files.newOutputStream(classFile.toPath())) {
output.write(data);
CodeChickenCorePlugin.logger.info("Saved class (byte[]) to " + classFile.toPath());
} catch (IOException e) {
CodeChickenCorePlugin.logger.error("Could not save class (byte[]) " + classname);
}
if (bytecodeFile.exists()) {
// noinspection ResultOfMethodCallIgnored
bytecodeFile.delete();
}
try (final OutputStream output = Files.newOutputStream(bytecodeFile.toPath())) {
final ClassReader classReader = new ClassReader(data);
classReader.accept(new TraceClassVisitor(null, new Textifier(), new PrintWriter(output)), 0);
CodeChickenCorePlugin.logger.info("Saved class (bytecode) to " + bytecodeFile.toPath());
} catch (IOException e) {
CodeChickenCorePlugin.logger.error("Could not save class (bytecode) " + classname);
}
}
}
@@ -0,0 +1,158 @@
package codechicken.lib.colour;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.lwjgl.opengl.GL11;
import codechicken.lib.config.ConfigTag.IConfigType;
import codechicken.lib.math.MathHelper;
import codechicken.lib.util.Copyable;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
public abstract class Colour implements Copyable<Colour> {
public static IConfigType<Colour> configRGB = new IConfigType<Colour>() {
@Override
public String configValue(Colour entry) {
String s = Long.toString(((long) entry.rgb()) << 32 >>> 32, 16);
while (s.length() < 6) s = "0" + s;
return "0x" + s.toUpperCase();
}
private final Pattern patternRGB = Pattern.compile("(\\d+),(\\d+),(\\d+)");
@Override
public Colour valueOf(String text) throws Exception {
Matcher matcherRGB = patternRGB.matcher(text.replaceAll("\\s", ""));
if (matcherRGB.matches()) return new ColourRGBA(
Integer.parseInt(matcherRGB.group(1)),
Integer.parseInt(matcherRGB.group(2)),
Integer.parseInt(matcherRGB.group(3)),
0xFF);
int hex = (int) Long.parseLong(text.replace("0x", ""), 16);
return new ColourRGBA(hex << 8 | 0xFF);
}
};
public byte r;
public byte g;
public byte b;
public byte a;
public Colour(int r, int g, int b, int a) {
this.r = (byte) r;
this.g = (byte) g;
this.b = (byte) b;
this.a = (byte) a;
}
public Colour(Colour colour) {
r = colour.r;
g = colour.g;
b = colour.b;
a = colour.a;
}
@SideOnly(Side.CLIENT)
public void glColour() {
GL11.glColor4ub(r, g, b, a);
}
@SideOnly(Side.CLIENT)
public void glColour(int a) {
GL11.glColor4ub(r, g, b, (byte) a);
}
public abstract int pack();
@Override
public String toString() {
return getClass().getSimpleName() + "[0x" + Integer.toHexString(pack()).toUpperCase() + "]";
}
public Colour add(Colour colour2) {
a += colour2.a;
r += colour2.r;
g += colour2.g;
b += colour2.b;
return this;
}
public Colour sub(Colour colour2) {
int ia = (a & 0xFF) - (colour2.a & 0xFF);
int ir = (r & 0xFF) - (colour2.r & 0xFF);
int ig = (g & 0xFF) - (colour2.g & 0xFF);
int ib = (b & 0xFF) - (colour2.b & 0xFF);
a = (byte) (ia < 0 ? 0 : ia);
r = (byte) (ir < 0 ? 0 : ir);
g = (byte) (ig < 0 ? 0 : ig);
b = (byte) (ib < 0 ? 0 : ib);
return this;
}
public Colour invert() {
a = (byte) (0xFF - (a & 0xFF));
r = (byte) (0xFF - (r & 0xFF));
g = (byte) (0xFF - (g & 0xFF));
b = (byte) (0xFF - (b & 0xFF));
return this;
}
public Colour multiply(Colour colour2) {
a = (byte) ((a & 0xFF) * ((colour2.a & 0xFF) / 255D));
r = (byte) ((r & 0xFF) * ((colour2.r & 0xFF) / 255D));
g = (byte) ((g & 0xFF) * ((colour2.g & 0xFF) / 255D));
b = (byte) ((b & 0xFF) * ((colour2.b & 0xFF) / 255D));
return this;
}
public Colour scale(double d) {
a = (byte) ((a & 0xFF) * d);
r = (byte) ((r & 0xFF) * d);
g = (byte) ((g & 0xFF) * d);
b = (byte) ((b & 0xFF) * d);
return this;
}
public Colour interpolate(Colour colour2, double d) {
return this.add(colour2.copy().sub(this).scale(d));
}
public Colour multiplyC(double d) {
r = (byte) MathHelper.clip((r & 0xFF) * d, 0, 255);
g = (byte) MathHelper.clip((g & 0xFF) * d, 0, 255);
b = (byte) MathHelper.clip((b & 0xFF) * d, 0, 255);
return this;
}
public abstract Colour copy();
public int rgb() {
return (r & 0xFF) << 16 | (g & 0xFF) << 8 | (b & 0xFF);
}
public int argb() {
return (a & 0xFF) << 24 | (r & 0xFF) << 16 | (g & 0xFF) << 8 | (b & 0xFF);
}
public int rgba() {
return (r & 0xFF) << 24 | (g & 0xFF) << 16 | (b & 0xFF) << 8 | (a & 0xFF);
}
public Colour set(Colour colour) {
r = colour.r;
g = colour.g;
b = colour.b;
a = colour.a;
return this;
}
public boolean equals(Colour colour) {
return colour != null && rgba() == colour.rgba();
}
}
@@ -0,0 +1,28 @@
package codechicken.lib.colour;
public class ColourARGB extends Colour {
public ColourARGB(int colour) {
super((colour >> 16) & 0xFF, (colour >> 8) & 0xFF, colour & 0xFF, (colour >> 24) & 0xFF);
}
public ColourARGB(int a, int r, int g, int b) {
super(r, g, b, a);
}
public ColourARGB(ColourARGB colour) {
super(colour);
}
public ColourARGB copy() {
return new ColourARGB(this);
}
public int pack() {
return pack(this);
}
public static int pack(Colour colour) {
return (colour.a & 0xFF) << 24 | (colour.r & 0xFF) << 16 | (colour.g & 0xFF) << 8 | (colour.b & 0xFF);
}
}
@@ -0,0 +1,50 @@
package codechicken.lib.colour;
public class ColourRGBA extends Colour {
public ColourRGBA(int colour) {
super((colour >> 24) & 0xFF, (colour >> 16) & 0xFF, (colour >> 8) & 0xFF, colour & 0xFF);
}
public ColourRGBA(double r, double g, double b, double a) {
super((int) (255 * r), (int) (255 * g), (int) (255 * b), (int) (255 * a));
}
public ColourRGBA(int r, int g, int b, int a) {
super(r, g, b, a);
}
public ColourRGBA(ColourRGBA colour) {
super(colour);
}
public int pack() {
return pack(this);
}
@Override
public Colour copy() {
return new ColourRGBA(this);
}
public static int pack(Colour colour) {
return (colour.r & 0xFF) << 24 | (colour.g & 0xFF) << 16 | (colour.b & 0xFF) << 8 | (colour.a & 0xFF);
}
public static int multiply(int c1, int c2) {
if (c1 == -1) return c2;
if (c2 == -1) return c1;
int r = (((c1 >>> 24) * (c2 >>> 24)) & 0xFF00) << 16;
int g = (((c1 >> 16 & 0xFF) * (c2 >> 16 & 0xFF)) & 0xFF00) << 8;
int b = ((c1 >> 8 & 0xFF) * (c2 >> 8 & 0xFF)) & 0xFF00;
int a = ((c1 & 0xFF) * (c2 & 0xFF)) >> 8;
return r | g | b | a;
}
public static int multiplyC(int c, float f) {
int r = (int) ((c >>> 24) * f);
int g = (int) ((c >> 16 & 0xFF) * f);
int b = (int) ((c >> 8 & 0xFF) * f);
return r << 24 | g << 16 | b << 8 | c & 0xFF;
}
}
@@ -0,0 +1,32 @@
package codechicken.lib.colour;
import java.awt.image.BufferedImage;
import net.minecraft.util.ResourceLocation;
import codechicken.lib.math.MathHelper;
import codechicken.lib.render.TextureUtils;
public class CustomGradient {
public int[] gradient;
public CustomGradient(ResourceLocation textureFile) {
BufferedImage img = TextureUtils.loadBufferedImage(textureFile);
if (img == null) throw new RuntimeException("File not found: " + textureFile.toString());
int[] data = new int[img.getWidth()];
img.getRGB(0, 0, img.getWidth(), 1, data, 0, img.getWidth());
gradient = new int[img.getWidth()];
for (int i = 0; i < data.length; i++) gradient[i] = (data[i] << 8) | (((data[i]) >> 24) & 0xFF);
}
public ColourRGBA getColour(double position) {
return new ColourRGBA(getColourI(position));
}
public int getColourI(double position) {
int off = (int) MathHelper.clip(gradient.length * position, 0, gradient.length - 1);
return gradient[off];
}
}
@@ -0,0 +1,110 @@
package codechicken.lib.config;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
public class ConfigFile extends ConfigTagParent {
public static final byte[] crlf = new byte[] { 0xD, 0xA };
public File file;
private boolean loading;
public ConfigFile(File file) {
newlinemode = 2;
load(file);
}
protected ConfigFile() {}
protected void load(File file) {
try {
if (!file.getParentFile().exists()) file.getParentFile().mkdirs();
if (!file.exists()) file.createNewFile();
} catch (IOException e) {
throw new RuntimeException(e);
}
this.file = file;
loadConfig();
}
protected void loadConfig() {
loading = true;
BufferedReader reader;
try {
reader = new BufferedReader(new FileReader(file));
while (true) {
reader.mark(2000);
String line = reader.readLine();
if (line != null && line.startsWith("#")) {
if (comment == null || comment.equals("")) comment = line.substring(1);
else comment = comment + "\n" + line.substring(1);
} else {
reader.reset();
break;
}
}
loadChildren(reader);
reader.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
loading = false;
}
@Override
public ConfigFile setComment(String header) {
super.setComment(header);
return this;
}
@Override
public ConfigFile setSortMode(int mode) {
super.setSortMode(mode);
return this;
}
@Override
public String getNameQualifier() {
return "";
}
public static String readLine(BufferedReader reader) throws IOException {
String line = reader.readLine();
return line == null ? null : line.replace("\t", "");
}
public static void writeLine(PrintWriter writer, String line, int tabs) {
for (int i = 0; i < tabs; i++) writer.print('\t');
writer.println(line);
}
public void saveConfig() {
if (loading) return;
PrintWriter writer;
try {
writer = new PrintWriter(file);
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
writeComment(writer, 0);
ConfigFile.writeLine(writer, "", 0);
saveTagTree(writer, 0, "");
writer.flush();
writer.close();
}
public boolean isLoading() {
return loading;
}
}
@@ -0,0 +1,225 @@
package codechicken.lib.config;
import java.io.PrintWriter;
public class ConfigTag extends ConfigTagParent {
public interface IConfigType<T> {
public String configValue(T entry);
public T valueOf(String text) throws Exception;
}
public ConfigTag(ConfigTagParent parent, String name) {
this.parent = parent;
this.name = name;
qualifiedname = parent.getNameQualifier() + name;
newline = parent.newlinemode == 2;
parent.addChild(this);
}
@Override
public String getNameQualifier() {
return qualifiedname + ".";
}
@Override
public void saveConfig() {
parent.saveConfig();
}
/**
* Called when the tag is loaded from a config file as opposed to constructed by a mod
*
* @return this
*/
public ConfigTag onLoaded() {
return this;
}
public void setValue(String value) {
this.value = value;
saveConfig();
}
public void setDefaultValue(String defaultValue) {
if (value == null) {
value = defaultValue;
saveConfig();
}
}
public void setIntValue(int i) {
setValue(Integer.toString(i));
}
public void setBooleanValue(boolean b) {
setValue(Boolean.toString(b));
}
public void setHexValue(int i) {
setValue("0x" + Long.toString(((long) i) << 32 >>> 32, 16));
}
public <T> void set(IConfigType<T> type, T entry) {
setValue(type.configValue(entry));
}
public String getValue() {
return value;
}
public String getValue(String defaultValue) {
setDefaultValue(defaultValue);
return value;
}
public int getIntValue() {
return Integer.parseInt(getValue());
}
public int getIntValue(int defaultValue) {
try {
if (value != null) return getIntValue();
} catch (NumberFormatException ignored) {}
setIntValue(defaultValue);
return defaultValue;
}
public boolean getBooleanValue() {
String value = getValue();
if (value != null && (value.equalsIgnoreCase("true") || value.equalsIgnoreCase("yes"))) return true;
else if (value != null && (value.equalsIgnoreCase("false") || value.equalsIgnoreCase("no"))) return false;
throw new NumberFormatException(qualifiedname + ".value=" + value);
}
public boolean getBooleanValue(boolean defaultValue) {
try {
if (value != null) return getBooleanValue();
} catch (NumberFormatException ignored) {}
setBooleanValue(defaultValue);
return defaultValue;
}
public int getHexValue() {
return (int) Long.parseLong(getValue().replace("0x", ""), 16);
}
public int getHexValue(int defaultValue) {
try {
if (value != null) return getHexValue();
} catch (NumberFormatException ignored) {}
setHexValue(defaultValue);
return defaultValue;
}
public <T> T get(IConfigType<T> type) {
try {
return type.valueOf(getValue());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public <T> T get(IConfigType<T> type, T defaultValue) {
try {
if (value != null) return get(type);
} catch (Exception ignored) {}
set(type, defaultValue);
return defaultValue;
}
public void save(PrintWriter writer, int tabs, String bracequalifier, boolean first) {
String vname;
if (qualifiedname.contains(".") && bracequalifier.length() > 0)
vname = qualifiedname.substring(bracequalifier.length() + 1);
else vname = qualifiedname;
if (newline && !first) ConfigFile.writeLine(writer, "", tabs);
writeComment(writer, tabs);
if (value != null) ConfigFile.writeLine(writer, vname + "=" + value, tabs);
if (!hasChildTags()) return;
if (brace) {
if (value == null) ConfigFile.writeLine(writer, vname, tabs);
ConfigFile.writeLine(writer, "{", tabs);
saveTagTree(writer, tabs + 1, qualifiedname);
ConfigFile.writeLine(writer, "}", tabs);
} else {
saveTagTree(writer, tabs, bracequalifier);
}
}
@Override
public ConfigTag setComment(String comment) {
super.setComment(comment);
return this;
}
@Override
public ConfigTag setSortMode(int mode) {
super.setSortMode(mode);
return this;
}
public ConfigTag setNewLine(boolean b) {
newline = b;
saveConfig();
return this;
}
public ConfigTag useBraces() {
brace = true;
if (parent.newlinemode == 1) newline = true;
saveConfig();
return this;
}
public ConfigTag setPosition(int pos) {
position = pos;
saveConfig();
return this;
}
public boolean containsTag(String tagname) {
return getTag(tagname, false) != null;
}
public int getId(String name, int defaultValue) {
return getTag(name).getIntValue(defaultValue);
}
public int getId(String name) {
int ret = getId(name, IDBase);
IDBase = ret + 1;
return ret;
}
public int getAcheivementId(String name, int defaultValue) {
return getTag(name).getIntValue(defaultValue);
}
public ConfigTag setBaseID(int i) {
IDBase = i;
return this;
}
public ConfigTagParent parent;
public String name;
public String qualifiedname;
public String value;
public boolean brace;
public boolean newline;
public int position = Integer.MAX_VALUE;
private int IDBase;
}
@@ -0,0 +1,220 @@
package codechicken.lib.config;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.TreeMap;
public abstract class ConfigTagParent {
public static class TagOrderComparator implements Comparator<ConfigTag> {
int sortMode;
public TagOrderComparator(int sortMode) {
this.sortMode = sortMode;
}
public int compare(ConfigTag o1, ConfigTag o2) {
if (o1.position != o2.position) return Integer.compare(o1.position, o2.position);
if (o1.brace != o2.brace) return o1.brace ? 1 : -1; // braced one goes after
if (sortMode == 1) {
if (Objects.equals(o1.value, o2.value)) return 0;
if (o1.value == null) return 1;
if (o2.value == null) return -1;
return o1.value.compareTo(o2.value);
} else {
return o1.name.compareTo(o2.name);
}
}
}
/**
* The immediate child tags of this tag
*/
private final TreeMap<String, ConfigTag> childtags = new TreeMap<>();
/**
* A map of all tags in the tree, meaning all tags in this tag and all tags in child tags (recursively). Allows for
* quick access to any tag in the tree, without the need to traverse the tree part by part.
*/
private final Map<String, ConfigTag> allTagsInTree = new HashMap<>();
public String comment;
/**
* 0 = name, 1 = value
*/
public int sortMode = 0;
/**
* The mode for determining when child tags should leave a blank line between them and the one above 0 = never, 1 =
* when braced, 2 = always
*/
public int newlinemode = 1;
public abstract void saveConfig();
public abstract String getNameQualifier();
public ConfigTagParent setComment(String comment) {
this.comment = comment;
saveConfig();
return this;
}
public ConfigTagParent setSortMode(int mode) {
sortMode = mode;
saveConfig();
return this;
}
public ConfigTagParent setNewLineMode(int mode) {
newlinemode = mode;
for (Entry<String, ConfigTag> entry : childtags.entrySet()) {
ConfigTag tag = entry.getValue();
if (newlinemode == 0) tag.newline = false;
else if (newlinemode == 1) tag.newline = tag.brace;
else if (newlinemode == 2) tag.newline = true;
}
saveConfig();
return this;
}
public Map<String, ConfigTag> childTagMap() {
return childtags;
}
public boolean hasChildTags() {
return !childtags.isEmpty();
}
public boolean containsTag(String tagname) {
return allTagsInTree.get(tagname) != null;
}
public ConfigTag getNewTag(String tagname) {
return new ConfigTag(this, tagname);
}
public ConfigTag getTag(String tagname, boolean create) {
ConfigTag tag = allTagsInTree.get(tagname);
if (tag == null && create) return getTagRecursive(tagname, create);
return tag;
}
public ConfigTag getTagRecursive(String tagname, boolean create) {
int dotpos = tagname.indexOf(".");
String basetagname = dotpos == -1 ? tagname : tagname.substring(0, dotpos);
ConfigTag basetag = childtags.get(basetagname);
if (basetag == null) {
if (!create) return null;
basetag = getNewTag(basetagname);
saveConfig();
}
if (dotpos == -1) return basetag;
return basetag.getTag(tagname.substring(dotpos + 1), create);
}
public ConfigTag getTag(String tagname) {
return getTag(tagname, true);
}
public boolean removeTag(String tagname) {
removeChildFromFlatMap(tagname);
ConfigTag tag = getTag(tagname, false);
if (tag == null) return false;
int dotpos = tagname.lastIndexOf(".");
String lastpart = dotpos == -1 ? tagname : tagname.substring(dotpos + 1, tagname.length());
if (tag.parent != null) {
boolean ret = tag.parent.childtags.remove(lastpart) != null;
if (ret) saveConfig();
return ret;
}
return false;
}
public void addChild(ConfigTag tag) {
childtags.put(tag.name, tag);
addChildToFlatMap(tag.name, tag);
}
private void addChildToFlatMap(String path, ConfigTag tag) {
allTagsInTree.put(path, tag);
// Stupid cast but these two garbage classes are interlinked anyway
if ((this instanceof ConfigTag t) && t.parent != null) t.parent.addChildToFlatMap(t.name + "." + path, tag);
}
private void removeChildFromFlatMap(String path) {
allTagsInTree.remove(path);
// Stupid cast but these two garbage classes are interlinked anyway
if ((this instanceof ConfigTag t) && t.parent != null) t.parent.removeChildFromFlatMap(t.name + "." + path);
}
public <T extends ConfigTag> ArrayList<T> getSortedTagList() {
ArrayList<T> taglist = new ArrayList<T>(childtags.size());
for (Entry<String, ConfigTag> tag : childtags.entrySet()) taglist.add((T) tag.getValue());
Collections.sort(taglist, new TagOrderComparator(sortMode));
return taglist;
}
public void loadChildren(BufferedReader reader) {
String comment = "";
String bracequalifier = "";
try {
while (true) {
String line = ConfigFile.readLine(reader);
if (line == null) break;
if (line.startsWith("#")) {
if (comment.equals("")) comment = line.substring(1);
else comment = comment + "\n" + line.substring(1);
} else if (line.contains("=")) {
String qualifiedname = line.substring(0, line.indexOf("="));
getTag(qualifiedname).onLoaded().setComment(comment)
.setValue(line.substring(line.indexOf("=") + 1));
comment = "";
bracequalifier = qualifiedname;
} else if (line.equals("{")) {
getTag(bracequalifier).setComment(comment).useBraces().loadChildren(reader);
comment = "";
bracequalifier = "";
} else if (line.equals("}")) {
break;
} else {
bracequalifier = line;
}
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public void saveTagTree(PrintWriter writer, int tabs, String bracequalifier) {
boolean first = true;
for (ConfigTag tag : getSortedTagList()) {
tag.save(writer, tabs, bracequalifier, first);
first = false;
}
}
public void writeComment(PrintWriter writer, int tabs) {
if (comment != null && !comment.equals("")) {
String[] comments = comment.split("\n");
for (int i = 0; i < comments.length; i++) ConfigFile.writeLine(writer, "#" + comments[i], tabs);
}
}
}
@@ -0,0 +1,16 @@
package codechicken.lib.config;
import java.io.File;
public class DefaultingConfigFile extends ConfigFile {
public DefaultingConfigFile(File file) {
super();
if (file.exists()) load(file);
}
@Override
public void saveConfig() {
if (file != null) super.saveConfig();
}
}
@@ -0,0 +1,125 @@
package codechicken.lib.config;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map.Entry;
public class SimpleProperties {
public HashMap<String, String> propertyMap = new HashMap<String, String>();
public File propertyFile;
public boolean saveOnChange = false;
public String encoding;
private boolean loading = false;
public SimpleProperties(File file, boolean saveOnChange, String encoding) {
propertyFile = file;
this.saveOnChange = saveOnChange;
this.encoding = encoding;
}
public SimpleProperties(File file, boolean saveOnChange) {
this(file, saveOnChange, Charset.defaultCharset().name());
}
public SimpleProperties(File file) {
this(file, true);
}
public void load() {
clear();
loading = true;
try {
BufferedReader reader = new BufferedReader(
new InputStreamReader(new FileInputStream(propertyFile), encoding));
while (true) {
String read = reader.readLine();
if (read == null) break;
int equalIndex = read.indexOf('=');
if (equalIndex == -1) continue;
setProperty(read.substring(0, equalIndex), read.substring(equalIndex + 1));
}
reader.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
loading = false;
}
public void save() {
try {
PrintStream writer = new PrintStream(propertyFile);
for (Entry<String, String> entry : propertyMap.entrySet()) {
writer.println(entry.getKey() + "=" + entry.getValue());
}
writer.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public void clear() {
propertyMap.clear();
}
public boolean hasProperty(String key) {
return propertyMap.containsKey(key);
}
public void removeProperty(String key) {
if (propertyMap.remove(key) != null && saveOnChange && !loading) save();
}
public void setProperty(String key, int value) {
setProperty(key, Integer.toString(value));
}
public void setProperty(String key, boolean value) {
setProperty(key, Boolean.toString(value));
}
public void setProperty(String key, String value) {
propertyMap.put(key, value);
if (saveOnChange && !loading) save();
}
public int getProperty(String property, int defaultvalue) {
try {
return Integer.parseInt(getProperty(property, Integer.toString(defaultvalue)));
} catch (NumberFormatException nfe) {
return defaultvalue;
}
}
public boolean getProperty(String property, boolean defaultvalue) {
try {
return Boolean.parseBoolean(getProperty(property, Boolean.toString(defaultvalue)));
} catch (NumberFormatException nfe) {
return defaultvalue;
}
}
public String getProperty(String property, String defaultvalue) {
String value = propertyMap.get(property);
if (value == null) {
setProperty(property, defaultvalue);
return defaultvalue;
}
return value;
}
public String getProperty(String property) {
return propertyMap.get(property);
}
}
@@ -0,0 +1,46 @@
package codechicken.lib.data;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraftforge.fluids.FluidStack;
import codechicken.lib.vec.BlockCoord;
public interface MCDataInput {
public long readLong();
public int readInt();
public short readShort();
public int readUShort();
public byte readByte();
public short readUByte();
public double readDouble();
public float readFloat();
public boolean readBoolean();
public char readChar();
public int readVarShort();
public int readVarInt();
public byte[] readByteArray(int length);
public String readString();
public BlockCoord readCoord();
public NBTTagCompound readNBTTagCompound();
public ItemStack readItemStack();
public FluidStack readFluidStack();
}
@@ -0,0 +1,17 @@
package codechicken.lib.data;
import java.io.InputStream;
public class MCDataInputStream extends InputStream {
private MCDataInput in;
public MCDataInputStream(MCDataInput in) {
this.in = in;
}
@Override
public int read() {
return in.readByte() & 0xFF;
}
}
@@ -0,0 +1,44 @@
package codechicken.lib.data;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraftforge.fluids.FluidStack;
import codechicken.lib.vec.BlockCoord;
public interface MCDataOutput {
public MCDataOutput writeLong(long l);
public MCDataOutput writeInt(int i);
public MCDataOutput writeShort(int s);
public MCDataOutput writeByte(int b);
public MCDataOutput writeDouble(double d);
public MCDataOutput writeFloat(float f);
public MCDataOutput writeBoolean(boolean b);
public MCDataOutput writeChar(char c);
public MCDataOutput writeVarInt(int i);
public MCDataOutput writeVarShort(int s);
public MCDataOutput writeByteArray(byte[] array);
public MCDataOutput writeString(String s);
public MCDataOutput writeCoord(int x, int y, int z);
public MCDataOutput writeCoord(BlockCoord coord);
public MCDataOutput writeNBTTagCompound(NBTTagCompound tag);
public MCDataOutput writeItemStack(ItemStack stack);
public MCDataOutput writeFluidStack(FluidStack liquid);
}
@@ -0,0 +1,17 @@
package codechicken.lib.data;
import java.io.OutputStream;
public class MCDataOutputStream extends OutputStream {
private MCDataOutput out;
public MCDataOutputStream(MCDataOutput out) {
this.out = out;
}
@Override
public void write(int b) {
out.writeByte(b);
}
}
@@ -0,0 +1,240 @@
package codechicken.lib.data;
import java.io.DataOutput;
import java.io.IOException;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompressedStreamTools;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraftforge.fluids.FluidStack;
import org.apache.commons.lang3.Validate;
import com.google.common.base.Charsets;
import codechicken.lib.vec.BlockCoord;
import cpw.mods.fml.common.network.ByteBufUtils;
public class MCDataOutputWrapper implements MCDataOutput {
/**
* Mimics ByteBufUtils Write an integer using variable length encoding.
*
* @param to The buffer to write to
* @param i The integer to write
*/
public static void writeVarInt(DataOutput to, int i) throws IOException {
while ((i & 0x80) != 0) {
to.writeByte(i & 0x7F | 0x80);
i >>>= 7;
}
to.writeByte(i);
}
/**
* Mimics ByteBufUtils Write an extended short using a short and a byte if necessary
*
* @param to The buffer to write to
* @param s The short to write, less than 0x7FFFFF
*/
public static void writeVarShort(DataOutput to, int s) throws IOException {
int low = s & 0x7FFF;
int high = (s & 0x7F8000) >> 15;
if (high != 0) low |= 0x8000;
to.writeShort(low);
if (high != 0) to.writeByte(high);
}
/**
* Mimics ByteBufUtils Write a String with UTF8 byte encoding to the buffer. It is encoded as <varint length>[<UTF8
* char bytes>]
*
* @param to the data output to write to
* @param string The string to write
*/
public static void writeUTF8String(DataOutput to, String string) throws IOException {
byte[] utf8Bytes = string.getBytes(Charsets.UTF_8);
Validate.isTrue(
ByteBufUtils.varIntByteCount(utf8Bytes.length) < 3,
"The string is too long for this encoding.");
writeVarInt(to, utf8Bytes.length);
to.write(utf8Bytes);
}
public DataOutput dataout;
public MCDataOutputWrapper(DataOutput out) {
dataout = out;
}
public MCDataOutputWrapper writeBoolean(boolean b) {
try {
dataout.writeBoolean(b);
} catch (IOException e) {
throw new RuntimeException(e);
}
return this;
}
public MCDataOutputWrapper writeByte(int b) {
try {
dataout.writeByte(b);
} catch (IOException e) {
throw new RuntimeException(e);
}
return this;
}
public MCDataOutputWrapper writeShort(int s) {
try {
dataout.writeShort(s);
} catch (IOException e) {
throw new RuntimeException(e);
}
return this;
}
public MCDataOutputWrapper writeInt(int i) {
try {
dataout.writeInt(i);
} catch (IOException e) {
throw new RuntimeException(e);
}
return this;
}
public MCDataOutputWrapper writeFloat(float f) {
try {
dataout.writeFloat(f);
} catch (IOException e) {
throw new RuntimeException(e);
}
return this;
}
public MCDataOutputWrapper writeDouble(double d) {
try {
dataout.writeDouble(d);
} catch (IOException e) {
throw new RuntimeException(e);
}
return this;
}
public MCDataOutputWrapper writeLong(long l) {
try {
dataout.writeLong(l);
} catch (IOException e) {
throw new RuntimeException(e);
}
return this;
}
@Override
public MCDataOutputWrapper writeChar(char c) {
try {
dataout.writeChar(c);
} catch (IOException e) {
throw new RuntimeException(e);
}
return this;
}
@Override
public MCDataOutput writeVarInt(int i) {
try {
writeVarInt(dataout, i);
} catch (IOException e) {
throw new RuntimeException(e);
}
return this;
}
@Override
public MCDataOutput writeVarShort(int s) {
try {
writeVarShort(dataout, s);
} catch (IOException e) {
throw new RuntimeException(e);
}
return this;
}
public MCDataOutputWrapper writeByteArray(byte[] barray) {
try {
dataout.write(barray);
} catch (IOException e) {
throw new RuntimeException(e);
}
return this;
}
public MCDataOutputWrapper writeCoord(int x, int y, int z) {
writeInt(x);
writeInt(y);
writeInt(z);
return this;
}
public MCDataOutputWrapper writeCoord(BlockCoord coord) {
writeInt(coord.x);
writeInt(coord.y);
writeInt(coord.z);
return this;
}
public MCDataOutputWrapper writeString(String s) {
try {
writeUTF8String(dataout, s);
} catch (IOException e) {
throw new RuntimeException(e);
}
return this;
}
public MCDataOutputWrapper writeItemStack(ItemStack stack) {
writeItemStack(stack, false);
return this;
}
public MCDataOutputWrapper writeItemStack(ItemStack stack, boolean large) {
if (stack == null) {
writeInt(-1);
} else {
writeInt(Item.getIdFromItem(stack.getItem()));
if (large) writeInt(stack.stackSize);
else writeByte(stack.stackSize);
writeShort(stack.getItemDamage());
writeNBTTagCompound(stack.stackTagCompound);
}
return this;
}
public MCDataOutputWrapper writeNBTTagCompound(NBTTagCompound compound) {
try {
if (compound == null) {
writeShort(-1);
} else {
byte[] bytes = CompressedStreamTools.compress(compound);
writeShort((short) bytes.length);
writeByteArray(bytes);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
return this;
}
public MCDataOutputWrapper writeFluidStack(FluidStack fluid) {
if (fluid == null) {
writeShort(-1);
} else {
writeShort(fluid.getFluidID());
writeVarInt(fluid.amount);
writeNBTTagCompound(fluid.tag);
}
return this;
}
}
Loaded 100 of 199 files, more files were not shown because too many files have changed in this diff. Show more