Compare commits

..
496 Commits
Author SHA1 Message Date
LexManos 66e4ae5142 Migrate to Github Actions 2025-12-02 15:37:29 -08:00
Jonathing a5a5faa09f Fix Material#isFlammable not being accounted for in flammability (#10572) 2025-07-16 09:47:14 -07:00
Jonathing e0717f5765 1.19.2 RB 5
https://forums.minecraftforge.net/topic/154385-forge-435-minecraft-1192/
2025-03-04 16:55:07 -08:00
Jonathing b3703dac1d Add '#forge:chorus_additionally_grows_on' tag for similar mechanics to '#minecraft:azalea_grows_on' but for chorus (#10464) 2025-03-04 14:44:47 -08:00
JonathingandLexManos 11e74bf8d3 Speed up mod annotation scanning by ~30% (#10472)
Co-authored-by: LexManos <[email protected]>
2025-03-04 14:40:07 -08:00
Jonathing dc0da958e0 Fix continuing to use items after dropping or when a shield breaks (#10382)
Fixes MC-231097 and MC-168573
Cache this.useItem before running item break logic, Fixes #10344
2025-03-04 14:39:51 -08:00
Jonathing defeedd11d Add fast graphics render type to block model jsons (#10400)
Make modded leaves behave like vanilla leaves by default (Fixes #10389)
2025-02-18 14:29:30 -08:00
Jonathing 756731a61f Backport even more future ResourceLocation methods (#10430) 2025-02-18 14:16:44 -08:00
Jonathing fd1b206cf2 Ensure NetworkConstants is loaded before mod construction (#10448) 2025-02-18 14:16:07 -08:00
JonathingandPaint_Ninja dfe1f9240c Add clientSideOnly feature to mods.toml (#10085) (backport of #9804 to 1.20.1) (#10367)
Co-authored-by: Paint_Ninja <[email protected]>
2025-02-18 14:15:55 -08:00
Jonathing f2c46fc2c1 Fix incorrect method reference in TntBlock.explode() (#10333) 2025-01-27 20:32:43 -08:00
Jonathing 9cb47ed7b7 Fix issue with shields being disabled by an attacker (#10323) 2025-01-27 20:32:33 -08:00
Jonathing 1f321b8bd2 Fix issues in VillagerTrades.EmeraldsForVillagerTypeItem related to custom Villager Types (#10360)
Add VillagerType#registerBiomeType
Co-authored-by: Joseph T. McQuigg <[email protected]>
2025-01-27 20:31:51 -08:00
Jonathing b1c37c25b5 Fix non-passengers being tickable without checking canUpdate() (#10306) 2025-01-22 14:33:21 -08:00
Jonathing f1a52f7326 Bump CoreMods to 5.2.4 (#10269) 2024-12-23 22:02:24 -08:00
Jonathing 9e54667efa Allow mipmap lowering to be disabled (#10250) 2024-12-23 22:02:10 -08:00
Jonathing 8383a0ebac Add optional fix of use item duration, disabled by default (#10244) 2024-12-23 21:37:27 -08:00
JonathingandPaint_Ninja 43850be0f6 Backport some Vanilla 1.21 ResourceLocation methods (#10239)
Co-authored-by: Paint_Ninja <[email protected]>
2024-12-23 21:24:20 -08:00
JonathingandPaint_Ninja 729cc6ab55 Deprecate @ObjectHolder, add a couple of fast-paths (#10226)
Co-authored-by: Paint_Ninja <[email protected]>
2024-12-23 21:24:13 -08:00
Jonathing 92998b1c32 Disable clean on TeamCity (#10260) 2024-12-23 21:06:13 -08:00
Jonathing babb17f2ad Bump JNA to 5.12.1 (#10186) 2024-11-26 12:09:30 -08:00
Jonathing 85d0c98e6b Bump CoreMods to 5.2 (#10132)
Full Changelog: https://gist.github.com/Jonathing/c3ad28b2a048ac839a7baba5417ee870

The key features are:
- ES6 language support
- Thoroughly updated ASMAPI, with full documentation
- Bug fixes (some optional for backwards-compatibility)
- Partial internal code cleanup
- Request CoreMods to not apply fix for ASMAPI.findFirstInstructionBefore by default

Related dependency bumps:
- Updated ASM to 9.7.1
- Updated Nashorn to 15.4
- Updated Log4J to 2.19.0 (included with installer)
2024-11-10 13:24:52 -08:00
Paint_Ninja dfcdb4f010 Cleanup FML Bindings (backport of #10004 to 1.19.2) (#10105) 2024-09-12 14:12:03 +01:00
Paint_NinjaandRealMangoRage 85c3ffffd1 Optionally supply FMLJavaModLoadingContext as a param to mod constructors (backport of #10074 to 1.19.2) (#10106)
Co-authored-by: RealMangoRage <[email protected]>
2024-09-12 14:11:54 +01:00
JonathingandVen f090e53e55 Fixed falling block entities not rendering as moving blocks (#10006) (#10020)
Co-authored-by: Ven <[email protected]>
2024-07-02 12:42:53 -07:00
Jonathingandthedarkcolour c1e29d2dfc Choose default JarJar mod file type based on parent JAR (#10025)
Co-authored-by: thedarkcolour <[email protected]>
2024-07-02 12:05:00 -07:00
LexManos b2d42fa577 1.19.2 RB 4
https://forums.minecraftforge.net/topic/149548-forge-434-minecraft-1192/
2024-06-06 15:04:11 -07:00
LexManos 1b5c118ec2 Update Gradle to 8.8 2024-06-06 14:37:37 -07:00
Paint_NinjaandJ-RAP d399884186 Fix NPE when acceptableValues in defineInList() does not allow nulls, fixes #9300, backport of #9903 (#9909)
Co-authored-by: J-RAP <[email protected]>
2024-04-18 21:41:55 +01:00
Paint_Ninja 091cc791b6 Optimise capabilities a tad, backport of #9886 (#9918) 2024-04-18 21:18:36 +01:00
Paint_Ninja c921aeec50 Make common config screen registration tasks easier, backport of #9884 (#9914) 2024-04-18 21:18:16 +01:00
Paint_Ninja f4aea1d8df Bump ASM, fix userdev, fix crowdin (#9925) 2024-04-18 19:57:21 +01:00
J-RAP ad271df245 Bump some deps (#9878)
- CoreMods 5.0.1 -> 5.1.2
- ASM 9.5 -> 9.6
- Installer 2.1 -> 2.2
- Installer tools 1.3.0 -> 1.4.1
2024-03-10 21:25:19 +00:00
Jonathan Colmenares 39dc348f8b Fix TagsProvider not honoring replace attribute (#9865) 2024-02-10 16:02:14 -08:00
Paint_Ninja 75eedc04a1 Make common DisplayTest registration tasks easier (#9838)
Backport of #9822 to 1.19.2
2023-12-31 15:37:33 +00:00
Paint_Ninja 81f99b0116 Optimise ForgeConfigSpec and make Range public (#9827)
Backport of #9810 to 1.19.2
2023-12-30 21:16:43 +00:00
Paint_Ninja f0a7a457bb Update to FG6 and Gradle 8, backport 1.20 MDK (#9754) 2023-11-02 13:41:09 -07:00
Paint_NinjaandSu5eD cf454b7da8 Improve mod description formatting in mods screen (#9771)
Co-authored-by: Su5eD <[email protected]>
2023-11-02 13:40:46 -07:00
Paint_Ninja afcce7d4e7 Backport CrashReportAnalyser to 1.19.2 (#9758) 2023-11-02 13:40:30 -07:00
Paint_Ninjaandembeddedt d4a2fbffa3 Optimise path filter in mod loading (#9712)
Co-authored-by: embeddedt <[email protected]>
2023-09-28 16:40:49 -07:00
Paint_NinjaandJab125 4b61de2088 Improve mod loading error message for errors inside mod constructors (#9709)
Co-authored-by: Jab125 <[email protected]>
2023-09-28 16:40:36 -07:00
LexManos bc2d0d1b25 1.19.2 RB 3 2023-09-21 11:59:41 -07:00
Paint_Ninja e2c1da98be Fix Level leak in debug HUD (#9701) 2023-09-03 11:03:37 -07:00
Paint_Ninjaanddhyces 0f6d11b1ee Keep order of sources in PackRepository (#9704)
Co-authored-by: dhyces <[email protected]>
2023-09-02 16:21:33 -07:00
Jonathan Colmenares 340d332e19 Fix parameter names in IForgeDimensionSpecialEffects.adjustLightmapColors to better describe what they are. (#9658) 2023-07-17 09:45:45 -07:00
Jonathan Colmenares 56f19dd53d Re-add in-game mod menu (#9655) 2023-07-17 08:51:03 -07:00
brandon3055 1fe420e4ab Fixed FluidUtil#tryFillContainer returning invalid result when simulating (#9358) 2023-07-15 10:52:57 -07:00
bconlon 945209c283 AlterGroundEvent for modifying block placement performed by AlterGroundDecorator (#9635) 2023-07-13 17:32:31 -07:00
embeddedt 3e5c3cabd5 Bump ASM to 9.5 (#9516) 2023-07-11 09:26:12 -07:00
Paint_Ninja b0f5a13f52 Improve logging for server connections (#9623) 2023-07-11 09:25:56 -07:00
Paint_Ninja 15fe8441f0 Log a proper duplicate mod(s) error message (#9625) 2023-07-11 09:25:42 -07:00
Brennan Ward babef71616 Fix erroneous getLevel call when firing SpecialSpawn (#9520) 2023-06-07 13:22:00 +00:00
Brennan Ward 1dd18ca27c [1.19.2] Fix the rest of the spawn event calls (#9482) 2023-05-31 11:52:38 +00:00
TelepathicGrunt 65c7390874 Loosen access for BucketItem's canBlockContainFluid (#9429) 2023-05-29 19:16:05 +00:00
Brennan WardandBrennan Ward fe3ad3b8f2 Fix event result being ignored (#9484)
Co-authored-by: Brennan Ward <[email protected]>
2023-05-08 22:52:15 +01:00
Brennan WardandBrennan Ward d05e76f7c4 Fix incorrect SpecialSpawn fire location (#9480)
Co-authored-by: Brennan Ward <[email protected]>
2023-05-03 07:08:07 +01:00
SizableShrimp bfa97bf097 [1.19.2] Fix forge grindstone hooks allowing stacks of non-stackable items (#9466) 2023-05-01 18:39:56 -05:00
Dennis C 469e9a6c1a Fix JSON model root transforms (#9411) 2023-03-22 11:09:58 +01:00
ferriarnus 58456c85af Fix StemBlock not checking canSustainPlant for the correct block
It now checks for Melons/Pumpkins instead of the stem itself.
2023-03-15 11:50:31 -07:00
cech12 7fe5b02ef3 Fix of inconsistent vaporization in BucketItem & FluidType (#9340) 2023-02-24 13:18:43 -08:00
SizableShrimp 184392e02e Backport ClientChatReceivedEvent.System for 1.19.2. Fixes #9352 (#9355) 2023-02-24 10:47:07 -08:00
Jonathan Colmenares d25a5466db Fire TickEvent.LevelTickEvent on ClientLevel tick (#9302) 2023-01-25 13:41:46 -08:00
Dennis C b5073c10ef Disable guiLight3d for generated item models (#9231) 2022-12-30 17:59:43 +01:00
sciwhiz12 16bc7cf783 Fix config key used by resource cache (#9253)
This bring it in line with the config key defined in the spec and
default config file in ResourceManagerBootCacheConfigurationHandler.

Fixes #9252
2022-12-26 13:20:27 -08:00
sciwhiz12 2d714f034f [1.19.2] Fix compatibility checker task configuration (#9233)
* Fix compatibility checker task configuration

The setupCheckJarCompatibility task exists to configure the main
compatibility checker task, checkJarCompatibility, because certain
configuration steps for that task could not be done until after the
configuration phase of Gradle.

However, that setup task previously held all the configuration for the
main check task in its task action. This caused problems because the
main check task's inputs are linked to other tasks, and the previous
situation made it so its configuration (by the setup task) happened
_after_ Gradle built the task dependency model/tree.

This meant that certain tasks which the main check task depended on did
not run before that task, because Gradle was unaware of this inter-task
dependency until it was too late (when it was already executing tasks).

This fixes the issue by moving the bulk of the configuration for the
main check task from the action of the setup task to the main
buildscript, therefore allowing Gradle to know about those task
dependencies and factor them in to its process of determining what tasks
to run and in what order.

The remaining configuration step in the setup task for the main check
task is linked to the setup task, and does not affect the task's
dependencies (because it uses a configuration which it resolves
immediately), so it stays in the setup task.

* Force checker setup task to never be up-to-date

The setup task configures the main check task, so it should always run
before that task. However, because it has an input and output, the setup
task is affected by Gradle's incremental build feature, which leads to
the possibility that Gradle considers the setup task as up-to-date,
therefore not executing its action and causing errors with the main
check task down the line.
2022-12-17 18:50:26 +01:00
LexManos 617ecb7ad3 43.2 Recommended Build. 2022-12-07 23:20:28 -08:00
Su5eD dd8239c255 Allow discovering services from the mods folder that use java's modular definition. (#9143) 2022-11-30 14:50:30 -08:00
Brennan Ward bdddc8c5d4 Make Datapack Registries support ICondition(s) (#9113) 2022-11-30 14:45:00 -08:00
Marc Hermans c1c619a109 Enable additional build types to handle pull request validation. (#9159) 2022-11-30 14:08:05 -08:00
sciwhiz12 f7eea35cb9 Check source permission level before selector permission (#9147)
In some situations, such as execution of a function by an advancement as
part of its reward, a command source stack may have a backing source of
a ServerPlayer which may lack the entity selector permission and have an
explicit permission level that should allow the use of entity selectors,
through CommandSourceStack#withPermission.

We now check if the permission level of the command source stack is
sufficient for entity selectors _before_ checking if the source is a
player and if they have the requisite permission.

This means that an operator permission level of 2 will always override
the Forge entity selector permission.

Fixes #9137
2022-11-30 14:07:18 -08:00
J.T. McQuigg a2434e1607 Fix fires spreading too/igniting custom portal frames. (#9142) 2022-11-30 14:06:22 -08:00
Minecraftschurli b806ecd0ff Add supplier to FlowerBlock so it works with custom MobEffects (#9139) 2022-11-30 14:04:15 -08:00
KnightMiner 8358b800e9 Fix some logical bugs related to the Grindstone Event (#9089) 2022-11-30 14:00:59 -08:00
Néstor Amador b25a092cf1 Call baked model's getModelData before getRenderTypes (#9163) 2022-11-28 17:53:19 +01:00
Jonathan Coates d812fdd0a3 Make Util.memoize thread-safe (#9155) 2022-11-23 09:18:04 +01:00
Néstor Amador 2d3ee8a228 Rendering tweaks and fixes: Part 4 (#9065) 2022-11-23 09:17:43 +01:00
matyrobbrt 97a9ca65f1 Fix Transformation loading PoseStack (#9083) 2022-11-21 20:49:41 +01:00
Néstor Amador f043fbbc51 Add simple block appearance API (#9066) 2022-11-21 20:48:30 +01:00
SizableShrimp a19ab3a8d4 Fix invalidated modded packets when on LAN (#9157) 2022-11-20 18:34:21 -08:00
Dennis C bc0517a404 Improve extensibility of DetectorRailBlock and PoweredRailBlock (#9130) 2022-11-08 12:18:48 -08:00
Su5eD dc9c0d7e35 Fix launch handler minecraft classpath locator (#9120) 2022-11-08 12:17:48 -08:00
matyrobbrt 1a2207b3b2 Add HitResult to EntityTeleportEvent$EnderPearl (#9135) 2022-11-08 12:17:18 -08:00
sciwhiz12 84ab9764e3 Throw aggregate exception for erroneous registry event dispatch (#9111)
This means that exceptions occurring during the dispatch of the registry
events, such as those from the suppliers of RegistryObjects, properly
cause a crash rather than merely being logged and allowing the game to
reach the main menu.

Fixes #8720
2022-11-08 12:17:00 -08:00
Nexus-Dino bef68991f0 Add missing semi-colon near the Dist import statement in example mod. 2022-11-08 12:16:49 -08:00
Nexus-Dino 526c13d662 Fix ClientModEvents example not subscribing to client-sided events (#9097) 2022-10-21 13:22:57 -07:00
matyrobbrt 67ffb78c23 Use GitHub action to lock issues with the spam label (#9087) 2022-10-21 13:22:31 -07:00
sciwhiz12 8f407c3a22 Remove structures slave map to Feature registry (#9091) 2022-10-21 13:22:18 -07:00
Dennis C 8980252e16 Improve logging of missing or unsupported dependencies (#9104) 2022-10-21 13:21:49 -07:00
DBotThePony 3baee80485 [1.19.x] Fix ValueSpec caching the return value incorrectly (#9046) 2022-10-14 17:43:21 +01:00
eerussianguy ca9599bb4d [1.19.x] Add event for registering spawn placements, and modifying existing (#9024) 2022-10-14 17:39:14 +01:00
eerussianguy 051db7907a [1.19.x] Add event for items being stacked or swapped in a GUI. (#9050) 2022-10-14 17:30:12 +01:00
Magnus Jensen bdba5ef2d3 [1.19.x] Fix PlayerInteractEvent.EntityInteractSpecific not cancelling on a server (#9079) 2022-10-14 17:18:17 +01:00
DBotThePony 838b9c0eda Fix canceling phantom spawns preventing any further attempts that tick. (#9041) 2022-10-13 11:40:56 -07:00
Magnus Jensen be584c54aa Rename fluid type milk translation keys (#9077) 2022-10-12 12:54:34 -07:00
ChampionAsh5357 1b3640b42d Fix minecart speed with water (#9076) 2022-10-12 12:51:13 -07:00
Sara Freimer be5dab5801 Add a cancellable event that gets fired when a Totem of Undying is used (#9069) 2022-10-12 12:46:08 -07:00
Marc Hermans aae628cd18 Fix performance issue and logging when resource caching is enabled (#9029) 2022-10-12 12:00:25 -07:00
Magnus Jensen e7bd08649f Fix NPE when feeding wolves and cats (#9074) 2022-10-07 19:55:40 -07:00
Paint_Ninja e1017a4c7e Fix logically breaking change to ForgeConfigSpec.Builder#comment where modders could not add a empty line to the start of comments. (#9061) 2022-10-03 11:50:32 -07:00
SizableShrimp 6f8ba9d295 Fix ServiceLoader bug
Signed-off-by: SizableShrimp <[email protected]>
2022-09-29 22:11:12 -07:00
SizableShrimp ac94478ae7 Fix ClientChatReceivedEvent for system messages
Signed-off-by: SizableShrimp <[email protected]>
2022-09-29 22:11:12 -07:00
DBotThePony 515c6082e0 Make ForgeConfigSpec$Builder.comment able to be called multiple times for the same entry. (#9056) 2022-09-27 23:23:59 -07:00
ChampionAsh5357 a753598113 Fix control modifier for mac with KeyMappings using Alt instead of Super (#9057) 2022-09-27 11:15:11 -07:00
J.T. McQuigg bc6c4be4e4 Fix is_desert tag not being applied correctly. (#9051) 2022-09-26 11:08:24 -07:00
Andy Dingley 98823a8f07 Fix mob griefing event for SmallFireballs not using owner entity. (#9038) 2022-09-21 13:24:25 -07:00
David Dempsey ecd8f1e54d Fix minecarts on rails not properly slowing down in water (#9033) 2022-09-21 13:20:03 -07:00
LexManos b0caea8e20 Change codestyle for BookShelves tag. Closes #9027
Add IS_CAVE tag Closes #8885
Add IS_DESERT tag Closes #8979
Simplify Mangrove Swamp tags Closes #8980
2022-09-09 11:27:39 -07:00
nikita488 e0477f8776 Allow faces of an "elements" model to have disabled ambient occlusion (#9019) 2022-09-08 16:17:44 +01:00
bconlon 94e1e54b53 [1.19.x] Recipe ID-based grouping between modded and vanilla recipes. (#8876) 2022-09-08 16:13:07 +01:00
nitro_dynamite18 9ce72331b7 Update fence_gates/wooden (#8936) 2022-09-08 16:12:26 +01:00
Jais Djurhuus-Kempel 1c31f42dae [1.19.x] Added event for growing fungus (#8981) 2022-09-08 16:11:59 +01:00
agnor99 0978a94358 Added Bookshelves block tag (#8991) 2022-09-08 16:11:39 +01:00
GizmoTheMoonPig e956a9c9f3 Create a Forge EntityType Tag for Bosses (#9017) 2022-09-08 16:10:48 +01:00
Monica S 82026d11a4 Allow mods to specify shader import namespace (#9021) 2022-09-08 16:10:31 +01:00
ferriarnus 6d233ac75c Grindstone Events (#8934)
One to modify the output, and one to modify the input.
2022-09-08 15:55:43 +01:00
Reece Mackie 73c1934e7e Fix the serialized names of the enum (#9014) 2022-09-04 19:46:54 +01:00
Technici4n bf1194ec75 Fix tryEmptyContainerAndStow duping fluids with stackable containers (#9004) 2022-09-03 21:48:07 +01:00
Ted Senft 22d2740725 Add mod mismatch event (#8989) 2022-09-03 21:26:43 +01:00
Minecraftschurli 02f26dc7a1 [1.19.x] add methods with more context to tree growers (#8956) 2022-09-03 20:24:00 +01:00
28Pollux28 db14cbb0e0 [1.19.X] Adding more precise events for Advancements (#8360) 2022-09-03 20:17:16 +01:00
Luke BemishandLexManos a2b35cae92 Default IItemHandler capability for shulker box itemstacks (#8827)
Co-authored-by: LexManos <[email protected]>
2022-09-03 20:16:25 +01:00
Take Weiland aab0e4c82e [1.19] Add hook for items to remain in the hotbar when picking blocks/entities (#8872) 2022-09-03 20:12:13 +01:00
Reece Mackieandsciwhiz12 6609708d14 [1.19.x] Block Model Builder Root Transform Support (#8860)
Co-authored-by: sciwhiz12 <[email protected]>
2022-09-03 20:11:46 +01:00
Budschie ed198f062c [1.19.x] Make LivingSetAttackTargetEvent compatible with the Brain/Behavior system. (Port of PR #8918) (#8954) 2022-09-03 20:11:10 +01:00
thedarkcolour 4e2d656e9d [1.19.x] Add IForgeBlock#onTreeGrow to replace IForgeBlock#onPlantGrow from 1.16 (#8999) 2022-09-03 20:07:09 +01:00
bconlon 2a4230868f [1.19.x] Moved Player.resetAttackStrengthTicker() to the end of Player.attack() (#9000) 2022-09-03 20:06:35 +01:00
Sirttas cf778b1759 fix misplaced patch in sapling block (#9005) 2022-09-03 20:05:37 +01:00
Brennan Ward 1b6daddd40 Fix failed entity interactions consuming the click. (#9007) 2022-09-03 20:00:57 +01:00
sciwhiz12 d7b137d144 Fix entity selector permission check to check original source (#8995)
Permission checks should be against the command source and not the
target entity, as is done in vanilla.

Fixes #8994
2022-08-25 11:42:11 -07:00
한현빈 b5d5855559 Hotfix for 1.19.2 item animation bug (#8987)
* [HOT FIX]: Fixes #8985 by no-oping for vanilla models instead of throwing error

Signed-off-by: tmvkrpxl0 <[email protected]>
2022-08-20 11:38:24 +02:00
LexManos c0aa8dd808 Add ability to Auto register capabilities via annotation (#8972) 2022-08-17 15:06:35 -07:00
LexManos 4f2f5c02a0 1.19.2 RB 2022-08-17 14:58:14 -07:00
agnor99 7a6843fa4a Added ItemDecorator API (#8794) 2022-08-17 23:39:56 +02:00
한현빈 f0ecf16c6b [1.19.x] Custom usage animations for items (#8932) 2022-08-17 23:08:13 +02:00
Take Weiland 8998fa71b2 Allow registering custom ColorResolvers (#8880) 2022-08-17 22:51:05 +02:00
Dennis C 4e677a7558 [1.19] Allow custom outline rendering on EntityRenderers and BlockEntityRenderers (#8938) 2022-08-17 00:01:33 +02:00
sciwhiz12 07254b36d7 Redirect checks for entity selector use to a permission (#8947)
This allows greater flexibility for configuring servers with
operator-like permissions to user groups through the permissions API and
their permissions handler of choice without needing to grant the
vanilla operator permission to any player.

The new permission is "forge:use_entity_selectors", which is granted by
default to players with permission level 2 (GAMEMASTERS) and above.

The hook falls back to checking the permission level if the source of
the command is not a ServerPlayer, such as for command blocks and
functions.
2022-08-16 14:11:54 -07:00
Brennan Ward a51b8d256d Allow FakePlayer to report its position (#8963) 2022-08-16 14:09:09 -07:00
Sara Freimer 75fcd9448e Add alternate version of renderEntityInInventory to allow for directly specifying the angles (#8961) 2022-08-16 13:57:30 -07:00
eerussianguy 6b45999702 Add cancellable ToastAddEvent (#8952) 2022-08-16 13:48:55 -07:00
eerussianguy a4f52f4057 Modify ScreenEvent.RenderInventoryMobEffects to allow moving the effect stack left or right (#8951) 2022-08-16 13:47:57 -07:00
Brennan Ward b8b3201372 Fix Enchantment#doPostHurt and Enchantment#doPostAttack being called twice for players. Fixes MC-248272 (#8948) 2022-08-16 13:40:10 -07:00
LexManos 41deadc1e2 Remove reflective implementation of ICustomPacket. (#8973)
Make vanilla custom packets able to be sent multiple times. Closes #8969
2022-08-16 13:17:25 -07:00
LexManos 82e8d06e54 Filter name spaces to directories only. Closes #8413 2022-08-14 12:22:38 -07:00
Marc Hermans 51db5f2ff7 Fix a corner case where the UMLB can not extract a version from a library. (#8967) 2022-08-14 12:18:22 -07:00
Alex O'Neill 2ec9e515ff Fix worlds with removed dimension types unable to load. (#8959) Closes #8800 2022-08-14 12:17:22 -07:00
Alex O'Neill 0579572148 Fix issue where unknown chunk generators would cause DFU to fail. (#8957) 2022-08-10 23:13:44 -07:00
TheMuso 83f4e6353c Fix comments and documentation that were missed during the review of #8712 (#8945) 2022-08-09 12:49:00 -07:00
Luis 130953e519 Make AnvilUpdateEvent fire even if the second input is empty, which means it fires even if only changing the item name. (#8905) 2022-08-09 12:48:46 -07:00
Sirttas 7981093591 Fix LivingEntity#isBlocking to use ToolActions#SHIELD_BLOCK instead of UseAnim#BLOCK (#8933) 2022-08-09 12:27:26 -07:00
Joseph B 79112d6208 Add Custom HolderSet Types allowing for logical combining of sets. (#8928) 2022-08-09 12:25:12 -07:00
Sara Freimer a3eb6263f4 Add values to VersionSupportMatrix to support loading mods that restrict versions to 1.19.1 on 1.19.2 (#8946) 2022-08-09 12:15:58 -07:00
Redstone_Dubstep d91bc9c73d Fix certain particles not updating their bounding box when their position changes (#8925) 2022-08-08 15:09:13 +02:00
LexManos c807665ab9 Update EventBus to address concurrency issue in ModLauncher Factory. Closes #8924 2022-08-07 17:35:15 -07:00
LexManos 7b97c181b9 1.19.2 2022-08-05 16:35:02 -07:00
Brennan Ward c42b0847d2 Remove calls to getStepHeight in Player#maybeBackOffFromEdge (#8927) 2022-08-05 11:35:47 -07:00
Sirttas f182cb00c1 Add forge tags for tools and armors, these DO NOT replace ToolActions, and are designed just for Recipes. (#8914) 2022-08-05 11:32:53 -07:00
J.T. McQuigg 3181b5da23 Add Biomes.BEACH to Tags (#8892) 2022-08-05 11:31:32 -07:00
Mysticdrew 983c119477 Let NetworkInstance.isRemotePresent check minecraft:register for channel IDs. (#8921) 2022-08-05 11:31:11 -07:00
Sara Freimer 874ff1bba2 Add an event for when the chunk ticket level is updated (#8909) 2022-08-05 11:21:14 -07:00
TheMuso 06d9d89f98 Re-add PotentialSpawns event (#8712) 2022-08-05 09:29:02 -07:00
Dennis C c713bad8c3 Fix misplaced patch in ItemEntityRenderer breaking ItemEntityRenderer#shouldBob() (#8919) 2022-08-04 22:14:28 -07:00
Marc Hermans fe19491822 [1.19] [HotFix] Fix the dedicated server not having access to the JiJ filesystems. (#8931) 2022-08-03 22:32:32 +01:00
SizableShrimp c80e8a1aca Match Mojang's action bar fix for MC-72687 (#8917) 2022-07-29 01:09:33 -07:00
SizableShrimp 6845c094ab Forge 1.19.1
Load natives from classpath
Make command argument types a forge registry
Add `EntityMobGriefingEvent` to `Allay#wantsToPickUp`
Overhaul `ServerChatEvent` to use `ChatDecorator` system
Remove `ClientChatEvent#setMessage` for now
Gradle 7.5

Signed-off-by: SizableShrimp <[email protected]>
2022-07-28 00:20:31 -05:00
LexManos 3c1126a7b4 Mark 1.19 RB 2022-07-26 18:49:28 -07:00
Néstor Amador 326e0329b9 Allow faces of an "elements" model to be made emissive (#8890) 2022-07-26 15:01:29 -07:00
coehlrich f9d0daa91c Fix invalid channel names sent from the server causing the network thread to error. (#8902) 2022-07-26 14:55:05 -07:00
LexManos 094200e687 Fix PlayerEvent.BreakSpeed using magic block position to signify invalid position. Closes #8906 2022-07-25 16:20:44 -07:00
Marc Hermans bb4818630c Fix cases where URIs would not work properly with JarInJar (#8900) 2022-07-23 00:46:45 -07:00
Jonathan Colmenares 7af3155b39 Add new hook to allow modification of lightmap via Dimension special effects (#8863) 2022-07-22 12:22:23 -07:00
Marc Hermans d988b4a811 Fix Forge's packet handling on play messages. (#8875) 2022-07-22 12:08:29 -07:00
zml 18f5bdb7ca Add API for tab list header/footer (#8803) 2022-07-21 21:01:21 -07:00
TelepathicGrunt f41d493552 Allow modded blocks overriding canStickTo prevent sticking to vanilla blocks/other modded blocks (#8837) 2022-07-21 13:06:02 -07:00
Néstor Amador 8cd2c9c63f Multiple tweaks and fixes to the recent changes in the client refactor PR: Part 3 (#8864)
Fix weighted baked models not respecting children render types
Allow fluid container model to use base texture as particle
Fix inverted behavior in composite model building. Fixes #8871
2022-07-20 15:25:07 -07:00
matyrobbrt 427b335cac Fix crossbows not firing ArrowLooseEvent (#8887) 2022-07-20 14:35:37 -07:00
Emma, Cypress, Rose ⚘ 2049096c6f Add User-Agent header to requests made by the update checker (#8881)
Format: Java-http-client/<Java version> MinecraftForge/<ForgeVer> <ModId>/<ModVersion>
2022-07-20 10:57:57 -07:00
Marc Hermans 98d4fa6dc2 Output the full path in a crash report so it is easier to find the outer mod when a crash in Jar-In-Jar occurs. (#8856) 2022-07-20 10:56:38 -07:00
Take Weiland 5306471aec Clean up the pick item ("middle mouse click") patches (#8870) 2022-07-20 10:56:16 -07:00
Kai aa8818b049 [1.19.x] Hotfix for test mods while the refactor is ongoing 2022-07-17 14:49:56 +01:00
Caltinor 2d86f17363 add event to SugarCaneBlock (#8877) 2022-07-16 02:21:27 +01:00
Brennan Ward 3a36a01913 Fix Global Loot Modifiers not using Dispatch Codec (#8859) 2022-07-12 11:19:35 -07:00
Nicholas Smit 47d70a7f31 Allow block render types to be set in datagen (#8852) 2022-07-12 11:19:03 -07:00
Sara Freimer d5b5e6f4db Fix renderBreakingTexture not using the target's model data (#8849) 2022-07-12 17:04:29 +02:00
Néstor Amador e76d814439 Multiple tweaks and fixes to the recent changes in the client refactor PR: Part 2 (#8854)
* Add getter for the component names in an unbaked geometry
* Fix render type hint not being copied in BlockGeometryBakingContext
* Ensure BlockRenderDispatches's renderSingleBlock uses the correct buffer
2022-07-12 17:04:03 +02:00
SizableShrimp b8b40e1f54 [1.19.x] Apply general renames, A SRG is provided for modders. (#8840)
See https://gist.github.com/SizableShrimp/882a671ff74256d150776da08c89ef72
2022-07-11 18:27:48 -07:00
LexManos 5e8c786406 Fix mob block breaking AI not working correctly when chunk 0,0 is unloaded. Closes #8853 2022-07-11 12:41:06 -07:00
Néstor Amador 5b8224f839 Fix crash when breaking blocks with multipart models and remove caching. Closes #8850 2022-07-11 11:24:21 -07:00
Silver_David cd621eb081 Fixed CompositeModel.Baked.Builder.build() passing arguments in the wrong order (#8846) 2022-07-10 11:11:07 -04:00
Néstor Amador b1113f0363 Make cutout mipmaps explicitly opt-in for item/entity rendering (#8845)
* Make cutout mipmaps explicitly opt-in for item/entity rendering

* Default render type domain to "minecraft" in model datagens
2022-07-10 11:10:57 -04:00
Silver_David daf5933b79 Fixed multipart block models not using the new model driven render type system. (#8844) 2022-07-10 11:10:43 -04:00
Marc Hermans 47fd2e8604 Update to the latest JarJar to fix a collision issue where multiple jars could provide an exact match. (#8847) 2022-07-10 11:07:55 -04:00
covers1624 05297fd72f Add FML config to disable DFU optimizations client-side. (#8842)
* Add client-side command line argument to disable DFU optimizations.

* Switch to using FMLConfig value instead.
2022-07-09 20:01:40 -04:00
CreativeMD f20cf19f94 [1.19] Fixed broken BufferBuilder.putBulkData(ByteBuffer) added by Forge (#8819)
* Fixes BufferBuilder.putBulkData(ByteBuffer)

* use nextElementByte

* Fixed merge conflict
2022-07-09 19:55:16 -04:00
Robert Kämpf 061cd3da53 [1.19.x] Fix shulker boxes allowing input of items, that return false for Item#canFitInsideContainerItems, through hoppers. (#8823)
* Make ShulkerBoxBlockEntity#canPlaceItemThroughFace delegate to Item#canFitInsideContainerItems.

* Switch to using Or and add comment.

* Switch Or to And.
2022-07-09 12:44:33 -04:00
Silver_David 03202a8ab4 [1.19.x] Added RenderLevelStageEvent to replace RenderLevelLastEvent (#8820)
* Ported RenderLevelStageEvent from 1.18.2

* Updated to fix merge conflicts
2022-07-09 12:36:47 -04:00
Nicholas Smit 8a67be4afd [1.19.x] Fix door datagenerator (#8821)
* Fix door datagenerator

Fix datagenerator for door blocks. Successor to #8687, addresses comments made there about statement complexity.

* Fix extra space around parameter

Fix extra space before comma around a parameter.
2022-07-09 12:21:06 -04:00
Drullkus 4c1ab67f33 Create PieceBeardifierModifier to re-enable piecewise beardifier definitions (#8798) 2022-07-09 12:12:55 -04:00
Dennis C 7e06a2105f Allow blocks to provide a dynamic MaterialColor for display on maps (#8812) 2022-07-09 12:10:02 -04:00
Flemmli97andFlemmli97 4a0c8be742 [1.19.x] BiomeTags Fixes/Improvements (#8711)
* dimension specific tag fix

* remove forge:is_beach cause vanilla has it already

* remove forge tags for new 1.19 vanilla tags (savanna, beach, overworld, end)

Co-authored-by: Flemmli97 <[email protected]>
2022-07-09 11:59:27 -04:00
Cyborgmas 0c030ee5e1 1.19 - Remove GlobalLootModifierSerializer and move to Codecs (#8721)
* convert GLM serializer class to codec

* cleanup

* GLM list needs to be sorted

* datagen

* simplify serialization

* fix test mods (oops)

* properly use suppliers for codec as they are registry obj
2022-07-09 11:51:41 -04:00
Random832 1134fac54c Implement item hooks for potions and enchantments (#8718)
* Implement item hooks for potions and enchantments

* code style fixes
2022-07-09 11:48:51 -04:00
desht ac44d72530 Re-apply missing patch to ServerLevel.EntityCallbacks#onTrackingEnd() (#8828) 2022-07-09 11:27:33 -04:00
agnor99 12468bd8d2 Double Bar Rendering fixed (#8806) (#8807)
* Double Bar Rendering fixed (#8806)

* Added requested changes by sciwhiz12
2022-07-09 11:22:15 -04:00
Néstor Amador a98eeb9d08 Multiple tweaks and fixes to the recent changes in the client refactor PR (#8836)
* Add an easy way to get the NamedGuiOverlay from a vanilla overlay

* Fix static member ordering crash in UnitTextureAtlasSprite

* Allow boss bar rendering to be cancelled

* Make fluid container datagen use the new name
2022-07-09 11:20:55 -04:00
Jonathan Colmenares b558b132cd Add FogMode to ViewportEvent.RenderFog (#8825) 2022-07-09 11:20:40 -04:00
Sara Freimer c102633566 Provide additional context to the getFieldOfView event (#8830) 2022-07-09 11:20:29 -04:00
bdew cce002ad29 Pass renderType to IForgeBakedModel.useAmbientOcclusion (#8834) 2022-07-09 11:20:18 -04:00
noeppi_noeppi b1ed321438 Load custom ITransformationServices from the classpath in dev (#8818)
* Add a classpath transformer discoverer to load custom transformation services from the classpath

* Update ClasspathTransformerDiscoverer to 1.18

* Update license year

* Update license header

* Fix the other license headers

* Update ClasspathTransformerDiscoverer to 1.19
2022-07-09 11:05:47 -04:00
Jonathan Coates c7c2478cb0 Handle modded packets on the network thread (#8703)
* Handle modded packets on the network thread

 - On the server we simply need to remove the call to
   ensureRunningOnSameThread.

 - On the client side, we now handle the packet at the very start of the
   call. We make sure we're running from a network thread to prevent
   calling the handling code twice.

   While this does mean we no longer call .release(), in practice this
   doesn't cause any leaks as ClientboundCustomPayloadPacket releases
   for us.

* Clarify behaviour a little in the documentation

* Javadoc formatting

* Add a helper method for handling packets on the main thread

Also rename the network thread one. Should make it clearer the expected
behaviour of the two, and make it clearer there's a potentially breaking
change.

* Add back consumer() methods

Also document EventNetworkChannel, to clarify the thread behaviour
there.

* Add since = "1.19" to deprecated annotations
2022-07-09 11:02:44 -04:00
Marc Hermans b70d99489b Cache resource listing calls in resource packs (#8829)
* Make the resource lookups cached.

* Include configurability and handle patch cleanup.

* Document and comment the cache manager.

* Make thread selection configurable.

* Implement a configurable loading mechanic that falls back to default behaviour when the config is not bound yet.

* Use boolean supplier and fix wildcard import.

* Clean up the VPR since this is more elegant.

* Clean up the VPR since this is more elegant.

* Address review comments.

* Address more review comments.

* Fix formatting on `getSource`

* Address comments by ichtt

* Adapt to pups requests.

* Stupid idea.

* Attempt this again with a copy on write list.

* Fix a concurrency and loading issue.

* Fix #8813
Checks if the paths are valid resource paths.

* Move the new methods on vanilla Patch.
2022-07-09 10:58:11 -04:00
cpw 57f45eaca0 Update SJH and JIJ 2022-07-09 10:42:30 -04:00
Marc Hermans 52fcc4d649 Fix #8833 (#8835) 2022-07-09 10:09:27 -04:00
Néstor Amador 959ab9abc9 Fix backwards fabulous check in SimpleBakedModel (#8832)
Yet another blunder we missed during the review of #8786.
2022-07-09 10:09:16 -04:00
Néstor Amador c3a91872fe Make texture atlas in StandaloneGeometryBakingContext configurable (#8831) 2022-07-09 10:08:43 -04:00
Néstor AmadorandDennis C 4d074f0a1e [1.19.X] Client code cleanup, updates, and other refactors (#8786)
* Revert "Allow safely registering RenderType predicates at any time (#8685)"

This reverts commit be7275443f.

* Renderable API refactors
- Rename "render values" to "context"
- Rename SimpleRenderable to CompositeRenderable to better reflect its use
- Remove IMultipartRenderValues since it doesn't have any real use
- Add extensive customization options to BakedModelRenderable

* ClientRegistry and MinecraftForgeClient refactors
- Add sprite loader manager and registration event
- Add spectator shader manager and registration event
- Add client tooltip factory manager and registration event
- Add recipe book manager and registration event
- Add key mapping registration event
- Remove ClientRegistry, as everything has been moved out of it
- Remove registration methods from MinecraftForgeClient, as they have dedicated events now

* Dimension special effects refactors
- Fold handlers into an extension class and remove public mutable fields
- Add dimension special effects manager and registration event

* HUD overlay refactors
- Rename to IGuiOverlay match vanilla (instead of Ingame)
- Add overlay manager and registration event
- Move vanilla overlays to a standalone enum

* Model loader refactors
- Rename IModelLoader to IGeometryLoader
- Add loader manager and registration event
- Fold all model events into one
- Move registration of additionally loaded models to an event
- Remove ForgeModelBakery and related classes as they served no purpose anymore

* Render properties refactors
- Rename all render properties to client extensions and relocate accordingly
- Move lookups to the respective interfaces

* Model data refactors
- Convert model data to a final class backed by an immutable map and document mutability requirements. This addresses several thread-safety issues in the current implementation which could result in race conditions
- Transfer ownership of the data manager to the client level. This addresses several issues that arise when multiple levels are used at once

* GUI and widget refactors
- Move all widgets to the correct package
- Rename GuiUtils and children to match vanilla naming

* New vertex pipeline API
- Move to vanilla's VertexConsumer
- Roll back recent PR making VertexConsumer format-aware. This is the opposite of what vanilla does, and should not be relevant with the updated lighting pipeline

* Lighting pipeline refactors
- Move to dedicated lighting package
- Separate flat and smooth lighters
- Convert from a vertex pipeline transformer to a pure vertex source (input is baked quads)

* Model geometry API refactors
- Rename IModelGeometry to IUnbakedGeometry
- Rename IModelConfiguration to IGeometryBakingContext
- Rename other elements to match vanilla naming
- Remove current changes to ModelState, as they do not belong there. Transforms should be specified through vanilla's system. ModelState is intended to transfer state from the blockstate JSON
- Remove multipart geometries and geometry parts. After some discussion, these should not be exposed. Instead, geometries should be baked with only the necessary parts enabled

* Make render types a first-class citizen in baked models
- Add named render types (block + entity + fabulous entity)
- Add named render type manager + registration event
- Make BakedModel aware of render types and transfer control over which ones are used to it instead of ItemBlockRenderTypes (fallback)
- (additional) Add concatenated list view. A wrapper for multiple lists that iterates through them in order without the cost of merging them. Useful for merging lists of baked quads

* General event refactors
- Several renames to either match vanilla or improve clarity
- Relocate client chat event dispatching out of common code

* Forge model type refactors
- Rename SeparatePerspectiveModel to SeparateTransformsModel
- Rename ItemModelMesherForge to ForgeItemModelShaper
- Rename DynamicBucketModel to DynamicFluidContainerModel
- Prefix all OBJ-related classes with "Obj" and decouple parsing from construction
- Extract ElementsModel from model loader registry
- Add EmptyModel (baked, unbaked and loader)
- Refactor CompositeModel to take over ItemMultiLayerBakedModel
- Remove FluidModel as it's not used and isn't compatible with the new fluid rendering in modern versions
- Move model loader registration to a proper event handler
- Update names of several JSON fields (backwards-compatible)
- Update datagens to match

* Miscellaneous changes and overlapping patches
- Dispatch all new registration events
- Convert ExtendedServerListData to a record
- Add/remove hooks from ForgeHooksClient as necessary

* Update test mods

* Fix VertexConsumerWrapper returning parent instead of itself

* Additional event cleanup pass

As discussed on Discord:
- Remove "@hidden" and "@see <callsite>" javadoc annotations from all client events and replace them with @ApiStatus.Internal annotation
- Make all events that shouldn't be fired directly into abstract classes with protected constructors
- Another styling pass, just in case (caught some missed classes)

* Add proper deprecation javadocs and de-dupe some vertex consumer code

* Replace sets of chunk render types with a faster BitSet-backed collection

This largely addresses potential performance concerns that using a plain HashSet might involve by making lookups and iteration as linear as they can likely be (aside from using a plain byte/int/long for bit storage). Further performance concerns related to the implementation may be addressed separately, as all the implementation details are hidden from the end user

* Requested changes

- Remove MinecraftForgeClient and move members to Minecraft, IForgeMinecraft and StencilManager
- Allow non-default elements to be passed into VertexConsumer and add support to derived classes
- Move array instantiation out of quad processing in lighting pipeline
- Fix flipped fluid container model
- Set default UV1 to the correct values in the remapping pipeline
- Minor documentation changes

* Add/update EXC entries and fix AT comment

* Add test mod as per Orion's request

* Additional requested changes

* Allow custom model types to request the particle texture to be loaded

* Even more requested changes

* Improve generics in ConcatenatedListView and add missing fallbacks

* Fix fluid render types being bound to the fluid and not its holder

* Remove non-contractual nullability in ChunkRenderTypeSet and add isEmpty

Additionally, introduce chunk render type checks in ItemBlockRenderTypes

Co-authored-by: Dennis C <[email protected]>
2022-07-07 18:34:51 -04:00
Paint_Ninja c2225ab1da Implement full support for IPv6 (#8742) 2022-07-01 15:38:53 -07:00
Dennis C bb03b1a7d1 Fix certain user-configured options being overwritten incorrectly due to validators. (#8780) 2022-06-28 13:23:35 -07:00
Dennis C be7275443f Allow safely registering RenderType predicates at any time (#8685) 2022-06-27 21:18:53 -07:00
Dennis C dc1c973684 Fix crash after loading error due to fluid texture gathering and config lookup (#8802) 2022-06-27 21:16:54 -07:00
Marc Hermans 06d568408c Remove the configuration option for handling empty tags in ingredients. (#8799)
Now empty tags are considered broken in all states.
2022-06-27 21:16:20 -07:00
TelepathicGrunt 2256e88fb4 Fix MC-105317 Structure blocks do not rotate entities correctly when loading (#8792) 2022-06-27 21:15:22 -07:00
Jonathan Coates 9b962c8ff0 Fire ChunkWatchEvents after sending packets (#8747) 2022-06-27 21:09:23 -07:00
cech12 7656b75992 Add item handler capability to chest boats (#8787) 2022-06-27 21:04:42 -07:00
Joseph B 58a5449c2f Add getter for correct BiomeSpecialEffectsBuilder to BiomeInfo$Builder (#8781) 2022-06-27 21:01:01 -07:00
Michael Bunting 702abe0665 Fix BlockToolModificationEvent missing cancelable annotation (#8778) 2022-06-27 20:59:47 -07:00
Sara Freimer 2070b77fd4 Fix ticking chunk tickets from forge's chunk manager not causing chunks to fully tick (#8775) 2022-06-27 20:58:57 -07:00
Dennis C fd00822015 Fix default audio device config loading string comparison issue (#8767) 2022-06-27 20:54:54 -07:00
dhyces 17565c0ea2 Fix missed vanilla method overrides in ForgeRegistry (#8766) 2022-06-27 20:48:11 -07:00
Budschie 22668ad2c2 Add MinecraftServer reference to ServerTickEvent (#8765) 2022-06-27 20:45:35 -07:00
Joseph B 0dcc3d700d Fix TagsProviders for datapack registries not recognizing existing files (#8761) 2022-06-27 20:43:50 -07:00
Dennis C 2ab3d9b8a3 Add callback after a BlockState was changed and the neighbors were updated (#8686) 2022-06-27 20:21:34 -07:00
Ketok d578d8f6df Add biome tag entries for 1.19 biomes (#8684) 2022-06-27 20:08:21 -07:00
eerussianguy fd61016a7e Make fishing rods use tool actions for relevant logic (#8681) 2022-06-27 20:07:51 -07:00
cpw 7f77d24f45 Update BootstrapLauncher to 1.1.1 and remove the forced
merge of text2speech since new BSL does it.

Signed-off-by: cpw <[email protected]>
2022-06-20 22:27:08 -04:00
cpw 3ebdcb34d1 Merge text2speech libs together so the natives are part of the jar
Signed-off-by: cpw <[email protected]>
2022-06-20 18:19:45 -04:00
King Lemming 05240fecf7 Make Forge ConfigValues implement Supplier. (#8776) 2022-06-20 23:07:48 +01:00
cpw d5860d7cfa Fix merge derp in AbstractModProvider and logic derp in ModDiscoverer
Signed-off-by: cpw <[email protected]>
2022-06-20 16:32:46 -04:00
cpw 7bb97dafda Add "send to mods in order" method to ModList and use it (#8759)
* Add "send to mods in order" method to ModList and use it in RegistryEvents and DataGen..
* Also preserve order in runAll
* Do better comparator thanks @pupnewfster
* postEvent as well.
2022-06-20 16:11:33 -04:00
cpw ca90babc4a Update SJH to 2.0.2.. (#8774)
* Update SJH to 2.0.3..
2022-06-20 16:11:13 -04:00
cpw 4b813e4319 Sanity check the version specified in the mod file (#8749)
* Sanity check the version specified in the mod file to
make sure it's compatible with JPMS standards for
version strings.

Closes #8748

Requires SPI 6
2022-06-20 16:09:19 -04:00
Marc Hermans fa84c22662 Fix SP-Devtime world loading crash due to missing server configs (#8757) 2022-06-17 11:38:41 -07:00
sciwhiz12 2ae640b530 Remove ForgeWorldPreset and related code (#8756)
Vanilla has a working replacement.
2022-06-17 08:56:12 +01:00
sciwhiz12 4f95a20c5e Change ConfigValue#get() to throw if called before config loaded (#8236)
This prevents silent issues where a mod gets the value of the setting
before configs are loaded, which means the default value is always
returned.

As there may be situations where the getting the config setting before
configs are loaded is needed, and it is not preferable to hardcode the
default value, the original behavior is made available through #getRaw.

Implements and closes #7716

* Remove getRaw() method

This is effectively replaced with the expression `spec.isLoaded() ?
configValue.get() : configValue.getDefault()`.

* Remove forceSystemNanoTime config setting

As implemented, it never had any effect as any place where the config
value would be queried happens before the configs are loaded.
2022-06-17 08:31:45 +01:00
sciwhiz12 915d570b17 Fix EnumArgument to use enum names for suggestions (#8728)
Previously, the suggestions used the string representation of the enum
through Enum#toString, which can differ from the name of the enum as
required by Enum#valueOf, causing invalid suggestions (both in gui and
through the error message).
2022-06-15 14:15:32 -07:00
Marc Hermans 5979636ee5 Jar-In-Jar (#8715) 2022-06-15 12:27:47 -07:00
Silverminer007 5acfc6ae3c [1.19] Fix data-gen output path of custom data-pack registries (#8724) 2022-06-15 16:22:00 +01:00
ChampionAsh5357 48341120fb Fix player dive and surface animations in custom fluids (#8738) 2022-06-15 14:02:16 +01:00
ChampionAsh5357 ff45bb4c27 [1.19.x] Affect ItemEntity Motion in Custom Fluids (#8737) 2022-06-15 14:01:57 +01:00
KnightMiner eabba46595 [1.19] Add support for items to add enchantments without setting them in NBT (#8719) 2022-06-15 00:52:58 +01:00
Joseph B 683bf99fe4 [1.19.x] Add stock biome modifier types for adding features and spawns (#8697) 2022-06-15 00:39:03 +01:00
ChampionAsh5357 2a05c7c01d [1.19.x] Fluid API Overhaul (#8695) 2022-06-14 23:07:51 +01:00
Sara Freimer e386229b66 Replace StructureSpawnListGatherEvent with StructureModifiers (#8717) 2022-06-14 12:05:07 -07:00
Magnus Jensen 59b8ec5625 Use stack sensitive translation key by default for FluidAttributes. (#8707) 2022-06-14 10:18:27 -07:00
ferriarnus 50ae5db357 Delete LootItemRandomChanceCondition which added looting bonus enchantment incorrectly. (#8733) 2022-06-14 10:17:38 -07:00
cpw 3aa99a1250 Update EventBus to 6.0, ModLauncher to 10.0.1 and BootstrapLauncher to 1.1 (#8725) 2022-06-14 10:15:46 -07:00
coehlrich 00c8513129 Replace support bot with support action (#8700) 2022-06-13 17:36:16 -07:00
Brennan Ward 9c1404fecc Fix Reach Distance / Attack Range being clamped at 6.0 (#8699) 2022-06-13 17:33:02 +01:00
Joseph B c11686ab6c [1.19.x] Fix mods' worldgen data not being loaded when creating new singleplayer worlds (#8693) 2022-06-13 17:21:21 +01:00
SizableShrimp 2818984f6c [1.19.x] Fix experimental confirmation screen (#8727)
Signed-off-by: SizableShrimp <[email protected]>
2022-06-13 17:20:50 +01:00
TelepathicGrunt db225ed04a Move is_mountain to forge's tag instead of vanilla's (#8726) 2022-06-13 02:39:04 +01:00
ChampionAsh5357 0ec4c34a34 [1.19.x] Add CommandBuildContext to Register Command Events (#8716) 2022-06-12 23:36:25 +01:00
Sara Freimer 597ebc3267 Only rewrite datagen cache when needed (#8709) 2022-06-10 20:35:40 -07:00
cpw e16f54eebe Implement a simple feature system for Forge (#8670)
* Implement a simple feature system for Forge. Allows mods to demand certain features are available in the loading system. An example for java_version is provided, but not expected to be used widely. This is more targeted to properties of the display, such as GL version and glsl profile.

Requires https://github.com/MinecraftForge/ForgeSPI/pull/13 to be merged first in ForgeSPI, and the SPI to be updated appropriately in build.gradle files.

* rebase onto 1.19 and add in SPI update
2022-06-09 17:00:39 -04:00
cpw 27480c15fa displayTest option in mods.toml (#8656)
* displayTest option in mods.toml
* "MATCH_VERSION" (or none) is existing match version string behaviour
* "IGNORE_SERVER_VERSION" accepts anything and sends special SERVERONLY string
* "IGNORE_ALL_VERSION" accepts anything and sends an empty string
* "NONE" allows the mod to supply their own displaytest using the IExtensionPoint mechanism.


* Update display test with feedback and added the mods.toml discussion in mdk.
2022-06-09 16:39:00 -04:00
cpw df0dea59f3 Update forgeSPI to v5 (#8696) 2022-06-09 15:59:48 -04:00
gigaherz d7bc564512 Make IVertexConsumers such as the lighting pipeline, be aware of which format they are dealing with. (#8692)
Also fix Lighting pipeline ignoring the overlay coords from the block renderer.
2022-06-09 21:39:16 +02:00
ferriarnus e6a73ef36c Fixed misaligned patch to invalidateCaps in Entity (#8705) 2022-06-09 11:41:51 -07:00
SizableShrimp 1ba7c6aecd Fix readAdditionalLevelSaveData (#8704) 2022-06-09 11:40:42 -07:00
AzureDoom 7c5e95222e Fixes setPos to syncPacketPositionCodec (#8702) 2022-06-09 11:40:21 -07:00
SizableShrimp 38df3d2a15 Fix wrong param passed to PlayLevelSoundEvent.AtEntity (#8688) 2022-06-09 11:39:35 -07:00
ferriarnus 3beaa817f3 Override initialize in SlotItemHandler, so it uses the itemhandler instead of container (#8679) 2022-06-09 11:39:04 -07:00
SizableShrimp 3ebd7ba0ef Update MDK for 1.19 changes (#8675) 2022-06-09 11:37:52 -07:00
LexManos 1ba9c34650 Add helper to RecipeType, and fix eclipse compiler error in test class. 2022-06-09 11:36:52 -07:00
cpw 2f9e726aea Update modlauncher to latest (#8691) 2022-06-08 16:02:50 -07:00
Sara Freimer ade2b8cc80 Fix getting entity data serializer id crashing due to improper port to new registry system (#8678) 2022-06-08 09:14:41 -07:00
Sara Freimer 9b144f4541 Fire registry events in the order vanilla registers to registries (#8677)
Custom registries are still fired in alphabetical order, after all vanilla registries.
Move forge's data_serializers registry to forge namespace.
2022-06-08 09:08:55 -07:00
cpw 0c35436217 Add method with pre/post wrap to allow setting/clearing mod context. (#8682)
Fixes ActiveContainer in ModContext not being present in registry events. Closes #8680
2022-06-08 08:38:53 -07:00
SizableShrimp 0e66b7b217 Fix the Curlie oopsie
Signed-off-by: SizableShrimp <[email protected]>
2022-06-07 17:08:56 -04:00
4ed9117799 Forge 1.19
* Bump pack.mcmeta formats
* 1.19 biome modifiers
* Mark ClientPlayerNetworkEvent.LoggedOutEvent's getters as nullable
* Add docs and package-info to client extension interfaces package
* Move RenderBlockOverlayEvent hooks to ForgeHooksClient
* Add package-infos to client events package
* Rename SoundLoadEvent to SoundEngineLoadEvent

This reduces confusion from consumers which may think the
name SoundLoadEvent refers to an individual sound being loaded rather
than the sound engine.
* Document and change SoundLoadEvent to fire on mod bus

Previously, it fired on both the mod bus and the Forge bus, which is
confusing for consumers.
* Delete SoundSetupEvent

Looking at its original implementation shows that there isn't an
appropriate place in the new sound code to reinsert the event, and the
place of 'sound engine/manager initialization event' is taken already by SoundLoadEvent.
* Perform some cleanup on client events

 - Removed nullable annotations from ClientPlayerNetworkEvent
 - Renamed #getPartialTicks methods to #getPartialTick, to be consistent
  with vanilla's naming of the partial tick
 - Cleanup documentation to remove line breaks, use the
  spelling 'cancelled' over
  'canceled', and improve docs on existing and
   new methods.
* Remove EntityEvent.CanUpdate

Closes MinecraftForge/MinecraftForge#6394
* Switch to Jetbrains nullability annotations
* New PlayLevelSoundEvent; replaces old PlaySoundAtEntityEvent
* Remove ForgeWorldPresetScreens
* Remove IForgeRegistryEntry
* Remove use of List<Throwable> in FML's CompletableFutures
* Add docs to mod loading stages, stages, and phases
* Gradle 7.4.2
* Use SLF4J in FMLLoader and other subprojects
* Switch dynamic versions in subprojects to pinned ones
* Switch ForgeRoot and MDK to FG plugin markers
* Configure Forge javadoc task

The task now uses a custom stylesheet with MCForge elements, and
configured to combine the generation from the four FML subprojects
(fmlloader, fmlcore, javafmllanguage, mclanguage) and the Forge project
into the javadoc output.
* Update docs/md files, for 1.19 update and the move away from IRC to Discord.
* Make "Potentially dangerous alternative prefix" a debug warning, not info.

Co-authored-by: Curle <[email protected]>
Co-authored-by: sciwhiz12 <[email protected]>
Signed-off-by: SizableShrimp <[email protected]>
2022-06-07 15:31:26 -05:00
ChampionAsh5357 270e778ac5 [1.18.x] Fix #8530 (Banner Pattern) NPE (#8666) 2022-06-07 17:43:17 +01:00
Dennis C 9528fd8bcc Revert "[1.18.x] Enable the Forge light pipeline by default (#8629)" (#8663) 2022-06-06 03:31:30 +01:00
Take Weiland 5a75314bb3 Fix eager loading of model loaders during datagen causing NPE (#8659) 2022-06-05 20:33:32 +01:00
Autovw cceb8db74e [1.18.x] Fix 2 crossbow animations not applying to custom variants (#8625) 2022-06-05 16:34:02 +01:00
Redstone_DubstepandCurle 8e7b08b96d [1.18.x] Added new Disconnection screen to display better channel/registry mismatch information (#8402)
Co-authored-by: Curle <[email protected]>
2022-06-05 16:01:17 +01:00
Gegy 194f11069f [1.18] Avoid exclusive synchronisation in block render type lookups (#8476) 2022-06-05 15:56:54 +01:00
sciwhiz12 5ef0d667e0 [1.18] Fix command redirects by replacing Commands#fillUsableCommands (#8616)
Commands#fillUsableCommands does not handle redirect nodes properly. It
blindly pulls from the cached node map for a redirect node, which may
have no result because the target node of the redirect has not been
visited yet.

CommandHelper#mergeCommandNode is better in this regard, because it
visits the target node of the redirect instead of blindly pulling from
the node map.

Fixes #7551
2022-06-05 15:47:52 +01:00
sciwhiz12 8a1c1d7e53 [1.18] Fix tags command suggestion to include dynamic registries (#8638)
Manually entering the names of dynamic registries work as expected. The
suggestions for registries didn't include dynamic registries because
they queried the static registries rather than querying all registries
from the server's `RegistryAccess` (which includes both static
registries and dynamic registries).
2022-06-05 15:45:14 +01:00
cpwandCurle 1353c1d9fa Low code language provider (#8633)
Signed-off-by: cpw <[email protected]>

Co-authored-by: Curle <[email protected]>
2022-06-05 15:44:46 +01:00
SizableShrimp 70a8663605 [1.18.x] Add checkJarCompatibility task (#8644)
Signed-off-by: SizableShrimp <[email protected]>
2022-06-05 15:40:26 +01:00
ChampionAsh5357andCurle f179eed971 [1.18.x] Fix Banner Patterns not being extensible (#8530)
Co-authored-by: Curle <[email protected]>
2022-06-05 15:39:29 +01:00
Flemmli97 d4c8708229 1.18.x Port BiomeDictionary over to biome tags (#8564) 2022-06-05 15:35:06 +01:00
Dennis C 4008057803 [1.18.x] Enable the Forge light pipeline by default (#8629) 2022-06-05 15:28:46 +01:00
997d8e0aa2 [1.18.x] Allow Modders to add custom data-pack registries through RegistryBuilder (#8630)
Co-authored-by: Silverminer007 <[email protected]>
Co-authored-by: Curle <[email protected]>
2022-06-05 15:27:30 +01:00
Take Weiland 15bd5f0d30 [1.18] Allow custom rarities to directly modify the style (#8648) 2022-06-05 15:24:54 +01:00
Take Weiland ccaa20b006 [1.18] Fix reload listener registration in ModelLoaderRegistry (#8650) 2022-06-05 15:24:29 +01:00
Dennis C c48698f680 Fix wrong position in Level#hasChunk() call in IForgeBlockGetter (#8654) 2022-06-05 15:23:49 +01:00
Take Weiland 4285c931e7 Add ItemStack context to Enchantment#getDamageBonus (#8635) 2022-06-01 09:19:18 -07:00
Brennan Ward 03c43cf3da Fix attack cooldown bar showing when out of reach of target. Closes #8639 (#8640) 2022-05-31 11:07:22 -07:00
Take Weiland 8d14797416 Improve TagsUpdatedEvent by adding update case information. (#8636) 2022-05-31 11:03:55 -07:00
sciwhiz12 e4837f65a3 Deprecate patched-in Style methods for removal, vanilla variants exist. (#8615) 2022-05-31 10:38:25 -07:00
sciwhiz12 ee46af66e5 Add pack-type-specific format versions in pack metadata. Fixes #8563 (#8612) 2022-05-31 10:36:44 -07:00
SizableShrimp 2bec354317 Catch and aggregate exceptions during NewRegistryEvent (#8601) 2022-05-31 10:34:06 -07:00
DaemonUmbra 727c7780b3 Added removeErroringEntities config option (#8627)
Counterpart to removeErroringBlockEntities
2022-05-23 20:03:03 +01:00
Take Weiland 5410f9b532 Add missing patches for not lowering mipmap level for small textures (#8622) 2022-05-23 20:02:51 +01:00
gigaherz 4c09d8d774 Make TransformType enum extensible, includes the possibility to specify a fallback type for cases where models don't specify the transform explicitly. (#8566)
Makes it possible to add new perspectives.
2022-05-22 17:55:48 +01:00
LexManos aded6fb847 Fix CheckSAS to actually validate that the SAS line will do something.
This removes all method level lines as they are not necessary now.
2022-05-21 13:16:58 -07:00
Brennan Ward c2ad951336 Add Attack Range attribute and Update Reach Distance (#8478) 2022-05-21 16:44:36 +01:00
Alex Thomson 7fb5dfa3e6 Implement PlayerNegotiationEvent (#8599) 2022-05-14 17:27:54 +01:00
sciwhiz12 0f8c2fa454 Fire EntityTravelToDimensionEvent in all expected cases (#8614)
Fixes #8520
2022-05-08 06:12:21 +01:00
sciwhiz12 dfc2aa9c6a Fix isEdible crash (#8613)
Fixes #8602
2022-05-08 04:41:30 +01:00
LexManos 8865092bb2 Fix typo in Snow Golem patch causing them to destroy blocks they shouldn't. Closes #8611 2022-05-07 12:24:09 -07:00
Sara Freimer abc3353375 Re-introduce an attribute for entity step height in a non-breaking way (#8607) 2022-05-05 19:11:59 +01:00
ChampionAsh5357 e7a8da4d0b Revert step height attribute (#8604) 2022-05-05 14:07:07 +01:00
SizableShrimp f938051373 [1.18.x] Fix ContextNbtProvider serializing the wrong name (#8575) 2022-05-03 20:27:37 +01:00
Dennis C 9db0d72232 Let BaseRailBlock decide if the calculated RailShape for placement or connection to neighbors is valid (#8562) 2022-05-03 19:58:53 +01:00
cech12 9e6e789b73 Fix shears not playing a breakage sound (#8600) 2022-05-03 19:17:05 +01:00
Leon Linhart bc0d7179cc Update IExtensionPoint javadoc to be correct (#8568) 2022-05-03 18:38:28 +01:00
Meldexun aafa34439a Fix IDs of Multi-part entities being desynced across client and server. (#8576) 2022-05-03 18:29:21 +01:00
Brennan Ward 168a3bc6fc Expose ICondition$IContext to modded reload listeners. (#8596) 2022-05-03 18:25:42 +01:00
Silver_David 2fb8b2eb18 Fix undead causing chunkloading leading to extensive lag (#8583) 2022-05-03 18:24:13 +01:00
DaemonUmbra da82705e86 Accomodate Bukkit-like Servers not sending Command Args (#8582)
Note to modded server devs:
Please, please, please implement full compatibility with [Brigadier](https://github.com/Mojang/Brigadier) instead of hacking around it.
2022-05-03 18:21:53 +01:00
Phylogeny a237a39d52 Restore translation key comments to ForgeConfigSpec (#8584) 2022-05-03 18:20:21 +01:00
Meldexun c042dc5542 Fix entity parts being ignored when collecting entities in an AABB (#8588)
Previously entity parts are only taken into consideration when the parent entity is in a chunk that intersects with the AABB
2022-05-03 18:17:26 +01:00
KnightMiner 1493d06b5a Fix EntityInteraction event running twice on client side (#8598) 2022-05-03 18:08:47 +01:00
Vincent Lee 9a11201a9e Introduce an attribute for step height additions (#8389) 2022-05-03 18:01:45 +01:00
KnightMiner c34094ea50 Fix shears passing on a client when interacting with a shearable entity (#8597)
Caused the offhand item to also interact with the entity, possibly sending a packet to the server causing both hands to interact
2022-05-02 10:46:58 -07:00
Alex Thomson c531b2b5c7 Allow Exception passed through CommandEvent to propagate (#8590) 2022-05-02 10:43:49 -07:00
8ade7bbaeb Mark 1.18.2 Recommended Build.
Co-authored-by: sciwhiz12 <[email protected]>
Co-authored-by: Marc Hermans <[email protected]>
Co-authored-by: Curle <[email protected]>
Co-authored-by: SizableShrimp <[email protected]>
Co-authored-by: David Quintana <[email protected]>
2022-04-18 16:35:06 -07:00
sciwhiz12 6347071976 Add event for hooking into StructuresBecomeConfiguredFix Fixes #8505
Pass-through unknown structure IDs with "unknown." prefix
This avoids the fixer throwing an exception due to the unknown
structure, which causes the chunk data to be dropped (and freshly
regenerated later). The deserializer logs and ignores the unknown
structure ID, avoiding full chunk data loss.
2022-04-17 15:12:05 -07:00
Wyn Price 17bd0c4f91 Fix missed patch for loading modded dimensions on Dedicated Server start (#8555) 2022-04-17 14:41:31 -07:00
LexManos bafaf90329 Fix potential concurrency issues with BiomeDictionary. Closes #8266 2022-04-14 11:13:14 -07:00
LexManos fcb81aa660 Fix debug text being rendered slightly wrong. 2022-04-14 10:58:43 -07:00
LexManos eb8fe02a5e Fix intrusive handlers on dummy objects. 2022-04-13 23:21:57 -07:00
sciwhiz12 c1874bb5ab Amend license header to include contributors and apply to FML subprojects (#8525)
After internal discussion, it was decided that we need to include
"contributors" to the license header. This avoids claiming that the
Java source files are under the exclusive copyright ownership of Forge
LLC, which excludes contributors that still hold copyright ownership
over their contributions (but is licensed under the LGPLv2.1 as stated
in the Forge CLA).
2022-04-13 20:42:00 -07:00
Robert Kämpf f0b90dc35d Add modern implementation of the Slider widget and deprecate the old one (#8496) 2022-04-13 19:59:38 +02:00
canitzp eed24f017f Implement ItemStack and LivingEntity sensitive method to get the FoodProperties for an Item (#8477) 2022-04-13 10:45:08 -07:00
SizableShrimp 7d79f0d581 Add use context and simulate flag to getToolModifiedState, enabled HOE_TILL action. (#8557) 2022-04-12 09:43:20 -07:00
sciwhiz12 94ce098056 Remove bad patch for AbstractFurnaceBlockEntity (#8561)
The patch prevented the entity from being marked as changed when an
item finished smelting.
2022-04-11 15:50:06 +01:00
Sara Freimer fbaf92105e Fix issues with custom forge ingredients causing sub ingredients to be prematurely and invalidly cached (#8550)
Add config option and skip checking for empty ingredients in shapeless recipe deserialization
2022-04-08 15:37:43 -07:00
Minecraftschurli 1e6845669c Add EnderManAngerEvent to make it possible to prevent endermen getting angry at a player based on more then their helmet. (#8406) 2022-04-08 10:14:50 -07:00
LexManos 796cb29904 Fix misaligned patch in BlockEntity.save. 2022-04-07 11:40:08 -07:00
SizableShrimp 42472a8ab8 Expose getHolder() method on RegistryObject, as helper for when absolutely necessary to pass into Vanilla code. (#8548)
It is recommended you avoid if you can.
2022-04-06 14:13:17 -07:00
Sara Freimer 954db14250 Fix return value of Recipe#isIncomplete being inaccurate for empty tags (#8549) 2022-04-04 18:10:41 -07:00
KnightMiner 56976e4d20 Simplfy default behavior of isSimple (#8543)
isSimple should only return true if the ingredient is any more sensitive then JUST itemA == itemB
It used to take metadata and damage into account, but that was removed in the flattening.
Also prevents fetching tag values too early, as tags are not ready during the ingredient constructor
2022-04-04 18:05:41 -07:00
Sr_endi c38e0de8f5 Implement IPlantable in BambooBlock (#8508) 2022-04-04 18:02:33 -07:00
LexManos d33f24ff33 Fix compiler error in eclipse, bump MCPConfig for FF/Record fix. 2022-04-04 18:02:20 -07:00
Technici4n 87c4f90fb2 Fix TagEmptyCondition by passing tag context into conditional and recipe deserializers. (#8546) 2022-04-02 00:09:20 -07:00
SizableShrimp 1f031ad2c3 Allow using DeferredRegisters for vanilla registries (#8527)
Catch and aggregate exceptions when applying object holders
2022-04-01 13:49:46 -07:00
sciwhiz12 8f0d3da1e4 Remove cut copper from copper storage blocks tag. Closes #8403 (#8539) 2022-03-30 12:57:37 -07:00
ChampionAsh5357 10ca83e90d Fix brewing stand input placement not auto-splitting stackable potions. (#8534) 2022-03-30 12:56:46 -07:00
SizableShrimp e5d4e5d3ab Fix lost validation of registry data on singleplayer world load (#8533)
Fix some leftover 1.18.2 TODOs
2022-03-25 17:52:48 -07:00
Cyborgmas c7e4e60052 1.18 Allow mod menus to have their own recipebook (#8028) 2022-03-24 22:08:17 +00:00
KnightMiner 093acab825 [1.18.x] Add 3 new ingredient types, and make existing ingredients compatible with datagen (#8517) 2022-03-24 22:04:32 +00:00
Jonathan Colmenaresandnoeppi_noeppi c3bd365baa [1.18.x] Add the projectile search event. (#8322)
Co-authored-by: noeppi_noeppi <[email protected]>
2022-03-24 21:52:58 +00:00
Cyborgmas 02fd859d5c Allow confirm-and-save of the Experimental Settings warning. (#7275) 2022-03-24 21:36:03 +00:00
KnightMiner 349e12f939 Add hook for powdered-snow shoes (#8514) 2022-03-24 21:17:12 +00:00
Martijn van den Brand 9d3eb9df8f Add some helper Access Transformers (#8490) 2022-03-24 21:14:27 +00:00
sciwhiz12 3c39a36c26 Fix incorrect method used in getStream (#8532)
The original correct method is getPath, but the patch uses getLocation.
The former is the actual resource path to the sound OGG file, while the
latter is the sound's location.

Fixes #8531
2022-03-24 01:11:17 +00:00
KnightMiner b0a64ff8ac [1.18] Make it easier to register custom skull blocks models (#8351) 2022-03-23 01:50:50 +01:00
eerussianguy e1ad29edd0 Rework fog events (#8492) 2022-03-23 01:43:39 +01:00
mezz 5ac711839f Update Forge Auto Renaming Tool to the latest version (#8515) 2022-03-22 00:17:49 -07:00
Take Weiland 415cdd0588 Add patches to enable MobEffects with IDs > 255 (#8380) 2022-03-21 23:10:33 -07:00
Jonathan Coates 7f23b3b525 Allow sound instances to play custom audio streams (#8295) 2022-03-21 22:44:02 -07:00
Joseph Tarbit de1050e420 Fix NPE caused by canceling onServerChatEvent (#8516) 2022-03-17 12:59:20 -07:00
SizableShrimp ad75cb8644 [1.18.2] Fix tags for custom forge registries. (#8495)
Tag-enabled registries must now be registered to vanilla's root registry. See RegistryBuilder#hasTags.
Modded tag-enabled registries have to use the format `data/<namespace>/tags/<registrynamespace>/<registryname>/<tag>.json`
This format is to prevent conflicts for registries with the same path but different namespaces
EX: Registry name `examplemod:shoe`, tag name `blue_shoes` would be `data/<namespace>/tags/examplemod/shoe/blue_shoes.json`
RegistryEvent.NewRegistry has been moved and renamed to NewRegistryEvent.
RegistryBuilder#create has been made private. See NewRegistryEvent#create
Created new ITagManager system for looking up Forge tags. See IForgeRegistry#tags.
Add lookup methods for Holders from forge registries. See IForgeRegistry#getHolder.
2022-03-16 13:36:00 -07:00
Sara Freimer 30f3a7dbba Lower custom item entity replacement from highest to high so mods can cancel it during a specific tick (#8417) 2022-03-15 15:09:28 -07:00
BlueAgent 9d74a3520f Fix MC-176559 related to the Mending enchantment (#7606) 2022-03-15 17:45:23 +00:00
Dennis C 57d6f31adb [1.18.x] Allow blocks to hide faces on a neighboring block (#8300)
* Allow blocks to hide faces on a neighboring block
* Allow blocks to opt-out of external face hiding
2022-03-13 22:59:59 +01:00
SizableShrimp 9bf227afeb [1.18.x] Fix FMLOnly in forgedev and userdev (#8512)
Signed-off-by: SizableShrimp <[email protected]>
2022-03-13 21:48:55 +00:00
Gabriel Harris-Rouquette 72f5b3f84d Clear local variable table on RuntimeEnumExtender transformation (#8502) 2022-03-12 23:08:50 -08:00
Sara Freimer df3c7ce19a Pass server resources to reload listener event (#8493) 2022-03-06 14:57:14 +00:00
Paint_Ninja 6cb444455d Use UTF-8 charset for Java compilation (#8486) 2022-03-06 14:53:15 +00:00
Andy Dingley 64ded22276 Use wither as griefing entity when it indirectly hurts an entity (#8431) 2022-03-06 14:49:53 +00:00
Joseph Tarbit 41c88f6e52 Provide access to the haveTime supplier in WorldTickEvent and ServerTickEvent (#8470) 2022-03-06 14:42:58 +00:00
sciwhiz12 cdd91968b4 Fix durability bar not respecting an item's custom max damage (#8482) 2022-03-06 14:32:36 +00:00
sciwhiz12 898696d770 Add event for controlling potion indicators size (#8483)
This event allows forcing the rendering of the potion indicators in the
inventory screen to either compact mode (icons only) or classic mode
(full width with potion effect name).
2022-03-06 14:31:12 +00:00
sciwhiz12 3dcb4a2c9c Introduce system mods to mod loading (#8238)
Core game mods are mods which are required to exist in the environment
during mod loading. These may be specially provided mods (for example,
the `minecraft` mod), or mods which are vital to the framework which
FML is connected to (for example, Forge and the `forge` mod).

These core game mods are used as the only existing mods in the mod list
if mod sorting or dependency verification fails. This allows later
steps in the which use resources from these mod files to work correctly
(up to when the error screen is shown and the game exits).
2022-03-06 14:21:00 +00:00
sciwhiz12 c458ff17fd Add missing module exports arg to server arguments list (#8500) 2022-03-06 01:31:53 +00:00
Frostygames0 7009c1aa89 Fixed swim speed attribute (#8499) 2022-03-05 15:19:22 +00:00
Dennis C 4311edd4cd Fix incorrect movement distance calculation (#8497) 2022-03-04 03:42:15 +00:00
LexManos 735382be03 Add support to Forge registry wrappers for new Holder system. Closes #8491
Fix TagBasedToolTypesTest not generating needed data correctly.
2022-03-02 13:38:02 -08:00
gigaherz 14bca0d757 Fix JNA not working at runtime and causing issues with natives. 2022-03-02 01:14:57 +01:00
425eff39ff Update to 1.18.2
Co-authored-by: sciwhiz12 <[email protected]>
Co-authored-by: Marc Hermans <[email protected]>
Co-authored-by: LexManos <[email protected]>
Co-authored-by: Curle <[email protected]>
Signed-off-by: SizableShrimp <[email protected]>
2022-03-01 14:16:46 -08:00
sciwhiz12 34291c1fb2 1.18.x Omnibus (#8239) 2022-03-01 18:59:37 +00:00
ichttt 4011c3fb07 Bump modlauncher and securejarhandler version (#8489) 2022-02-28 14:31:10 -08:00
LexManos 104daf8ef0 Update license headers to compact SPDX format.
License has not changed, this is just more compact and doesn't include years.
Bump version for RB.
2022-02-28 13:41:23 -08:00
LexManos d9a04b881a Remove - from allowed characters in mod ids.
The Java Module System does not allow them in module ids.
Closes #8488
2022-02-28 13:23:53 -08:00
gigaherz ae62362d49 Fix static initializer crash when loading BakedRenderable. 2022-02-28 22:03:31 +01:00
sciwhiz12 2f8c3ea738 Fix regressions for onAddedTo/RemovedFromWorld and related events (#8434) 2022-02-28 17:23:19 +00:00
SizableShrimp f0c2554b1c [1.18] Integrate the gametest framework with Forge (#8225)
Signed-off-by: SizableShrimp <[email protected]>
2022-02-25 01:06:32 +00:00
sciwhiz12 bb547a5748 Re-add missing Shulker patch for EntityTeleportEvent (#8481) 2022-02-25 00:51:00 +00:00
sciwhiz12 5dd3842b77 Fix entity type in conversion event to Drowned (#8479) 2022-02-25 00:49:48 +00:00
Sara Freimer 2ab4685149 Add VanillaGameEvent to allow for globally listening to vanilla's GameEvents (#8472) 2022-02-22 15:12:06 -08:00
Sara Freimer edbc07ed22 Provide damage source context to Item#onDestroyed(ItemEntity) (#8473) 2022-02-22 14:38:53 -08:00
Sara Freimer e225dbc8d1 Add missing shear and elytra game events (#8471) 2022-02-22 14:24:14 -08:00
sciwhiz12 117be913da Fix comment for permission handler config setting (#8466) 2022-02-22 14:21:47 -08:00
Brennan Ward 512d4d7271 Apply nullable annotations to LootingLevelEvent (#8422) 2022-02-22 14:20:29 -08:00
LexManos a9237cff75 Fix Mob Spawner logic with CustomSpawnRules. Closes #8398 2022-02-22 14:18:52 -08:00
Take Weiland bc24487d0e Fix LivingDropsEvent not having all drops for foxes (#8387) 2022-02-15 09:41:06 -08:00
Take Weiland c3e0b071a2 Add missing Locale parameter to String.format calls, Fixes getArmorResource functionality on some locaales. (#8463) 2022-02-15 09:27:10 -08:00
Take Weiland 21787234f4 Allow items to hide parts of their tooltips by default (#8358) 2022-02-15 09:23:18 -08:00
Marc Hermans a9958b19db Prevent 1.x Branches being treated as Pull Requests. (#8443) 2022-02-12 09:28:14 -08:00
Take Weiland b25d9562f2 Fix RegistryObject not working if created after registry events (#8383) 2022-02-08 13:05:38 -08:00
Marc Hermans 2765c0d8d9 Add support for tagging StructureFeatures (#8408) 2022-02-08 12:48:57 -08:00
Take Weiland 82a20911cb Re-added the patch for LivingExperienceDropEvent and enable it for dragons (#8388) 2022-02-08 12:39:01 -08:00
Sara Freimer f19f7e4670 Implement getPickupSound on ForgeFlowingFluid (#8374) 2022-02-08 12:24:47 -08:00
Frinn38 e10f5c637e Add getCodec method in ForgeRegistry (#8333) 2022-02-08 12:12:28 -08:00
eerussianguy 4bfe562f14 Fix #8298 (MobBucketItem) and add test mod (#8313) 2022-02-08 11:55:25 -08:00
Joseph Tarbit 5e64ef9ecb Deprecate IForgeAbstractMinecart::getCartItem (#8283) 2022-02-08 11:38:25 -08:00
Take Weiland dda1be91ea Fix HoeItem patch incorrectly applied during migration. (#8384) 2022-02-08 11:28:22 -08:00
Take Weiland 4f4849b60c Fix issues with client only commands in combination with server only commands not using MC's command system. (#8452) 2022-02-08 11:24:55 -08:00
Dipo 3b754fef5e Fix FoliagePlacerType and TreeDecoratorType registry (#8394) 2022-02-04 01:28:55 +00:00
Take Weiland 5e295f2485 Fix PlayerChangeGameModeEvent (#8441) 2022-02-04 00:08:41 +00:00
Dennis C 5c9258491f Fix comparison of custom ParticleRenderTypes leading to broken particle effects. (#8385) 2022-01-30 14:26:03 +00:00
LexManos af87677516 Fix cases where null is potentially sent to Screen events. Closes #8432 2022-01-27 23:38:08 -08:00
mezz a68c886ea2 Ensure ScreenEvent doesn't accept null screens (#8296) 2022-01-27 19:47:58 -08:00
Bagel b129e385cc Update cobblestone tags (#8292) 2022-01-27 19:39:44 -08:00
Marc Hermans fdc921923c Prevent release of custom payload packet buffer on the server side. (#8181) 2022-01-27 19:33:45 -08:00
SizableShrimp 476e20ae96 Make MinecraftLocator respect non-MOD FML Mod Types Fixes #8344 (#8346) 2022-01-22 10:26:14 -08:00
Joseph B d63516f2ac Fix vanilla worlds being marked experimental (#8415) 2022-01-22 03:46:44 +00:00
KnightMiner fd522d38b0 Simplify usage of IItemRenderProperties::getArmorModel (#8349) 2022-01-22 00:37:55 +01:00
Take Weiland 5f0d4abf23 Hide mod update notification while screen is still fading in (#8386) 2022-01-21 22:38:46 +01:00
LexManos 8e3e8b2120 Revert "Hooks to allow registering and managing custom DFU schemes and types. (#8242)" 2022-01-20 15:39:47 -08:00
Marc Hermans 72fd6808d8 Provide NPE protection against out of order init of the TYPES and REF (#8410) 2022-01-20 14:58:48 -08:00
Brennan Ward 2c35d04495 Add ShieldBlockEvent (#8261) 2022-01-20 13:43:22 -08:00
gigaherz f704d65d5a Add renderable API to allow easier rendering of OBJ and other custom models, from Entity and BlockEntity renderers. (#8259)
This is a redesign of a discarded section of my initial model system rewrite, back in 1.14.
In order to use it with the OBJ loader, you can use OBJLoader.INSTANCE.loadModel to get the OBJModel, and then call OBJModel#bakeRenderable() to get a SimpleRenderable object to render with.

The SimpleRenderable support animation, by providing different transformation matrices for each part in the MultipartTransforms.

Additionally, a BakedRenderable helper exists to turn an arbitrary BakedModel into a renderable.

After trying to get the B3D loader to work, I decided it wasn't worth the trouble and marked it for removal instead.
2022-01-20 13:30:39 -08:00
sciwhiz12 6c6a4817e7 Merge values of defaulted optional tags, Fixes issue where multiple mods declare the same optional tag. (#8250) 2022-01-20 12:26:54 -08:00
Girafi ef3408c1eb Added new 1.18 biomes to the BiomeDictionary (#8246) 2022-01-20 12:21:45 -08:00
Marc Hermans 0ea593c50e Hooks to allow registering and managing custom DFU schemes and types. (#8242) 2022-01-20 12:20:39 -08:00
Take Weiland 643b972e97 Ping data compression (#8169) 2022-01-20 11:51:40 -08:00
Joseph B 93ce9e72f7 Expand the LevelStem codec to allow dimension jsons to specify that the dimension's chunk generator should use the overworld/server's seed (#7955) 2022-01-20 11:46:08 -08:00
coehlrich f1bafce275 Add Client Commands (#7754) 2022-01-20 11:32:55 -08:00
SuperMartijn642 75408c1a70 Remove references to the now-broken BlockEntity#save(CompoundTag) method (#8235) 2022-01-19 19:27:34 +00:00
cpw 00fafb07ce update McModLauncher libraries to newer versions...
Signed-off-by: cpw <[email protected]>
2022-01-17 21:46:45 -05:00
cpw e49a347aea add extra keystore properties
Signed-off-by: cpw <[email protected]>
2022-01-16 18:29:05 -05:00
cpw 2c8ca313a0 TeamCity change in 'MinecraftForge / MinecraftForge' project: project parameters were changed 2022-01-16 23:26:56 +00:00
cpw fe7dcdf637 TeamCity change in 'MinecraftForge / MinecraftForge' project: project parameters were changed 2022-01-16 23:26:35 +00:00
cpw 15daa2955d TeamCity change in 'MinecraftForge / MinecraftForge' project: project parameters were changed 2022-01-16 23:05:42 +00:00
cpw 03af8a53a2 TeamCity change in 'MinecraftForge / MinecraftForge' project: project parameters were changed 2022-01-16 23:05:18 +00:00
cpw c7e4e4b5b4 TeamCity change in 'MinecraftForge / MinecraftForge' project: project parameters were changed 2022-01-16 23:03:39 +00:00
cpw d477425f70 TeamCity change in 'MinecraftForge / MinecraftForge' project: project parameters were changed 2022-01-16 23:02:55 +00:00
cpw a3449f2866 fix crowdin key
Signed-off-by: cpw <[email protected]>
2022-01-15 14:46:27 -05:00
cpw 2a1f98aec2 TeamCity change in 'MinecraftForge / MinecraftForge' project: project parameters were changed 2022-01-15 19:43:05 +00:00
cpw bc9bd40d03 TeamCity change in 'MinecraftForge / MinecraftForge' project: project parameters were changed 2022-01-15 19:42:19 +00:00
cpw 58344b0b15 TeamCity change in 'MinecraftForge / MinecraftForge' project: project parameters were changed 2022-01-15 19:42:08 +00:00
cpw edcc8b3c97 fix secondary branches builds
Signed-off-by: cpw <[email protected]>
2022-01-15 14:21:01 -05:00
OrionDevelopment d494ba9be4 TeamCity change in 'MinecraftForge / MinecraftForge' project: parameters of 'Build - Secondary Branches' build configuration were updated 2022-01-15 18:58:23 +00:00
OrionDevelopment b92f56503e TeamCity change in 'MinecraftForge / MinecraftForge' project: VCS roots of 'Build - Secondary Branches' build configuration were updated 2022-01-15 18:57:37 +00:00
OrionDevelopment 5a9be79785 TeamCity change in 'MinecraftForge / MinecraftForge' project: VCS roots of 'Build - Secondary Branches' build configuration were updated 2022-01-15 18:56:12 +00:00
OrionDevelopment 225c2125c6 TeamCity change in 'MinecraftForge / MinecraftForge' project: VCS roots of 'Build - Secondary Branches' build configuration were updated 2022-01-15 18:55:02 +00:00
OrionDevelopment e2a932108e TeamCity change in 'MinecraftForge / MinecraftForge' project: parameters of 'Build - Secondary Branches' build configuration were updated 2022-01-15 18:54:11 +00:00
OrionDevelopment ec38717702 TeamCity change in 'MinecraftForge / MinecraftForge' project: parameters of 'Build - Secondary Branches' build configuration were updated 2022-01-15 18:50:32 +00:00
OrionDevelopment 3009f5350c TeamCity change in 'MinecraftForge / MinecraftForge' project: VCS roots of 'Build - Secondary Branches' build configuration were updated 2022-01-15 18:48:59 +00:00
Marc Hermansandcpw a24dd3c8ee Remove primary branches from building on secondary branch configuration and publish crowdin data. (#8397)
* Remove the normalized branch names also from the filter.

* Add the additional publishing arguments to get the crowdin information.

* TeamCity change in 'MinecraftForge / MinecraftForge' project: project parameters were changed

* Fix the configuration.

* Remove the required patch and use the base script.

* Make a note about the reference.

Co-authored-by: cpw <[email protected]>
2022-01-15 12:45:09 -05:00
cpw 3fae26a470 TeamCity change in 'MinecraftForge / MinecraftForge' project: project parameters were changed 2022-01-15 17:20:24 +00:00
Marc Hermans a44ac01aee Correct the build configuration to support a setup. (#8395)
* Add a setup task and publish the correct versions.

* Reconfigure build task and disable the normal build and test cycle on everything but pull requests, run an assemble there.

* Fix the derp in the build configuration.
2022-01-15 11:44:42 -05:00
Marc Hermans b09f8d0fc8 Enable the TeamCity CI pipeline (#8368)
* Setup the build.gradle

* Setup the teamcity toolchain.

* Revert the usage of the local build of GU.

* Automatically add it now, it will always exist and is added to maven automatically by GU.

* Implement the branch filter and move the constant for the minimal changelog tag to a constant in the extension.

* Adding the JDK and Gradle version to the build script.
2022-01-15 10:39:09 -05:00
Take Weiland 57a916bf09 Fix and improve Ingredient invalidation (#8361) 2022-01-14 15:05:57 +00:00
Alex O'Neill 15d3df2818 Rework world persistence hooks to fix the double registry injection when loading single player worlds. (#8234) 2022-01-11 18:00:04 -08:00
SuperMartijn642 63a42bad98 Update tags for new 1.17 and 1.18 content (#7891) 2022-01-10 16:15:50 -08:00
Dennis C 28d3c491a0 Fix TerrainParticle rendering black under certain conditions (#8378) 2022-01-10 00:55:57 +00:00
cech12 551296813e Allow modded tools to work on glow lichen (#8371) 2022-01-09 21:23:03 +00:00
sciwhiz12 62b99be117 Fix custom climbable blocks not sending a death message (#8372)
Fixes #8370
2022-01-09 21:18:27 +00:00
Sara Freimer 6683e9e660 Provide access to the blockstate in BucketPickup#getPickupSound for multiply-logged blocks (#8357) 2022-01-08 21:20:09 +00:00
Sara Freimer 3b9df7df1b Fix clients being unable to deserialize tags for custom registries (#8352) 2022-01-08 20:47:28 +00:00
Bagel a9a8d7ed8c Fix particles going fullbright for a few frames when first spawning (#8291) 2022-01-08 20:28:22 +00:00
Take Weiland 80770898c6 Also create parent directories when creating config files (#8364) 2022-01-08 18:44:11 +00:00
JTK222 335cb5edc4 Fix crash with PermissionsAPI (#8330)
Fixes a crash in singleplayer, when the internal server didn't shut down correctly between world loads.
2022-01-02 18:43:07 +00:00
sciwhiz12 7259887176 Re-add missing default spawn lists in features (#8285)
Fixes #8265
Fixes #8301
2021-12-27 16:23:43 +00:00
JTK222 0320c185b5 Fixed incorrect generic in PermissionAPI (#8317) 2021-12-22 13:22:16 +00:00
JTK222andLexManos 2f5f696b68 Redo of the whole PermissionAPI (#7780)
Co-authored-by: LexManos <[email protected]>
2021-12-20 18:34:57 +00:00
JTK222 d33e9c8251 Fix misplaced patch in SpreadingSnowyDirtBlock.
Fixes #8308.
2021-12-19 18:28:24 +00:00
Sara Freimer 21c50da8ec Add RenderArmEvent to make overriding just the arm rendering not require copying nearly as much vanilla code (#8254) 2021-12-13 13:58:16 -08:00
Bagel e2a205d2e7 Add MobEffect tags (#8231) 2021-12-13 13:32:04 -08:00
Dennis C 950e7b032a Log missing or unsupported dependencies (#8218) 2021-12-13 11:48:43 -08:00
sciwhiz12 d1a55a147e Fix datagen test for sounds definitions provider (#8249) 2021-12-13 11:32:53 -08:00
Vincent Lee 1fd8b1a4b8 Fix wrong stage being declared in transition to common (#8267) 2021-12-13 11:14:02 -08:00
Curle 41ea5b195b Update to 1.18.1
Co-Authored by:
- Curle
_ Orion
2021-12-10 20:00:29 +01:00
Marc Hermans 14e152579b [CVE-2021-44228]: Update Log4J to fix the security issue inside it. (#8268) 2021-12-10 01:23:30 -08:00
Jared dcf7bb1af2 Fix KeyMappings only checking if they conflict with themselves. (#8256) 2021-12-08 00:09:25 +00:00
Dennis C 456a48b12a Fix ChunkWatchEvent not being fired (#8253) 2021-12-05 19:39:59 +00:00
Jonathan Coates aceb878a64 Call handleUpdateTag for BlockEntities again (#8237) 2021-12-04 01:30:13 +00:00
Joseph B f451e21f39 Fix test worldgen data (#8248) 2021-12-03 22:10:09 +00:00
LexManos c6ac740d31 Allow Forge Registries to return key information for overridden objects. Fixes #8230 2021-12-02 12:15:19 -08:00
Curle dbf98d3888 Save Chunk capabilities to the chunk, rather than recursively to the capabilities. 2021-12-02 19:16:47 +00:00
gigaherz 1b7bdc3ec6 Fix LevelChunk capability attach crash.
Fix client chunks not having capability providers attached.
Add capability attach tests.
2021-12-02 16:24:23 +01:00
gigaherz d414e31f08 Make HandshakeConsumer public again.
Fixes #8241
2021-12-02 15:15:20 +01:00
Curle b2036e9d23 Complete TODO in ShapedRecipe patch causing logspam related to minecraft:air 2021-12-02 00:43:25 +00:00
Curle abe4afe152 Add missing biomes back to the BiomeDictionary 2021-12-02 00:43:00 +00:00
Curle e7ad43c993 Readd Mixin 0.8.5 to fix modules issues. 2021-12-01 22:11:42 +00:00
Curle 7631600b53 Readd PoseStack field to RenderTooltipEvent. 2021-12-01 16:55:29 +00:00
Curle 530a1e8eb0 Fix custom loot serializers using wrong registry names 2021-12-01 01:21:21 +00:00
LexManos 54b2c18fcf Fix DungeonHooks not returning correct values. Fixes dungeons in world spawning pigs. 2021-11-30 17:14:56 -08:00
LexManos eb1a9b57c6 Fix dedicated server install. Closes #8226
Fix example mod
Fix obf issue with records. Closes #8228
Fix dependencies beingg out of sync from vanilla. Closes #8227
Disable mixin due to module incompatibility.
2021-11-30 16:22:58 -08:00
gigaherz 5b6d54555e Fix mod resources not loading.
Add BreakingItemParticle.java.patch which I forgot to commit during the porting.
2021-11-30 21:44:35 +01:00
2397 changed files with 65313 additions and 45507 deletions

No files matched your search

-16
View File
@@ -1,16 +0,0 @@
# Configuration for support-requests - https://github.com/dessant/support-requests
# Label used to mark issues as support requests
supportLabel: Forum
# Comment to post on issues marked as support requests. Add a link
# to a support page, or set to `false` to disable
supportComment: >
👋 We use the issue tracker exclusively for final bug reports and feature requests.
However, this issue appears to be better suited for the
[Forge Support Forums](http://www.minecraftforge.net/forum/forum/18-support-bug-reports/).
Please create a new topic on the support forum with this issue, and the conversation can
continue there.
# Whether to close issues marked as support requests
close: true
# Whether to lock issues marked as support requests
lock: true
+28
View File
@@ -0,0 +1,28 @@
name: Publish
on:
push:
branches: [ '1.19.2' ]
permissions:
contents: read
jobs:
build:
uses: MinecraftForge/SharedActions/.github/workflows/gradle.yml@main
with:
java: 17
gradle_setup: './gradlew setup'
gradle_tasks: 'build publish'
artifact_name: 'forge'
secrets:
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
PROMOTE_ARTIFACT_WEBHOOK: ${{ secrets.PROMOTE_ARTIFACT_WEBHOOK }}
PROMOTE_ARTIFACT_USERNAME: ${{ secrets.PROMOTE_ARTIFACT_USERNAME }}
PROMOTE_ARTIFACT_PASSWORD: ${{ secrets.PROMOTE_ARTIFACT_PASSWORD }}
MAVEN_USER: ${{ secrets.MAVEN_USER }}
MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }}
SIGN_KEY_ALIAS: ${{ secrets.SIGN_KEY_ALIAS }}
SIGN_KEY_PASSWORD: ${{ secrets.SIGN_KEY_PASSWORD }}
SIGN_KEYSTORE_PASSWORD: ${{ secrets.SIGN_KEYSTORE_PASSWORD }}
SIGN_KEYSTORE_DATA: ${{ secrets.SIGN_KEYSTORE_DATA }}
+42
View File
@@ -0,0 +1,42 @@
name: 'Spam label'
on:
issues:
types: [labeled]
pull_request:
types: [labeled]
discussion:
types: [labeled]
permissions:
contents: read
issues: write
pull-requests: write
discussions: write
jobs:
lock:
if: ${{ (github.event.label.name == 'spam') && (github.event.action == 'labeled') }}
runs-on: ubuntu-latest
steps:
- uses: peter-evans/close-issue@v2
name: Close Issue
with:
close-reason: 'not_planned'
if: ${{ github.event_name != 'pull_request' }}
- run: gh pr close ${{ github.event.pull_request.html_url }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
name: Close PR
if: ${{ github.event_name == 'pull_request' }}
- uses: maxkomarychev/[email protected]
name: Lock PR
if: ${{ github.event_name == 'pull_request' }}
with:
token: "${{ secrets.GITHUB_TOKEN }}"
issue_number: ${{ github.event.number }}
- uses: OSDKDev/[email protected]
with:
repo-token: "${{ secrets.GITHUB_TOKEN }}"
name: Lock issue
if: ${{ github.event_name != 'pull_request' }}
+27
View File
@@ -0,0 +1,27 @@
name: Support Requests
on:
issues:
types:
- labeled
- unlabeled
- reopened
permissions:
issues: write
jobs:
support:
runs-on: ubuntu-latest
steps:
- uses: dessant/support-requests@v2
with:
support-label: Forum
issue-comment: >
:wave: We use the issue tracker exclusively for final bug reports and feature requests.
However, this issue appears to be better suited for the
[Forge Support Forums](https://forums.minecraftforge.net/) or
[Forge Discord](https://discord.gg/UvedJ9m). Please create a new topic on the support forum
with this issue or ask in the `#tech-support` channel in the Discord server, and the
conversation can continue there.
lock-issue: true
+1
View File
@@ -33,6 +33,7 @@
/projects/**/*.launch
/repo/
src/generated/resources/.cache/
src/generated_test/resources/.cache/
#Patch rejects
/patches-/
Vendored
-125
View File
@@ -1,125 +0,0 @@
@Library('forge-shared-library')_
pipeline {
options {
disableConcurrentBuilds()
}
agent {
docker {
image 'gradle:7-jdk16'
//args '-v forgegc:/home/gradle/.gradle_cache/'
}
}
environment {
GRADLE_ARGS = '--no-daemon --console=plain' // No daemon for now as FG3 kinda derps. //'-Dorg.gradle.daemon.idletimeout=5000'
DISCORD_WEBHOOK = credentials('forge-discord-jenkins-webhook')
DISCORD_PREFIX = "Job: Forge Branch: ${BRANCH_NAME} Build: #${BUILD_NUMBER}"
JENKINS_HEAD = 'https://wiki.jenkins-ci.org/download/attachments/2916393/headshot.png'
}
stages {
stage('notify_start') {
when {
not {
changeRequest()
}
}
steps {
discordSend(
title: "${DISCORD_PREFIX} Started",
successful: true,
result: 'ABORTED', //White border
thumbnail: JENKINS_HEAD,
webhookURL: DISCORD_WEBHOOK
)
}
}
/*
stage('pull_cache') {
steps {
sh 'cp -r /home/gradle/.gradle_cache/jdks/ /home/gradle/.gradle/jdks/'
sh 'cp -r /home/gradle/.gradle_cache/wrapper/ /home/gradle/.gradle/wrapper/'
sh 'cp -r /home/gradle/.gradle_cache/caches/ /home/gradle/.gradle/caches/'
}
}
*/
stage('setup') {
steps {
withGradle {
sh './gradlew ${GRADLE_ARGS} --refresh-dependencies --continue setup'
}
script {
env.MYVERSION = sh(returnStdout: true, script: './gradlew :forge:properties -q | grep "^version:" | cut -d" " -f2').trim()
env.FMLONLY_VERSION = sh(returnStdout: true, script: './gradlew :fmlonly:properties -q | grep "^version:" | cut -d" " -f2').trim()
}
}
}
stage('changelog') {
when {
not {
changeRequest()
}
}
steps {
writeChangelog(currentBuild, 'build/changelog.txt')
}
}
stage('publish') {
when {
not {
changeRequest()
}
}
environment {
CROWDIN = credentials('forge-crowdin')
KEYSTORE = credentials('forge-jenkins-keystore-old')
KEYSTORE_KEYPASS = credentials('forge-jenkins-keystore-old-keypass')
KEYSTORE_STOREPASS = credentials('forge-jenkins-keystore-old-keypass')
}
steps {
withCredentials([usernamePassword(credentialsId: 'maven-forge-user', usernameVariable: 'MAVEN_USER', passwordVariable: 'MAVEN_PASSWORD')]) {
withGradle {
sh './gradlew ${GRADLE_ARGS} publish -PkeystoreKeyPass=${KEYSTORE_KEYPASS} -PkeystoreStorePass=${KEYSTORE_STOREPASS} -Pkeystore=${KEYSTORE} -PcrowdinKey=${CROWDIN}'
}
}
}
post {
success {
build job: 'filegenerator', parameters: [string(name: 'COMMAND', value: "promote net.minecraftforge:forge ${env.MYVERSION} latest")], propagate: false, wait: false
build job: 'filegenerator', parameters: [string(name: 'COMMAND', value: "promote net.minecraftforge:fmlonly ${env.FMLONLY_VERSION} latest")], propagate: false, wait: false
}
}
}
stage('test_publish_pr') { //Publish to local repo to test full process, but don't include credentials so it can't sign/publish to maven
when {
changeRequest()
}
environment {
CROWDIN = credentials('forge-crowdin')
}
steps {
withGradle {
sh './gradlew ${GRADLE_ARGS} publish -PcrowdinKey=${CROWDIN}'
}
}
}
}
post {
always {
script {
archiveArtifacts artifacts: 'projects/forge/build/libs/**/*.*', fingerprint: true, onlyIfSuccessful: true, allowEmptyArchive: true
if (env.CHANGE_ID == null) { // This is unset for non-PRs
discordSend(
title: "${DISCORD_PREFIX} Finished ${currentBuild.currentResult}",
description: '```\n' + getChanges(currentBuild) + '\n```',
successful: currentBuild.resultIsBetterOrEqualTo("SUCCESS"),
result: currentBuild.currentResult,
thumbnail: JENKINS_HEAD,
webhookURL: DISCORD_WEBHOOK
)
}
}
}
}
}
+2 -16
View File
@@ -1,16 +1,2 @@
Minecraft Forge
Copyright (c) 2016-${year}.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation version 2.1
of the License.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Copyright (c) Forge Development LLC and contributors
SPDX-License-Identifier: LGPL-2.1-only
+506 -149
View File
File diff suppressed because it is too large. Load diff
+5 -3
View File
@@ -2,8 +2,10 @@ repositories {
maven { url = 'https://maven.minecraftforge.net/' }
mavenCentral()
}
dependencies {
implementation 'org.ow2.asm:asm:9.1'
implementation 'org.ow2.asm:asm-tree:9.1'
implementation 'net.minecraftforge:srgutils:0.4.+'
implementation 'org.ow2.asm:asm:9.5'
implementation 'org.ow2.asm:asm-tree:9.5'
implementation 'net.minecraftforge:srgutils:0.5.+'
implementation 'commons-io:commons-io:2.12.0'
}
@@ -4,7 +4,7 @@ import groovy.json.JsonBuilder
import org.gradle.api.DefaultTask
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.tasks.InputFile
import org.gradle.api.tasks.OutputFile
import org.gradle.api.tasks.Internal
import org.gradle.api.tasks.TaskAction
import org.objectweb.asm.ClassReader
import org.objectweb.asm.Opcodes
@@ -17,7 +17,9 @@ import java.util.zip.ZipInputStream
abstract class BytecodeFinder extends DefaultTask {
@InputFile abstract RegularFileProperty getJar()
@OutputFile abstract RegularFileProperty getOutput()
// It should be fine to mark the output as internal as we want to control when we run it anyways.
// This also shuts Gradle 8 up about implicit task dependencies.
@Internal abstract RegularFileProperty getOutput()
BytecodeFinder() {
output.convention(project.layout.buildDirectory.dir(name).map { it.file("output.json") })
@@ -28,36 +28,80 @@ abstract class CheckSAS extends DefaultTask {
}
def comment = idx == -1 ? null : line.substring(idx)
if (idx != -1) line = line.substring(0, idx - 1)
def (cls, desc) = (line.trim() + ' ').split(' ', -1)
def (cls, name, desc) = (line.trim().replace('(', ' (') + ' ').split(' ', -1)
cls = cls.replaceAll('\\.', '/')
desc = desc.replace('(', ' (')
if (json[cls] == null || (!desc.isEmpty() && (json[cls]['methods'] == null || json[cls]['methods'][desc] == null))) {
if (json[cls] == null) {
println('Invalid: ' + line)
return
}
//Class SAS
if (desc.isEmpty()) {
lines.add(cls + (comment == null ? '' : ' ' + comment))
if (json[cls]['methods'] != null)
(json[cls]['methods'] as TreeMap).each {
findChildMethods(json, cls, it.key).each { lines.add('\t' + it) }
} else if (name.isEmpty()) { //Class SAS
def toAdd = []
def clsSided = isSided(json[cls])
def sided = clsSided
/* TODO: MergeTool doesn't do fields
if (json[cls]['fields'] != null) {
for (entry in json[cls]['fields']) {
if (isSided(entry.value)) {
sided = true
toAdd.add('\t' + cls + ' ' + entry.key)
}
}
return
}
//Method SAS
lines.add(cls + ' ' + desc.replace(' ', '') + (comment == null ? '' : ' ' + comment))
findChildMethods(json, cls, desc).each { lines.add('\t' + it) }
}
*/
if (json[cls]['methods'] != null) {
for (entry in json[cls]['methods']) {
if (isSided(entry.value)) {
sided = true
toAdd.add('\t' + cls + ' ' + entry.key.replaceAll(' ', ''))
findChildMethods(json, cls, entry.key).each { lines.add('\t' + it) }
findChildMethods(json, cls, entry.key).each { println(line + ' -- ' + it) }
} else if (clsSided) {
findChildMethods(json, cls, entry.key).each { lines.add('\t' + it) }
findChildMethods(json, cls, entry.key).each { println(line + ' -- ' + it) }
}
}
}
if (sided) {
lines.add(cls + (comment == null ? '' : ' ' + comment))
lines.addAll(toAdd.sort())
} else
println('Invalid: ' + line)
} else if (desc.isEmpty()) { // Fields
/* TODO: MergeTool doesn't do fields
if (json[cls]['fields'] != null && isSided(json[cls]['fields'][name]))
lines.add(cls + ' ' + name + (comment == null ? '' : ' ' + comment))
else
*/
println('Invalid: ' + line)
} else { // Methods
if (json[cls]['methods'] == null || !isSided(json[cls]['methods'][name + ' ' + desc]))
println('Invalid: ' + line)
else {
lines.add(cls + ' ' + name + desc + (comment == null ? '' : ' ' + comment))
findChildMethods(json, cls, name + ' ' + desc).each { println(line + ' -- ' + it) }
findChildMethods(json, cls, name + ' ' + desc).each { lines.add('\t' + it) }
}
}
}
f.text = lines.join('\n')
}
}
protected static isSided(json) {
if (json == null || json['annotations'] == null)
return false
for (ann in json['annotations']) {
if ('Lnet/minecraftforge/api/distmarker/OnlyIn;'.equals(ann.desc))
return true
}
return false
}
protected static findChildMethods(json, cls, desc)
{
return json.values().findAll{ it.methods != null && it.methods[desc] != null && it.methods[desc].override == cls}
return json.values().findAll{ it.methods != null && it.methods[desc] != null && it.methods[desc].override == cls && isSided(it.methods[desc]) }
.collect { it.name + ' ' + desc.replace(' ', '') } as TreeSet
}
}
@@ -0,0 +1,44 @@
package net.minecraftforge.forge.tasks
import org.apache.commons.io.IOUtils
import org.gradle.api.DefaultTask
import org.gradle.api.file.ConfigurableFileCollection
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.tasks.InputFiles
import org.gradle.api.tasks.OutputFile
import org.gradle.api.tasks.TaskAction
import java.util.zip.ZipEntry
import java.util.zip.ZipInputStream
import java.util.zip.ZipOutputStream
abstract class MergeJars extends DefaultTask {
MergeJars() {
output.convention(project.layout.buildDirectory.dir(name).map { it.file('output.jar') })
}
@TaskAction
void run() {
def jars = inputJars.files
try (ZipOutputStream zout = new ZipOutputStream(new FileOutputStream(output.get().asFile))) {
for (def jar : jars) {
try (ZipInputStream zin = new ZipInputStream(new FileInputStream(jar))) {
def entry
while ((entry = zin.getNextEntry()) != null) {
ZipEntry _new = new ZipEntry(entry.getName())
_new.setTime(0) //SHOULD be the same time as the main entry, but NOOOO _new.setTime(entry.getTime()) throws DateTimeException, so you get 0, screw you!
zout.putNextEntry(_new)
IOUtils.copy(zin, zout)
}
}
}
}
}
@InputFiles
abstract ConfigurableFileCollection getInputJars()
@OutputFile
abstract RegularFileProperty getOutput()
}
@@ -0,0 +1,57 @@
package net.minecraftforge.forge.tasks
import org.gradle.api.DefaultTask
import org.gradle.api.artifacts.Dependency
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.provider.Property
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.Optional
import org.gradle.api.tasks.OutputFile
import org.gradle.api.tasks.TaskAction
import java.nio.file.Files
import java.nio.file.StandardCopyOption
abstract class SetupCheckJarCompatibility extends DefaultTask {
SetupCheckJarCompatibility() {
group = 'jar compatibility'
onlyIf {
inputVersion.getOrNull() != null
}
outputs.upToDateWhen { false } // Never up to date, because this setup task should always run
baseBinPatchesOutput.convention(project.layout.buildDirectory.dir(name).map { it.file('joined.lzma') })
}
@TaskAction
void run() {
def inputVersion = inputVersion.get()
def fmlLibs = project.configurations.detachedConfiguration(project.PACKED_DEPS.collect {
def artifactId = it.split(':')[1]
return project.dependencies.create("net.minecraftforge:${artifactId}:${inputVersion}")
}.toArray(Dependency[]::new))
project.tasks.named('checkJarCompatibility') {
baseLibraries.from(project.provider {
fmlLibs.resolvedConfiguration.lenientConfiguration.files
})
}
def baseForgeUserdev = project.layout.buildDirectory.dir(name).map { it.file("forge-${inputVersion}-userdev.jar") }.get().asFile
project.rootProject.extensions.download.run {
src "https://maven.minecraftforge.net/net/minecraftforge/forge/${inputVersion}/forge-${inputVersion}-userdev.jar"
dest baseForgeUserdev
}
def joinedLzma = project.zipTree(baseForgeUserdev).matching { it.include('joined.lzma') }.singleFile
Files.copy(joinedLzma.toPath(), baseBinPatchesOutput.get().asFile.toPath(), StandardCopyOption.REPLACE_EXISTING)
}
@Input
@Optional
abstract Property<String> getInputVersion()
@OutputFile
abstract RegularFileProperty getBaseBinPatchesOutput()
}
@@ -1,5 +1,6 @@
package net.minecraftforge.forge.tasks
import groovy.json.JsonBuilder
import groovy.json.JsonSlurper
import java.io.File
@@ -16,15 +17,18 @@ public class Util {
}
return md.digest().collect {String.format "%02x", it}.join()
}
File.metaClass.getSha1 = { !delegate.exists() ? null : delegate.sha1() }
File.metaClass.json = { -> new JsonSlurper().parseText(delegate.text) }
File.metaClass.getJson = { return delegate.exists() ? new JsonSlurper().parse(delegate) : [:] }
File.metaClass.setJson = { json -> delegate.text = new JsonBuilder(json).toPrettyString() }
Date.metaClass.iso8601 = { ->
def format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
def result = format.format(delegate)
return result[0..21] + ':' + result[22..-1]
}
String.metaClass.rsplit = { String del, int limit = -1 ->
def lst = new ArrayList()
def x = 0, idx
@@ -37,7 +41,7 @@ public class Util {
return lst
}
}
public static String[] getClasspath(project, libs, artifact) {
def ret = []
artifactTree(project, artifact).each { key, lib ->
@@ -47,7 +51,7 @@ public class Util {
}
return ret
}
public static def getArtifacts(project, config, classifiers) {
def ret = [:]
config.resolvedConfiguration.resolvedArtifacts.each {
@@ -70,14 +74,6 @@ public class Util {
if (!checkExists(url)) {
url = "https://maven.minecraftforge.net/${path}"
}
//TODO remove when Mojang launcher is updated
if (!classifiers && art.classifier != null) {
//Mojang launcher doesn't currently support classifiers, so... move it to part of the version, and force the extension to 'jar'
// However, keep the path normal so that our mirror system works.
art.version = "${art.version}-${art.classifier}"
art.classifier = null
art.extension = 'jar'
}
ret[key] = [
name: "${art.group}:${art.name}:${art.version}" + (art.classifier == null ? '' : ":${art.classifier}") + (art.extension == 'jar' ? '' : "@${art.extension}"),
downloads: [
@@ -92,14 +88,14 @@ public class Util {
}
return ret
}
public static def getMavenPath(task) {
public static def getMavenPath(task) {
def classifier = task.archiveClassifier.get()
def dep = "${task.project.group}:${task.project.name}:${task.project.version}" + (classifier == '' ? '' : ':' + classifier)
return "${task.project.group.replace('.', '/')}/${task.project.name}/${task.project.version}/${task.project.name}-${task.project.version}".toString() + (classifier == '' ? '' : '-' + classifier) + '.jar'
}
public static def getMavenDep(task) {
public static def getMavenDep(task) {
def classifier = task.archiveClassifier.get()
return "${task.project.group}:${task.project.name}:${task.project.version}" + (classifier == '' ? '' : ':' + classifier)
}
@@ -123,7 +119,7 @@ public class Util {
def files = cfg.resolve()
return getArtifacts(project, cfg, true)
}
private static boolean checkExists(url) {
try {
def code = new URL(url).openConnection().with {
@@ -138,4 +134,9 @@ public class Util {
throw e
}
}
public static String getLatestForgeVersion(mcVersion) {
def json = new JsonSlurper().parseText(new URL("https://files.minecraftforge.net/net/minecraftforge/forge/promotions_slim.json").getText("UTF-8"))
return json.promos["$mcVersion-latest"]
}
}
+3 -3
View File
@@ -1,11 +1,11 @@
Contributing to Forge
=====================
1) Keep patches to Minecraft classes minimal. If you need a lot of things done, you may either add to relevant forge classes or make a new class.
1) Keep patches to Minecraft classes together. If you need a lot of things done, you may either add to relevant forge classes or make a new class. Try not to spread out your patches across multiple disjoint lines, as this makes maintenance of your patches difficult.
2) An example mod must be provided for all PRs adding events/hooks to Forge. Whether it's a full mod using your proposed hooks, or just a pastebin containing a simple example, an example mod is required. Please also explain in detail what your new hook does.
2) TODO: Test Mods
3) Follow Forge coding guidelines (braces on newlines, spaces instead of tabs, etc)
3) Follow the code style of the class you're working in (braces on newlines & spaces instead of tabs in Forge classes, inline brackets in patches, etc).
For more information, refer to [the wiki](https://github.com/MinecraftForge/MinecraftForge/wiki/If-you-want-to-contribute-to-Forge)
-9
View File
@@ -1,9 +0,0 @@
# On the Contribution of an RF-lite Energy System: "Energy"
Forge has acquired an Energy system, after many years of debate on the topic. The prevalence of the RF API has warranted the inclusion of a similar (but simpler) implementation to forge for 1.10.2 and onwards.
Those who wish to use an RF like API, feel free to use it. If you don't want to think about Energy, but know you need it, you can use it *if you wish*. If you want to interoperate with other energy systems, feel free to use this to broker with them.
# On Diversity in Energy Systems
Forge has always supported diversity in energy-like systems. If you have a burning desire to simulate electricity flow in all it's glory, we fully support you and look forward to playing your mod. If you wish to have pneumatic power, we have no objections, and would love to see your wonderful creations. If you have a power system of your own devising that is simply beyond our imagination, please, blow us away.
# On Modder Obligations
As a modder, you are under *no* obligation to use or support the forge Energy system. If anyone, user, mod-pack maker or even us, tells you otherwise, refer them to this statement. The Forge energy system is not intended to supplant diversity in energy systems. It is not intended to be one-size-fits-all. The choice to support it, is the choice of the modder.
-127
View File
@@ -1,127 +0,0 @@
# FML
Entrypoint : ```FMLServiceProvider.onLoad```
- Verify environment
-- Check all libraries are present: ```accesstransformer```, ```coremod```, ```deobfuscator```
-- Check versions are suitable: ```modlauncher```, ```accesstransformer```, ```coremod```, ```deobfuscator```
- Find deobfuscated and patched MC
-- If not found, trigger job to generate that (loaded later at FMLLaunchProvider.launch)
Injected arguments:
- ```mods``` : CSV list of mod files to load
- ```modlist``` : JSON formatted list of mod files in a maven-like repository format
Entrypoint : ```FMLServiceProvider.initializer```
- Setup paths
-- ```mods``` folder
-- ```config``` folder
- FML config file read (JSON?)
- Trigger initial loading
Entrypoint : ```FMLLaunchProvider.launch```
- Launches the patched and deobfuscated game
- - If that wasn't found it'll be generated from the vanilla jar and patch/deobf files (see above)
- Possible we'll use an alternative launch for the development environment
(A goal is that we pre-generate this JAR during forge installation or modpack installation)
## Loading
- First we discover all mods
- - IModLocator instances present in system are found and queried to compile a master list of all mod artifacts of the three types
- LANGPROVIDERs are added to the supported language system : IModLanguageProvider
- The MODS from the list have their META-INF/mods.json file queried for mod instances to load
- - MODS are cross-referenced for their language being available
- - MODS are cross-referenced for their libraries being available
- - MODS are cross-referenced for their MOD dependencies being available
- - MODS with META-INF/coremods.json specification are loaded into the COREMOD system
- - MODS with META-INF/accesstransformer.json are loaded into the ACCESSTRANSFORMER system
- - MODS are enqueued to the background loading system
- FMLLaunchProvider will be triggered from the ModLauncher to start the game
## Game loading
- Events triggered from loadGame will launch various phases of modloading as before
-- Deprecation of old "FML" events in favour of Forge events
-- If a mod hasn't completed scanning there might be a pause waiting for it to complete before loading (testing indicates this should be a very rare occurrence and isn't worse than existing status quo where all scanning and loading is on-thread)
### ```IModLocator```
Finds mods from various sources of various types
manifest is queried for type: FMLModType
- MOD : this file will be scanned as a mod. This is default if nothing is present
- LIBRARY : this file will be added to the classpath and no further processing is done
- LANGPROVIDER : this file will be loaded as a language provider
#### ```ModsFolderLocator```
- scans for jar files from mods folder
-- able to load all types
-- loads in all environments
-- maybe able to do runtime name transformation for dev time?
Standard mechanism to find and load mods
#### ```ExplodedDirectoryLocator```
- loads a directory as a mod
-- only able to load mods
-- should only load in dev env
Intended as a mechanism to allow development of mods easily by pointing at a compiled output directory
#### ```ArgumentModsLocator``` : NYI
- loads mods from the arguments on the command line
-- able to load all types
-- loads in all environments
### ```IModLanguageProvider```
Provides mod and language provider services
- Provides a means to transform a Mod File (from the IModLocator) into a list of modcontainer objects based on mods.json
- Scanning work will be done in background threads
- Language providers can be provided as JARs via the modlocator for ease of distribution
#### ```FMLModLanguageProvider```
This is the standard Java @Mod implementation provider
- provided by default (always supported)
- All scanning for @Mod will be done in the background thread
#### ```ScalaModLanguageProvider```
This is the scala language provider. It'll be provided separately as a JAR mod download.
- API contract will need definition
Other languages? Kotlin? Alternative Scala versions? Javascript?
## Coremods
Coremods are now forcefully separated into _injection_ and _runtime_ phases.
### Injection
Injection is the act of intercepting the loading of a class and modifying the inbound class with alterations such as additions, replacements and deletions
Injections will be written using Javascript. Two functions are required: a function providing the list of injection sites, and the function to transform the injection site.
All injection sites will need to be pre-specified by the coremod in their metadata. Lookup services should be provided in the Javascript API.
Javascript API for common coremod injection tasks needs to be developed, to allow common best-practice tooling for these complex tasks.
Runtime coremod code (code that has been injected) is Java as usual.
## Background loading thread
Early in loading, a background thread is triggered which will perform scanning tasks for common resources, such as @Mod instances and other annotations. This thread will also be responsible for loading any cached resources, either those defined at build time or pre-computed from previous runs. It may also be tasked with writing those precomputed resources.
There will be a IPreLoaderJobProvider that will allow extension of the scope of these tasks
+47 -23
View File
@@ -2,25 +2,21 @@
MinecraftForge
=============
[![Stable Release](https://img.shields.io/badge/dynamic/json?url=https://files.minecraftforge.net/net/minecraftforge/forge/promotions_slim.json&label=Stable&prefix=1.17.1-&query=$.promos["1.17.1-recommended"]&color=brightgreen&logo=data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyBjbGFzcz0ic3ZnLWlubGluZS0tZmEgZmEtc3RhciBmYS13LTE4IiBhcmlhLWhpZGRlbj0idHJ1ZSIgZGF0YS1pY29uPSJzdGFyIiBkYXRhLXByZWZpeD0iZmFzIiBmb2N1c2FibGU9ImZhbHNlIiByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCA1NzYgNTEyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgo8cGF0aCBkPSJNMjU5LjMgMTcuOEwxOTQgMTUwLjIgNDcuOSAxNzEuNWMtMjYuMiAzLjgtMzYuNyAzNi4xLTE3LjcgNTQuNmwxMDUuNyAxMDMtMjUgMTQ1LjVjLTQuNSAyNi4zIDIzLjIgNDYgNDYuNCAzMy43TDI4OCA0MzkuNmwxMzAuNyA2OC43YzIzLjIgMTIuMiA1MC45LTcuNCA0Ni40LTMzLjdsLTI1LTE0NS41IDEwNS43LTEwM2MxOS0xOC41IDguNS01MC44LTE3LjctNTQuNkwzODIgMTUwLjIgMzE2LjcgMTcuOGMtMTEuNy0yMy42LTQ1LjYtMjMuOS01Ny40IDB6IiBmaWxsPSJ3aGl0ZSIvPgo8L3N2Zz4K)](https://files.minecraftforge.net)
[![Latest Release](https://img.shields.io/badge/dynamic/json?url=https://files.minecraftforge.net/net/minecraftforge/forge/promotions_slim.json&label=Latest&prefix=1.17.1-&query=$.promos["1.17.1-latest"]&color=blue&logo=data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyBjbGFzcz0ic3ZnLWlubGluZS0tZmEgZmEtYnVnIGZhLXctMTYiIGFyaWEtaGlkZGVuPSJ0cnVlIiBkYXRhLWljb249ImJ1ZyIgZGF0YS1wcmVmaXg9ImZhcyIgZm9jdXNhYmxlPSJmYWxzZSIgcm9sZT0iaW1nIiB2aWV3Qm94PSIwIDAgNTEyIDUxMiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTUxMS45ODggMjg4LjljLS40NzggMTcuNDMtMTUuMjE3IDMxLjEtMzIuNjUzIDMxLjFINDI0djE2YzAgMjEuODY0LTQuODgyIDQyLjU4NC0xMy42IDYxLjE0NWw2MC4yMjggNjAuMjI4YzEyLjQ5NiAxMi40OTcgMTIuNDk2IDMyLjc1OCAwIDQ1LjI1NS0xMi40OTggMTIuNDk3LTMyLjc1OSAxMi40OTYtNDUuMjU2IDBsLTU0LjczNi01NC43MzZDMzQ1Ljg4NiA0NjcuOTY1IDMxNC4zNTEgNDgwIDI4MCA0ODBWMjM2YzAtNi42MjctNS4zNzMtMTItMTItMTJoLTI0Yy02LjYyNyAwLTEyIDUuMzczLTEyIDEydjI0NGMtMzQuMzUxIDAtNjUuODg2LTEyLjAzNS05MC42MzYtMzIuMTA4bC01NC43MzYgNTQuNzM2Yy0xMi40OTggMTIuNDk3LTMyLjc1OSAxMi40OTYtNDUuMjU2IDAtMTIuNDk2LTEyLjQ5Ny0xMi40OTYtMzIuNzU4IDAtNDUuMjU1bDYwLjIyOC02MC4yMjhDOTIuODgyIDM3OC41ODQgODggMzU3Ljg2NCA4OCAzMzZ2LTE2SDMyLjY2NkMxNS4yMyAzMjAgLjQ5MSAzMDYuMzMuMDEzIDI4OC45LS40ODQgMjcwLjgxNiAxNC4wMjggMjU2IDMyIDI1Nmg1NnYtNTguNzQ1bC00Ni42MjgtNDYuNjI4Yy0xMi40OTYtMTIuNDk3LTEyLjQ5Ni0zMi43NTggMC00NS4yNTUgMTIuNDk4LTEyLjQ5NyAzMi43NTgtMTIuNDk3IDQ1LjI1NiAwTDE0MS4yNTUgMTYwaDIyOS40ODlsNTQuNjI3LTU0LjYyN2MxMi40OTgtMTIuNDk3IDMyLjc1OC0xMi40OTcgNDUuMjU2IDAgMTIuNDk2IDEyLjQ5NyAxMi40OTYgMzIuNzU4IDAgNDUuMjU1TDQyNCAxOTcuMjU1VjI1Nmg1NmMxNy45NzIgMCAzMi40ODQgMTQuODE2IDMxLjk4OCAzMi45ek0yNTcgMGMtNjEuODU2IDAtMTEyIDUwLjE0NC0xMTIgMTEyaDIyNEMzNjkgNTAuMTQ0IDMxOC44NTYgMCAyNTcgMHoiIGZpbGw9IndoaXRlIi8+Cjwvc3ZnPgo=
)](https://files.minecraftforge.net) [![Discord](https://img.shields.io/discord/313125603924639766.svg?color=%237289da&label=Discord&logo=discord&logoColor=%237289da)](https://discord.gg/UvedJ9m) [![Support](https://img.shields.io/badge/Patreon-Support-orange.svg?logo=Patreon)](https://www.patreon.com/LexManos)
[![Stable Release](https://img.shields.io/badge/dynamic/json?url=https://files.minecraftforge.net/net/minecraftforge/forge/promotions_slim.json&label=Stable&prefix=1.19.2-&query=$.promos["1.19.2-recommended"]&color=brightgreen&logo=data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyBjbGFzcz0ic3ZnLWlubGluZS0tZmEgZmEtc3RhciBmYS13LTE4IiBhcmlhLWhpZGRlbj0idHJ1ZSIgZGF0YS1pY29uPSJzdGFyIiBkYXRhLXByZWZpeD0iZmFzIiBmb2N1c2FibGU9ImZhbHNlIiByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCA1NzYgNTEyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgo8cGF0aCBkPSJNMjU5LjMgMTcuOEwxOTQgMTUwLjIgNDcuOSAxNzEuNWMtMjYuMiAzLjgtMzYuNyAzNi4xLTE3LjcgNTQuNmwxMDUuNyAxMDMtMjUgMTQ1LjVjLTQuNSAyNi4zIDIzLjIgNDYgNDYuNCAzMy43TDI4OCA0MzkuNmwxMzAuNyA2OC43YzIzLjIgMTIuMiA1MC45LTcuNCA0Ni40LTMzLjdsLTI1LTE0NS41IDEwNS43LTEwM2MxOS0xOC41IDguNS01MC44LTE3LjctNTQuNkwzODIgMTUwLjIgMzE2LjcgMTcuOGMtMTEuNy0yMy42LTQ1LjYtMjMuOS01Ny40IDB6IiBmaWxsPSJ3aGl0ZSIvPgo8L3N2Zz4K)](https://files.minecraftforge.net)
[![Latest Release](https://img.shields.io/badge/dynamic/json?url=https://files.minecraftforge.net/net/minecraftforge/forge/promotions_slim.json&label=Latest&prefix=1.19.2-&query=$.promos["1.19.2-latest"]&color=blue&logo=data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyBjbGFzcz0ic3ZnLWlubGluZS0tZmEgZmEtYnVnIGZhLXctMTYiIGFyaWEtaGlkZGVuPSJ0cnVlIiBkYXRhLWljb249ImJ1ZyIgZGF0YS1wcmVmaXg9ImZhcyIgZm9jdXNhYmxlPSJmYWxzZSIgcm9sZT0iaW1nIiB2aWV3Qm94PSIwIDAgNTEyIDUxMiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTUxMS45ODggMjg4LjljLS40NzggMTcuNDMtMTUuMjE3IDMxLjEtMzIuNjUzIDMxLjFINDI0djE2YzAgMjEuODY0LTQuODgyIDQyLjU4NC0xMy42IDYxLjE0NWw2MC4yMjggNjAuMjI4YzEyLjQ5NiAxMi40OTcgMTIuNDk2IDMyLjc1OCAwIDQ1LjI1NS0xMi40OTggMTIuNDk3LTMyLjc1OSAxMi40OTYtNDUuMjU2IDBsLTU0LjczNi01NC43MzZDMzQ1Ljg4NiA0NjcuOTY1IDMxNC4zNTEgNDgwIDI4MCA0ODBWMjM2YzAtNi42MjctNS4zNzMtMTItMTItMTJoLTI0Yy02LjYyNyAwLTEyIDUuMzczLTEyIDEydjI0NGMtMzQuMzUxIDAtNjUuODg2LTEyLjAzNS05MC42MzYtMzIuMTA4bC01NC43MzYgNTQuNzM2Yy0xMi40OTggMTIuNDk3LTMyLjc1OSAxMi40OTYtNDUuMjU2IDAtMTIuNDk2LTEyLjQ5Ny0xMi40OTYtMzIuNzU4IDAtNDUuMjU1bDYwLjIyOC02MC4yMjhDOTIuODgyIDM3OC41ODQgODggMzU3Ljg2NCA4OCAzMzZ2LTE2SDMyLjY2NkMxNS4yMyAzMjAgLjQ5MSAzMDYuMzMuMDEzIDI4OC45LS40ODQgMjcwLjgxNiAxNC4wMjggMjU2IDMyIDI1Nmg1NnYtNTguNzQ1bC00Ni42MjgtNDYuNjI4Yy0xMi40OTYtMTIuNDk3LTEyLjQ5Ni0zMi43NTggMC00NS4yNTUgMTIuNDk4LTEyLjQ5NyAzMi43NTgtMTIuNDk3IDQ1LjI1NiAwTDE0MS4yNTUgMTYwaDIyOS40ODlsNTQuNjI3LTU0LjYyN2MxMi40OTgtMTIuNDk3IDMyLjc1OC0xMi40OTcgNDUuMjU2IDAgMTIuNDk2IDEyLjQ5NyAxMi40OTYgMzIuNzU4IDAgNDUuMjU1TDQyNCAxOTcuMjU1VjI1Nmg1NmMxNy45NzIgMCAzMi40ODQgMTQuODE2IDMxLjk4OCAzMi45ek0yNTcgMGMtNjEuODU2IDAtMTEyIDUwLjE0NC0xMTIgMTEyaDIyNEMzNjkgNTAuMTQ0IDMxOC44NTYgMCAyNTcgMHoiIGZpbGw9IndoaXRlIi8+Cjwvc3ZnPgo=
)](https://files.minecraftforge.net) [![Discord](https://img.shields.io/discord/313125603924639766.svg?color=%237289da&label=Discord&logo=discord&logoColor=%237289da)][Discord] [![Support](https://img.shields.io/badge/Patreon-Support-orange.svg?logo=Patreon)](https://www.patreon.com/LexManos)
Forge is a free, open-source modding API all of your favourite mods use!
| Version | Support |
| ------------- | ------------- |
| 1.17.x | Active |
| 1.16.x | LTS |
| Version | Support |
|--------------|-----------------------------|
| All versions | [Supported][Support-Policy] |
* [Download]
* [Forum]
* [Discord]
* [Documentation]
#### Notes:
- Introduced in 1.13 was a new FML, information found [here](NewFML.md).
# Installing Forge
Go to [the Forge website](https://files.minecraftforge.net)
@@ -32,37 +28,65 @@ You can download the installer for the *Recommended Build* or the
into your vanilla launcher environment, where you can then create a new
profile using that version and play the game!
For support and questions, visit [the Support Forum](https://www.minecraftforge.net/forum/forum/18-support-bug-reports/).
For support and questions, visit [the Support Forum][Support-Forum] or [the Forge Discord server][Discord].
[Here is a short video from Rorax showing how to install and setup Forge.](https://www.youtube.com/watch?v=lB3ArN_-3Oc)
## Required Java Versions
We require the version of Java that Minecraft requires, which is currently:
| Minecraft | Java |
|---------------|-------------------|
| 1.20.6+ | [21][Adoptium-21] |
| 1.18 - 1.20.4 | [17][Adoptium-17] |
| 1.17.1 | [16][Adoptium-16] |
| 1.16.5- | [8][Adoptium-8] |
**If you are on Windows and have difficulty using Java to launch JAR files, consider using [Jarfix by Johann Löfflmann][Jarfix].**
# Creating Mods
[See the "Getting Started" section in the Forge Documentation](https://mcforge.readthedocs.io/en/latest/gettingstarted/).
[See the "Getting Started" section in the Forge Documentation](https://docs.minecraftforge.net/en/1.19.2/gettingstarted/).
# Contribute to Forge
If you wish to actually inspect Forge, submit PRs or otherwise work
with Forge itself, you're in the right place!
[See the guide to setting up a Forge workspace](http://mcforge.readthedocs.io/en/latest/forgedev/).
[See the guide to setting up a Forge workspace](https://docs.minecraftforge.net/en/1.19.2/forgedev/).
### Pull requests
[See the "Making Changes and Pull Requests" section in the Forge documentation](https://mcforge.readthedocs.io/en/latest/forgedev/#making-changes-and-pull-requests).
[See the "Making Changes and Pull Requests" section in the Forge documentation](https://docs.minecraftforge.net/en/1.19.2/forgedev/#making-changes-and-pull-requests).
Please read the contributing guidelines found [here](CONTRIBUTING.md) before making a pull request.
### Contributor License Agreement
We require all contributors to acknowledge the [Forge Contributor
License Agreement](https://cla-assistant.io/MinecraftForge/MinecraftForge). Please ensure you have a valid email address
associated with your GitHub account to do this. If you have previously
We require all contributors to acknowledge the [Forge Contributor License Agreement](https://cla-assistant.io/MinecraftForge/MinecraftForge).
Please ensure you have a valid email address associated with your GitHub account to do this. If you have previously
signed it, you should be OK.
#### Donate
*Forge is a large project with many collaborators working on it around the clock. Forge is and will always remain free to use and modify. However, it costs money to run such a large project as this, so please consider [becoming a patron](https://www.patreon.com/LexManos).*
*Forge is a large project with many collaborators working on it around the clock. Forge is and will always remain free
to use and modify. However, it costs money to run such a large project as this, so please consider
[becoming a patron](https://www.patreon.com/LexManos).*
[Download]: https://files.minecraftforge.net/
[Forum]: https://www.minecraftforge.net/forum/
[Discord]: https://discord.gg/UvedJ9m
[Documentation]: https://mcforge.readthedocs.io
[Adoptium-21]: https://adoptium.net/temurin/releases/?version=21
[Adoptium-17]: https://adoptium.net/temurin/releases/?version=17
[Adoptium-16]: https://adoptium.net/temurin/releases/?version=16
[Adoptium-8]: https://adoptium.net/temurin/releases/?version=8
[Jarfix]: https://johann.loefflmann.net/en/software/jarfix/index.html
[Forum]: https://forums.minecraftforge.net/
[Support-Forum]: https://forums.minecraftforge.net/forum/18-support-bug-reports/
[Support-Policy]: https://forums.minecraftforge.net/topic/144690-new-tiered-support-policy
[Discord]: https://discord.minecraftforge.net/
[Documentation]: https://docs.minecraftforge.net/en/1.19.2/
[Getting-Started]: https://docs.minecraftforge.net/en/1.19.2/gettingstarted/
[ForgeDev]: https://docs.minecraftforge.net/en/1.19.2/forgedev/
[Pull-Requests]: https://docs.minecraftforge.net/en/1.19.2/forgedev/#making-changes-and-pull-requests
[Patreon]: https://www.patreon.com/LexManos
+3 -2
View File
@@ -76,7 +76,7 @@ If you're certain you've found an issue that is directly caused by Forge, you ha
1. **Forge Forums:** There's a dedicated [Support & Bug Report](http://www.minecraftforge.net/forum/forum/18-support-bug-reports/) section on the Forge forums, which is led by team of moderators and volunteers who will try to deal with your reports as quickly as possible. *As a player you should probably report here first.*
- For modders, there also is a separate [Modder Support](http://www.minecraftforge.net/forum/forum/70-modder-support/) section where you can ask all your development-related questions. *You should prefer this section for coding help.*
2. **Forge IRC Channel:** You can find a lot of help on the official [`#minecraftforge`](irc://irc.esper.net:6667/minecraftforge) channel on EsperNet. Especially smaller issues that you quickly need help with could be reported there. *Be aware that the channel is more suited towards development questions, so while you may get support there as a player, you should almost always prefer the forums.*
2. **Forge Discord Server:** You can find a lot of help on the official [Discord Server](https://discord.gg/forge), especially smaller issues that you quickly need help with. *Be aware that the channel is more suited towards development questions, so while you may get support there as a player, you should almost always prefer the forums.*
3. **Forge Issue Tracker:** If you're absolutely certain that you've found an issue in the Forge codebase (e.g. you're a modder yourself and have analyzed the stacktrace and relevant code), don't refrain from reporting it on this repository's [issue tracker](https://github.com/MinecraftForge/MinecraftForge/issues). *Please do not use the issues as a means of getting coding help. For developers, the IRC and the [official documentation](https://mcforge.readthedocs.io) are the best sources of information.*
### Mod Support
@@ -84,7 +84,8 @@ If you're certain you've found an issue that is directly caused by Forge, you ha
A lot of mods also use GitHub or other source management systems and their integrated issue trackers. The following options will give you the best chances of reporting your issue in the right place:
- **CurseForge:** Many mods are hosted on the [CurseForge platform](https://minecraft.curseforge.com) nowadays. Chances are you already downloaded them from there or as a part of a modpack hosted there. Projects may specify an issue reporting link on their own page, so simply look for it on the mod's project page and you should be directed to the preferred means of error reporting.
- **Searching for a repository directly:** You may need to try and find a repository directly on source control sites. The most common ones are [GitHub](https://github.com) and [BitBucket](https://bitbucket.org). Both come with search capabilities, so simply try to search for the mod's name.
- **Modrinth:** Some modders use [Modrinth](https://modrinth.com/mods) to host their mods, but be mindful that not all mods on this platform are for the Forge modloader.
- **Searching for a repository directly:** You may need to try and find a repository directly on source control sites. The most common ones are [GitHub](https://github.com), [GitLab](https://gitlab.com), and [BitBucket](https://bitbucket.org). Both come with search capabilities, so simply try to search for the mod's name.
### Vanilla Support
+6 -11
View File
@@ -1,12 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'>
<svg enable-background="new 164.072 372.466 294.41 46.56" version="1.1" viewBox="164.072 372.466 294.41 46.56" xml:space="preserve" xmlns="http://www.w3.org/2000/svg">
<g fill="#DFA86A">
<polygon points="266.16 417.99 277.12 417.99 277.12 401.05 295.09 401.05 295.09 390.78 277.12 390.78 277.12 383.77 296.18 383.77 296.18 373.5 266.16 373.5"/>
<path d="m337.33 378.7c-2.103-2.057-4.629-3.64-7.51-4.704-2.743-1.015-5.786-1.528-9.041-1.528l-0.356 2e-3c-3.362 0-6.503 0.556-9.338 1.651-2.857 1.106-5.357 2.707-7.434 4.761-2.073 2.052-3.714 4.559-4.877 7.45-1.158 2.876-1.748 6.104-1.748 9.59 0 3.417 0.59 6.582 1.753 9.403 1.163 2.829 2.807 5.297 4.88 7.329 2.073 2.03 4.572 3.621 7.425 4.724 2.834 1.096 5.975 1.651 9.339 1.651h0.023c3.402-0.043 6.57-0.639 9.42-1.772 2.863-1.142 5.375-2.757 7.465-4.804 2.091-2.051 3.742-4.524 4.91-7.358 1.162-2.823 1.75-5.987 1.75-9.402 0-3.487-0.588-6.705-1.748-9.568-1.168-2.874-2.82-5.371-4.913-7.425zm-4.644 16.762c0 1.96-0.302 3.782-0.896 5.413-0.587 1.607-1.42 3.011-2.479 4.167-1.05 1.147-2.335 2.065-3.821 2.728-1.479 0.656-3.164 0.99-5.008 0.99-1.84 0-3.514-0.333-4.973-0.988-1.47-0.662-2.747-1.578-3.799-2.729-1.062-1.156-1.895-2.559-2.479-4.167-0.595-1.63-0.896-3.451-0.896-5.413 0-1.801 0.298-3.497 0.887-5.044 0.584-1.536 1.419-2.894 2.479-4.037 1.048-1.132 2.323-2.03 3.792-2.674 1.465-0.642 3.145-0.968 4.988-0.968 1.848 0 3.539 0.326 5.025 0.971 1.481 0.643 2.766 1.541 3.812 2.671 1.062 1.143 1.896 2.501 2.479 4.036 0.589 1.548 0.889 3.245 0.889 5.044z"/>
<path d="m376.27 395.65c1.902-2.327 2.867-5.221 2.867-8.603 0-2.614-0.508-4.84-1.506-6.613-0.997-1.762-2.354-3.188-4.035-4.234-1.603-0.995-3.445-1.705-5.482-2.114-1.938-0.388-3.969-0.583-6.037-0.583h-16.021v44.487h10.961v-17.282h2.35l9.447 17.282h13.127l-11.199-18.646c2.262-0.728 4.116-1.964 5.528-3.694zm-19.254-12.223h4.426c0.844 0 1.73 0.054 2.636 0.16 0.784 0.094 1.503 0.283 2.132 0.568 0.496 0.225 0.888 0.553 1.193 0.998 0.283 0.415 0.428 1.031 0.428 1.836 0 0.931-0.16 1.643-0.459 2.06-0.34 0.472-0.771 0.813-1.32 1.046-0.686 0.289-1.459 0.477-2.301 0.554-0.975 0.089-1.963 0.136-2.938 0.136h-3.795l-2e-3 -7.358z"/>
<path d="m394.82 386.38c1.05-1.132 2.325-2.03 3.793-2.674 1.464-0.642 3.144-0.968 4.988-0.968 1.843 0 3.611 0.311 5.26 0.921 1.609 0.599 2.992 1.449 4.107 2.531l1.314 1.278 8.019-8.105-1.454-1.298c-2.355-2.103-5.066-3.586-8.058-4.407-2.879-0.789-5.987-1.189-9.247-1.189-3.361 0-6.503 0.556-9.339 1.651-2.856 1.106-5.355 2.707-7.431 4.761-2.074 2.052-3.716 4.559-4.88 7.45-1.158 2.876-1.746 6.104-1.746 9.59 0 3.417 0.59 6.582 1.752 9.403 1.164 2.829 2.807 5.297 4.88 7.329 2.073 2.03 4.572 3.621 7.425 4.724 2.832 1.096 5.975 1.651 9.339 1.651 6.501 0 12.475-1.432 17.751-4.25l0.979-0.522v-23.814h-19.313v10.27h8.354v6.639c-0.871 0.397-1.834 0.709-2.881 0.933-1.5 0.314-3.127 0.478-4.83 0.478-1.841 0-3.514-0.333-4.973-0.988-1.472-0.662-2.748-1.578-3.801-2.729-1.06-1.156-1.893-2.559-2.478-4.167-0.595-1.63-0.896-3.451-0.896-5.413 0-1.801 0.299-3.497 0.887-5.044 0.586-1.54 1.421-2.897 2.479-4.041z"/>
<polygon points="437.69 407.72 437.69 400.36 456.41 400.36 456.41 390.09 437.69 390.09 437.69 383.77 457.44 383.77 457.44 373.5 426.72 373.5 426.72 417.99 458.48 417.99 458.48 407.72"/>
</g>
<path d="m243.63 379.09l-37.842-1.852 46.229-0.034v-3.727h-52.125l-1e-3 7.798v6.201c0 0.115-1.52-9.144-1.87-11.734h-4.098v13.029c0 0.123-1.753-10.888-1.939-12.264h-27.914c1.902 1.648 12.401 10.598 19.865 14.28 3.741 1.846 8.33 1.86 12.414 1.974 2.075 0.06 4.25 0.217 5.803 1.754 2.255 2.236 2.758 5.704 0.814 8.33-1.922 2.594-7.335 3.156-7.335 3.156l-4.509 5.531v6.424h10.251l0.319-6.348 8.863-6.285c-0.946 0.757-3.058 2.783-6.229 7.666-0.717 1.102-1.275 2.306-1.711 3.49 2.238-1.896 6.84-3.194 12.153-3.194 5.307 0 9.903 1.295 12.146 3.188-0.437-1.185-0.994-2.385-1.709-3.483-3.172-4.883-5.284-6.909-6.229-7.666l8.863 6.285 0.32 6.348h9.565v-6.424l-4.507-5.531s-6.675-0.425-8.423-3.156c-5.032-7.869 2.115-20.082 18.836-23.756z" fill="#1E2D41"/>
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="164.072 372.466 294.41 46.56">
<g fill="#DFA86A">
<path d="M266.16 417.99h10.96v-16.94h17.97v-10.27h-17.97v-7.01h19.06V373.5h-30.02zM337.33 378.7c-2.103-2.057-4.629-3.64-7.51-4.704-2.743-1.015-5.786-1.528-9.041-1.528l-.356.002c-3.362 0-6.503.556-9.338 1.651-2.857 1.106-5.357 2.707-7.434 4.761-2.073 2.052-3.714 4.559-4.877 7.45-1.158 2.876-1.748 6.104-1.748 9.59 0 3.417.59 6.582 1.753 9.403 1.163 2.829 2.807 5.297 4.88 7.329 2.073 2.03 4.572 3.621 7.425 4.724 2.834 1.096 5.975 1.651 9.339 1.651h.023c3.402-.043 6.57-.639 9.42-1.772 2.863-1.142 5.375-2.757 7.465-4.804 2.091-2.051 3.742-4.524 4.91-7.358 1.162-2.823 1.75-5.987 1.75-9.402 0-3.487-.588-6.705-1.748-9.568-1.168-2.874-2.82-5.371-4.913-7.425zm-4.644 16.762c0 1.96-.302 3.782-.896 5.413-.587 1.607-1.42 3.011-2.479 4.167-1.05 1.147-2.335 2.065-3.821 2.728-1.479.656-3.164.99-5.008.99-1.84 0-3.514-.333-4.973-.988-1.47-.662-2.747-1.578-3.799-2.729-1.062-1.156-1.895-2.559-2.479-4.167-.595-1.63-.896-3.451-.896-5.413 0-1.801.298-3.497.887-5.044.584-1.536 1.419-2.894 2.479-4.037 1.048-1.132 2.323-2.03 3.792-2.674 1.465-.642 3.145-.968 4.988-.968 1.848 0 3.539.326 5.025.971 1.481.643 2.766 1.541 3.812 2.671 1.062 1.143 1.896 2.501 2.479 4.036.589 1.548.889 3.245.889 5.044zM376.27 395.65c1.902-2.327 2.867-5.221 2.867-8.603 0-2.614-.508-4.84-1.506-6.613-.997-1.762-2.354-3.188-4.035-4.234-1.603-.995-3.445-1.705-5.482-2.114-1.938-.388-3.969-.583-6.037-.583h-16.021v44.487h10.961v-17.282h2.35l9.447 17.282h13.127l-11.199-18.646c2.262-.728 4.116-1.964 5.528-3.694zm-19.254-12.223h4.426c.844 0 1.73.054 2.636.16.784.094 1.503.283 2.132.568.496.225.888.553 1.193.998.283.415.428 1.031.428 1.836 0 .931-.16 1.643-.459 2.06-.34.472-.771.813-1.32 1.046-.686.289-1.459.477-2.301.554-.975.089-1.963.136-2.938.136h-3.795l-.002-7.358z"/>
<path d="M394.82 386.38c1.05-1.132 2.325-2.03 3.793-2.674 1.464-.642 3.144-.968 4.988-.968 1.843 0 3.611.311 5.26.921 1.609.599 2.992 1.449 4.107 2.531l1.314 1.278 8.019-8.105-1.454-1.298c-2.355-2.103-5.066-3.586-8.058-4.407-2.879-.789-5.987-1.189-9.247-1.189-3.361 0-6.503.556-9.339 1.651-2.856 1.106-5.355 2.707-7.431 4.761-2.074 2.052-3.716 4.559-4.88 7.45-1.158 2.876-1.746 6.104-1.746 9.59 0 3.417.59 6.582 1.752 9.403 1.164 2.829 2.807 5.297 4.88 7.329 2.073 2.03 4.572 3.621 7.425 4.724 2.832 1.096 5.975 1.651 9.339 1.651 6.501 0 12.475-1.432 17.751-4.25l.979-.522v-23.814h-19.313v10.27h8.354v6.639c-.871.397-1.834.709-2.881.933-1.5.314-3.127.478-4.83.478-1.841 0-3.514-.333-4.973-.988-1.472-.662-2.748-1.578-3.801-2.729-1.06-1.156-1.893-2.559-2.478-4.167-.595-1.63-.896-3.451-.896-5.413 0-1.801.299-3.497.887-5.044.586-1.54 1.421-2.897 2.479-4.041zM437.69 407.72v-7.36h18.72v-10.27h-18.72v-6.32h19.75V373.5h-30.72v44.49h31.76v-10.27z"/>
</g>
<path fill="#1E2D41" d="m243.63 379.09-37.842-1.852 46.229-.034v-3.727h-52.125l-.001 7.798v6.201c0 .115-1.52-9.144-1.87-11.734h-4.098v13.029c0 .123-1.753-10.888-1.939-12.264H164.07c1.902 1.648 12.401 10.598 19.865 14.28 3.741 1.846 8.33 1.86 12.414 1.974 2.075.06 4.25.217 5.803 1.754 2.255 2.236 2.758 5.704.814 8.33-1.922 2.594-7.335 3.156-7.335 3.156l-4.509 5.531v6.424h10.251l.319-6.348 8.863-6.285c-.946.757-3.058 2.783-6.229 7.666-.717 1.102-1.275 2.306-1.711 3.49 2.238-1.896 6.84-3.194 12.153-3.194 5.307 0 9.903 1.295 12.146 3.188-.437-1.185-.994-2.385-1.709-3.483-3.172-4.883-5.284-6.909-6.229-7.666l8.863 6.285.32 6.348h9.565v-6.424l-4.507-5.531s-6.675-.425-8.423-3.156c-5.032-7.869 2.115-20.082 18.836-23.756z"/>
</svg>

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

+12 -3
View File
@@ -1,6 +1,7 @@
plugins {
id 'com.github.ben-manes.versions'
id 'org.javamodularity.moduleplugin' version '1.8.3' apply false
id 'org.cadixdev.licenser'
}
apply plugin: 'java-library'
apply plugin: 'jacoco'
@@ -9,10 +10,12 @@ apply plugin: 'org.javamodularity.moduleplugin'
dependencyUpdates.rejectVersionIf { isNonStable(it.candidate.version) }
dependencies {
compileOnly('org.jetbrains:annotations:21.0.1')
compileOnly("org.jetbrains:annotations:${JETBRAINS_ANNOTATIONS_VERSION}")
api("net.minecraftforge:eventbus:${EVENTBUS_VERSION}")
implementation(project(':fmlloader'))
api('net.minecraftforge:eventbus:5.0.+')
implementation('commons-io:commons-io:2.5')
implementation("commons-io:commons-io:${COMMONS_IO_VERSION}")
}
task sourcesJar(type: Jar) {
@@ -53,6 +56,12 @@ tasks.withType(JavaCompile) {
options.compilerArgs << '-Xlint:unchecked'
}
license {
header = rootProject.file('LICENSE-header.txt')
include 'net/minecraftforge/'
}
artifacts {
archives jar
archives sourcesJar
@@ -1,35 +1,40 @@
/*
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml;
import cpw.mods.modlauncher.util.ServiceLoaderUtils;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.fml.config.IConfigEvent;
import net.minecraftforge.fml.loading.FMLLoader;
import java.util.ServiceConfigurationError;
import java.util.ServiceLoader;
import java.util.function.Supplier;
public class Bindings {
private static final Bindings INSTANCE = new Bindings();
private Bindings() {}
private final IBindingsProvider provider;
private Bindings() {
final var providers = ServiceLoaderUtils.streamServiceLoader(()->ServiceLoader.load(FMLLoader.getGameLayer(), IBindingsProvider.class), sce->{}).toList();
if (providers.size() != 1) {
throw new IllegalStateException("Could not find bindings provider");
}
this.provider = providers.get(0);
}
/**
* The provider of the bindings
* @implNote May also throw a {@link ServiceConfigurationError}
*/
private static final IBindingsProvider PROVIDER = ServiceLoader.load(FMLLoader.getGameLayer(), IBindingsProvider.class)
.findFirst().orElseThrow(() -> new IllegalStateException("Could not find bindings provider"));
/**
* @return A supplier of net.minecraftforge.common.MinecraftForge#EVENT_BUS
*/
public static Supplier<IEventBus> getForgeBus() {
return INSTANCE.provider.getForgeBusSupplier();
return PROVIDER.getForgeBusSupplier();
}
public static Supplier<I18NParser> getMessageParser() {
return INSTANCE.provider.getMessageParser();
return PROVIDER.getMessageParser();
}
public static Supplier<IConfigEvent.ConfigConfig> getConfigConfiguration() {
return INSTANCE.provider.getConfigConfiguration();
return PROVIDER.getConfigConfiguration();
}
}
@@ -1,3 +1,8 @@
/*
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml;
import java.util.ArrayList;
@@ -1,20 +1,6 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml;
@@ -1,20 +1,6 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml;
@@ -1,3 +1,8 @@
/*
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml;
public interface I18NParser {
@@ -1,3 +1,8 @@
/*
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml;
import net.minecraftforge.eventbus.api.IEventBus;
@@ -0,0 +1,5 @@
/*
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
@@ -1,20 +1,6 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml;
@@ -22,41 +8,111 @@ package net.minecraftforge.fml;
import java.util.function.BiPredicate;
import java.util.function.Supplier;
/**
* An extension point for a mod container.
*
* <p>An extension point can be registered for a mod container using {@link ModContainer#registerExtensionPoint(Class, Supplier)}
* and retrieved (if present) using {@link ModContainer#getCustomExtension(Class)}. An extension point allows a mod to
* supply an arbitrary value as a record class to another mod or framework through their mod container class, avoiding
* the use of {@link InterModComms} or other external frameworks to pass around these values.</p>
*
* <p>The usual way to declare an extension point is to implement this interface on a record class, with the type
* parameter being a reference to the class itself. For example, {@code record MyExtension(...) extends
* IExtensionPoint<MyExtension>} would declare an extension point which supplies a {@code MyExtension} object. However,
* there is no hard requirement that an extension point's type parameter must be in reference to itself; the type
* parameter may reference another record class instead.</p>
*
* @param <T> the type of the record which is held by the extension point
*/
@SuppressWarnings("unused") // Type parameter T
public interface IExtensionPoint<T extends Record>
{
/**
* Compatibility display test for the mod.
* Used for displaying compatibility with remote servers with the same mod, and on disk saves.
* Extension point for the compatibility display test used on the server selection screen.
*
* The supplier provides my "local" version for sending across the impl or writing to disk
* The predicate tests the version from a remote instance or save for acceptability (Boolean is true for impl, false for local save)
* and returns true if the version is compatible.
* <em>Note: "server" and "client" refers to the {@linkplain net.minecraftforge.api.distmarker.Dist#DEDICATED_SERVER dedicated server}
* and {@linkplain net.minecraftforge.api.distmarker.Dist#CLIENT game client} physical distributions, rather than the
* {@linkplain LogicalSide logical server and client}.</em>
*
* <p>Return {@code net.minecraftforge.impl.impl.FMLNetworkConstants#IGNORESERVERONLY} in the supplier, if you wish to be ignored
* as a server side only mod.</p>
* <p>Return true in the predicate for all values of the input string (when impl boolean is true) if you are client side,
* and don't care about matching any potential server version.</p>
* <p>The {@link Supplier} provides the local compatibility version, which is sent from the server to the client
* for multiplayer connections or stored to disk for the world save. The {@link BiPredicate} accepts the remote
* compatibility version and a boolean indicating whether the remote version is from the server or a world save,
* where {@code true} means it is from the server and {@code false} means it is from the world save. The return
* value of the predicate determines whether the remote version is "compatible" for the purposes of the display test.</p>
*
* <p>
* Examples: A server only mod
* </p>
* <p>The local compatibility version may be of the value {@link net.minecraftforge.network.NetworkConstants#IGNORESERVERONLY},
* in which case clients will ignore the mod's presence if it is present on the server but not on the client.
* However, the remote version test predicate must still accept this value as a remote version in order to display
* as compatible if the mod is present on the client.</p>
*
* <p><strong>The compatibility display test does not necessarily indicate the success or failure of an actual
* connection attempt.</strong> Factors such as display test extension misconfiguration, truncation of ping data,
* difference of registry data or network channels between server and client, and others may cause the result of the
* compatibility test to not reflect the actual likelihood of a connection successfully being established between
* the server and the client.</p>
*
* <p>An example declaration of a display test extension registration for a regular mod (requires to be present on
* server and client) is as follows:</p>
* <pre>{@code
* registerExtensionPoint(DISPLAYTEST, ()->Pair.of(
* ()->FMLNetworkConstants.IGNORESERVERONLY, // ignore me, I'm a server only mod
* (s,b)->true // i accept anything from the server or the save, if I'm asked
* )
* String compatibilityVersion = "1"; // Could be linked with a network channel version or mod version
* ModLoadingContext.get().registerExtensionPoint(IExtensionPoint.DisplayTest.class,
* () -> new IExtensionPoint.DisplayTest(
* () -> compatibilityVersion,
* (remoteVersion, isFromServer) -> remoteVersion.equals(compatibilityVersion)
* )
* );
* }</pre>
*
* <p>
* Examples: A client only mod
* </p>
* <p>An example declaration of a display test extension registration for a <em>server-side-only</em> mod (does not
* require to be present on the client) is as follows:</p>
* <pre>{@code
* registerExtensionPoint(DISPLAYTEST, ()->Pair.of(
* ()->"anything. i don't care", // if i'm actually on the server, this string is sent but i'm a client only mod, so it won't be
* (remoteversionstring,networkbool)->networkbool // i accept anything from the server, by returning true if it's asking about the server
* )
* ModLoadingContext.get().registerExtensionPoint(IExtensionPoint.DisplayTest.class,
* () -> new IExtensionPoint.DisplayTest(
* // Ignore this mod if not present on the client
* () -> NetworkConstants.IGNORESERVERONLY,
* // If present on the client, accept any version if from a server
* (remoteVersion, isFromServer) -> isFromServer
* )
* );
* }</pre>
*
* <p>An example declaration of a display test extension registration for a <em>client-side-only</em> mod (does not
* require to be present on the server) is as follows:</p>
* <pre>{@code
* ModLoadingContext.get().registerExtensionPoint(IExtensionPoint.DisplayTest.class,
* () -> new IExtensionPoint.DisplayTest(
* // Send any version from server to client, since we will be accepting any version as well
* () -> "dQw4w9WgXcQ",
* // Accept any version on the client, from server or from save
* (remoteVersion, isFromServer) -> true
* )
* );
* }</pre>
*
* @see net.minecraftforge.network.ServerStatusPing
* @see net.minecraftforge.client.ForgeHooksClient#processForgeListPingData(net.minecraft.network.protocol.status.ServerStatus, net.minecraft.client.multiplayer.ServerData)
*/
record DisplayTest(Supplier<String> suppliedVersion, BiPredicate<String, Boolean> remoteVersionTest) implements IExtensionPoint<DisplayTest> {}
@SuppressWarnings("JavadocReference") // reference to NetworkConstants, ForgeHooksClient
record DisplayTest(Supplier<String> suppliedVersion, BiPredicate<String, Boolean> remoteVersionTest) implements IExtensionPoint<DisplayTest> {
public static final String IGNORESERVERONLY = "OHNOES\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31\uD83D\uDE31";
/**
* Ignores any version information coming from the server - use for server only mods
*/
public static final Supplier<DisplayTest> IGNORE_SERVER_VERSION = () -> new DisplayTest(IGNORESERVERONLY, (remoteVersion, isFromServer) -> true);
/**
* Ignores all information and provides no information
*/
public static final Supplier<DisplayTest> IGNORE_ALL_VERSION = () -> new DisplayTest("", (remoteVersion, isFromServer) -> true);
/**
* An optional alternative to {@link #DisplayTest(Supplier, BiPredicate)} which accepts a constant version string
* instead of a {@link Supplier}.
* <p>Internally, the provided version string is wrapped in a Supplier for you.</p>
*/
public DisplayTest(String version, BiPredicate<String, Boolean> remoteVersionTest) {
this(() -> version, remoteVersionTest);
}
}
}
@@ -1,25 +1,86 @@
/*
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml;
import net.minecraftforge.eventbus.api.Event;
import net.minecraftforge.fml.event.IModBusEvent;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
import java.util.function.Function;
/**
* A mod loading state. During mod loading, the mod loader transitions between states in a defined sorted list of states,
* grouped into various {@link ModLoadingPhase phases}.
*
* @see IModStateProvider
*/
public interface IModLoadingState {
/**
* {@return the name of this state}
*/
String name();
/**
* {@return the name of the state immediately previous to this state} This may be a blank name, which indicates this
* is either the first mod loading state or an exceptional mod loading state (such as a situation where errors
* prevent the loading process from continuing normally).
*/
String previous();
/**
* {@return the mod loading phase this state belongs to} For exceptional mod loading states, this should be
* {@link ModLoadingPhase#ERROR}.
*/
ModLoadingPhase phase();
/**
* {@return a function returning a human-friendly message for this state}
*/
Function<ModList, String> message();
/**
* {@return an optional runnable, which runs before starting the transition from this state to the next}
* @see #buildTransition(Executor, Executor, Function, Function)
*/
Optional<Consumer<ModList>> inlineRunnable();
default <T extends Event & IModBusEvent> Optional<CompletableFuture<List<Throwable>>> buildTransition(final Executor syncExecutor, final Executor parallelExecutor) {
return buildTransition(syncExecutor, parallelExecutor, e->CompletableFuture.runAsync(()->{}, e), e->CompletableFuture.runAsync(()->{}, e));
/**
* Builds the transition task for this state with a blank pre-sync and post-sync task.
*
* @param syncExecutor a synchronous executor
* @param parallelExecutor a parallel executor
* @param <T> a type of event fired on the mod-specific event bus
* @return a transition task for this state
* @see #buildTransition(Executor, Executor, Function, Function)
*/
default <T extends Event & IModBusEvent>
Optional<CompletableFuture<Void>> buildTransition(final Executor syncExecutor,
final Executor parallelExecutor) {
return buildTransition(syncExecutor, parallelExecutor,
e -> CompletableFuture.runAsync(() -> {}, e),
e -> CompletableFuture.runAsync(() -> {}, e));
}
<T extends Event & IModBusEvent> Optional<CompletableFuture<List<Throwable>>> buildTransition(Executor syncExecutor, Executor parallelExecutor, Function<Executor, CompletableFuture<Void>> preSyncTask, Function<Executor, CompletableFuture<Void>> postSyncTask);
/**
* Builds the transition task for this state. The pre-sync and post-sync task functions allow the transition builder
* to run these tasks on the same executor as the actual event dispatch and pre/post hooks.
*
* @param syncExecutor a synchronous executor
* @param parallelExecutor a parallel executor
* @param preSyncTask a function which returns a task to run before event pre-dispatch hook
* @param postSyncTask a function which returns a task to run after event post-dispatch hook
* @param <T> a type of event fired on the mod-specific event bus
* @return a transition task for this state
*/
<T extends Event & IModBusEvent>
Optional<CompletableFuture<Void>> buildTransition(final Executor syncExecutor,
final Executor parallelExecutor,
final Function<Executor, CompletableFuture<Void>> preSyncTask,
final Function<Executor, CompletableFuture<Void>> postSyncTask);
}
@@ -1,7 +1,21 @@
/*
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml;
import java.util.List;
/**
* Provides a list of mod loading states which the mod loader may transition between.
*
* <p>There may be multiple mod state providers in a single application, where all states from each provider is
* combined into a single list and ordered.</p>
*/
public interface IModStateProvider {
/**
* {@return the list of mod loading states known to this provider}
*/
List<IModLoadingState> getAllStates();
}
@@ -1,10 +1,14 @@
/*
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml;
import net.minecraftforge.eventbus.api.Event;
import net.minecraftforge.fml.event.IModBusEvent;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
@@ -19,18 +23,26 @@ public interface IModStateTransition {
return new NoopTransition();
}
default <T extends Event & IModBusEvent> CompletableFuture<List<Throwable>> build(Executor syncExecutor, Executor parallelExecutor, Function<Executor, CompletableFuture<Void>> preSyncTask, Function<Executor, CompletableFuture<Void>> postSyncTask) {
List<CompletableFuture<List<Throwable>>> cfs = new ArrayList<>();
default <T extends Event & IModBusEvent>
CompletableFuture<Void> build(final Executor syncExecutor,
final Executor parallelExecutor,
final Function<Executor, CompletableFuture<Void>> preSyncTask,
final Function<Executor, CompletableFuture<Void>> postSyncTask) {
List<CompletableFuture<Void>> futures = new ArrayList<>();
this.eventFunctionStream().get()
.map(f->(EventGenerator<T>)f)
.reduce((head, tail)-> addCompletableFutureTaskForModDispatch(syncExecutor, parallelExecutor, cfs, head, ModLoadingStage::currentState, tail))
.ifPresent(last-> addCompletableFutureTaskForModDispatch(syncExecutor, parallelExecutor, cfs, last, nextModLoadingStage(), null));
.map(f -> (EventGenerator<T>) f)
.reduce((head, tail) -> addCompletableFutureTaskForModDispatch(syncExecutor, parallelExecutor, futures, head, ModLoadingStage::currentState, tail))
.ifPresent(last -> addCompletableFutureTaskForModDispatch(syncExecutor, parallelExecutor, futures, last, nextModLoadingStage(), null));
final CompletableFuture<Void> preSyncTaskCF = preSyncTask.apply(syncExecutor);
final CompletableFuture<List<Throwable>> eventDispatchCF = ModList.gather(cfs).thenCompose(ModList::completableFutureFromExceptionList);
final CompletableFuture<List<Throwable>> postEventDispatchCF = preSyncTaskCF.thenComposeAsync(n -> eventDispatchCF, parallelExecutor).thenApply(r -> {
postSyncTask.apply(syncExecutor);
return r;
});
final CompletableFuture<Void> eventDispatchCF = ModList.gather(futures).thenCompose(ModList::completableFutureFromExceptionList);
final CompletableFuture<Void> postEventDispatchCF = preSyncTaskCF
.thenComposeAsync(n -> eventDispatchCF, parallelExecutor)
.thenApply(r -> {
postSyncTask.apply(syncExecutor);
return null;
});
return this.finalActivityGenerator().apply(syncExecutor, postEventDispatchCF);
}
@@ -38,18 +50,31 @@ public interface IModStateTransition {
return ModLoadingStage::nextState;
}
private <T extends Event & IModBusEvent> EventGenerator<T> addCompletableFutureTaskForModDispatch(final Executor syncExecutor, final Executor parallelExecutor, final List<CompletableFuture<List<Throwable>>> completeableFutures, final EventGenerator<T> eventGenerator, BiFunction<ModLoadingStage, Throwable, ModLoadingStage> nextState, final EventGenerator<T> nextGenerator) {
completeableFutures.add(((BiFunction<Executor, EventGenerator<T>, CompletableFuture<List<Throwable>>>)preDispatchHook()).apply(threadSelector().apply(syncExecutor, parallelExecutor), eventGenerator));
completeableFutures.add(ModList.get().futureVisitor(eventGenerator, nextState).apply(threadSelector().apply(syncExecutor, parallelExecutor)));
completeableFutures.add(((BiFunction<Executor, EventGenerator<T>, CompletableFuture<List<Throwable>>>)postDispatchHook()).apply(threadSelector().apply(syncExecutor, parallelExecutor), eventGenerator));
private <T extends Event & IModBusEvent>
EventGenerator<T> addCompletableFutureTaskForModDispatch(final Executor syncExecutor,
final Executor parallelExecutor,
final List<CompletableFuture<Void>> completableFutures,
final EventGenerator<T> eventGenerator,
final BiFunction<ModLoadingStage, Throwable, ModLoadingStage> nextState,
final EventGenerator<T> nextGenerator) {
final Executor selectedExecutor = threadSelector().apply(syncExecutor, parallelExecutor);
var preDispatchHook = (BiFunction<Executor, EventGenerator<T>, CompletableFuture<Void>>) preDispatchHook();
completableFutures.add(preDispatchHook.apply(selectedExecutor, eventGenerator));
completableFutures.add(ModList.get().futureVisitor(eventGenerator, nextState).apply(threadSelector().apply(syncExecutor, parallelExecutor)));
var postDispatchHook = (BiFunction<Executor, EventGenerator<T>, CompletableFuture<Void>>) postDispatchHook();
completableFutures.add(postDispatchHook.apply(selectedExecutor, eventGenerator));
return nextGenerator;
}
Supplier<Stream<EventGenerator<?>>> eventFunctionStream();
ThreadSelector threadSelector();
BiFunction<Executor, CompletableFuture<List<Throwable>>, CompletableFuture<List<Throwable>>> finalActivityGenerator();
BiFunction<Executor, ? extends EventGenerator<?>, CompletableFuture<List<Throwable>>> preDispatchHook();
BiFunction<Executor, ? extends EventGenerator<?>, CompletableFuture<List<Throwable>>> postDispatchHook();
BiFunction<Executor, CompletableFuture<Void>, CompletableFuture<Void>> finalActivityGenerator();
BiFunction<Executor, ? extends EventGenerator<?>, CompletableFuture<Void>> preDispatchHook();
BiFunction<Executor, ? extends EventGenerator<?>, CompletableFuture<Void>> postDispatchHook();
interface EventGenerator<T extends Event & IModBusEvent> extends Function<ModContainer, T> {
static <FN extends Event & IModBusEvent> EventGenerator<FN> fromFunction(Function<ModContainer, FN> fn) {
@@ -71,17 +96,17 @@ record NoopTransition() implements IModStateTransition {
}
@Override
public BiFunction<Executor, CompletableFuture<List<Throwable>>, CompletableFuture<List<Throwable>>> finalActivityGenerator() {
public BiFunction<Executor, CompletableFuture<Void>, CompletableFuture<Void>> finalActivityGenerator() {
return (e, t) -> t.thenApplyAsync(Function.identity(), e);
}
@Override
public BiFunction<Executor, ? extends EventGenerator<?>, CompletableFuture<List<Throwable>>> preDispatchHook() {
return (t, f)-> CompletableFuture.completedFuture(Collections.emptyList());
public BiFunction<Executor, ? extends EventGenerator<?>, CompletableFuture<Void>> preDispatchHook() {
return (t, f)-> CompletableFuture.completedFuture(null);
}
@Override
public BiFunction<Executor, ? extends EventGenerator<?>, CompletableFuture<List<Throwable>>> postDispatchHook() {
return (t, f)-> CompletableFuture.completedFuture(Collections.emptyList());
public BiFunction<Executor, ? extends EventGenerator<?>, CompletableFuture<Void>> postDispatchHook() {
return (t, f)-> CompletableFuture.completedFuture(null);
}
}
@@ -1,20 +1,6 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml;
@@ -1,20 +1,6 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml;
@@ -1,20 +1,6 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml;
@@ -1,20 +1,6 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml;
@@ -1,30 +1,45 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml;
import net.minecraftforge.api.distmarker.Dist;
/**
* A logical side of the Minecraft game.
* <p>
* The {@linkplain Dist#CLIENT client distribution} has a copy of the logical client and the logical server, while the
* {@linkplain Dist#DEDICATED_SERVER dedicated server distribution} only holds
* the logical server.
*
* @see Dist
*/
public enum LogicalSide
{
CLIENT, SERVER;
/**
* The logical client of the Minecraft game, which interfaces with the player's inputs and renders the player's
* viewpoint.
* <p>
* The logical client is only shipped with the client distribution of the game.
*
* @see Dist#CLIENT
*/
CLIENT,
/**
* The logical server of the Minecraft game, responsible for connecting to clients and running the simulation logic
* on the level.
* <p>
* The logical server is shipped with both client and dedicated server distributions. The client distribution runs
* the logical server for singleplayer mode and LAN play.
*
* @see Dist#DEDICATED_SERVER
*/
SERVER;
/**
* @return if the logical side is a server.
* {@return if this logical side is the server}
*/
public boolean isServer()
{
@@ -32,7 +47,7 @@ public enum LogicalSide
}
/**
* @return if the logical side is a client.
* {@return if the logical side is the client}
*/
public boolean isClient()
{
@@ -1,20 +1,6 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml;
@@ -23,6 +9,7 @@ import net.minecraftforge.eventbus.api.Event;
import net.minecraftforge.fml.config.IConfigEvent;
import net.minecraftforge.fml.config.ModConfig;
import net.minecraftforge.fml.event.IModBusEvent;
import net.minecraftforge.fml.loading.moddiscovery.ModFileInfo;
import net.minecraftforge.forgespi.language.IModInfo;
import java.util.EnumMap;
@@ -34,6 +21,7 @@ import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.function.BiFunction;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.function.Supplier;
@@ -70,9 +58,25 @@ public abstract class ModContainer
this.namespace = this.modId;
this.modInfo = info;
this.modLoadingStage = ModLoadingStage.CONSTRUCT;
// default displaytest extension checks for version string match
registerExtensionPoint(IExtensionPoint.DisplayTest.class, () -> new IExtensionPoint.DisplayTest(()->this.modInfo.getVersion().toString(),
(incoming, isNetwork)->Objects.equals(incoming, this.modInfo.getVersion().toString())));
final String displayTestString = info.getConfig().<String>getConfigElement("displayTest")
.orElseGet(() -> (Boolean) info.getOwningFile().getFileProperties().getOrDefault(ModFileInfo.CLIENT_SIDE_ONLY_PROP, Boolean.FALSE) ? "IGNORE_ALL_VERSION" : "MATCH_VERSION");
Supplier<IExtensionPoint.DisplayTest> displayTestSupplier = switch (displayTestString) {
case "MATCH_VERSION" -> // default displaytest checks for version string match
() -> new IExtensionPoint.DisplayTest(() -> this.modInfo.getVersion().toString(),
(incoming, isNetwork) -> Objects.equals(incoming, this.modInfo.getVersion().toString()));
case "IGNORE_SERVER_VERSION" -> // Ignores any version information coming from the server - use for server only mods
IExtensionPoint.DisplayTest.IGNORE_SERVER_VERSION;
case "IGNORE_ALL_VERSION" -> // Ignores all information and provides no information
IExtensionPoint.DisplayTest.IGNORE_ALL_VERSION;
case "NONE" -> null; // NO display test at all - use this if you're going to do your own display test
default -> // any other value throws an exception
throw new IllegalArgumentException("Invalid displayTest value supplied in mods.toml");
};
if (displayTestSupplier != null)
registerExtensionPoint(IExtensionPoint.DisplayTest.class, displayTestSupplier);
else
extensionPoints.remove(IExtensionPoint.DisplayTest.class);
}
/**
@@ -141,6 +145,22 @@ public abstract class ModContainer
extensionPoints.put(point, extension);
}
public void registerDisplayTest(IExtensionPoint.DisplayTest displayTest) {
registerExtensionPoint(IExtensionPoint.DisplayTest.class, () -> displayTest);
}
public void registerDisplayTest(Supplier<IExtensionPoint.DisplayTest> displayTest) {
registerExtensionPoint(IExtensionPoint.DisplayTest.class, displayTest);
}
public void registerDisplayTest(String version, BiPredicate<String, Boolean> remoteVersionTest) {
registerDisplayTest(new IExtensionPoint.DisplayTest(version, remoteVersionTest));
}
public void registerDisplayTest(Supplier<String> suppliedVersion, BiPredicate<String, Boolean> remoteVersionTest) {
registerDisplayTest(new IExtensionPoint.DisplayTest(suppliedVersion, remoteVersionTest));
}
public void addConfig(final ModConfig modConfig) {
configs.put(modConfig.getType(), modConfig);
}
@@ -1,20 +1,6 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml;
@@ -35,8 +21,9 @@ import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
@@ -67,6 +54,7 @@ public class ModList
private List<ModContainer> mods;
private Map<String, ModContainer> indexedMods;
private List<ModFileScanData> modFileScanData;
private List<ModContainer> sortedContainers;
private ModList(final List<ModFile> modFiles, final List<ModInfo> sortedList)
{
@@ -85,7 +73,7 @@ public class ModList
}
private String fileToLine(IModFile mf) {
return String.format("%-50.50s|%-30.30s|%-30.30s|%-20.20s|%-10.10s|Manifest: %s", mf.getFileName(),
return String.format(Locale.ENGLISH, "%-50.50s|%-30.30s|%-30.30s|%-20.20s|%-10.10s|Manifest: %s", mf.getFileName(),
mf.getModInfos().get(0).getDisplayName(),
mf.getModInfos().get(0).getModId(),
mf.getModInfos().get(0).getVersion(),
@@ -124,7 +112,7 @@ public class ModList
return this.fileById.get(modid);
}
<T extends Event & IModBusEvent> Function<Executor, CompletableFuture<List<Throwable>>> futureVisitor(
<T extends Event & IModBusEvent> Function<Executor, CompletableFuture<Void>> futureVisitor(
final IModStateTransition.EventGenerator<T> eventGenerator,
final BiFunction<ModLoadingStage, Throwable, ModLoadingStage> stateChange) {
return executor -> gather(
@@ -133,12 +121,12 @@ public class ModList
.collect(Collectors.toList()))
.thenComposeAsync(ModList::completableFutureFromExceptionList, executor);
}
static CompletionStage<List<Throwable>> completableFutureFromExceptionList(List<? extends Map.Entry<?, Throwable>> t) {
static CompletionStage<Void> completableFutureFromExceptionList(List<? extends Map.Entry<?, Throwable>> t) {
if (t.stream().noneMatch(e->e.getValue()!=null)) {
return CompletableFuture.completedFuture(Collections.emptyList());
return CompletableFuture.completedFuture(null);
} else {
final List<Throwable> throwables = t.stream().filter(e -> e.getValue() != null).map(Map.Entry::getValue).collect(Collectors.toList());
CompletableFuture<List<Throwable>> cf = new CompletableFuture<>();
CompletableFuture<Void> cf = new CompletableFuture<>();
final RuntimeException accumulator = new RuntimeException();
cf.completeExceptionally(accumulator);
throwables.forEach(exception -> {
@@ -169,6 +157,7 @@ public class ModList
void setLoadedMods(final List<ModContainer> modContainers)
{
this.mods = modContainers;
this.sortedContainers = modContainers.stream().sorted(Comparator.comparingInt(c->sortedList.indexOf(c.getModInfo()))).toList();
this.indexedMods = modContainers.stream().collect(Collectors.toMap(ModContainer::getModId, Function.identity()));
}
@@ -232,6 +221,10 @@ public class ModList
indexedMods.forEach(modContainerConsumer);
}
public void forEachModInOrder(Consumer<ModContainer> containerConsumer) {
this.sortedContainers.forEach(containerConsumer);
}
public <T> Stream<T> applyForEachModContainer(Function<ModContainer, T> function) {
return indexedMods.values().stream().map(function);
}
@@ -1,20 +1,6 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml;
@@ -22,18 +8,22 @@ package net.minecraftforge.fml;
import com.google.common.collect.ImmutableList;
import net.minecraftforge.eventbus.api.Event;
import net.minecraftforge.fml.event.IModBusEvent;
import net.minecraftforge.fml.loading.FMLEnvironment;
import net.minecraftforge.fml.loading.FMLLoader;
import net.minecraftforge.fml.loading.LoadingModList;
import net.minecraftforge.fml.loading.moddiscovery.InvalidModIdentifier;
import net.minecraftforge.fml.loading.moddiscovery.ModFile;
import net.minecraftforge.fml.loading.moddiscovery.ModFileInfo;
import net.minecraftforge.fml.loading.moddiscovery.ModInfo;
import net.minecraftforge.fml.loading.progress.StartupMessageManager;
import net.minecraftforge.forgespi.language.IModInfo;
import net.minecraftforge.forgespi.language.IModLanguageProvider;
import net.minecraftforge.forgespi.locating.ForgeFeature;
import net.minecraftforge.forgespi.locating.IModFile;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@@ -42,6 +32,7 @@ import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.concurrent.Executor;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
@@ -110,7 +101,7 @@ public class ModLoader
.map(file -> new ModLoadingWarning(null, ModLoadingStage.VALIDATE, InvalidModIdentifier.identifyJarProblem(file.getFilePath()).orElse("fml.modloading.brokenfile"), file.getFileName()))
.collect(Collectors.toList());
FMLLoader.getLoadingModList().getModFiles().stream()
.filter(ModFileInfo::missingLicense) //Search for files with missing licenses
.filter(ModFileInfo::missingLicense)
.filter(modFileInfo -> modFileInfo.getMods().stream().noneMatch(thisModInfo -> this.loadingExceptions.stream().map(ModLoadingException::getModInfo).anyMatch(otherInfo -> otherInfo == thisModInfo))) //Ignore files where any other mod already encountered an error
.map(modFileInfo -> new ModLoadingException(null, ModLoadingStage.VALIDATE, "fml.modloading.missinglicense", null, modFileInfo.getFile()))
.forEach(this.loadingExceptions::add);
@@ -147,6 +138,7 @@ public class ModLoader
* @param periodicTask Optional periodic task to perform on the main thread while other activities run
*/
public void gatherAndInitializeMods(final ModWorkManager.DrivenExecutor syncExecutor, final Executor parallelExecutor, final Runnable periodicTask) {
ForgeFeature.registerFeature("java_version", ForgeFeature.VersionFeatureTest.forVersionString(IModInfo.DependencySide.SERVER, System.getProperty("java.version")));
loadingStateValid = true;
statusConsumer.ifPresent(c->c.accept("Waiting for scan to complete"));
FMLLoader.backgroundScanHandler.waitForScanToComplete(periodicTask);
@@ -159,6 +151,22 @@ public class ModLoader
loadingStateValid = false;
throw new LoadingFailedException(loadingExceptions);
}
statusConsumer.ifPresent(c->c.accept("Validating features"));
List<? extends ForgeFeature.Bound> failedBounds = loadingModList.getMods().stream()
.map(ModInfo::getForgeFeatures)
.flatMap(Collection::stream)
.filter(bound -> !ForgeFeature.testFeature(FMLEnvironment.dist, bound))
.toList();
if (!failedBounds.isEmpty()) {
LOGGER.fatal(CORE, "Failed to validate feature bounds for mods");
modList.setLoadedMods(Collections.emptyList());
loadingStateValid = false;
throw new LoadingFailedException(failedBounds.stream()
.map(fb -> new ModLoadingException(fb.modInfo(), ModLoadingStage.CONSTRUCT, "fml.modloading.feature.missing", null, fb.featureName(), fb.featureBound(), ForgeFeature.featureValue(fb)))
.toList());
}
statusConsumer.ifPresent(c->c.accept("Building Mod List"));
final List<ModContainer> modContainers = loadingModList.getModFiles().stream()
.map(ModFileInfo::getFile)
@@ -210,7 +218,7 @@ public class ModLoader
state.buildTransition(syncExecutor, parallelExecutor, preSyncTask, postSyncTask).ifPresent(t->waitForTransition(state, syncExecutor, ticker, t));
}
private void waitForTransition(final IModLoadingState state, final ModWorkManager.DrivenExecutor syncExecutor, final Runnable ticker, final CompletableFuture<List<Throwable>> transition) {
private void waitForTransition(final IModLoadingState state, final ModWorkManager.DrivenExecutor syncExecutor, final Runnable ticker, final CompletableFuture<Void> transition) {
while (!transition.isDone()) {
syncExecutor.drive(ticker);
}
@@ -236,7 +244,7 @@ public class ModLoader
}
}
private List<ModContainer> buildMods(final ModFile modFile)
private List<ModContainer> buildMods(final IModFile modFile)
{
final Map<String, IModInfo> modInfoMap = modFile.getModFileInfo().getMods().stream().collect(Collectors.toMap(IModInfo::getModId, Function.identity()));
@@ -258,7 +266,7 @@ public class ModLoader
return containers.stream().filter(mc -> mc.modLoadingStage != ModLoadingStage.ERROR).collect(Collectors.toList());
}
private ModContainer buildModContainerFromTOML(final ModFile modFile, final Map<String, IModInfo> modInfoMap, final Map.Entry<String, ? extends IModLanguageProvider.IModLanguageLoader> idToProviderEntry) {
private ModContainer buildModContainerFromTOML(final IModFile modFile, final Map<String, IModInfo> modInfoMap, final Map.Entry<String, ? extends IModLanguageProvider.IModLanguageLoader> idToProviderEntry) {
try {
final String modId = idToProviderEntry.getKey();
final IModLanguageProvider.IModLanguageLoader languageLoader = idToProviderEntry.getValue();
@@ -287,7 +295,7 @@ public class ModLoader
LOGGER.error("Cowardly refusing to send event generator to a broken mod state");
return;
}
ModList.get().forEachModContainer((id, mc) -> mc.acceptEvent(generator.apply(mc)));
ModList.get().forEachModInOrder(mc -> mc.acceptEvent(generator.apply(mc)));
}
public <T extends Event & IModBusEvent> void postEvent(T e) {
@@ -295,7 +303,18 @@ public class ModLoader
LOGGER.error("Cowardly refusing to send event {} to a broken mod state", e.getClass().getName());
return;
}
ModList.get().forEachModContainer((id, mc) -> mc.acceptEvent(e));
ModList.get().forEachModInOrder(mc -> mc.acceptEvent(e));
}
public <T extends Event & IModBusEvent> void postEventWithWrapInModOrder(T e, BiConsumer<ModContainer, T> pre, BiConsumer<ModContainer, T> post) {
if (!loadingStateValid) {
LOGGER.error("Cowardly refusing to send event {} to a broken mod state", e.getClass().getName());
return;
}
ModList.get().forEachModInOrder(mc -> {
pre.accept(mc, e);
mc.acceptEvent(e);
post.accept(mc, e);
});
}
public List<ModLoadingWarning> getWarnings()
@@ -1,54 +1,61 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml;
import com.mojang.logging.LogUtils;
import net.minecraftforge.fml.config.IConfigSpec;
import net.minecraftforge.fml.config.ModConfig;
import org.slf4j.Logger;
import java.util.function.BiPredicate;
import java.util.function.Supplier;
public class ModLoadingContext
{
private static final Logger LOGGER = LogUtils.getLogger();
private static final ThreadLocal<ModLoadingContext> context = ThreadLocal.withInitial(ModLoadingContext::new);
private ModContainer activeContainer;
private Object languageExtension;
private ModLoadingStage stage;
/**
* @deprecated Use the context provided by your language loader in your mod's constructor.
*/
@Deprecated(forRemoval = true, since = "1.21.1")
public static ModLoadingContext get() {
return context.get();
}
private ModContainer activeContainer;
/**
* @deprecated Going to be moved to ForgeHooks for internal use.
*/
@Deprecated(forRemoval = true, since = "1.21.1")
public void setActiveContainer(final ModContainer container) {
this.activeContainer = container;
this.languageExtension = container == null ? null : container.contextExtension.get();
}
/**
* Going to be moved to ForgeHooks for internal use.
* @deprecated Override/Use {@link ModLoadingContext#getContainer()}
*/
@Deprecated(forRemoval = true, since = "1.21.1")
public ModContainer getActiveContainer() {
return activeContainer == null ? ModList.get().getModContainerById("minecraft").orElseThrow(()->new RuntimeException("Where is minecraft???!")) : activeContainer;
}
@Deprecated(forRemoval = true, since = "1.21.1")
public String getActiveNamespace() {
return activeContainer == null ? "minecraft" : activeContainer.getNamespace();
}
public ModContainer getContainer() {
return getActiveContainer();
}
/**
* Register an {@link IExtensionPoint} with the mod container.
* @param point The extension point to register
@@ -56,15 +63,67 @@ public class ModLoadingContext
* @param <T> The type signature of the extension operator
*/
public <T extends Record & IExtensionPoint<T>> void registerExtensionPoint(Class<? extends IExtensionPoint<T>> point, Supplier<T> extension) {
getActiveContainer().registerExtensionPoint(point, extension);
getContainer().registerExtensionPoint(point, extension);
}
/**
* Register a {@link IExtensionPoint.DisplayTest} with the mod container.
* <p>A shorthand for registering a DisplayTest with {@link #registerExtensionPoint(Class, Supplier)}.</p>
* @param displayTest The {@link IExtensionPoint.DisplayTest} to register
*/
public void registerDisplayTest(IExtensionPoint.DisplayTest displayTest) {
getContainer().registerDisplayTest(() -> displayTest);
}
/**
* Register a {@link IExtensionPoint.DisplayTest} with the mod container.
* <p>A shorthand for registering a DisplayTest supplier with {@link #registerExtensionPoint(Class, Supplier)}.</p>
* @param displayTest The {@link Supplier<IExtensionPoint.DisplayTest>} to register
*/
public void registerDisplayTest(Supplier<IExtensionPoint.DisplayTest> displayTest) {
getContainer().registerDisplayTest(displayTest);
}
/**
* Register a {@link IExtensionPoint.DisplayTest} with the mod container.
* <p>A shorthand for registering a DisplayTest with {@link #registerExtensionPoint(Class, Supplier)} that also
* creates the DisplayTest instance for you using the provided parameters.</p>
* @see IExtensionPoint.DisplayTest#DisplayTest(String, BiPredicate)
*/
public void registerDisplayTest(String version, BiPredicate<String, Boolean> remoteVersionTest) {
getContainer().registerDisplayTest(new IExtensionPoint.DisplayTest(version, remoteVersionTest));
}
/**
* Register a {@link IExtensionPoint.DisplayTest} with the mod container.
* <p>A shorthand for registering a DisplayTest with {@link #registerExtensionPoint(Class, Supplier)} that also
* creates the DisplayTest instance for you using the provided parameters.</p>
* @see IExtensionPoint.DisplayTest#DisplayTest(Supplier, BiPredicate)
*/
public void registerDisplayTest(Supplier<String> suppliedVersion, BiPredicate<String, Boolean> remoteVersionTest) {
getContainer().registerDisplayTest(new IExtensionPoint.DisplayTest(suppliedVersion, remoteVersionTest));
}
public void registerConfig(ModConfig.Type type, IConfigSpec<?> spec) {
getActiveContainer().addConfig(new ModConfig(type, spec, getActiveContainer()));
if (spec.isEmpty())
{
// This handles the case where a mod tries to register a config, without any options configured inside it.
LOGGER.debug("Attempted to register an empty config for type {} on mod {}", type, getContainer().getModId());
return;
}
getContainer().addConfig(new ModConfig(type, spec, getContainer()));
}
public void registerConfig(ModConfig.Type type, IConfigSpec<?> spec, String fileName) {
getActiveContainer().addConfig(new ModConfig(type, spec, getActiveContainer(), fileName));
if (spec.isEmpty())
{
// This handles the case where a mod tries to register a config, without any options configured inside it.
LOGGER.debug("Attempted to register an empty config for type {} on mod {} using file name {}", type, getContainer().getModId(), fileName);
return;
}
getContainer().addConfig(new ModConfig(type, spec, getContainer(), fileName));
}
@@ -1,20 +1,6 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml;
@@ -1,9 +1,38 @@
/*
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml;
/**
* Phases of mod loading, for grouping mod loading states.
*/
public enum ModLoadingPhase {
/**
* Special phase for exceptional situations and error handling, where mod loading cannot continue normally.
*
* <p>There is conventionally only one state with this phase.</p>
*/
ERROR, // Special state for error handling
/**
* Phase for discovering and gathering mods for loading.
*/
GATHER,
/**
* Phase for the loading of mods found from mod discovery.
*
* @see #GATHER
*/
LOAD,
/**
* Phase after mod loading has completed, for post-loading tasks.
*
* @see #LOAD
*/
COMPLETE,
DONE;
/**
* Marker phase for the last state in the full mod loading process.
*/
DONE
}
@@ -1,34 +1,57 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml;
/**
* Mod loading stage of mod containers during the mod loading process. These will have a corresponding {@link ModLoadingState}
* in the basic mod loading process provided by FML.
*
* <p>Each mod loading stage has a global {@link DeferredWorkQueue}, which is populated during the execution of the state
* associated with this stage and emptied at the end of the state's execution.</p>
*/
public enum ModLoadingStage
{
/**
* Special stage for exceptional situations and error handling.
*/
ERROR,
/**
* Validation of the mod list.
* TODO: figure out where this is used and why this exists instead of CONSTRUCT being the first normal stage
*/
VALIDATE,
/**
* Default stage of mod containers after construction.
*/
CONSTRUCT,
/**
* Common (non-side-specific) setup and initialization.
*/
COMMON_SETUP,
/**
* Side-specific setup and initialization.
*
* @see net.minecraftforge.api.distmarker.Dist
*/
SIDED_SETUP,
/**
* Stage for enqueuing {@link net.minecraftforge.fml.InterModComms} messages for later processing.
*/
ENQUEUE_IMC,
/**
* Stage for processing received messages though {@link net.minecraftforge.fml.InterModComms}.
*/
PROCESS_IMC,
/**
* Marks the completion of mod loading for this container.
*/
COMPLETE,
/**
* Marks the completion of the full mod loading process.
*/
DONE;
private final DeferredWorkQueue deferredWorkQueue;
@@ -37,14 +60,27 @@ public enum ModLoadingStage
deferredWorkQueue = new DeferredWorkQueue(this);
}
/**
* {@return the next stage after this stage, or {@link #ERROR} if the exception is not {@code null}}
*
* @param exception the exception that occurred during this stage, may be {@code null}
*/
ModLoadingStage nextState(Throwable exception) {
return exception != null ? ERROR : values()[this.ordinal()+1];
}
/**
* {@return this stage, or {@link #ERROR} if the exception is not {@code null}}
*
* @param exception the exception that occurred during this stage, may be {@code null}
*/
public ModLoadingStage currentState(Throwable exception) {
return exception != null ? ERROR : this;
}
/**
* {@return the deferred work queue for this stage}
*/
public DeferredWorkQueue getDeferredWorkQueue() {
return deferredWorkQueue;
}
@@ -1,33 +1,98 @@
/*
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml;
import net.minecraftforge.eventbus.api.Event;
import net.minecraftforge.fml.event.IModBusEvent;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
import java.util.function.Function;
public record ModLoadingState(String name, String previous, Function<ModList, String> message, ModLoadingPhase phase, Optional<Consumer<ModList>> inlineRunnable, Optional<IModStateTransition> transition) implements IModLoadingState {
/**
* Implementation of the {@link IModLoadingState} interface.
*
* @param name the name of this state
* @param previous the name of the state immediately previous to this state
* @param message a function returning a human-friendly message for this state
* @param phase the mod loading phase this state belongs to
* @param inlineRunnable an optional runnable, which runs before starting the transition from this state to the next
* @param transition optional state transition information
*/
public record ModLoadingState(String name, String previous,
Function<ModList, String> message,
ModLoadingPhase phase,
Optional<Consumer<ModList>> inlineRunnable,
Optional<IModStateTransition> transition) implements IModLoadingState {
@Override
public <T extends Event & IModBusEvent> Optional<CompletableFuture<List<Throwable>>> buildTransition(final Executor syncExecutor, final Executor parallelExecutor, Function<Executor, CompletableFuture<Void>> preSyncTask, Function<Executor, CompletableFuture<Void>> postSyncTask) {
return transition.map(t->t.build(syncExecutor, parallelExecutor, preSyncTask, postSyncTask));
public <T extends Event & IModBusEvent>
Optional<CompletableFuture<Void>> buildTransition(final Executor syncExecutor,
final Executor parallelExecutor,
final Function<Executor, CompletableFuture<Void>> preSyncTask,
final Function<Executor, CompletableFuture<Void>> postSyncTask) {
return transition.map(t -> t.build(syncExecutor, parallelExecutor, preSyncTask, postSyncTask));
}
/**
* {@return an empty mod loading state} The mod loading state has a blank human-readable message, no inline runnable,
* and no state transition information.
*
* @param name the name of the state
* @param previous the name of the immediately previous state to this state
* @param phase the mod loading phase the state belongs to
*/
public static ModLoadingState empty(final String name, final String previous, final ModLoadingPhase phase) {
return new ModLoadingState(name, previous, ml->"", phase, Optional.empty(), Optional.empty());
return new ModLoadingState(name, previous, ml -> "", phase, Optional.empty(), Optional.empty());
}
public static ModLoadingState withTransition(final String name, final String previous, final ModLoadingPhase phase, IModStateTransition transition) {
return new ModLoadingState(name, previous, ml->"Processing transition "+name, phase, Optional.empty(), Optional.of(transition));
/**
* Returns a mod loading state with state transition information and a default human-friendly message of
* {@code Processing transition [name]}.
*
* @param name the name of the state
* @param previous the name of the immediately previous state to this state
* @param phase the mod loading phase the state belongs to
* @param transition the state transition information
* @return a mod loading state with state transition information and a default message
*/
public static ModLoadingState withTransition(final String name, final String previous, final ModLoadingPhase phase,
final IModStateTransition transition) {
return new ModLoadingState(name, previous, ml -> "Processing transition " + name, phase, Optional.empty(), Optional.of(transition));
}
public static ModLoadingState withTransition(final String name, final String previous, final Function<ModList, String> message, final ModLoadingPhase phase, IModStateTransition transition) {
/**
* Returns a mod loading state with state transition information and a custom human-friendly message function.
*
* @param name the name of the state
* @param previous the name of the immediately previous state to this state
* @param message a function returning a human-friendly message for this state
* @param phase the mod loading phase the state belongs to
* @param transition the state transition information
* @return a mod loading state with state transition information and a custom message
*/
public static ModLoadingState withTransition(final String name, final String previous,
final Function<ModList, String> message, final ModLoadingPhase phase,
final IModStateTransition transition) {
return new ModLoadingState(name, previous, message, phase, Optional.empty(), Optional.of(transition));
}
public static ModLoadingState withInline(final String name, final String previous, final ModLoadingPhase phase, Consumer<ModList> inline) {
return new ModLoadingState(name, previous, ml->"Processing work "+name, phase, Optional.of(inline), Optional.empty());
/**
* Returns a mod loading state with an inline runnable and a default human-friendly message of {@code Processing
* work [name]}.
*
* @param name the name of the state
* @param previous the name of the immediately previous state to this state
* @param phase the mod loading phase the state belongs to
* @param inline an optional runnable, which runs before starting the transition from this state to the next
* @return a mod loading state with an inline runnable and default message
*/
public static ModLoadingState withInline(final String name, final String previous, final ModLoadingPhase phase,
final Consumer<ModList> inline) {
return new ModLoadingState(name, previous, ml -> "Processing work " + name, phase, Optional.of(inline), Optional.empty());
}
}
@@ -1,20 +1,6 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml;
@@ -1,3 +1,8 @@
/*
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml;
import com.google.common.graph.GraphBuilder;
@@ -1,20 +1,6 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml;
@@ -1,20 +1,6 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml;
@@ -1,20 +1,6 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml;
@@ -1,3 +1,8 @@
/*
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml;
import java.util.concurrent.Executor;
@@ -1,20 +1,6 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml;
@@ -131,14 +117,22 @@ public class VersionChecker
/**
* Returns the response body as a String for the given URL while following redirects
*/
private String openUrlString(URL url) throws IOException, URISyntaxException, InterruptedException {
private String openUrlString(URL url, IModInfo mod) throws IOException, URISyntaxException, InterruptedException {
URL currentUrl = url;
final StringBuilder sb = new StringBuilder();
sb.append("Java-http-client/").append(System.getProperty("java.version")).append(' ');
sb.append("MinecraftForge/").append(FMLLoader.versionInfo().mcAndForgeVersion()).append(' ');
sb.append(mod.getModId()).append('/').append(mod.getVersion());
final String userAgent = sb.toString();
for (int redirects = 0; redirects < MAX_HTTP_REDIRECTS; redirects++)
{
var request = HttpRequest.newBuilder()
.uri(currentUrl.toURI())
.timeout(Duration.ofSeconds(HTTP_TIMEOUT_SECS))
.setHeader("Accept-Encoding", "gzip")
.setHeader("User-Agent", userAgent)
.GET()
.build();
@@ -180,7 +174,7 @@ public class VersionChecker
URL url = mod.getUpdateURL().get();
LOGGER.info("[{}] Starting version check at {}", mod.getModId(), url.toString());
String data = openUrlString(url);
String data = openUrlString(url, mod);
LOGGER.debug("[{}] Received version check data:\n{}", mod.getModId(), data);
@@ -1,20 +1,6 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml.config;
@@ -24,11 +10,11 @@ import com.electronwill.nightconfig.core.file.CommentedFileConfig;
import com.electronwill.nightconfig.core.file.FileWatcher;
import com.electronwill.nightconfig.core.io.ParsingException;
import com.electronwill.nightconfig.core.io.WritingMode;
import com.mojang.logging.LogUtils;
import net.minecraftforge.fml.loading.FMLConfig;
import net.minecraftforge.fml.loading.FMLPaths;
import org.apache.commons.io.FilenameUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.slf4j.Logger;
import java.io.IOException;
import java.nio.file.Files;
@@ -38,7 +24,7 @@ import java.util.function.Function;
import static net.minecraftforge.fml.config.ConfigTracker.CONFIG;
public class ConfigFileTypeHandler {
private static final Logger LOGGER = LogManager.getLogger();
private static final Logger LOGGER = LogUtils.getLogger();
static ConfigFileTypeHandler TOML = new ConfigFileTypeHandler();
private static final Path defaultConfigPath = FMLPaths.GAMEDIR.get().resolve(FMLConfig.defaultConfigPath());
@@ -81,6 +67,7 @@ public class ConfigFileTypeHandler {
}
private boolean setupConfigFile(final ModConfig modConfig, final Path file, final ConfigFormat<?> conf) throws IOException {
Files.createDirectories(file.getParent());
Path p = defaultConfigPath.resolve(modConfig.getFileName());
if (Files.exists(p)) {
LOGGER.info(CONFIG, "Loading default config file from path {}", p);
@@ -1,38 +1,24 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml.config;
import com.electronwill.nightconfig.core.CommentedConfig;
import com.electronwill.nightconfig.core.file.CommentedFileConfig;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.MarkerManager;
import com.mojang.logging.LogUtils;
import org.slf4j.Logger;
import org.slf4j.Marker;
import org.slf4j.MarkerFactory;
import java.nio.file.Path;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
public class ConfigTracker {
private static final Logger LOGGER = LogManager.getLogger();
static final Marker CONFIG = MarkerManager.getMarker("CONFIG");
private static final Logger LOGGER = LogUtils.getLogger();
static final Marker CONFIG = MarkerFactory.getMarker("CONFIG");
public static final ConfigTracker INSTANCE = new ConfigTracker();
private final ConcurrentHashMap<String, ModConfig> fileMap;
private final EnumMap<ModConfig.Type, Set<ModConfig>> configSets;
@@ -1,3 +1,8 @@
/*
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml.config;
import net.minecraftforge.eventbus.api.Event;
@@ -1,3 +1,8 @@
/*
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml.config;
import com.electronwill.nightconfig.core.CommentedConfig;
@@ -1,20 +1,6 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml.config;
@@ -27,6 +13,7 @@ import net.minecraftforge.fml.loading.StringUtils;
import java.io.ByteArrayInputStream;
import java.nio.file.Path;
import java.util.Locale;
import java.util.concurrent.Callable;
public class ModConfig
@@ -54,7 +41,7 @@ public class ModConfig
private static String defaultConfigName(Type type, String modId) {
// config file name would be "forge-client.toml" and "forge-server.toml"
return String.format("%s-%s.toml", modId, type.extension());
return String.format(Locale.ROOT, "%s-%s.toml", modId, type.extension());
}
public Type getType() {
return type;
@@ -1,20 +1,6 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml.event;
@@ -1,20 +1,6 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml.util;
@@ -1,20 +1,6 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml.util;
@@ -1,20 +1,6 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml.util;
@@ -1,20 +1,6 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml.util;
@@ -1,20 +1,6 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml.util;
@@ -1,20 +1,6 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml.util.thread;
@@ -1,20 +1,6 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml.util.thread;
@@ -1,20 +1,6 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml.util.thread;
+33 -18
View File
@@ -1,6 +1,7 @@
plugins {
id 'com.github.ben-manes.versions'
id 'org.javamodularity.moduleplugin' version '1.8.3' apply false
id 'org.cadixdev.licenser'
}
apply plugin: 'java-library'
apply plugin: 'jacoco'
@@ -10,28 +11,36 @@ dependencyUpdates.rejectVersionIf { isNonStable(it.candidate.version) }
configurations.forEach{ it.transitive = false }
dependencies {
implementation('net.sf.jopt-simple:jopt-simple:5.0.4')
compileOnly('org.jetbrains:annotations:21.0.0')
compileOnly("org.jetbrains:annotations:${JETBRAINS_ANNOTATIONS_VERSION}")
api("org.ow2.asm:asm:${ASM_VERSION}")
api("org.ow2.asm:asm-tree:${ASM_VERSION}")
api("org.ow2.asm:asm-commons:${ASM_VERSION}")
api('net.minecraftforge:forgespi:4.0.+')
api('org.apache.logging.log4j:log4j-api:2.14.1')
api('com.google.guava:guava:21.0')
api('com.google.code.gson:gson:2.8.0')
api('org.apache.maven:maven-artifact:3.8.1')
api('org.apache.commons:commons-lang3:3.8.1')
api('com.electronwill.night-config:core:3.6.3')
api('com.electronwill.night-config:toml:3.6.3')
api('cpw.mods:modlauncher:9.0.+')
api('net.minecraftforge:coremods:5.0.+')
api("net.minecraftforge:forgespi:${SPI_VERSION}")
api("org.apache.logging.log4j:log4j-api:${LOG4J_VERSION}")
api("org.slf4j:slf4j-api:${SLF4J_API_VERSION}")
api("com.google.guava:guava:${GUAVA_VERSION}")
api("com.google.code.gson:gson:${GSON_VERSION}")
api("org.apache.maven:maven-artifact:${APACHE_MAVEN_ARTIFACT_VERSION}")
api("org.apache.commons:commons-lang3:${APACHE_COMMONS_LANG3_VERSION}")
api("com.electronwill.night-config:core:${NIGHTCONFIG_VERSION}")
api("com.electronwill.night-config:toml:${NIGHTCONFIG_VERSION}")
api("cpw.mods:modlauncher:${MODLAUNCHER_VERSION}")
api("net.minecraftforge:coremods:${COREMODS_VERSION}")
api("com.mojang:logging:${MOJANG_LOGGING_VERSION}")
api "net.minecraftforge:JarJarSelector:${JARJAR_VERSION}"
api "net.minecraftforge:JarJarMetadata:${JARJAR_VERSION}"
implementation("net.sf.jopt-simple:jopt-simple:${JOPT_SIMPLE_VERSION}")
implementation("cpw.mods:securejarhandler:${SECUREJARHANDLER_VERSION}")
implementation('org.apache.logging.log4j:log4j-core:2.14.1')
annotationProcessor('org.apache.logging.log4j:log4j-core:2.14.1')
implementation('net.minecraftforge:accesstransformers:8.0.4')
implementation('net.minecrell:terminalconsoleappender:1.2.0')
// implementation('org.jline:jline:3.12.+')
testCompileOnly('org.jetbrains:annotations:21.0.0')
implementation("net.minecraftforge:accesstransformers:${ACCESSTRANSFORMERS_VERSION}")
implementation("net.minecrell:terminalconsoleappender:${TERMINALCONSOLEAPPENDER_VERSION}")
// implementation("org.jline:jline:${JLINE_VERSION}")
implementation("org.apache.logging.log4j:log4j-core:${LOG4J_VERSION}")
annotationProcessor("org.apache.logging.log4j:log4j-core:${LOG4J_VERSION}")
testCompileOnly("org.jetbrains:annotations:${JETBRAINS_ANNOTATIONS_VERSION}")
testRuntimeOnly("cpw.mods:bootstraplauncher:${BOOTSTRAPLAUNCHER_VERSION}")
}
@@ -69,6 +78,12 @@ tasks.withType(JavaCompile) {
options.compilerArgs << '-Xlint:unchecked'
}
license {
header = rootProject.file('LICENSE-header.txt')
include 'net/minecraftforge/'
}
artifacts {
archives jar
archives sourcesJar
@@ -1,20 +1,6 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml.common.asm;
@@ -1,27 +1,18 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml.common.asm;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
@@ -34,26 +25,56 @@ import cpw.mods.modlauncher.serviceapi.ILaunchPluginService;
* Will also de-finalize all fields in on class level annotations.
*/
public class ObjectHolderDefinalize implements ILaunchPluginService {
private final String OBJECT_HOLDER = "Lnet/minecraftforge/registries/ObjectHolder;"; //Don't directly reference this to prevent class loading.
// Hardcoded map of vanilla classes that should have object holders for each field of the given registry type.
// IMPORTANT: Updates to this collection must be reflected in ObjectHolderRegistry. Duplicated cuz classloaders, yay!
// Classnames are validated in ObjectHolderRegistry.
private static final Map<String, VanillaObjectHolderData> VANILLA_OBJECT_HOLDERS = Stream.of(
new VanillaObjectHolderData("net.minecraft.world.level.block.Blocks", "block", "net.minecraft.world.level.block.Block"),
new VanillaObjectHolderData("net.minecraft.world.item.Items", "item", "net.minecraft.world.item.Item"),
new VanillaObjectHolderData("net.minecraft.world.item.enchantment.Enchantments", "enchantment", "net.minecraft.world.item.enchantment.Enchantment"),
new VanillaObjectHolderData("net.minecraft.world.effect.MobEffects", "mob_effect", "net.minecraft.world.effect.MobEffect"),
new VanillaObjectHolderData("net.minecraft.core.particles.ParticleTypes", "particle_type", "net.minecraft.core.particles.ParticleType"),
new VanillaObjectHolderData("net.minecraft.sounds.SoundEvents", "sound_event", "net.minecraft.sounds.SoundEvent")
).collect(Collectors.toMap(VanillaObjectHolderData::holderClass, Function.identity()));
private static final Set<String> VANILLA_OBJECT_HOLDER_CLASSES = VANILLA_OBJECT_HOLDERS.keySet().stream()
.map(it -> it.replace('.', '/'))
.collect(Collectors.toUnmodifiableSet());
private static final String OBJECT_HOLDER = "Lnet/minecraftforge/registries/ObjectHolder;"; //Don't directly reference this to prevent class loading.
private static final int PUBLIC_STATIC_FINAL_FLAGS = Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC | Opcodes.ACC_FINAL;
@Override
public String name() {
return "object_holder_definalize";
}
private static final EnumSet<Phase> YAY = EnumSet.of(Phase.AFTER);
private static final EnumSet<Phase> NAY = EnumSet.noneOf(Phase.class);
@Override
public EnumSet<Phase> handlesClass(Type classType, boolean isEmpty)
{
return isEmpty ? NAY : YAY;
public EnumSet<Phase> handlesClass(Type classType, boolean isEmpty) {
if (isEmpty)
return NAY;
// Let's skip processing classes that definitely don't have object holders
String internalName = classType.getInternalName();
// Forge classes that aren't in the debug package (that package is used for tests)
if (internalName.startsWith("net/minecraftforge/") && !internalName.substring(18).contains("debug")
&& !internalName.equals("net/minecraftforge/common/crafting/ConditionalRecipe"))
return NAY;
// Vanilla classes that don't have object holders
if (internalName.startsWith("com/mojang/"))
return NAY;
// ...except specific ones we added to the VANILLA_OBJECT_HOLDERS map
if (internalName.startsWith("net/minecraft/") && !VANILLA_OBJECT_HOLDER_CLASSES.contains(internalName))
return NAY;
return YAY;
}
private boolean hasHolder(List<AnnotationNode> lst)
{
private boolean hasHolder(List<AnnotationNode> lst) {
return lst != null && lst.stream().anyMatch(n -> n.desc.equals(OBJECT_HOLDER));
}
@@ -76,10 +97,9 @@ public class ObjectHolderDefinalize implements ILaunchPluginService {
{
final AtomicBoolean changes = new AtomicBoolean();
//Must be public static finals, and non-array objects
final int flags = Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC | Opcodes.ACC_FINAL;
//Fix Annotated Fields before injecting from class level
classNode.fields.stream().filter(f -> ((f.access & flags) == flags) && f.desc.startsWith("L") && hasHolder(f.visibleAnnotations)).forEach(f ->
classNode.fields.stream().filter(f -> ((f.access & PUBLIC_STATIC_FINAL_FLAGS) == PUBLIC_STATIC_FINAL_FLAGS) && f.desc.startsWith("L") && hasHolder(f.visibleAnnotations)).forEach(f ->
{
int prev = f.access;
f.access &= ~Opcodes.ACC_FINAL; //Strip final
@@ -87,11 +107,9 @@ public class ObjectHolderDefinalize implements ILaunchPluginService {
changes.compareAndSet(false, prev != f.access);
});
if (hasHolder(classNode.visibleAnnotations)) //Class level, de-finalize all fields and add @ObjectHolder to them!
if (VANILLA_OBJECT_HOLDERS.containsKey(classType.getClassName())) //Class level, de-finalize all fields and add @ObjectHolder to them!
{
@SuppressWarnings("unused")
String value = getValue(classNode.visibleAnnotations);
classNode.fields.stream().filter(f -> ((f.access & flags) == flags) && f.desc.startsWith("L")).forEach(f ->
classNode.fields.stream().filter(f -> ((f.access & PUBLIC_STATIC_FINAL_FLAGS) == PUBLIC_STATIC_FINAL_FLAGS) && f.desc.startsWith("L")).forEach(f ->
{
int prev = f.access;
f.access &= ~Opcodes.ACC_FINAL;
@@ -109,4 +127,5 @@ public class ObjectHolderDefinalize implements ILaunchPluginService {
return changes.get() ? ComputeFlags.SIMPLE_REWRITE : ComputeFlags.NO_REWRITE;
}
private record VanillaObjectHolderData(String holderClass, String registryName, String registryType) {}
}
@@ -1,20 +1,6 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml.common.asm;
@@ -23,9 +9,7 @@ import java.util.EnumSet;
import java.util.List;
import java.util.stream.Collectors;
import net.minecraftforge.fml.loading.AdvancedLogMessageAdapter;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.mojang.logging.LogUtils;
import org.objectweb.asm.Label;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
@@ -35,6 +19,9 @@ import org.objectweb.asm.tree.FieldNode;
import org.objectweb.asm.tree.MethodNode;
import cpw.mods.modlauncher.serviceapi.ILaunchPluginService;
import org.slf4j.Logger;
import org.slf4j.Marker;
import org.slf4j.MarkerFactory;
/**
* Modifies specified enums to allow runtime extension by making the $VALUES field non-final and
@@ -42,7 +29,7 @@ import cpw.mods.modlauncher.serviceapi.ILaunchPluginService;
*/
public class RuntimeEnumExtender implements ILaunchPluginService {
private static final Logger LOGGER = LogManager.getLogger();
private static final Logger LOGGER = LogUtils.getLogger();
private final Type STRING = Type.getType(String.class);
private final Type ENUM = Type.getType(Enum.class);
private final Type MARKER_IFACE = Type.getType("Lnet/minecraftforge/common/IExtensibleEnum;");
@@ -77,43 +64,49 @@ public class RuntimeEnumExtender implements ILaunchPluginService {
final int flags = Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC | Opcodes.ACC_FINAL | Opcodes.ACC_SYNTHETIC;
FieldNode values = classNode.fields.stream().filter(f -> f.desc.contentEquals(array.getDescriptor()) && ((f.access & flags) == flags)).findFirst().orElse(null);
if (!classNode.interfaces.contains(MARKER_IFACE.getInternalName())) {
return ComputeFlags.NO_REWRITE;
}
//Static methods named "create" with first argument as a string
List<MethodNode> candidates = classNode.methods.stream()
.filter(m -> ((m.access & Opcodes.ACC_STATIC) != 0) && m.name.equals("create"))
.collect(Collectors.toList());
if (candidates.isEmpty()) {
throw new IllegalStateException("IExtensibleEnum has no candidate factory methods: " + classType.getClassName());
}
candidates.forEach(mtd ->
{
Type[] args = Type.getArgumentTypes(mtd.desc);
if (args.length == 0 || !args[0].equals(STRING)) {
LOGGER.fatal(()->new AdvancedLogMessageAdapter(sb-> {
if (LOGGER.isErrorEnabled(LogUtils.FATAL_MARKER))
{
StringBuilder sb = new StringBuilder();
sb.append("Enum has create method without String as first parameter:\n");
sb.append(" Enum: ").append(classType.getDescriptor()).append("\n");
sb.append(" Target: ").append(mtd.name).append(mtd.desc).append("\n");
}));
LOGGER.error(LogUtils.FATAL_MARKER, sb.toString());
}
throw new IllegalStateException("Enum has create method without String as first parameter: " + mtd.name + mtd.desc);
}
Type ret = Type.getReturnType(mtd.desc);
if (!ret.equals(classType)) {
LOGGER.fatal(()->new AdvancedLogMessageAdapter(sb-> {
if (LOGGER.isErrorEnabled(LogUtils.FATAL_MARKER))
{
StringBuilder sb = new StringBuilder();
sb.append("Enum has create method with incorrect return type:\n");
sb.append(" Enum: ").append(classType.getDescriptor()).append("\n");
sb.append(" Target: ").append(mtd.name).append(mtd.desc).append("\n");
sb.append(" Found: ").append(ret.getClassName()).append(", Expected: ").append(classType.getClassName());
}));
LOGGER.error(LogUtils.FATAL_MARKER, sb.toString());
}
throw new IllegalStateException("Enum has create method with incorrect return type: " + mtd.name + mtd.desc);
}
Type[] ctrArgs = new Type[args.length + 1];
ctrArgs[0] = STRING;
ctrArgs[1] = Type.INT_TYPE;
@@ -125,23 +118,29 @@ public class RuntimeEnumExtender implements ILaunchPluginService {
MethodNode ctr = classNode.methods.stream().filter(m -> m.name.equals("<init>") && m.desc.equals(desc)).findFirst().orElse(null);
if (ctr == null)
{
LOGGER.fatal(()->new AdvancedLogMessageAdapter(sb-> {
if (LOGGER.isErrorEnabled(LogUtils.FATAL_MARKER))
{
StringBuilder sb = new StringBuilder();
sb.append("Enum has create method with no matching constructor:\n");
sb.append(" Enum: ").append(classType.getDescriptor()).append("\n");
sb.append(" Candidate: ").append(mtd.desc).append("\n");
sb.append(" Target: ").append(desc).append("\n");
classNode.methods.stream().filter(m -> m.name.equals("<init>")).forEach(m -> sb.append(" : ").append(m.desc).append("\n"));
}));
LOGGER.error(LogUtils.FATAL_MARKER, sb.toString());
}
throw new IllegalStateException("Enum has create method with no matching constructor: " + desc);
}
if (values == null)
{
LOGGER.fatal(()->new AdvancedLogMessageAdapter(sb-> {
if (LOGGER.isErrorEnabled(LogUtils.FATAL_MARKER))
{
StringBuilder sb = new StringBuilder();
sb.append("Enum has create method but we could not find $VALUES. Found:\n");
classNode.fields.stream().filter(f -> (f.access & Opcodes.ACC_STATIC) != 0).
forEach(m -> sb.append(" ").append(m.name).append(" ").append(m.desc).append("\n"));
}));
LOGGER.error(LogUtils.FATAL_MARKER, sb.toString());
}
throw new IllegalStateException("Enum has create method but we could not find $VALUES");
}
@@ -149,6 +148,19 @@ public class RuntimeEnumExtender implements ILaunchPluginService {
mtd.access |= Opcodes.ACC_SYNCHRONIZED;
mtd.instructions.clear();
mtd.localVariables.clear();
if (mtd.tryCatchBlocks != null)
{
mtd.tryCatchBlocks.clear();
}
if (mtd.visibleLocalVariableAnnotations != null)
{
mtd.visibleLocalVariableAnnotations.clear();
}
if (mtd.invisibleLocalVariableAnnotations != null)
{
mtd.invisibleLocalVariableAnnotations.clear();
}
InstructionAdapter ins = new InstructionAdapter(mtd);
int vars = 0;
@@ -1,62 +0,0 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.fml.loading;
import org.apache.logging.log4j.message.Message;
import org.apache.logging.log4j.util.StringBuilderFormattable;
import java.util.function.Consumer;
public class AdvancedLogMessageAdapter implements Message, StringBuilderFormattable {
private static final long serialVersionUID = -8291754833965087436L;
private static final Object[] EMPTY = new Object[0];
private final Consumer<StringBuilder> logMessageBuilder;
public AdvancedLogMessageAdapter(final Consumer<StringBuilder> logMessageBuilder) {
this.logMessageBuilder = logMessageBuilder;
}
@Override
public String getFormattedMessage() {
return "";
}
@Override
public String getFormat() {
return "";
}
@Override
public Object[] getParameters() {
return EMPTY;
}
@Override
public Throwable getThrowable() {
return null;
}
@Override
public void formatTo(final StringBuilder buffer) {
logMessageBuilder.accept(buffer);
}
}
@@ -1,20 +1,6 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml.loading;
@@ -0,0 +1,38 @@
/*
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml.loading;
import com.mojang.logging.LogUtils;
import org.slf4j.Logger;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Path;
import java.nio.file.Paths;
public class ClasspathLocatorUtils {
private static final Logger LOGGER = LogUtils.getLogger();
public static Path findJarPathFor(final String resourceName, final String jarName, final URL resource) {
try {
Path path;
final URI uri = resource.toURI();
if (uri.getScheme().equals("jar") && uri.getRawSchemeSpecificPart().contains("!/")) {
int lastExcl = uri.getRawSchemeSpecificPart().lastIndexOf("!/");
path = Paths.get(new URI(uri.getRawSchemeSpecificPart().substring(0, lastExcl)));
} else {
path = Paths.get(new URI("file://"+uri.getRawSchemeSpecificPart().substring(0, uri.getRawSchemeSpecificPart().length()-resourceName.length())));
}
//LOGGER.debug(CORE, "Found JAR {} at path {}", jarName, path.toString());
return path;
} catch (NullPointerException | URISyntaxException e) {
LOGGER.error(LogMarkers.SCAN, "Failed to find JAR for class {} - {}", resourceName, jarName);
throw new RuntimeException("Unable to locate "+resourceName+" - "+jarName, e);
}
}
}
@@ -0,0 +1,61 @@
/*
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml.loading;
import cpw.mods.modlauncher.api.NamedPath;
import cpw.mods.modlauncher.serviceapi.ITransformerDiscoveryService;
import org.apache.logging.log4j.LogManager;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
public class ClasspathTransformerDiscoverer implements ITransformerDiscoveryService {
private final List<Path> legacyClasspath = Arrays.stream(System.getProperty("legacyClassPath", "").split(File.pathSeparator)).map(Path::of).toList();
@Override
public List<NamedPath> candidates(Path gameDirectory) {
return Collections.emptyList();
}
@Override
public List<NamedPath> candidates(final Path gameDirectory, final String launchTarget) {
if (launchTarget != null && launchTarget.contains("dev")) {
this.scan(gameDirectory);
}
return List.copyOf(found);
}
private final static List<NamedPath> found = new ArrayList<>();
public static List<Path> allExcluded() {
return found.stream().map(np->np.paths()[0]).toList();
}
private void scan(final Path gameDirectory) {
try {
locateTransformers("META-INF/services/cpw.mods.modlauncher.api.ITransformationService");
locateTransformers("META-INF/services/net.minecraftforge.forgespi.locating.IModLocator");
} catch (IOException e) {
LogManager.getLogger().error("Error during discovery of transform services from the classpath", e);
}
}
private void locateTransformers(String resource) throws IOException {
final Enumeration<URL> resources = ClassLoader.getSystemClassLoader().getResources(resource);
while (resources.hasMoreElements()) {
URL url = resources.nextElement();
Path path = ClasspathLocatorUtils.findJarPathFor(resource, url.toString(), url);
if (legacyClasspath.stream().anyMatch(path::equals) || !Files.exists(path) || Files.isDirectory(path))
continue;
found.add(new NamedPath(path.toUri().toString(), path));
}
}
}
@@ -1,20 +1,6 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml.loading;
@@ -61,7 +47,7 @@ public class EarlyLoadingException extends RuntimeException {
return errorMessages;
}
EarlyLoadingException(final String message, final Throwable originalException, List<ExceptionData> errorMessages) {
public EarlyLoadingException(final String message, final Throwable originalException, List<ExceptionData> errorMessages) {
super(message, originalException);
this.errorMessages = errorMessages;
}
@@ -1,20 +1,6 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml.loading;
@@ -24,8 +10,8 @@ import com.electronwill.nightconfig.core.file.CommentedFileConfig;
import com.electronwill.nightconfig.core.file.FileNotFoundAction;
import com.electronwill.nightconfig.core.io.ParsingException;
import com.electronwill.nightconfig.core.io.WritingMode;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.mojang.logging.LogUtils;
import org.slf4j.Logger;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -35,7 +21,7 @@ import static net.minecraftforge.fml.loading.LogMarkers.CORE;
public class FMLConfig
{
private static final Logger LOGGER = LogManager.getLogger();
private static final Logger LOGGER = LogUtils.getLogger();
private static FMLConfig INSTANCE = new FMLConfig();
private static ConfigSpec configSpec = new ConfigSpec();
static {
@@ -43,6 +29,7 @@ public class FMLConfig
configSpec.define("maxThreads", -1);
configSpec.define("versionCheck", Boolean.TRUE);
configSpec.define("defaultConfigPath", "defaultconfigs");
configSpec.define("disableOptimizedDFU", Boolean.TRUE);
}
private CommentedFileConfig configData;
@@ -74,11 +61,14 @@ public class FMLConfig
{
final Path configFile = FMLPaths.FMLCONFIG.get();
INSTANCE.loadFrom(configFile);
LOGGER.trace(CORE, "Loaded FML config from {}", FMLPaths.FMLCONFIG.get());
LOGGER.trace(CORE, "Splash screen is {}", FMLConfig::splashScreenEnabled);
LOGGER.trace(CORE, "Max threads for mod loading computed at {}", FMLConfig::loadingThreadCount);
LOGGER.trace(CORE, "Version check is {}", FMLConfig::runVersionCheck);
LOGGER.trace(CORE, "Default config paths at {}", FMLConfig::defaultConfigPath);
if (LOGGER.isTraceEnabled(CORE))
{
LOGGER.trace(CORE, "Loaded FML config from {}", FMLPaths.FMLCONFIG.get());
LOGGER.trace(CORE, "Splash screen is {}", FMLConfig.splashScreenEnabled());
LOGGER.trace(CORE, "Max threads for mod loading computed at {}", FMLConfig.loadingThreadCount());
LOGGER.trace(CORE, "Version check is {}", FMLConfig.runVersionCheck());
LOGGER.trace(CORE, "Default config paths at {}", FMLConfig.defaultConfigPath());
}
FMLPaths.getOrCreateGameRelativePath(Paths.get(FMLConfig.defaultConfigPath()), "default config directory");
}
@@ -99,4 +89,8 @@ public class FMLConfig
public static String defaultConfigPath() {
return INSTANCE.configData.<String>getOptional("defaultConfigPath").orElse("defaultconfigs");
}
public static boolean isOptimizedDFUDisabled() {
return INSTANCE.configData.<Boolean>getOptional("disableOptimizedDFU").orElse(Boolean.TRUE);
}
}
@@ -1,20 +1,6 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml.loading;
@@ -1,24 +1,11 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml.loading;
import com.mojang.logging.LogUtils;
import cpw.mods.modlauncher.Launcher;
import cpw.mods.modlauncher.api.*;
import cpw.mods.modlauncher.serviceapi.ILaunchPluginService;
@@ -35,8 +22,7 @@ import net.minecraftforge.fml.loading.targets.CommonLaunchHandler;
import net.minecraftforge.forgespi.Environment;
import net.minecraftforge.forgespi.coremod.ICoreModProvider;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.slf4j.Logger;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -49,7 +35,7 @@ import static net.minecraftforge.fml.loading.LogMarkers.SCAN;
public class FMLLoader
{
private static final Logger LOGGER = LogManager.getLogger();
private static final Logger LOGGER = LogUtils.getLogger();
private static AccessTransformerService accessTransformer;
private static ModDiscoverer modDiscoverer;
private static ICoreModProvider coreModProvider;
@@ -76,47 +62,50 @@ public class FMLLoader
final Package modLauncherPackage = ITransformationService.class.getPackage();
LOGGER.debug(CORE,"FML found ModLauncher version : {}", modLauncherPackage.getImplementationVersion());
if (!modLauncherPackage.isCompatibleWith("4.0")) {
LOGGER.fatal(CORE,"Found incompatible ModLauncher specification : {}, version {} from {}", modLauncherPackage.getSpecificationVersion(), modLauncherPackage.getImplementationVersion(), modLauncherPackage.getImplementationVendor());
LOGGER.error(CORE, "Found incompatible ModLauncher specification : {}, version {} from {}", modLauncherPackage.getSpecificationVersion(), modLauncherPackage.getImplementationVersion(), modLauncherPackage.getImplementationVendor());
throw new IncompatibleEnvironmentException("Incompatible modlauncher found "+modLauncherPackage.getSpecificationVersion());
}
// Allows us to communicate properties with other services through ModLauncher
setupBlackboardKeys();
accessTransformer = (AccessTransformerService) environment.findLaunchPlugin("accesstransformer").orElseThrow(()-> {
LOGGER.fatal(CORE,"Access Transformer library is missing, we need this to run");
LOGGER.error(CORE, "Access Transformer library is missing, we need this to run");
return new IncompatibleEnvironmentException("Missing AccessTransformer, cannot run");
});
final Package atPackage = accessTransformer.getClass().getPackage();
LOGGER.debug(CORE,"FML found AccessTransformer version : {}", atPackage.getImplementationVersion());
if (!atPackage.isCompatibleWith("1.0")) {
LOGGER.fatal(CORE,"Found incompatible AccessTransformer specification : {}, version {} from {}", atPackage.getSpecificationVersion(), atPackage.getImplementationVersion(), atPackage.getImplementationVendor());
LOGGER.error(CORE, "Found incompatible AccessTransformer specification : {}, version {} from {}", atPackage.getSpecificationVersion(), atPackage.getImplementationVersion(), atPackage.getImplementationVendor());
throw new IncompatibleEnvironmentException("Incompatible accesstransformer found "+atPackage.getSpecificationVersion());
}
eventBus = environment.findLaunchPlugin("eventbus").orElseThrow(()-> {
LOGGER.fatal(CORE,"Event Bus library is missing, we need this to run");
LOGGER.error(CORE, "Event Bus library is missing, we need this to run");
return new IncompatibleEnvironmentException("Missing EventBus, cannot run");
});
final Package eventBusPackage = eventBus.getClass().getPackage();
LOGGER.debug(CORE,"FML found EventBus version : {}", eventBusPackage.getImplementationVersion());
if (!eventBusPackage.isCompatibleWith("1.0")) {
LOGGER.fatal(CORE,"Found incompatible EventBus specification : {}, version {} from {}", eventBusPackage.getSpecificationVersion(), eventBusPackage.getImplementationVersion(), eventBusPackage.getImplementationVendor());
LOGGER.error(CORE, "Found incompatible EventBus specification : {}, version {} from {}", eventBusPackage.getSpecificationVersion(), eventBusPackage.getImplementationVersion(), eventBusPackage.getImplementationVendor());
throw new IncompatibleEnvironmentException("Incompatible eventbus found "+eventBusPackage.getSpecificationVersion());
}
runtimeDistCleaner = (RuntimeDistCleaner)environment.findLaunchPlugin("runtimedistcleaner").orElseThrow(()-> {
LOGGER.fatal(CORE,"Dist Cleaner is missing, we need this to run");
LOGGER.error(CORE, "Dist Cleaner is missing, we need this to run");
return new IncompatibleEnvironmentException("Missing DistCleaner, cannot run!");
});
LOGGER.debug(CORE, "Found Runtime Dist Cleaner");
var coreModProviders = ServiceLoaderUtils.streamWithErrorHandling(ServiceLoader.load(FMLLoader.class.getModule().getLayer(), ICoreModProvider.class), sce -> LOGGER.fatal(CORE, "Failed to load a coremod library, expect problems", sce)).toList();
var coreModProviders = ServiceLoaderUtils.streamWithErrorHandling(ServiceLoader.load(FMLLoader.class.getModule().getLayer(), ICoreModProvider.class), sce -> LOGGER.error(CORE, "Failed to load a coremod library, expect problems", sce)).toList();
if (coreModProviders.isEmpty()) {
LOGGER.fatal(CORE, "Found no coremod provider. Cannot run");
LOGGER.error(CORE, "Found no coremod provider. Cannot run");
throw new IncompatibleEnvironmentException("No coremod library found");
} else if (coreModProviders.size() > 1) {
LOGGER.fatal(CORE, "Found multiple coremod providers : {}. Cannot run", coreModProviders.stream().map(p -> p.getClass().getName()).collect(Collectors.toList()));
LOGGER.error(CORE, "Found multiple coremod providers : {}. Cannot run", coreModProviders.stream().map(p -> p.getClass().getName()).collect(Collectors.toList()));
throw new IncompatibleEnvironmentException("Multiple coremod libraries found");
}
@@ -128,7 +117,7 @@ public class FMLLoader
LOGGER.debug(CORE, "Found ForgeSPI package implementation version {}", Environment.class.getPackage().getImplementationVersion());
LOGGER.debug(CORE, "Found ForgeSPI package specification {}", Environment.class.getPackage().getSpecificationVersion());
if (Integer.parseInt(Environment.class.getPackage().getSpecificationVersion()) < 2) {
LOGGER.fatal(CORE, "Found an out of date ForgeSPI implementation: {}, loading cannot continue", Environment.class.getPackage().getSpecificationVersion());
LOGGER.error(CORE, "Found an out of date ForgeSPI implementation: {}, loading cannot continue", Environment.class.getPackage().getSpecificationVersion());
throw new IncompatibleEnvironmentException("ForgeSPI is out of date, we cannot continue");
}
@@ -136,11 +125,17 @@ public class FMLLoader
Class.forName("com.electronwill.nightconfig.core.Config", false, environment.getClass().getClassLoader());
Class.forName("com.electronwill.nightconfig.toml.TomlFormat", false, environment.getClass().getClassLoader());
} catch (ClassNotFoundException e) {
LOGGER.fatal(CORE, "Failed to load NightConfig");
LOGGER.error(CORE, "Failed to load NightConfig");
throw new IncompatibleEnvironmentException("Missing NightConfig");
}
}
private static void setupBlackboardKeys() {
LOGGER.debug(CORE, "Requesting CoreMods to not apply the fix for ASMAPI.findFirstInstructionBefore by default");
var blackboardKey = TypesafeMap.Key.getOrCreate(Launcher.INSTANCE.blackboard(), "coremods.use_old_findFirstInstructionBefore", Boolean.class);
Launcher.INSTANCE.blackboard().<Boolean>computeIfAbsent(blackboardKey, k -> true);
}
static void setupLaunchHandler(final IEnvironment environment, final Map<String, Object> arguments)
{
final String launchTarget = environment.getProperty(IEnvironment.Keys.LAUNCHTARGET.get()).orElse("MISSING");
@@ -148,12 +143,12 @@ public class FMLLoader
final Optional<ILaunchHandlerService> launchHandler = environment.findLaunchHandler(launchTarget);
LOGGER.debug(CORE, "Using {} as launch service", launchTarget);
if (launchHandler.isEmpty()) {
LOGGER.fatal(CORE,"Missing LaunchHandler {}, cannot continue", launchTarget);
LOGGER.error(CORE, "Missing LaunchHandler {}, cannot continue", launchTarget);
throw new RuntimeException("Missing launch handler: " + launchTarget);
}
if (!(launchHandler.get() instanceof CommonLaunchHandler)) {
LOGGER.fatal(CORE, "Incompatible Launch handler found - type {}, cannot continue", launchHandler.get().getClass().getName());
LOGGER.error(CORE, "Incompatible Launch handler found - type {}, cannot continue", launchHandler.get().getClass().getName());
throw new RuntimeException("Incompatible launch handler found");
}
commonLaunchHandler = (CommonLaunchHandler)launchHandler.get();
@@ -1,27 +1,13 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml.loading;
import com.mojang.logging.LogUtils;
import cpw.mods.modlauncher.api.IEnvironment;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.slf4j.Logger;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -36,7 +22,7 @@ public enum FMLPaths
CONFIGDIR("config"),
FMLCONFIG(false, CONFIGDIR, "fml.toml");
private static final Logger LOGGER = LogManager.getLogger();
private static final Logger LOGGER = LogUtils.getLogger();
private final Path relativePath;
private final boolean isDirectory;
private Path absolutePath;
@@ -75,7 +61,10 @@ public enum FMLPaths
{
FileUtils.getOrCreateDirectory(path.absolutePath, path.name());
}
LOGGER.debug(CORE,"Path {} is {}", ()-> path, ()-> path.absolutePath);
if (LOGGER.isDebugEnabled(CORE))
{
LOGGER.debug(CORE, "Path {} is {}", path, path.absolutePath);
}
}
}
@@ -1,32 +1,18 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml.loading;
import com.mojang.logging.LogUtils;
import cpw.mods.modlauncher.api.*;
import joptsimple.ArgumentAcceptingOptionSpec;
import joptsimple.OptionSpecBuilder;
import net.minecraftforge.fml.loading.moddiscovery.ModFile;
import net.minecraftforge.forgespi.Environment;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import java.util.ArrayList;
import java.util.Arrays;
@@ -40,7 +26,7 @@ import static net.minecraftforge.fml.loading.LogMarkers.CORE;
public class FMLServiceProvider implements ITransformationService
{
private static final Logger LOGGER = LogManager.getLogger();
private static final Logger LOGGER = LogUtils.getLogger();
private ArgumentAcceptingOptionSpec<String> modsOption;
private ArgumentAcceptingOptionSpec<String> modListsOption;
private ArgumentAcceptingOptionSpec<String> mavenRootsOption;
@@ -1,27 +1,14 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml.loading;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.mojang.logging.LogUtils;
import org.slf4j.Logger;
import java.io.File;
import java.io.IOException;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.Files;
@@ -31,7 +18,7 @@ import static net.minecraftforge.fml.loading.LogMarkers.CORE;
public class FileUtils
{
private static final Logger LOGGER = LogManager.getLogger();
private static final Logger LOGGER = LogUtils.getLogger();
public static Path getOrCreateDirectory(Path dirPath, String dirLabel) {
if (!Files.isDirectory(dirPath.getParent())) {
@@ -39,20 +26,20 @@ public class FileUtils
}
if (!Files.isDirectory(dirPath))
{
LOGGER.debug(CORE,"Making {} directory : {}", dirLabel, dirPath);
LOGGER.debug(CORE, "Making {} directory : {}", dirLabel, dirPath);
try {
Files.createDirectory(dirPath);
} catch (IOException e) {
if (e instanceof FileAlreadyExistsException) {
LOGGER.fatal(CORE,"Failed to create {} directory - there is a file in the way", dirLabel);
LOGGER.error(CORE, "Failed to create {} directory - there is a file in the way", dirLabel);
} else {
LOGGER.fatal(CORE,"Problem with creating {} directory (Permissions?)", dirLabel, e);
LOGGER.error(CORE, "Problem with creating {} directory (Permissions?)", dirLabel, e);
}
throw new RuntimeException("Problem creating directory", e);
}
LOGGER.debug(CORE,"Created {} directory : {}", dirLabel, dirPath);
LOGGER.debug(CORE, "Created {} directory : {}", dirLabel, dirPath);
} else {
LOGGER.debug(CORE,"Found existing {} directory : {}", dirLabel, dirPath);
LOGGER.debug(CORE, "Found existing {} directory : {}", dirLabel, dirPath);
}
return dirPath;
}
@@ -67,4 +54,16 @@ public class FileUtils
return "";
}
}
public static boolean matchFileName(String path, String... matches) {
// Extract file name from path
String name = path.substring(Math.min(path.lastIndexOf(File.separatorChar) + 1, path.length()));
// Check if it contains any of the desired keywords
for (String match : matches) {
if (name.contains(match)) {
return true;
}
}
return false;
}
}
@@ -1,20 +1,6 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml.loading;
@@ -1,24 +1,11 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml.loading;
import com.mojang.logging.LogUtils;
import cpw.mods.modlauncher.Launcher;
import cpw.mods.modlauncher.api.IModuleLayerManager;
import cpw.mods.modlauncher.util.ServiceLoaderUtils;
@@ -26,11 +13,10 @@ import net.minecraftforge.fml.loading.progress.StartupMessageManager;
import net.minecraftforge.forgespi.language.IModLanguageProvider;
import net.minecraftforge.fml.loading.moddiscovery.ExplodedDirectoryLocator;
import net.minecraftforge.fml.loading.moddiscovery.ModFile;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.maven.artifact.versioning.ArtifactVersion;
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
import org.apache.maven.artifact.versioning.VersionRange;
import org.slf4j.Logger;
import java.net.URISyntaxException;
import java.nio.file.Files;
@@ -52,7 +38,7 @@ import static net.minecraftforge.fml.loading.LogMarkers.LOADING;
public class LanguageLoadingProvider
{
private static final Logger LOGGER = LogManager.getLogger();
private static final Logger LOGGER = LogUtils.getLogger();
private final List<IModLanguageProvider> languageProviders = new ArrayList<>();
private final ServiceLoader<IModLanguageProvider> serviceLoader;
private final Map<String, ModLanguageWrapper> languageProviderMap = new HashMap<>();
@@ -95,7 +81,7 @@ public class LanguageLoadingProvider
loadLanguageProviders();
}
private void loadLanguageProviders() {
LOGGER.debug(CORE, "Found {} language providers", ServiceLoaderUtils.streamServiceLoader(()->serviceLoader, sce->LOGGER.fatal("Problem with language loaders")).count());
LOGGER.debug(CORE, "Found {} language providers", ServiceLoaderUtils.streamServiceLoader(()->serviceLoader, sce->LOGGER.error("Problem with language loaders")).count());
serviceLoader.forEach(languageProviders::add);
languageProviders.forEach(lp -> {
@@ -108,7 +94,7 @@ public class LanguageLoadingProvider
Optional<String> implementationVersion = JarVersionLookupHandler.getImplementationVersion(lp.getClass());
String impl = implementationVersion.orElse(Files.isDirectory(lpPath) ? FMLLoader.versionInfo().forgeVersion().split("\\.")[0] : null);
if (impl == null) {
LOGGER.fatal(CORE, "Found unversioned language provider {}", lp.name());
LOGGER.error(CORE, "Found unversioned language provider {}", lp.name());
throw new RuntimeException("Failed to find implementation version for language provider "+ lp.name());
}
LOGGER.debug(CORE, "Found language provider {}, version {}", lp.name(), impl);
@@ -148,7 +134,7 @@ public class LanguageLoadingProvider
}
public IModLanguageProvider findLanguage(ModFile mf, String modLoader, VersionRange modLoaderVersion) {
final String languageFileName = mf.getLocator() instanceof ExplodedDirectoryLocator ? "in-development" : mf.getFileName();
final String languageFileName = mf.getProvider() instanceof ExplodedDirectoryLocator ? "in-development" : mf.getFileName();
final ModLanguageWrapper mlw = languageProviderMap.get(modLoader);
if (mlw == null) {
LOGGER.error(LOADING,"Missing language {} version {} wanted by {}", modLoader, modLoaderVersion, languageFileName);
@@ -1,31 +1,17 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml.loading;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.mojang.logging.LogUtils;
import org.slf4j.Logger;
import static net.minecraftforge.fml.loading.LogMarkers.CORE;
public class LauncherVersion {
private static final Logger LOGGER = LogManager.getLogger();
private static final Logger LOGGER = LogUtils.getLogger();
private static final String launcherVersion;
static {
@@ -1,32 +1,18 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml.loading;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.mojang.logging.LogUtils;
import org.slf4j.Logger;
import java.nio.file.Files;
import java.nio.file.Path;
public class LibraryFinder {
private static final Logger LOGGER = LogManager.getLogger();
private static final Logger LOGGER = LogUtils.getLogger();
private static Path libsPath;
static Path findLibsPath() {
if (libsPath == null) {
@@ -1,20 +1,6 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml.loading;
@@ -24,11 +10,18 @@ import net.minecraftforge.fml.loading.moddiscovery.BackgroundScanHandler;
import net.minecraftforge.fml.loading.moddiscovery.ModFile;
import net.minecraftforge.fml.loading.moddiscovery.ModFileInfo;
import net.minecraftforge.fml.loading.moddiscovery.ModInfo;
import net.minecraftforge.forgespi.locating.IModFile;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.stream.Collectors;
/**
@@ -42,7 +35,7 @@ public class LoadingModList
private final List<ModInfo> sortedList;
private final Map<String, ModFileInfo> fileById;
private final List<EarlyLoadingException> preLoadErrors;
private List<ModFile> brokenFiles;
private List<IModFile> brokenFiles;
private LoadingModList(final List<ModFile> modFiles, final List<ModInfo> sortedList)
{
@@ -168,11 +161,11 @@ public class LoadingModList
return preLoadErrors;
}
public void setBrokenFiles(final List<ModFile> brokenFiles) {
public void setBrokenFiles(final List<IModFile> brokenFiles) {
this.brokenFiles = brokenFiles;
}
public List<ModFile> getBrokenFiles() {
public List<IModFile> getBrokenFiles() {
return this.brokenFiles;
}
}
@@ -1,30 +1,16 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml.loading;
import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.MarkerManager;
import org.slf4j.Marker;
import org.slf4j.MarkerFactory;
public class LogMarkers {
public static final Marker CORE = MarkerManager.getMarker("CORE");
public static final Marker LOADING = MarkerManager.getMarker("LOADING");
public static final Marker SCAN = MarkerManager.getMarker("SCAN");
public static final Marker SPLASH = MarkerManager.getMarker("SPLASH");
public static final Marker CORE = MarkerFactory.getMarker("CORE");
public static final Marker LOADING = MarkerFactory.getMarker("LOADING");
public static final Marker SCAN = MarkerFactory.getMarker("SCAN");
public static final Marker SPLASH = MarkerFactory.getMarker("SPLASH");
}
@@ -1,9 +1,14 @@
/*
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml.loading;
import com.mojang.logging.LogUtils;
import cpw.mods.modlauncher.api.INameMappingService;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.slf4j.Logger;
import java.io.BufferedReader;
import java.io.IOException;
@@ -15,7 +20,7 @@ import java.util.function.BiConsumer;
import java.util.function.BiFunction;
public class MCPNamingService implements INameMappingService {
private static final Logger LOGGER = LogManager.getLogger();
private static final Logger LOGGER = LogUtils.getLogger();
private HashMap<String, String> methods;
private HashMap<String, String> fields;
@@ -1,20 +1,6 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml.loading;
@@ -1,38 +1,33 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml.loading;
import com.mojang.logging.LogUtils;
import cpw.mods.jarhandling.SecureJar;
import cpw.mods.modlauncher.api.LamdbaExceptionUtils;
import cpw.mods.modlauncher.api.NamedPath;
import cpw.mods.modlauncher.serviceapi.ITransformerDiscoveryService;
import org.apache.logging.log4j.LogManager;
import org.slf4j.Logger;
import java.io.File;
import java.io.IOException;
import java.lang.module.ModuleDescriptor;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipFile;
import java.util.Set;
public class ModDirTransformerDiscoverer implements ITransformerDiscoveryService {
private static final Logger LOGGER = LogUtils.getLogger();
private static final Set<String> SERVICES = Set.of(
"cpw.mods.modlauncher.api.ITransformationService",
"net.minecraftforge.forgespi.locating.IModLocator",
"net.minecraftforge.forgespi.locating.IDependencyLocator"
);
@Override
public List<NamedPath> candidates(final Path gameDirectory) {
ModDirTransformerDiscoverer.scan(gameDirectory);
@@ -54,7 +49,7 @@ public class ModDirTransformerDiscoverer implements ITransformerDiscoveryService
try (var walk = Files.walk(modsDir, 1)){
walk.forEach(ModDirTransformerDiscoverer::visitFile);
} catch (IOException | IllegalStateException ioe) {
LogManager.getLogger().error("Error during early discovery", ioe);
LOGGER.error("Error during early discovery", ioe);
}
}
@@ -62,14 +57,11 @@ public class ModDirTransformerDiscoverer implements ITransformerDiscoveryService
if (!Files.isRegularFile(path)) return;
if (!path.toString().endsWith(".jar")) return;
if (LamdbaExceptionUtils.uncheck(() -> Files.size(path)) == 0) return;
try (ZipFile zf = new ZipFile(new File(path.toUri()))) {
if (zf.getEntry("META-INF/services/cpw.mods.modlauncher.api.ITransformationService") != null) {
found.add(new NamedPath(zf.getName(), path));
} else if (zf.getEntry("META-INF/services/net.minecraftforge.forgespi.locating.IModLocator") != null) {
found.add(new NamedPath(zf.getName(), path));
}
} catch (IOException ioe) {
LogManager.getLogger().error("Zip Error when loading jar file {}", path, ioe);
}
SecureJar jar = SecureJar.from(path);
jar.moduleDataProvider().descriptor().provides().stream()
.map(ModuleDescriptor.Provides::service)
.filter(SERVICES::contains)
.forEach(s -> found.add(new NamedPath(s, path)));
}
}
@@ -1,27 +1,13 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml.loading;
import com.mojang.logging.LogUtils;
import cpw.mods.modlauncher.api.LamdbaExceptionUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.slf4j.Logger;
import java.io.IOException;
import java.io.InputStream;
@@ -38,7 +24,7 @@ import static net.minecraftforge.fml.loading.LogMarkers.CORE;
public class ModJarURLHandler extends URLStreamHandler
{
private static final Logger LOGGER = LogManager.getLogger();
private static final Logger LOGGER = LogUtils.getLogger();
// modjar://modid/path/to/file
@Override
protected URLConnection openConnection(URL url) {
@@ -1,26 +1,15 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml.loading;
import com.google.common.graph.GraphBuilder;
import com.google.common.graph.MutableGraph;
import com.mojang.logging.LogUtils;
import cpw.mods.jarhandling.SecureJar;
import net.minecraftforge.fml.loading.moddiscovery.MinecraftLocator;
import net.minecraftforge.forgespi.language.IModFileInfo;
import net.minecraftforge.forgespi.language.IModInfo;
import net.minecraftforge.fml.loading.EarlyLoadingException.ExceptionData;
@@ -29,15 +18,15 @@ import net.minecraftforge.fml.loading.moddiscovery.ModFileInfo;
import net.minecraftforge.fml.loading.moddiscovery.ModInfo;
import net.minecraftforge.fml.loading.toposort.CyclePresentException;
import net.minecraftforge.fml.loading.toposort.TopologicalSort;
import net.minecraftforge.forgespi.locating.IModFile;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.maven.artifact.versioning.ArtifactVersion;
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
import org.slf4j.Logger;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.jar.Manifest;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static java.util.stream.Collectors.*;
@@ -45,15 +34,16 @@ import static net.minecraftforge.fml.loading.LogMarkers.LOADING;
public class ModSorter
{
private static final Logger LOGGER = LogManager.getLogger();
private static final Logger LOGGER = LogUtils.getLogger();
private final UniqueModListBuilder uniqueModListBuilder;
private List<ModFile> modFiles;
private List<ModInfo> sortedList;
private Map<String, ModInfo> modIdNameLookup;
private List<ModFile> forgeAndMC;
private Map<String, IModInfo> modIdNameLookup;
private List<ModFile> systemMods;
private ModSorter(final List<ModFile> modFiles)
{
this.modFiles = modFiles;
this.uniqueModListBuilder = new UniqueModListBuilder(modFiles);
}
public static LoadingModList sort(List<ModFile> mods, final List<ExceptionData> errors)
@@ -63,13 +53,13 @@ public class ModSorter
ms.buildUniqueList();
} catch (EarlyLoadingException e) {
// We cannot build any list with duped mods. We have to abort immediately and report it
return LoadingModList.of(ms.forgeAndMC, ms.forgeAndMC.stream().map(mf->(ModInfo)mf.getModInfos().get(0)).collect(toList()), e);
return LoadingModList.of(ms.systemMods, ms.systemMods.stream().map(mf->(ModInfo)mf.getModInfos().get(0)).collect(toList()), e);
}
// try and validate dependencies
final List<ExceptionData> failedList = Stream.concat(ms.verifyDependencyVersions().stream(), errors.stream()).toList();
// if we miss one or the other, we abort now
if (!failedList.isEmpty()) {
return LoadingModList.of(ms.forgeAndMC, ms.forgeAndMC.stream().map(mf->(ModInfo)mf.getModInfos().get(0)).collect(toList()), new EarlyLoadingException("failure to validate mod list", null, failedList));
return LoadingModList.of(ms.systemMods, ms.systemMods.stream().map(mf->(ModInfo)mf.getModInfos().get(0)).collect(toList()), new EarlyLoadingException("failure to validate mod list", null, failedList));
} else {
// Otherwise, lets try and sort the modlist and proceed
EarlyLoadingException earlyLoadingException = null;
@@ -88,11 +78,12 @@ public class ModSorter
// lambdas are identity based, so sorting them is impossible unless you hold reference to them
final MutableGraph<ModFileInfo> graph = GraphBuilder.directed().build();
AtomicInteger counter = new AtomicInteger();
Map<IModFileInfo, Integer> infos = modFiles.stream()
Map<ModFileInfo, Integer> infos = modFiles.stream()
.map(ModFile::getModFileInfo)
.filter(ModFileInfo.class::isInstance)
.map(ModFileInfo.class::cast)
.collect(toMap(Function.identity(), e -> counter.incrementAndGet()));
infos.keySet().forEach(i -> graph.addNode((ModFileInfo) i));
infos.keySet().forEach(graph::addNode);
modFiles.stream()
.map(ModFile::getModInfos)
.<IModInfo>mapMulti(Iterable::forEach)
@@ -108,11 +99,10 @@ public class ModSorter
catch (CyclePresentException e)
{
Set<Set<ModFileInfo>> cycles = e.getCycles();
LOGGER.error(LOADING, () -> new AdvancedLogMessageAdapter(buffer ->
buffer.append("Mod Sorting failed.\n")
.append("Detected Cycles: ")
.append(cycles)
.append('\n')));
if (LOGGER.isErrorEnabled(LOADING))
{
LOGGER.error(LOADING, "Mod Sorting failed.\nDetected Cycles: {}\n", cycles);
}
var dataList = cycles.stream()
.<ModFileInfo>mapMulti(Iterable::forEach)
.<IModInfo>mapMulti((mf,c)->mf.getMods().forEach(c))
@@ -135,10 +125,9 @@ public class ModSorter
private void addDependency(MutableGraph<ModFileInfo> topoGraph, IModInfo.ModVersion dep)
{
final ModFileInfo self = (ModFileInfo)dep.getOwner().getOwningFile();
final ModInfo targetModInfo = modIdNameLookup.get(dep.getModId());
final IModInfo targetModInfo = modIdNameLookup.get(dep.getModId());
// soft dep that doesn't exist. Just return. No edge required.
if (targetModInfo == null) return;
final ModFileInfo target = targetModInfo.getOwningFile();
if (targetModInfo == null || !(targetModInfo.getOwningFile() instanceof final ModFileInfo target)) return;
if (self == target)
return; // in case a jar has two mods that have dependencies between
switch (dep.getOrdering()) {
@@ -149,62 +138,49 @@ public class ModSorter
private void buildUniqueList()
{
// Collect mod files by module name. This will be used for deduping purposes
final Map<String, List<IModFile>> modFilesByFirstId = modFiles.stream()
.collect(groupingBy(mf -> mf.getModFileInfo().moduleName()));
final UniqueModListBuilder.UniqueModListData uniqueModListData = uniqueModListBuilder.buildUniqueList();
// Capture forge and MC here, so we can keep them for later
forgeAndMC = new ArrayList<>();
var mc = modFilesByFirstId.get("minecraft");
if (mc != null && !mc.isEmpty())
forgeAndMC.add((ModFile) mc.get(0));
else
throw new IllegalStateException("Failed to find minecraft somehow?");
// TODO: remove this hardcoding and make it more flexible
var forge = modFilesByFirstId.get("forge");
if (forge != null && !forge.isEmpty())
forgeAndMC.add((ModFile) forge.get(0)); // Silently ignore if Forge isn't present
this.modFiles = uniqueModListData.modFiles();
// Select the newest by artifact version sorting of non-unique files thus identified
this.modFiles = modFilesByFirstId.entrySet().stream()
.map(this::selectNewestModInfo)
.map(Map.Entry::getValue)
.map(ModFile.class::cast)
.collect(toList());
detectSystemMods(uniqueModListData.modFilesByFirstId());
// Transform to the full mod id list
final Map<String, List<ModInfo>> modIds = modFiles.stream()
.map(ModFile::getModInfos)
.flatMap(Collection::stream)
.map(ModInfo.class::cast)
.collect(groupingBy(IModInfo::getModId));
// Its theoretically possible that some mod has somehow moved an id to a secondary place, thus causing a dupe.
// We can't handle this
final List<ModInfo> dupedMods = modIds.values().stream()
.filter(modInfos -> modInfos.size() > 1)
.map(modInfos -> modInfos.get(0))
.toList();
if (!dupedMods.isEmpty()) {
final List<EarlyLoadingException.ExceptionData> duplicateModErrors = dupedMods.stream()
.map(dm -> new EarlyLoadingException.ExceptionData("fml.modloading.dupedmod",
dm, Objects.toString(dm))).toList();
throw new EarlyLoadingException("Duplicate mods found", null, duplicateModErrors);
}
modIdNameLookup = modIds.entrySet().stream()
.collect(toMap(Map.Entry::getKey, e -> e.getValue().get(0)));
modIdNameLookup = uniqueModListData.modFilesByFirstId().entrySet().stream()
.filter(e -> !e.getValue().get(0).getModInfos().isEmpty())
.collect(Collectors.toMap(
Map.Entry::getKey,
e -> e.getValue().get(0).getModInfos().get(0)
));
}
private Map.Entry<String, IModFile> selectNewestModInfo(Map.Entry<String, List<IModFile>> fullList) {
List<IModFile> modInfoList = fullList.getValue();
if (modInfoList.size() > 1) {
LOGGER.debug("Found {} mods for first modid {}, selecting most recent based on version data", modInfoList.size(), fullList.getKey());
modInfoList.sort(Comparator.<IModFile, ArtifactVersion>comparing(mf -> mf.getModInfos().get(0).getVersion()).reversed());
LOGGER.debug("Selected file {} for modid {} with version {}", modInfoList.get(0).getFileName(), fullList.getKey(), modInfoList.get(0).getModInfos().get(0).getVersion());
private void detectSystemMods(final Map<String, List<ModFile>> modFilesByFirstId)
{
// Capture system mods (ex. MC, Forge) here, so we can keep them for later
final Set<String> systemMods = new HashSet<>();
// The minecraft mod is always a system mod
systemMods.add("minecraft");
// Find mod file from MinecraftLocator to define the system mods
modFiles.stream()
.filter(modFile -> modFile.getProvider().getClass() == MinecraftLocator.class)
.map(ModFile::getSecureJar)
.map(SecureJar::moduleDataProvider)
.map(SecureJar.ModuleDataProvider::getManifest)
.map(Manifest::getMainAttributes)
.map(mf -> mf.getValue("FML-System-Mods"))
.filter(Objects::nonNull)
.findFirst()
.ifPresent(value -> systemMods.addAll(Arrays.asList(value.split(","))));
LOGGER.debug("Configured system mods: {}", systemMods);
this.systemMods = new ArrayList<>();
for (String systemMod : systemMods) {
var container = modFilesByFirstId.get(systemMod);
if (container != null && !container.isEmpty()) {
LOGGER.debug("Found system mod: {}", systemMod);
this.systemMods.add((ModFile) container.get(0));
} else {
throw new IllegalStateException("Failed to find system mod: " + systemMod);
}
}
return Map.entry(fullList.getKey(), modInfoList.get(0));
}
private List<EarlyLoadingException.ExceptionData> verifyDependencyVersions()
@@ -233,6 +209,27 @@ public class ModSorter
LOGGER.debug(LOADING, "Found {} mod requirements missing ({} mandatory, {} optional)", missingVersions.size(), mandatoryMissing, missingVersions.size() - mandatoryMissing);
if (!missingVersions.isEmpty()) {
if (mandatoryMissing > 0) {
LOGGER.error(
LOADING,
"Missing or unsupported mandatory dependencies:\n{}",
missingVersions.stream()
.filter(IModInfo.ModVersion::isMandatory)
.map(ver -> formatDependencyError(ver, modVersions))
.collect(Collectors.joining("\n"))
);
}
if (missingVersions.size() - mandatoryMissing > 0) {
LOGGER.error(
LOADING,
"Unsupported installed optional dependencies:\n{}",
missingVersions.stream()
.filter(ver -> !ver.isMandatory())
.map(ver -> formatDependencyError(ver, modVersions))
.collect(Collectors.joining("\n"))
);
}
return missingVersions.stream()
.map(mv -> new ExceptionData(mv.isMandatory() ? "fml.modloading.missingdependency" : "fml.modloading.missingdependency.optional",
mv.getOwner(), mv.getModId(), mv.getOwner().getModId(), mv.getVersionRange(),
@@ -242,6 +239,18 @@ public class ModSorter
return Collections.emptyList();
}
private static String formatDependencyError(IModInfo.ModVersion dependency, Map<String, ArtifactVersion> modVersions)
{
ArtifactVersion installed = modVersions.get(dependency.getModId());
return String.format(
"\tMod ID: '%s', Requested by: '%s', Expected range: '%s', Actual version: '%s'",
dependency.getModId(),
dependency.getOwner().getModId(),
dependency.getVersionRange(),
installed != null ? installed.toString() : "[MISSING]"
);
}
private boolean modVersionNotContained(final IModInfo.ModVersion mv, final Map<String, ArtifactVersion> modVersions)
{
return !(VersionSupportMatrix.testVersionSupportMatrix(mv.getVersionRange(), mv.getModId(), "mod", (modId, range) -> modVersions.containsKey(modId) &&
@@ -1,20 +1,6 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml.loading;
@@ -30,14 +16,11 @@ import java.util.function.Consumer;
import java.util.stream.Collectors;
import com.google.common.collect.Streams;
import com.mojang.logging.LogUtils;
import cpw.mods.modlauncher.serviceapi.ILaunchPluginService;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.api.distmarker.OnlyIns;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.MarkerManager;
import org.objectweb.asm.Handle;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
@@ -47,11 +30,14 @@ import org.objectweb.asm.tree.AnnotationNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.FieldNode;
import org.objectweb.asm.tree.MethodNode;
import org.slf4j.Logger;
import org.slf4j.Marker;
import org.slf4j.MarkerFactory;
public class RuntimeDistCleaner implements ILaunchPluginService
{
private static final Logger LOGGER = LogManager.getLogger();
private static final Marker DISTXFORM = MarkerManager.getMarker("DISTXFORM");
private static final Logger LOGGER = LogUtils.getLogger();
private static final Marker DISTXFORM = MarkerFactory.getMarker("DISTXFORM");
private static String DIST;
private static final String ONLYIN = Type.getDescriptor(OnlyIn.class);
private static final String ONLYINS = Type.getDescriptor(OnlyIns.class);
@@ -67,7 +53,7 @@ public class RuntimeDistCleaner implements ILaunchPluginService
AtomicBoolean changes = new AtomicBoolean();
if (remove(classNode.visibleAnnotations, DIST))
{
LOGGER.fatal(DISTXFORM, "Attempted to load class {} for invalid dist {}", classNode.name, DIST);
LOGGER.error(DISTXFORM, "Attempted to load class {} for invalid dist {}", classNode.name, DIST);
throw new RuntimeException("Attempted to load class "+ classNode.name + " for invalid dist "+ DIST);
}
@@ -1,20 +1,6 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml.loading;
@@ -1,20 +1,6 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml.loading;
@@ -1,26 +1,11 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml.loading;
import org.apache.logging.log4j.Logger;
import org.slf4j.Logger;
import java.io.PrintStream;
/**
@@ -0,0 +1,145 @@
/*
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml.loading;
import com.mojang.logging.LogUtils;
import net.minecraftforge.fml.loading.moddiscovery.ModFile;
import net.minecraftforge.forgespi.language.IModInfo;
import org.apache.maven.artifact.versioning.ArtifactVersion;
import org.slf4j.Logger;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.joining;
import static net.minecraftforge.fml.loading.LogMarkers.LOADING;
public class UniqueModListBuilder
{
private final static Logger LOGGER = LogUtils.getLogger();
private final List<ModFile> modFiles;
public UniqueModListBuilder(final List<ModFile> modFiles) {this.modFiles = modFiles;}
public UniqueModListData buildUniqueList()
{
List<ModFile> uniqueModList;
List<ModFile> uniqueLibListWithVersion;
// Collect mod files by module name. This will be used for deduping purposes
final Map<String, List<ModFile>> modFilesByFirstId = modFiles.stream()
.filter(mf -> mf.getModFileInfo() != null)
.collect(groupingBy(UniqueModListBuilder::getModId));
final Map<String, List<ModFile>> libFilesWithVersionByModuleName = modFiles.stream()
.filter(mf -> mf.getModFileInfo() == null)
.collect(groupingBy(UniqueModListBuilder::getModId));
// Select the newest by artifact version sorting of non-unique files thus identified
uniqueModList = modFilesByFirstId.entrySet().stream()
.map(this::selectNewestModInfo)
.toList();
// Select the newest by artifact version sorting of non-unique files thus identified
uniqueLibListWithVersion = libFilesWithVersionByModuleName.entrySet().stream()
.map(this::selectNewestModInfo)
.toList();
// Transform to the full mod id list
final Map<String, List<IModInfo>> modIds = uniqueModList.stream()
.filter(mf -> mf.getModFileInfo() != null) //Filter out non-mod files, we don't care about those for now.....
.map(ModFile::getModInfos)
.flatMap(Collection::stream)
.collect(groupingBy(IModInfo::getModId));
// Transform to the full lib id list
final Map<String, List<ModFile>> versionedLibIds = uniqueLibListWithVersion.stream()
.map(UniqueModListBuilder::getModId)
.collect(Collectors.toMap(
Function.identity(),
libFilesWithVersionByModuleName::get
));
// Its theoretically possible that some mod has somehow moved an id to a secondary place, thus causing a dupe.
// We can't handle this
final List<String> dupedModErrors = modIds.values().stream()
.filter(modInfos -> modInfos.size() > 1)
.map(mods -> String.format("\tMod ID: '%s' from mod files: %s",
mods.get(0).getModId(),
mods.stream()
.map(modInfo -> modInfo.getOwningFile().getFile().getFileName()).collect(joining(", "))
)).toList();
if (!dupedModErrors.isEmpty()) {
LOGGER.error(LOADING, "Found duplicate mods:\n{}", dupedModErrors.stream().collect(joining("\n")));
throw new EarlyLoadingException("Duplicate mods found", null, dupedModErrors.stream()
.map(s -> new EarlyLoadingException.ExceptionData(s))
.toList());
}
final List<String> dupedLibErrors = versionedLibIds.values().stream()
.filter(modFiles -> modFiles.size() > 1)
.map(mods -> String.format("\tLibrary: '%s' from files: %s",
getModId(mods.get(0)),
mods.stream()
.map(modFile -> modFile.getFileName()).collect(joining(", "))
)).toList();
if (!dupedLibErrors.isEmpty()) {
LOGGER.error(LOADING, "Found duplicate plugins or libraries:\n{}", dupedLibErrors.stream().collect(joining("\n")));
throw new EarlyLoadingException("Duplicate plugins or libraries found", null, dupedLibErrors.stream()
.map(s -> new EarlyLoadingException.ExceptionData(s))
.toList());
}
// Collect unique mod files by module name. This will be used for deduping purposes
final Map<String, List<ModFile>> uniqueModFilesByFirstId = uniqueModList.stream()
.collect(groupingBy(UniqueModListBuilder::getModId));
final List<ModFile> loadedList = new ArrayList<>();
loadedList.addAll(uniqueModList);
loadedList.addAll(uniqueLibListWithVersion);
return new UniqueModListData(loadedList, uniqueModFilesByFirstId);
}
private ModFile selectNewestModInfo(Map.Entry<String, List<ModFile>> fullList) {
List<ModFile> modInfoList = fullList.getValue();
if (modInfoList.size() > 1) {
LOGGER.debug("Found {} mods for first modid {}, selecting most recent based on version data", modInfoList.size(), fullList.getKey());
modInfoList.sort(Comparator.comparing(this::getVersion).reversed());
LOGGER.debug("Selected file {} for modid {} with version {}", modInfoList.get(0).getFileName(), fullList.getKey(), this.getVersion(modInfoList.get(0)));
}
return modInfoList.get(0);
}
private ArtifactVersion getVersion(final ModFile mf)
{
if (mf.getModFileInfo() == null || mf.getModInfos() == null || mf.getModInfos().isEmpty()) {
return mf.getJarVersion();
}
return mf.getModInfos().get(0).getVersion();
}
private static String getModId(ModFile modFile) {
if (modFile.getModFileInfo() == null || modFile.getModFileInfo().getMods().isEmpty()) {
return modFile.getSecureJar().name();
}
return modFile.getModFileInfo().moduleName();
}
public record UniqueModListData(List<ModFile> modFiles, Map<String, List<ModFile>> modFilesByFirstId) {}
}
@@ -1,3 +1,8 @@
/*
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml.loading;
import java.util.Map;
@@ -1,24 +1,11 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml.loading;
import net.minecraftforge.forgespi.language.MavenVersionAdapter;
import org.apache.maven.artifact.versioning.ArtifactVersion;
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
import org.apache.maven.artifact.versioning.VersionRange;
@@ -32,16 +19,12 @@ public class VersionSupportMatrix {
private static final HashMap<String, List<ArtifactVersion>> overrideVersions = new HashMap<>();
static {
final ArtifactVersion version = new DefaultArtifactVersion(FMLLoader.versionInfo().mcVersion());
// if (MavenVersionAdapter.createFromVersionSpec("[1.16.4,1.16.5]").containsVersion(version)) {
// // 1.16.4 is Compatible with 1.16.3
// add("languageloader.javafml", "34");
// add("mod.minecraft", "1.16.3");
// add("mod.forge", "34.1.42");
// // 1.16.5 is Compatible with 1.16.4, and thus 1.16.3
// add("languageloader.javafml", "35");
// add("mod.minecraft", "1.16.4");
// add("mod.forge", "35.1.37");
// }
if (MavenVersionAdapter.createFromVersionSpec("[1.19.2]").containsVersion(version)) {
// 1.19.2 is Compatible with 1.19.1
add("languageloader.javafml", "42");
add("mod.minecraft", "1.19.1");
add("mod.forge", "42.0.9");
}
}
private static void add(String key, String value) {
overrideVersions.computeIfAbsent(key, k -> new ArrayList<>()).add(new DefaultArtifactVersion(value));
@@ -1,20 +1,6 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2021.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Copyright (c) Forge Development LLC and contributors
* SPDX-License-Identifier: LGPL-2.1-only
*/
package net.minecraftforge.fml.loading.log4j;
Loaded 100 of 2397 files, more files were not shown because too many files have changed in this diff. Show more