From aff05a4cf37e3050c1641f595de3c4b18f7445d9 Mon Sep 17 00:00:00 2001 From: LexManos Date: Wed, 4 Oct 2023 12:03:07 -0700 Subject: [PATCH] Cleanup FMLLoader and Launch Handlers. Cleanup some of the build.gradle Start work on restructuring test mods. They are now treated as their own jars, as well as having their mods.toml auto-generated. No more mods.toml conflicts! Add pattern matching support to Data run modlist. --- .gitignore | 6 +- build.gradle | 424 +++++++----------- fmlloader/build.gradle | 1 + .../common/asm/ObjectHolderDefinalize.java | 1 + .../fml/common/asm/RuntimeEnumExtender.java | 2 - .../fml/loading/BackgroundWaiter.java | 2 - .../fml/loading/EarlyLoadingException.java | 2 + .../minecraftforge/fml/loading/FMLConfig.java | 2 - .../minecraftforge/fml/loading/FMLLoader.java | 2 +- .../fml/loading/FMLServiceProvider.java | 1 + .../minecraftforge/fml/loading/FileUtils.java | 35 -- .../fml/loading/JarVersionLookupHandler.java | 1 + .../fml/loading/LanguageLoadingProvider.java | 1 - .../loading/ModDirTransformerDiscoverer.java | 3 - .../fml/loading/ModJarURLHandler.java | 96 ---- .../minecraftforge/fml/loading/ModSorter.java | 4 +- .../moddiscovery/AbstractModProvider.java | 43 +- .../moddiscovery/ClasspathLocator.java | 24 +- .../moddiscovery/InvalidModFileException.java | 7 +- .../moddiscovery/ModAnnotationVisitor.java | 44 +- .../fml/loading/moddiscovery/ModFile.java | 8 +- .../loading/moddiscovery/ModFileParser.java | 1 - .../loading/moddiscovery/ModListHandler.java | 9 +- .../loading/moddiscovery/ModValidator.java | 5 +- .../progress/StartupNotificationManager.java | 2 - .../fml/loading/targets/ArgumentList.java | 3 + .../targets/CommonClientLaunchHandler.java | 47 -- .../targets/CommonDevLaunchHandler.java | 157 ++++--- .../loading/targets/CommonLaunchHandler.java | 83 ++-- .../targets/CommonServerLaunchHandler.java | 57 --- .../targets/CommonUserdevLaunchHandler.java | 42 -- .../targets/ForgeClientDevLaunchHandler.java | 18 - .../targets/ForgeClientLaunchHandler.java | 25 -- .../ForgeClientUserdevLaunchHandler.java | 21 - .../targets/ForgeDataDevLaunchHandler.java | 19 - .../ForgeDataUserdevLaunchHandler.java | 24 - .../targets/ForgeDevLaunchHandler.java | 295 ++++++++++++ .../ForgeGametestDevLaunchHandler.java | 18 - .../ForgeGametestUserdevLaunchHandler.java | 18 - .../targets/ForgeProdLaunchHandler.java | 99 ++++ .../targets/ForgeServerDevLaunchHandler.java | 18 - .../targets/ForgeServerLaunchHandler.java | 28 -- .../ForgeServerUserdevLaunchHandler.java | 18 - .../targets/ForgeUserdevLaunchHandler.java | 66 ++- .../toposort/CyclePresentException.java | 1 + .../minecraftforge/fml/server/ServerMain.java | 68 --- ...cpw.mods.cl.ModularURLHandler.IURLProvider | 0 ...mods.modlauncher.api.ILaunchHandlerService | 25 +- src/generated_test/resources/EMPTY | 0 .../resources/{ => empty}/pack.mcmeta | 0 .../loot_modifiers/global_loot_modifiers.json | 0 .../loot_modifiers/bamboo_silk.json | 0 .../loot_modifiers/dungeon_loot.json | 0 .../loot_modifiers/smelting.json | 0 .../loot_modifiers/wheat_harvest.json | 0 .../resources/mdk_datagen}/pack.mcmeta | 2 +- .../client/ForgeHooksClient.java | 9 - .../client/gui/overlay/VanillaGuiOverlay.java | 1 + .../data/loading/DatagenModLoader.java | 53 ++- .../event/AddReloadListenerEvent.java | 21 +- .../CreativeModeTabTest.java | 2 +- .../loot/GlobalLootModifiersTest.java | 2 +- .../java/net/minecraftforge/mdk/Datagen.java} | 13 +- .../{ => global_loot_test}/META-INF/mods.toml | 12 - 64 files changed, 883 insertions(+), 1108 deletions(-) delete mode 100644 fmlloader/src/main/java/net/minecraftforge/fml/loading/FileUtils.java delete mode 100644 fmlloader/src/main/java/net/minecraftforge/fml/loading/ModJarURLHandler.java delete mode 100644 fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/CommonClientLaunchHandler.java delete mode 100644 fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/CommonServerLaunchHandler.java delete mode 100644 fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/CommonUserdevLaunchHandler.java delete mode 100644 fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/ForgeClientDevLaunchHandler.java delete mode 100644 fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/ForgeClientLaunchHandler.java delete mode 100644 fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/ForgeClientUserdevLaunchHandler.java delete mode 100644 fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/ForgeDataDevLaunchHandler.java delete mode 100644 fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/ForgeDataUserdevLaunchHandler.java create mode 100644 fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/ForgeDevLaunchHandler.java delete mode 100644 fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/ForgeGametestDevLaunchHandler.java delete mode 100644 fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/ForgeGametestUserdevLaunchHandler.java create mode 100644 fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/ForgeProdLaunchHandler.java delete mode 100644 fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/ForgeServerDevLaunchHandler.java delete mode 100644 fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/ForgeServerLaunchHandler.java delete mode 100644 fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/ForgeServerUserdevLaunchHandler.java delete mode 100644 fmlloader/src/main/java/net/minecraftforge/fml/server/ServerMain.java delete mode 100644 fmlloader/src/main/resources/META-INF/services/cpw.mods.cl.ModularURLHandler.IURLProvider delete mode 100644 src/generated_test/resources/EMPTY rename src/generated_test/resources/{ => empty}/pack.mcmeta (100%) rename src/generated_test/resources/{ => global_loot_test}/data/forge/loot_modifiers/global_loot_modifiers.json (100%) rename src/generated_test/resources/{ => global_loot_test}/data/global_loot_test/loot_modifiers/bamboo_silk.json (100%) rename src/generated_test/resources/{ => global_loot_test}/data/global_loot_test/loot_modifiers/dungeon_loot.json (100%) rename src/generated_test/resources/{ => global_loot_test}/data/global_loot_test/loot_modifiers/smelting.json (100%) rename src/generated_test/resources/{ => global_loot_test}/data/global_loot_test/loot_modifiers/wheat_harvest.json (100%) rename src/{generated_mdk/resources => generated_test/resources/mdk_datagen}/pack.mcmeta (79%) rename src/test/java/net/minecraftforge/debug/{ => creativetabs}/CreativeModeTabTest.java (99%) rename src/{test_old/java/net/minecraftforge/mdk/MdkDatagen.java => test/java/net/minecraftforge/mdk/Datagen.java} (86%) rename src/test/resources/{ => global_loot_test}/META-INF/mods.toml (52%) diff --git a/.gitignore b/.gitignore index 74683483cc..05b99b77fc 100644 --- a/.gitignore +++ b/.gitignore @@ -34,9 +34,9 @@ /projects/**/run/ /projects/**/*.launch /repo/ -src/generated/resources/.cache/ -src/generated_test/resources/.cache/ -src/generated_mdk/resources/.cache/ +src/generated/resources/**/.cache/ +src/generated_test/resources/**/.cache/ +src/generated_mdk/resources/**/.cache/ #Patch rejects #/patches-/ diff --git a/build.gradle b/build.gradle index 39b9888242..83ce5272d5 100644 --- a/build.gradle +++ b/build.gradle @@ -68,6 +68,7 @@ ext { SLF4J_API_VERSION = '1.8.0-beta4' APACHE_MAVEN_ARTIFACT_VERSION = '3.8.5' JARJAR_VERSION = '0.3.19' + JIMFS_VERSION = '1.3.0' // Google's InMemory File System. Used by ForgeDev Tests for now, but could be useful for a lot of things. // These versions should be kept in sync with the version manifest JSON // To use a version newer than the version manifest JSON, the dependency must be added to the installer configuration @@ -276,14 +277,17 @@ project(':clean') { } def sharedDeps = { - moduleonly "cpw.mods:securejarhandler:${SECUREJARHANDLER_VERSION}" - moduleonly "org.ow2.asm:asm:${ASM_VERSION}" - moduleonly "org.ow2.asm:asm-commons:${ASM_VERSION}" - moduleonly "org.ow2.asm:asm-tree:${ASM_VERSION}" - moduleonly "org.ow2.asm:asm-util:${ASM_VERSION}" - moduleonly "org.ow2.asm:asm-analysis:${ASM_VERSION}" - moduleonly "cpw.mods:bootstraplauncher:${BOOTSTRAPLAUNCHER_VERSION}" - moduleonly "net.minecraftforge:JarJarFileSystems:${JARJAR_VERSION}" + moduleonly("cpw.mods:securejarhandler:${SECUREJARHANDLER_VERSION}") + moduleonly("org.ow2.asm:asm:${ASM_VERSION}") + moduleonly("org.ow2.asm:asm-commons:${ASM_VERSION}") + moduleonly("org.ow2.asm:asm-tree:${ASM_VERSION}") + moduleonly("org.ow2.asm:asm-util:${ASM_VERSION}") + moduleonly("org.ow2.asm:asm-analysis:${ASM_VERSION}") + moduleonly("cpw.mods:bootstraplauncher:${BOOTSTRAPLAUNCHER_VERSION}") + moduleonly("net.minecraftforge:JarJarFileSystems:${JARJAR_VERSION}") + moduleonly("com.google.jimfs:jimfs:${JIMFS_VERSION}") { + transitive = false + } installer "cpw.mods:securejarhandler:${SECUREJARHANDLER_VERSION}" installer "org.ow2.asm:asm:${ASM_VERSION}" @@ -320,50 +324,6 @@ def sharedDeps = { } def sharedFmlonlyForge = { Project prj -> - ['Client', 'Server', 'Joined'].each { side -> - ['slim', 'extra'].each { type -> - prj.task([type: DownloadMavenArtifact], "download${side}${type.capitalize()}") { - artifact = "net.minecraft:${side.toLowerCase()}:${MC_VERSION}-${MCP_VERSION}:${type}" - } - } - - if (side.equals('Joined')) { - prj.task([type: DownloadMavenArtifact], "createJoinedSRG") { - artifact = "net.minecraft:joined:${MC_VERSION}-${MCP_VERSION}:srg" - } - } else { - prj.task([type: RenameJar, dependsOn: prj.tasks.createMcp2Srg], "create${side}SRG") { - tool = FART - args = [ - '--input', '{input}', - '--output', '{output}', - '--names', '{mappings}', - '--ann-fix', '--ids-fix', '--src-fix', '--record-fix' - ] - mappings = prj.tasks.createMcp2Srg.srg - input = prj.tasks.getByName("download${side}Slim").output - output = prj.file("build/create${side}SRG/output.jar") - } - } - - def gen = prj.tasks.getByName("gen${side}BinPatches") - def createSRG = prj.tasks.getByName("create${side}SRG") - gen.dependsOn(createSRG) - gen.tool = BINPATCH_TOOL - gen.cleanJar = createSRG.output - - prj.task([type: ApplyBinPatches, dependsOn: gen], "apply${side}BinPatches") { - clean = gen.cleanJar - patch = gen.output - tool = BINPATCH_TOOL - } - } - - prj.task([type: DownloadMavenArtifact], 'downloadInstaller') { - artifact = "net.minecraftforge:installer:${INSTALLER_VERSION}:shrunk" - changing = true - } - prj.afterEvaluate { [prj.tasks.universalJar, prj.tasks.installerJar].each { t -> def signTask = prj.task([type: SignJar, dependsOn: t], "sign${t.name.capitalize()}") { @@ -383,7 +343,6 @@ def sharedFmlonlyForge = { Project prj -> } prj.tasks.userdevConfig { - def launchPrefix = prj.name == "forge" ? "forge" : "fml" getArtifacts(prj, prj.configurations.installer, true).each { key, lib -> libraries.add(lib.name) } getArtifacts(prj, prj.configurations.moduleonly, true).each { key, lib -> libraries.add(lib.name) @@ -396,46 +355,28 @@ def sharedFmlonlyForge = { Project prj -> inject = '' // We don't have a userdev sourceset anymore. Empty as a gradle workaround... runs { client { - environment 'MOD_CLASSES', '{source_roots}' environment 'MCP_MAPPINGS', '{mcp_mappings}' - - // Natives are loaded from the classpath now in all cases - // property 'nativesDirectory', '{natives}' - if (prj.name == 'forge') { - property 'forge.enableGameTest', 'true' - } - - args '--launchTarget', "${launchPrefix}clientuserdev" + property 'forge.enableGameTest', 'true' + args '--launchTarget', "forge_userdev_client" args '--version', 'MOD_DEV' args '--assetIndex', '{asset_index}' args '--assetsDir', '{assets_root}' } server { - environment 'MOD_CLASSES', '{source_roots}' environment 'MCP_MAPPINGS', '{mcp_mappings}' - - if (prj.name == 'forge') { - property 'forge.enableGameTest', 'true' - } - - args '--launchTarget', "${launchPrefix}serveruserdev" + property 'forge.enableGameTest', 'true' + args '--launchTarget', "forge_userdev_server" } - if (prj.name == 'forge') { - gameTestServer { - environment 'MOD_CLASSES', '{source_roots}' - environment 'MCP_MAPPINGS', '{mcp_mappings}' - - args '--launchTarget', "${launchPrefix}gametestserveruserdev" - } - } + gameTestServer { + environment 'MCP_MAPPINGS', '{mcp_mappings}' + args '--launchTarget', "forge_userdev_server_gametest" + } data { - environment 'MOD_CLASSES', '{source_roots}' environment 'MCP_MAPPINGS', '{mcp_mappings}' - - args '--launchTarget', "${launchPrefix}datauserdev" + args '--launchTarget', "forge_userdev_data" args '--assetIndex', '{asset_index}' args '--assetsDir', '{assets_root}' } @@ -456,11 +397,7 @@ def sharedFmlonlyForge = { Project prj -> run.jvmArgs '-Djava.net.preferIPv6Addresses=system' - if (run.name.contains('client')) { - run.client true - } else { - run.client false - } + run.client run.name.contains('client') // SecureJarHandler bootstrap values. run.property 'ignoreList', prj.configurations.moduleonly.files.collect {it.name.replaceAll(/([-_]([.\d]*\d+)|\.jar$)/, '') }.join(',') + ",client-extra,fmlcore,javafmllanguage,lowcodelanguage,mclanguage,${prj.name}-" @@ -481,42 +418,29 @@ def sharedFmlonlyForge = { Project prj -> run.jvmArgs '--add-exports', 'jdk.naming.dns/com.sun.jndi.dns=java.naming' } for (def run : prj.patcher.runs) { - if (run.parents) continue // We already added this to the parent run config + def isTest = run.name.endsWith('_test') + + run.taskName = run.name + run.environment 'FORGE_SPEC', prj.SPEC_VERSION + run.workingDirectory prj.file('run/' + run.name) + run.ideaModule rootProject.name + '.' + prj.name + '.' + (isTest ? 'test' : 'main') + + run.mods { + minecraft { source prj.sourceSets.main } + } + + if (isTest) { + run.property 'forge.enableGameTest', 'true' - if (run.name.contains('client') || run.name.contains('data')) { - // Natives are loaded from the classpath now in all cases - // run.property 'nativesDirectory', prj.extractNatives.output.get().asFile - run.args '--assetsDir', prj.downloadAssets.output - run.args '--assetIndex', "{asset_index}" - } - - if (run.name.contains('client')) { - run.property 'org.lwjgl.system.SharedLibraryExtractDirectory', 'lwjgl_dll' - run.args '--username', 'Dev' - run.args '--version', prj.name - //run.args '--uuid', '0' - run.args '--accessToken', '0' - run.args '--userType', 'mojang' - run.args '--versionType', 'release' - } - - if (prj.name == 'forge') { - run.environment 'FORGE_SPEC', prj.SPEC_VERSION - } - } - - eclipse.project.resourceFilter { - appliesTo = 'FOLDERS' - type = 'EXCLUDE_ALL' - matcher { - id = 'org.eclipse.ui.ide.multiFilter' - arguments = '1.0-name-matches-false-false-run' - } + run.mods { + tests { sources prj.sourceSets.test } + } + } } def MODULE_PATH = Util.getArtifacts(prj, prj.configurations.moduleonly, false).values().collect{"libraries/${it.downloads.artifact.path}"} def tokens = [ - TASK: prj.name.equals('forge') ? 'forgeserver' : 'fmlserver', + TASK: 'forge_server', MAVEN_PATH: prj.ext.MAVEN_PATH.toString(), FORGE_VERSION: FORGE_VERSION, MC_VERSION: MC_VERSION, @@ -560,8 +484,6 @@ def sharedFmlonlyForge = { Project prj -> exclude 'args.txt' filter(ReplaceTokens, tokens: tokens) into('data/') - //rename 'run.sh', "run_forge_${VERSION.replace('-', '_').sh" - //rename 'run.bat', "run_forge_${VERSION.replace('-', '_').bat" } } } @@ -609,10 +531,21 @@ project(':forge') { } } - eclipse.classpath.file.whenMerged { - // Disable optional warnings on the minecraft decompiled source code. It just muddies the warning window and hides warnings in our own codebase - def src = entries.find { it.path == 'src/main/java' } - src.entryAttributes['ignore_optional_problems'] = 'true' + eclipse { + classpath.file.whenMerged { + // Disable optional warnings on the minecraft decompiled source code. It just muddies the warning window and hides warnings in our own codebase + def src = entries.find { it.path == 'src/main/java' } + src.entryAttributes['ignore_optional_problems'] = 'true' + } + + project.resourceFilter { + appliesTo = 'FOLDERS' + type = 'EXCLUDE_ALL' + matcher { + id = 'org.eclipse.ui.ide.multiFilter' + arguments = '1.0-name-matches-false-false-run' + } + } } ext { @@ -661,160 +594,64 @@ project(':forge') { runs { forge_client { - workingDirectory file('run/client') property 'eventbus.checkTypesOnDispatch', 'true' - args '--launchTarget', 'forgeclientdev' - ideaModule "${rootProject.name}.${project.name}.main" - mods { - minecraft { source sourceSets.main } - } + property 'org.lwjgl.system.SharedLibraryExtractDirectory', 'lwjgl_dll' + + args '--launchTarget', 'forge_dev_client', + '--username', 'Dev', + '--version', project.name, + '--accessToken', '0', + '--userType', 'mojang', + '--versionType', 'release', + '--assetsDir', downloadAssets.output, + '--assetIndex', "{asset_index}" } - forge_test_client { - workingDirectory file('run/client_test') + forge_client_test { parent runs.forge_client - taskName 'forge_test_client' - - property 'forge.enableGameTest', 'true' - environment 'MOD_CLASSES', 'dummy' // Needed to work around FG limitation, FG will replace this! - - ideaModule "${rootProject.name}.${project.name}.test" - - mods { - tests { sources sourceSets.test } - } } forge_server { - workingDirectory file('run/server') - args '--launchTarget', 'forgeserverdev' - ideaModule "${rootProject.name}.${project.name}.main" - - mods { - minecraft { source sourceSets.main } - } + args '--launchTarget', 'forge_dev_server' } - forge_test_server { - workingDirectory file('run/server_test') + forge_server_test { parent runs.forge_server - taskName 'forge_test_server' - - property 'forge.enableGameTest', 'true' - environment 'MOD_CLASSES', 'dummy' // Needed to work around FG limitation, FG will replace this! - - ideaModule "${rootProject.name}.${project.name}.test" - - mods { - tests { sources sourceSets.test } - } } - forge_gameTestServer { - taskName 'forge_gameTestServer' - args '--launchTarget', 'forgegametestserverdev' - ideaModule "${rootProject.name}.${project.name}.main" - - mods { - minecraft { source sourceSets.main } - } + forge_server_gametest { + args '--launchTarget', 'forge_dev_server_gametest' } - forge_test_gameTestServer { - parent runs.forge_gameTestServer - taskName 'forge_test_gameTestServer' - - ideaModule "${rootProject.name}.${project.name}.test" - - mods { - tests { sources sourceSets.test } - } + forge_server_gametest_test { + parent runs.forge_server_gametest } - def forgeDataArgs = [ - '--mod', 'forge', - '--all', - '--output', rootProject.file('src/generated/resources/'), - '--validate', - '--existing', sourceSets.main.resources.srcDirs[0] - ] forge_data { - taskName 'forge_data' - args '--launchTarget', 'forgedatadev' - ideaModule "${rootProject.name}.${project.name}.main" - - mods { - minecraft { source sourceSets.main } - } - - args forgeDataArgs + args '--launchTarget', 'forge_dev_data', + '--mod', 'forge', + '--all', + '--validate', + '--output', rootProject.file('src/generated/resources/'), + '--validate', + '--existing', sourceSets.main.resources.srcDirs[0], + '--assetsDir', downloadAssets.output, + '--assetIndex', "{asset_index}" } - forge_test_data { - parent runs.forge_data - taskName 'forge_test_data' - - environment 'MOD_CLASSES', 'dummy' // Needed to work around FG limitation, FG will replace this! - - ideaModule "${rootProject.name}.${project.name}.test" - - mods { - tests { sources sourceSets.test } - } - - afterEvaluate { - // Clear forge's main datagen args - args.removeAll { - forgeDataArgs.contains(it instanceof File ? (it as File).absolutePath : it.toString()) - } - - args '--flat', '--all', '--validate', - '--mod', 'empty', - //'--mod', 'data_gen_test', - //'--mod', 'piston_event_test', - '--mod', 'global_loot_test', - //'--mod', 'scaffolding_test', - //'--mod', 'custom_tag_types_test', - //'--mod', 'new_model_loader_test', - //'--mod', 'remove_tag_datagen_test', - //'--mod', 'tag_based_tool_types', - //'--mod', 'custom_transformtype_test', - //'--mod', 'data_pack_registries_test', - //'--mod', 'biome_modifiers_test', - //'--mod', 'structure_modifiers_test', - //'--mod', 'custom_preset_editor_test', - '--output', rootProject.file('src/generated_test/resources/'), - '--existing', sourceSets.main.resources.srcDirs[0], - '--existing', sourceSets.test.resources.srcDirs[0] - } + forge_data_test { + args '--launchTarget', 'forge_dev_data', + '--mod', '.+', + '--all', + '--validate', + '--output', rootProject.file('src/generated_test/resources/'), + '--existing', sourceSets.main.resources.srcDirs[0], + '--existing', sourceSets.test.resources.srcDirs[0], + '--assetsDir', downloadAssets.output, + '--assetIndex', "{asset_index}" } - forge_mdk_data { - parent runs.forge_data - taskName 'forge_mdk_data' - - environment 'MOD_CLASSES', 'dummy' // Needed to work around FG limitation, FG will replace this! - - ideaModule "${rootProject.name}.${project.name}.test" - - mods { - tests { sources sourceSets.test } - } - - afterEvaluate { - // Clear forge's main datagen args - args.removeAll { - forgeDataArgs.contains(it instanceof File ? (it as File).absolutePath : it.toString()) - } - - args '--flat', '--all', '--validate', - '--mod', 'mdk_datagen', - '--output', rootProject.file('src/generated_mdk/resources/'), - '--existing', sourceSets.main.resources.srcDirs[0], - '--existing', sourceSets.test.resources.srcDirs[0] - } - } - } + } } afterEvaluate { @@ -847,7 +684,6 @@ project(':forge') { ext { MANIFESTS = [ '/': [ - 'Timestamp': new Date().format("yyyy-MM-dd'T'HH:mm:ssZ"), 'GitCommit': gradleutils.gitInfo.abbreviatedId, 'Git-Branch': gradleutils.gitInfo.branch, 'FML-System-Mods': 'forge' @@ -914,7 +750,7 @@ project(':forge') { libraries.addAll downloadLibraries.librariesOutput.map { rf -> Files.readAllLines(rf.asFile.toPath()).stream().map(File::new).collect(java.util.stream.Collectors.toList()) } } - task findFieldInstanceChecks(type: FieldCompareFinder, dependsOn: ['createJoinedSRG']) { + tasks.register("findFieldInstanceChecks", FieldCompareFinder) { jar = createJoinedSRG.output output = rootProject.file('src/main/resources/coremods/field_to_instanceof.json') fields { @@ -933,7 +769,7 @@ project(':forge') { } } - task findFinalizeSpawnTargets(type: BytecodePredicateFinder, dependsOn: ['createJoinedSRG']) { + tasks.register("findFinalizeSpawnTargets", BytecodePredicateFinder) { jar = createJoinedSRG.output output = rootProject.file('src/main/resources/coremods/finalize_spawn_targets.json') predicate = { @@ -952,6 +788,74 @@ project(':forge') { tasks.jar.finalizedBy 'validateDeprecations' + tasks.register("downloadInstaller", DownloadMavenArtifact) { + artifact = "net.minecraftforge:installer:${INSTALLER_VERSION}:shrunk" + changing = true + } + tasks.register("downloadClientSlim", DownloadMavenArtifact) { + artifact = "net.minecraft:client:${MC_VERSION}-${MCP_VERSION}:slim" + } + tasks.register("downloadClientExtra", DownloadMavenArtifact) { + artifact = "net.minecraft:client:${MC_VERSION}-${MCP_VERSION}:extra" + } + tasks.register("downloadServerSlim", DownloadMavenArtifact) { + artifact = "net.minecraft:server:${MC_VERSION}-${MCP_VERSION}:slim" + } + tasks.register("downloadServerExtra", DownloadMavenArtifact) { + artifact = "net.minecraft:server:${MC_VERSION}-${MCP_VERSION}:extra" + } + tasks.register("downloadJoinedSlim", DownloadMavenArtifact) { + artifact = "net.minecraft:joined:${MC_VERSION}-${MCP_VERSION}:slim" + } + tasks.register("downloadJoinedExtra", DownloadMavenArtifact) { + artifact = "net.minecraft:joined:${MC_VERSION}-${MCP_VERSION}:extra" + } + tasks.register("createJoinedSRG", DownloadMavenArtifact) { + artifact = "net.minecraft:joined:${MC_VERSION}-${MCP_VERSION}:srg" + } + tasks.register("createClientSRG", RenameJar) { + tool = FART + args = ['--input', '{input}', '--output', '{output}', '--names', '{mappings}', '--ann-fix', '--ids-fix', '--src-fix', '--record-fix'] + mappings = createMcp2Srg.srg + input = downloadClientSlim.output + output = file("build/createClientSRG/output.jar") + } + tasks.register("createServerSRG", RenameJar) { + tool = FART + args = ['--input', '{input}', '--output', '{output}', '--names', '{mappings}', '--ann-fix', '--ids-fix', '--src-fix', '--record-fix'] + mappings = createMcp2Srg.srg + input = downloadServerSlim.output + output = file("build/createServerSRG/output.jar") + } + genClientBinPatches { + tool = BINPATCH_TOOL + cleanJar = createClientSRG.output + } + genServerBinPatches { + tool = BINPATCH_TOOL + cleanJar = createServerSRG.output + } + genJoinedBinPatches { + tool = BINPATCH_TOOL + cleanJar = createJoinedSRG.output + } + tasks.register("applyClientBinPatches", ApplyBinPatches) { + tool = BINPATCH_TOOL + clean = genClientBinPatches.cleanJar + patch = genClientBinPatches.output + } + tasks.register("applyServerBinPatches", ApplyBinPatches) { + tool = BINPATCH_TOOL + clean = genServerBinPatches.cleanJar + patch = genServerBinPatches.output + } + tasks.register("applyJoinedBinPatches", ApplyBinPatches) { + tool = BINPATCH_TOOL + clean = genJoinedBinPatches.cleanJar + patch = genJoinedBinPatches.output + } + + tasks.register('checkAll') { dependsOn 'checkLicenses' group = 'checks' @@ -1065,7 +969,7 @@ project(':forge') { inheritsFrom: MC_VERSION, logging: {}, arguments: [ - game: ['--launchTarget', 'forgeclient', + game: ['--launchTarget', 'forge_client', '--fml.forgeVersion', FORGE_VERSION, '--fml.mcVersion', MC_VERSION, '--fml.forgeGroup', project.group, @@ -1369,7 +1273,7 @@ project(':forge') { rename 'gitignore\\.txt', '.gitignore' rename 'gitattributes\\.txt', '.gitattributes' } - from(rootProject.file('src/generated_mdk/resources/')) { + from(rootProject.file('src/generated_test/resources/mdk_datagen/')) { into('src/main/resources/') exclude '**/.cache/' } diff --git a/fmlloader/build.gradle b/fmlloader/build.gradle index 7d29c81b72..ffacc03c0a 100644 --- a/fmlloader/build.gradle +++ b/fmlloader/build.gradle @@ -35,6 +35,7 @@ dependencies { implementation("cpw.mods:securejarhandler:${SECUREJARHANDLER_VERSION}") implementation("net.minecraftforge:accesstransformers:${ACCESSTRANSFORMERS_VERSION}") implementation("net.minecrell:terminalconsoleappender:${TERMINALCONSOLEAPPENDER_VERSION}") + implementation("com.google.jimfs:jimfs:${JIMFS_VERSION}") // implementation("org.jline:jline:${JLINE_VERSION}") implementation("org.apache.logging.log4j:log4j-core:${LOG4J_VERSION}") diff --git a/fmlloader/src/main/java/net/minecraftforge/fml/common/asm/ObjectHolderDefinalize.java b/fmlloader/src/main/java/net/minecraftforge/fml/common/asm/ObjectHolderDefinalize.java index 1337ec2f46..517adc0631 100644 --- a/fmlloader/src/main/java/net/minecraftforge/fml/common/asm/ObjectHolderDefinalize.java +++ b/fmlloader/src/main/java/net/minecraftforge/fml/common/asm/ObjectHolderDefinalize.java @@ -56,6 +56,7 @@ public class ObjectHolderDefinalize implements ILaunchPluginService { return lst != null && lst.stream().anyMatch(n -> n.desc.equals(OBJECT_HOLDER)); } + @SuppressWarnings("unused") private String getValue(List lst) { AnnotationNode ann = lst.stream().filter(n -> n.desc.equals(OBJECT_HOLDER)).findFirst().get(); diff --git a/fmlloader/src/main/java/net/minecraftforge/fml/common/asm/RuntimeEnumExtender.java b/fmlloader/src/main/java/net/minecraftforge/fml/common/asm/RuntimeEnumExtender.java index f92012eca7..32bc948558 100644 --- a/fmlloader/src/main/java/net/minecraftforge/fml/common/asm/RuntimeEnumExtender.java +++ b/fmlloader/src/main/java/net/minecraftforge/fml/common/asm/RuntimeEnumExtender.java @@ -20,8 +20,6 @@ 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 diff --git a/fmlloader/src/main/java/net/minecraftforge/fml/loading/BackgroundWaiter.java b/fmlloader/src/main/java/net/minecraftforge/fml/loading/BackgroundWaiter.java index cac3c4f5c2..3be9974cd6 100644 --- a/fmlloader/src/main/java/net/minecraftforge/fml/loading/BackgroundWaiter.java +++ b/fmlloader/src/main/java/net/minecraftforge/fml/loading/BackgroundWaiter.java @@ -5,8 +5,6 @@ package net.minecraftforge.fml.loading; -import net.minecraftforge.fml.loading.progress.StartupNotificationManager; - import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; diff --git a/fmlloader/src/main/java/net/minecraftforge/fml/loading/EarlyLoadingException.java b/fmlloader/src/main/java/net/minecraftforge/fml/loading/EarlyLoadingException.java index 371fe9e44b..ec2cfe5c72 100644 --- a/fmlloader/src/main/java/net/minecraftforge/fml/loading/EarlyLoadingException.java +++ b/fmlloader/src/main/java/net/minecraftforge/fml/loading/EarlyLoadingException.java @@ -14,6 +14,8 @@ import java.util.List; * or server. */ public class EarlyLoadingException extends RuntimeException { + private static final long serialVersionUID = 2302192216172508006L; + public static class ExceptionData { private final IModInfo modInfo; private final String i18message; diff --git a/fmlloader/src/main/java/net/minecraftforge/fml/loading/FMLConfig.java b/fmlloader/src/main/java/net/minecraftforge/fml/loading/FMLConfig.java index 88ed60233e..2c8b7a8735 100644 --- a/fmlloader/src/main/java/net/minecraftforge/fml/loading/FMLConfig.java +++ b/fmlloader/src/main/java/net/minecraftforge/fml/loading/FMLConfig.java @@ -42,7 +42,6 @@ public class FMLConfig private final String entry; private final Object defaultValue; private final String comment; - private final Class valueType; private final Function entryFunction; ConfigValue(final String entry, final Object defaultValue, final String comment) { @@ -52,7 +51,6 @@ public class FMLConfig this.entry = entry; this.defaultValue = defaultValue; this.comment = comment; - this.valueType = defaultValue.getClass(); this.entryFunction = entryFunction; } diff --git a/fmlloader/src/main/java/net/minecraftforge/fml/loading/FMLLoader.java b/fmlloader/src/main/java/net/minecraftforge/fml/loading/FMLLoader.java index 721b9a18f8..d5f7c79430 100644 --- a/fmlloader/src/main/java/net/minecraftforge/fml/loading/FMLLoader.java +++ b/fmlloader/src/main/java/net/minecraftforge/fml/loading/FMLLoader.java @@ -16,7 +16,6 @@ import net.minecraftforge.fml.loading.moddiscovery.ModFile; import net.minecraftforge.fml.loading.moddiscovery.ModValidator; import net.minecraftforge.accesstransformer.service.AccessTransformerService; import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.fml.loading.progress.StartupNotificationManager; import net.minecraftforge.fml.loading.targets.CommonLaunchHandler; import net.minecraftforge.forgespi.Environment; import net.minecraftforge.forgespi.coremod.ICoreModProvider; @@ -137,6 +136,7 @@ public class FMLLoader throw new RuntimeException("Missing launch handler: " + launchTarget); } + // TODO: What the fuck is the point of using a service if you require a specific concrete class if (!(launchHandler.get() instanceof CommonLaunchHandler)) { LOGGER.error(CORE, "Incompatible Launch handler found - type {}, cannot continue", launchHandler.get().getClass().getName()); throw new RuntimeException("Incompatible launch handler found"); diff --git a/fmlloader/src/main/java/net/minecraftforge/fml/loading/FMLServiceProvider.java b/fmlloader/src/main/java/net/minecraftforge/fml/loading/FMLServiceProvider.java index e8647f17f5..d297620d8e 100644 --- a/fmlloader/src/main/java/net/minecraftforge/fml/loading/FMLServiceProvider.java +++ b/fmlloader/src/main/java/net/minecraftforge/fml/loading/FMLServiceProvider.java @@ -126,6 +126,7 @@ public class FMLServiceProvider implements ITransformationService targetMcpMappings = option.value(mappingsOption); } + @SuppressWarnings("rawtypes") @Override public @NotNull List transformers() { diff --git a/fmlloader/src/main/java/net/minecraftforge/fml/loading/FileUtils.java b/fmlloader/src/main/java/net/minecraftforge/fml/loading/FileUtils.java deleted file mode 100644 index 570d8d3789..0000000000 --- a/fmlloader/src/main/java/net/minecraftforge/fml/loading/FileUtils.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) Forge Development LLC and contributors - * SPDX-License-Identifier: LGPL-2.1-only - */ - -package net.minecraftforge.fml.loading; - -import java.io.File; -import java.nio.file.Path; - -public class FileUtils -{ - - public static String fileExtension(final Path path) { - String fileName = path.getFileName().toString(); - int idx = fileName.lastIndexOf('.'); - if (idx > -1) { - return fileName.substring(idx+1); - } else { - 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; - } -} diff --git a/fmlloader/src/main/java/net/minecraftforge/fml/loading/JarVersionLookupHandler.java b/fmlloader/src/main/java/net/minecraftforge/fml/loading/JarVersionLookupHandler.java index 491b240cce..b3f0c8e5eb 100644 --- a/fmlloader/src/main/java/net/minecraftforge/fml/loading/JarVersionLookupHandler.java +++ b/fmlloader/src/main/java/net/minecraftforge/fml/loading/JarVersionLookupHandler.java @@ -11,6 +11,7 @@ import java.util.Optional; * Finds Version data from a package, with possible default values */ public class JarVersionLookupHandler { + public static Optional getImplementationVersion(final String pkgName) { // Note that with Java 9, you'll probably want the module's version data, hence pulling this out final String pkgVersion = Package.getPackage(pkgName).getImplementationVersion(); diff --git a/fmlloader/src/main/java/net/minecraftforge/fml/loading/LanguageLoadingProvider.java b/fmlloader/src/main/java/net/minecraftforge/fml/loading/LanguageLoadingProvider.java index e1663a1ea0..edaf98a2bd 100644 --- a/fmlloader/src/main/java/net/minecraftforge/fml/loading/LanguageLoadingProvider.java +++ b/fmlloader/src/main/java/net/minecraftforge/fml/loading/LanguageLoadingProvider.java @@ -9,7 +9,6 @@ import com.mojang.logging.LogUtils; import cpw.mods.modlauncher.Launcher; import cpw.mods.modlauncher.api.IModuleLayerManager; import cpw.mods.modlauncher.util.ServiceLoaderUtils; -import net.minecraftforge.fml.loading.progress.StartupNotificationManager; import net.minecraftforge.forgespi.language.IModLanguageProvider; import net.minecraftforge.fml.loading.moddiscovery.ExplodedDirectoryLocator; import net.minecraftforge.fml.loading.moddiscovery.ModFile; diff --git a/fmlloader/src/main/java/net/minecraftforge/fml/loading/ModDirTransformerDiscoverer.java b/fmlloader/src/main/java/net/minecraftforge/fml/loading/ModDirTransformerDiscoverer.java index 9609f85638..072ab5d44c 100644 --- a/fmlloader/src/main/java/net/minecraftforge/fml/loading/ModDirTransformerDiscoverer.java +++ b/fmlloader/src/main/java/net/minecraftforge/fml/loading/ModDirTransformerDiscoverer.java @@ -7,7 +7,6 @@ package net.minecraftforge.fml.loading; import com.mojang.logging.LogUtils; import cpw.mods.jarhandling.SecureJar; -import cpw.mods.modlauncher.Launcher; import cpw.mods.modlauncher.api.LamdbaExceptionUtils; import cpw.mods.modlauncher.api.NamedPath; import cpw.mods.modlauncher.serviceapi.ITransformerDiscoveryService; @@ -19,8 +18,6 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.List; -import java.util.ServiceLoader; -import java.util.zip.ZipFile; import java.util.Set; public class ModDirTransformerDiscoverer implements ITransformerDiscoveryService { diff --git a/fmlloader/src/main/java/net/minecraftforge/fml/loading/ModJarURLHandler.java b/fmlloader/src/main/java/net/minecraftforge/fml/loading/ModJarURLHandler.java deleted file mode 100644 index 19b8220b7e..0000000000 --- a/fmlloader/src/main/java/net/minecraftforge/fml/loading/ModJarURLHandler.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * 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.slf4j.Logger; - -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.net.URLConnection; -import java.net.URLStreamHandler; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Objects; -import java.util.Optional; -import java.util.jar.Manifest; - -import static net.minecraftforge.fml.loading.LogMarkers.CORE; - -public class ModJarURLHandler extends URLStreamHandler -{ - private static final Logger LOGGER = LogUtils.getLogger(); - // modjar://modid/path/to/file - @Override - protected URLConnection openConnection(URL url) { - return new ModJarURLConnection(url); - } - - @Override - protected int hashCode(final URL u) { - return Objects.hash(u.getHost(), u.getFile()); - } - - @Override - protected boolean equals(final URL u1, final URL u2) { - return Objects.equals(u1.getProtocol(), u2.getProtocol()) - && Objects.equals(u1.getHost(), u2.getHost()) - && Objects.equals(u1.getFile(), u2.getFile()); - } - - static class ModJarURLConnection extends URLConnection { - private Path resource; - private String modpath; - private String modid; - private Optional manifest; - - public ModJarURLConnection(final URL url) { - super(url); - } - - @Override - public void connect() - { -// if (resource == null) { -// modid = url.getHost(); -// // trim first char -// modpath = url.getPath().substring(1); -// resource = FMLLoader.getLoadingModList().getModFileById(modid).getFile().findResource(modpath); -// manifest = FMLLoader.getLoadingModList().getModFileById(modid).getManifest(); -// } - } - - @Override - public InputStream getInputStream() throws IOException - { - connect(); - LOGGER.trace(CORE, "Loading modjar URL {} got resource {} {}", url, resource, resource != null ? Files.exists(resource) : "missing"); - return Files.newInputStream(resource); - } - - @Override - public long getContentLengthLong() { - try { - connect(); - return Files.size(resource); - } catch (IOException e) { - return -1L; - } - } - - // Used to cache protectiondomains by "top level object" aka the modid - @Override - public URL getURL() { - return LamdbaExceptionUtils.uncheck(()->new URL("modjar://"+modid)); - } - - public Optional getManifest() { - return manifest; - } - } -} diff --git a/fmlloader/src/main/java/net/minecraftforge/fml/loading/ModSorter.java b/fmlloader/src/main/java/net/minecraftforge/fml/loading/ModSorter.java index ea9e1b35b7..bd40d36555 100644 --- a/fmlloader/src/main/java/net/minecraftforge/fml/loading/ModSorter.java +++ b/fmlloader/src/main/java/net/minecraftforge/fml/loading/ModSorter.java @@ -10,7 +10,6 @@ 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; import net.minecraftforge.fml.loading.moddiscovery.ModFile; @@ -72,7 +71,6 @@ public class ModSorter } } - @SuppressWarnings("UnstableApiUsage") private void sort() { // lambdas are identity based, so sorting them is impossible unless you hold reference to them @@ -121,7 +119,6 @@ public class ModSorter .collect(toList()); } - @SuppressWarnings("UnstableApiUsage") private void addDependency(MutableGraph topoGraph, IModInfo.ModVersion dep) { final ModFileInfo self = (ModFileInfo)dep.getOwner().getOwningFile(); @@ -133,6 +130,7 @@ public class ModSorter switch (dep.getOrdering()) { case BEFORE -> topoGraph.putEdge(self, target); case AFTER -> topoGraph.putEdge(target, self); + default -> {} } } diff --git a/fmlloader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/AbstractModProvider.java b/fmlloader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/AbstractModProvider.java index 12fecc540b..c3c855b1e2 100644 --- a/fmlloader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/AbstractModProvider.java +++ b/fmlloader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/AbstractModProvider.java @@ -27,8 +27,7 @@ import java.util.Optional; import java.util.function.Function; import java.util.jar.Manifest; -public abstract class AbstractModProvider implements IModProvider -{ +public abstract class AbstractModProvider implements IModProvider { private static final Logger LOGGER = LogUtils.getLogger(); protected static final String MODS_TOML = "META-INF/mods.toml"; protected static final String MANIFEST = "META-INF/MANIFEST.MF"; @@ -36,25 +35,24 @@ public abstract class AbstractModProvider implements IModProvider protected IModLocator.ModFileOrException createMod(Path... path) { var mjm = new ModJarMetadata(); var sj = SecureJar.from( - Manifest::new, - jar -> jar.moduleDataProvider().findFile(MODS_TOML).isPresent() ? mjm : JarMetadata.from(jar, path), - path + Manifest::new, + jar -> jar.moduleDataProvider().findFile(MODS_TOML).isPresent() ? mjm : JarMetadata.from(jar, path), + path ); IModFile mod; var type = sj.moduleDataProvider().getManifest().getMainAttributes().getValue(ModFile.TYPE); - if (type == null) { + if (type == null) type = getDefaultJarModType(); - } + if (sj.moduleDataProvider().findFile(MODS_TOML).isPresent()) { LOGGER.debug(LogMarkers.SCAN, "Found {} mod of type {}: {}", MODS_TOML, type, path); mod = new ModFile(sj, this, ModFileParser::modsTomlParser); } else if (type != null) { LOGGER.debug(LogMarkers.SCAN, "Found {} mod of type {}: {}", MANIFEST, type, path); mod = new ModFile(sj, this, this::manifestParser, type); - } else { - return new IModLocator.ModFileOrException(null, new ModFileLoadingException("Invalid mod file found "+ Arrays.toString(path))); - } + } else + return new IModLocator.ModFileOrException(null, new ModFileLoadingException("Invalid mod file found " + Arrays.toString(path))); mjm.setModFile(mod); return new IModLocator.ModFileOrException(mod, null); @@ -87,36 +85,19 @@ public abstract class AbstractModProvider implements IModProvider } private record DefaultModFileInfo(IModFile mod, String license, IConfigurable configurable) implements IModFileInfo, IConfigurable { - @Override - public Optional getConfigElement(final String... strings) - { - return Optional.empty(); - } - - @Override - public List getConfigList(final String... strings) - { - return null; - } - + @Override public Optional getConfigElement(final String... strings) { return Optional.empty(); } + @Override public List getConfigList(final String... strings) { return null; } @Override public List getMods() { return Collections.emptyList(); } @Override public List requiredLanguageLoaders() { return Collections.emptyList(); } @Override public boolean showAsResourcePack() { return false; } @Override public Map getFileProperties() { return Collections.emptyMap(); } - @Override - public String getLicense() { return license; } - + @Override public String getLicense() { return license; } @Override public IModFile getFile() { return mod; } @Override public IConfigurable getConfig() { return configurable; } - // These Should never be called as it's only called from ModJarMetadata.version and we bypass that @Override public String moduleName() { return mod.getSecureJar().name(); } @Override public String versionString() { return null; } @Override public List usesServices() { return null; } - - @Override - public String toString() { - return "IModFileInfo(" + mod.getFilePath() + ")"; - } + @Override public String toString() { return "IModFileInfo(" + mod.getFilePath() + ")"; } } } diff --git a/fmlloader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ClasspathLocator.java b/fmlloader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ClasspathLocator.java index 0a8f482ced..347d8d639d 100644 --- a/fmlloader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ClasspathLocator.java +++ b/fmlloader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ClasspathLocator.java @@ -12,12 +12,9 @@ import org.slf4j.Logger; import java.io.File; import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; import java.net.URL; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; import java.util.Enumeration; @@ -25,8 +22,7 @@ import java.util.List; import java.util.Map; import java.util.stream.Stream; -public class ClasspathLocator extends AbstractJarFileModLocator -{ +public class ClasspathLocator extends AbstractJarFileModLocator { private static final Logger LOGGER = LogUtils.getLogger(); private final List legacyClasspath = Arrays.stream(System.getProperty("legacyClassPath", "").split(File.pathSeparator)).map(Path::of).toList(); private boolean enabled = false; @@ -73,22 +69,4 @@ public class ClasspathLocator extends AbstractJarFileModLocator var launchTarget = (String) arguments.get("launchTarget"); enabled = launchTarget != null && launchTarget.contains("dev"); } - - private 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); - } - } } diff --git a/fmlloader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/InvalidModFileException.java b/fmlloader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/InvalidModFileException.java index 1177e18972..8e57e3729e 100644 --- a/fmlloader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/InvalidModFileException.java +++ b/fmlloader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/InvalidModFileException.java @@ -11,12 +11,11 @@ import net.minecraftforge.forgespi.locating.ModFileLoadingException; import java.util.Locale; import java.util.Optional; -public class InvalidModFileException extends ModFileLoadingException -{ +public class InvalidModFileException extends ModFileLoadingException { + private static final long serialVersionUID = 1230464325917450374L; private final IModFileInfo modFileInfo; - public InvalidModFileException(String message, IModFileInfo modFileInfo) - { + public InvalidModFileException(String message, IModFileInfo modFileInfo) { super(String.format(Locale.ROOT, "%s (%s)", message, Optional.ofNullable(modFileInfo).map(mf->mf.getFile().getFileName()).orElse("MISSING FILE NAME"))); this.modFileInfo = modFileInfo; } diff --git a/fmlloader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModAnnotationVisitor.java b/fmlloader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModAnnotationVisitor.java index d48dd65df3..8fd1fd3e34 100644 --- a/fmlloader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModAnnotationVisitor.java +++ b/fmlloader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModAnnotationVisitor.java @@ -10,72 +10,58 @@ import org.objectweb.asm.Opcodes; import java.util.LinkedList; -public class ModAnnotationVisitor extends AnnotationVisitor -{ +public class ModAnnotationVisitor extends AnnotationVisitor { private final ModAnnotation annotation; private LinkedList annotations; private boolean array; - private String name; private boolean isSubAnnotation; - public ModAnnotationVisitor(LinkedList annotations, ModAnnotation annotation) - { + public ModAnnotationVisitor(LinkedList annotations, ModAnnotation annotation) { super(Opcodes.ASM9); this.annotations = annotations; this.annotation = annotation; } - public ModAnnotationVisitor(LinkedList annotations, ModAnnotation annotation, String name) - { + public ModAnnotationVisitor(LinkedList annotations, ModAnnotation annotation, String name) { this(annotations, annotation); this.array = true; - this.name = name; annotation.addArray(name); } - public ModAnnotationVisitor(LinkedList annotations, ModAnnotation annotation, boolean isSubAnnotation) - { + public ModAnnotationVisitor(LinkedList annotations, ModAnnotation annotation, boolean isSubAnnotation) { this(annotations, annotation); this.isSubAnnotation = true; } @Override - public void visit(String key, Object value) - { + public void visit(String key, Object value) { annotation.addProperty(key, value); } @Override - public void visitEnum(String name, String desc, String value) - { + public void visitEnum(String name, String desc, String value) { annotation.addEnumProperty(name, desc, value); } @Override - public AnnotationVisitor visitArray(String name) - { + public AnnotationVisitor visitArray(String name) { return new ModAnnotationVisitor(annotations, annotation, name); } + @Override - public AnnotationVisitor visitAnnotation(String name, String desc) - { - ModAnnotation ma = annotations.getFirst(); - final ModAnnotation childAnnotation = ma.addChildAnnotation(name, desc); + public AnnotationVisitor visitAnnotation(String name, String desc) { + var ma = annotations.getFirst(); + var childAnnotation = ma.addChildAnnotation(name, desc); annotations.addFirst(childAnnotation); - return new ModAnnotationVisitor(annotations, childAnnotation,true); + return new ModAnnotationVisitor(annotations, childAnnotation, true); } + @Override - public void visitEnd() - { + public void visitEnd() { if (array) - { annotation.endArray(); - } if (isSubAnnotation) - { - ModAnnotation child = annotations.removeFirst(); - annotations.addLast(child); - } + annotations.addLast(annotations.removeFirst()); } } diff --git a/fmlloader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModFile.java b/fmlloader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModFile.java index f95c4dedb1..164add39ab 100644 --- a/fmlloader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModFile.java +++ b/fmlloader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModFile.java @@ -10,7 +10,6 @@ import com.mojang.logging.LogUtils; import cpw.mods.jarhandling.SecureJar; import net.minecraftforge.fml.loading.FMLLoader; import net.minecraftforge.fml.loading.LogMarkers; -import net.minecraftforge.fml.loading.progress.StartupNotificationManager; import net.minecraftforge.forgespi.language.IModFileInfo; import net.minecraftforge.forgespi.language.IModInfo; import net.minecraftforge.forgespi.language.IModLanguageProvider; @@ -207,8 +206,11 @@ public class ModFile implements IModFile { this.securityStatus = status; } - public ArtifactVersion getJarVersion() - { + public SecureJar.Status getSecurityStatus() { + return this.securityStatus; + } + + public ArtifactVersion getJarVersion() { return new DefaultArtifactVersion(this.jarVersion); } diff --git a/fmlloader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModFileParser.java b/fmlloader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModFileParser.java index 9d519b5aaa..9cac458341 100644 --- a/fmlloader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModFileParser.java +++ b/fmlloader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModFileParser.java @@ -22,7 +22,6 @@ import java.nio.file.Path; import java.util.Collections; import java.util.List; import java.util.Map; -import java.util.stream.Collectors; public class ModFileParser { private static final Logger LOGGER = LogUtils.getLogger(); diff --git a/fmlloader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModListHandler.java b/fmlloader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModListHandler.java index a9b4a9233d..471d1fb6aa 100644 --- a/fmlloader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModListHandler.java +++ b/fmlloader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModListHandler.java @@ -7,7 +7,6 @@ package net.minecraftforge.fml.loading.moddiscovery; import com.mojang.logging.LogUtils; import net.minecraftforge.fml.loading.FMLPaths; -import net.minecraftforge.fml.loading.FileUtils; import net.minecraftforge.fml.loading.LogMarkers; import net.minecraftforge.fml.loading.MavenCoordinateResolver; import org.apache.commons.lang3.tuple.Pair; @@ -63,7 +62,7 @@ public class ModListHandler { return Collections.emptyList(); } - String extension = FileUtils.fileExtension(filePath); + String extension = fileExtension(filePath); if (Objects.equals("list",extension)) { return readListFile(filePath).stream().filter(s -> !s.isEmpty()).collect(Collectors.toList()); } else { @@ -72,6 +71,12 @@ public class ModListHandler { return Collections.emptyList(); } + private static String fileExtension(final Path path) { + String fileName = path.getFileName().toString(); + int idx = fileName.lastIndexOf('.'); + return idx > -1 ? fileName.substring(idx+1) : ""; + } + /** * Simple list file, ending in ".list" with one mod coordinate per line * @param filePath path diff --git a/fmlloader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModValidator.java b/fmlloader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModValidator.java index 08e3275b58..2483ac4397 100644 --- a/fmlloader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModValidator.java +++ b/fmlloader/src/main/java/net/minecraftforge/fml/loading/moddiscovery/ModValidator.java @@ -9,7 +9,6 @@ import com.mojang.logging.LogUtils; import cpw.mods.modlauncher.api.IModuleLayerManager; import cpw.mods.modlauncher.api.ITransformationService; import net.minecraftforge.fml.loading.*; -import net.minecraftforge.fml.loading.progress.StartupNotificationManager; import net.minecraftforge.forgespi.language.IModFileInfo; import net.minecraftforge.forgespi.locating.IModFile; import org.jetbrains.annotations.NotNull; @@ -23,7 +22,7 @@ import java.util.stream.Collectors; public class ModValidator { private static final Logger LOGGER = LogUtils.getLogger(); - private final Map> modFiles; + //private final Map> modFiles; private final List candidatePlugins; private final List candidateMods; private LoadingModList loadingModList; @@ -31,7 +30,7 @@ public class ModValidator { private final List discoveryErrorData; public ModValidator(final Map> modFiles, final List brokenFiles, final List discoveryErrorData) { - this.modFiles = modFiles; + //this.modFiles = modFiles; this.candidateMods = lst(modFiles.get(IModFile.Type.MOD)); this.candidateMods.addAll(lst(modFiles.get(IModFile.Type.GAMELIBRARY))); this.candidatePlugins = lst(modFiles.get(IModFile.Type.LANGPROVIDER)); diff --git a/fmlloader/src/main/java/net/minecraftforge/fml/loading/progress/StartupNotificationManager.java b/fmlloader/src/main/java/net/minecraftforge/fml/loading/progress/StartupNotificationManager.java index 56b26f739d..2e714d5ed1 100644 --- a/fmlloader/src/main/java/net/minecraftforge/fml/loading/progress/StartupNotificationManager.java +++ b/fmlloader/src/main/java/net/minecraftforge/fml/loading/progress/StartupNotificationManager.java @@ -10,8 +10,6 @@ import com.google.common.base.CharMatcher; import java.util.*; import java.util.function.Consumer; -import java.util.stream.Stream; -import java.util.stream.StreamSupport; public class StartupNotificationManager { private static volatile EnumMap> messages = new EnumMap<>(Message.MessageType.class); diff --git a/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/ArgumentList.java b/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/ArgumentList.java index 69ce04db9e..cf17ddf779 100644 --- a/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/ArgumentList.java +++ b/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/ArgumentList.java @@ -6,6 +6,8 @@ package net.minecraftforge.fml.loading.targets; import com.mojang.logging.LogUtils; + +import org.jetbrains.annotations.ApiStatus; import org.slf4j.Logger; import java.util.ArrayList; @@ -19,6 +21,7 @@ import java.util.function.Supplier; * A class that attempts to parse command line arguments into key value pairs to allow addition and editing. * Can not use JOptSimple as that doesn't parse out the values for keys unless the spec says it has a value. */ +@ApiStatus.Internal class ArgumentList { private static final Logger LOGGER = LogUtils.getLogger(); private List> entries = new ArrayList<>(); diff --git a/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/CommonClientLaunchHandler.java b/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/CommonClientLaunchHandler.java deleted file mode 100644 index 6225f4df06..0000000000 --- a/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/CommonClientLaunchHandler.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) Forge Development LLC and contributors - * SPDX-License-Identifier: LGPL-2.1-only - */ - -package net.minecraftforge.fml.loading.targets; - -import cpw.mods.modlauncher.api.ServiceRunner; -import net.minecraftforge.fml.loading.FMLLoader; -import net.minecraftforge.fml.loading.LibraryFinder; -import net.minecraftforge.fml.loading.VersionInfo; -import net.minecraftforge.api.distmarker.Dist; - -import java.nio.file.Path; -import java.util.List; -import java.util.stream.Stream; - -public abstract class CommonClientLaunchHandler extends CommonLaunchHandler { - @Override public Dist getDist() { return Dist.CLIENT; } - @Override public String getNaming() { return "srg"; } - @Override public boolean isProduction() { return true; } - - @Override - protected ServiceRunner makeService(final String[] arguments, final ModuleLayer gameLayer) { - return ()->clientService(arguments, gameLayer); - } - - @Override - public LocatedPaths getMinecraftPaths() { - final var vers = FMLLoader.versionInfo(); - var mc = LibraryFinder.findPathForMaven("net.minecraft", "client", "", "srg", vers.mcAndMCPVersion()); - var mcextra = LibraryFinder.findPathForMaven("net.minecraft", "client", "", "extra", vers.mcAndMCPVersion()); - var mcstream = Stream.builder().add(mc).add(mcextra); - var modstream = Stream.>builder(); - - processMCStream(vers, mcstream, modstream); - - var fmlcore = LibraryFinder.findPathForMaven(vers.forgeGroup(), "fmlcore", "", "", vers.mcAndForgeVersion()); - var javafmllang = LibraryFinder.findPathForMaven(vers.forgeGroup(), "javafmllanguage", "", "", vers.mcAndForgeVersion()); - var lowcodelang = LibraryFinder.findPathForMaven(vers.forgeGroup(), "lowcodelanguage", "", "", vers.mcAndForgeVersion()); - var mclang = LibraryFinder.findPathForMaven(vers.forgeGroup(), "mclanguage", "", "", vers.mcAndForgeVersion()); - - return new LocatedPaths(mcstream.build().toList(), null, modstream.build().toList(), List.of(fmlcore, javafmllang, lowcodelang, mclang)); - } - - protected abstract void processMCStream(VersionInfo versionInfo, Stream.Builder mc, Stream.Builder> mods); -} diff --git a/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/CommonDevLaunchHandler.java b/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/CommonDevLaunchHandler.java index 5a8ba6d897..19e586ed3b 100644 --- a/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/CommonDevLaunchHandler.java +++ b/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/CommonDevLaunchHandler.java @@ -7,46 +7,30 @@ package net.minecraftforge.fml.loading.targets; import cpw.mods.jarhandling.SecureJar; import cpw.mods.modlauncher.api.ServiceRunner; -import net.minecraftforge.fml.loading.FileUtils; - +import net.minecraftforge.fml.loading.LogMarkers; import java.io.File; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.Arrays; +import java.util.ArrayList; +import java.util.HashMap; import java.util.List; -import java.util.Objects; +import java.util.Map; +import java.util.Optional; import java.util.function.BiPredicate; import java.util.regex.Matcher; import java.util.regex.Pattern; -import java.util.stream.Stream; -public abstract class CommonDevLaunchHandler extends CommonLaunchHandler { +import org.jetbrains.annotations.ApiStatus; + +@ApiStatus.Internal +abstract class CommonDevLaunchHandler extends CommonLaunchHandler { + protected CommonDevLaunchHandler(LaunchType type, String prefix) { + super(type, prefix); + } + @Override public String getNaming() { return "mcp"; } @Override public boolean isProduction() { return false; } - @Override - public LocatedPaths getMinecraftPaths() { - // Minecraft is extra jar {resources} + our exploded directories in dev - final var mcstream = Stream.builder(); - - // The extra jar is on the classpath, so try and pull it out of the legacy classpath - var legacyCP = Objects.requireNonNull(System.getProperty("legacyClassPath"), "Missing legacyClassPath, cannot find client-extra").split(File.pathSeparator); - var extra = findJarOnClasspath(legacyCP, "client-extra"); - - // The MC code/Patcher edits are in exploded directories - final var modstream = Stream.>builder(); - final var mods = getModClasses(); - final var minecraft = mods.remove("minecraft"); - if (minecraft == null) - throw new IllegalStateException("Could not find 'minecraft' mod paths."); - minecraft.stream().distinct().forEach(mcstream::add); - mods.values().forEach(modstream::add); - - mcstream.add(extra); - var mcFilter = getMcFilter(extra, minecraft, modstream); - return new LocatedPaths(mcstream.build().toList(), mcFilter, modstream.build().toList(), getFmlStuff(legacyCP)); - } - @Override protected String[] preLaunch(String[] arguments, ModuleLayer layer) { super.preLaunch(arguments, layer); @@ -79,34 +63,34 @@ public abstract class CommonDevLaunchHandler extends CommonLaunchHandler { return args.getArguments(); } - protected List getFmlStuff(String[] classpath) { - // We also want the FML things, fmlcore, javafmllanguage, mclanguage, I don't like hard coding these, but hey whatever works for now. - return Arrays.stream(classpath) - .filter(e -> FileUtils.matchFileName(e, "fmlcore", "javafmllanguage", "lowcodelanguage", "mclanguage")) - .map(Paths::get) - .toList(); + protected List getLibraries(String[] classpath) { + // TODO: These should all be FMLModType: LIBRARY, find them that way? + // Or at the very least include version info + var fmlcore = findJarOnClasspath(classpath, "fmlcore"); + var javafmllang = findJarOnClasspath(classpath, "javafmllanguage"); + var lowcodelang = findJarOnClasspath(classpath, "lowcodelanguage"); + var mclang = findJarOnClasspath(classpath, "mclanguage"); + return List.of(fmlcore, javafmllang, lowcodelang, mclang); } - protected static Path findJarOnClasspath(String[] classpath, String match) { - return Paths.get(Arrays.stream(classpath) - .filter(e -> FileUtils.matchFileName(e, match)) - .findFirst() - .orElseThrow(() -> new IllegalStateException("Could not find " + match + " in classpath"))); - } - - protected BiPredicate getMcFilter(Path extra, List minecraft, Stream.Builder> mods) { - final var packages = getPackages(); - final var extraPath = extra.toString().replace('\\', '/'); + protected BiPredicate getMcFilter(Path extra, List minecraft) { + var packages = getPackages(); // Pulled out so it is passed to the lambda as value + var extraPath = extra.toString().replace('\\', '/'); // We serve everything, except for things in the forge packages. BiPredicate mcFilter = (path, base) -> { if (base.equals(extraPath) || - path.endsWith("/")) return true; + path.endsWith("/")) return true; for (var pkg : packages) if (path.startsWith(pkg)) return false; return true; }; + return mcFilter; + } + + protected Path getForgeMod(List minecraft) { + var packages = getPackages(); // Pulled out so it is passed to the lambda as value // We need to separate out our resources/code so that we can show up as a different data pack. var modJar = SecureJar.from((path, base) -> { if (!path.endsWith(".class")) return true; @@ -114,14 +98,18 @@ public abstract class CommonDevLaunchHandler extends CommonLaunchHandler { if (path.startsWith(pkg)) return true; return false; }, minecraft.stream().distinct().toArray(Path[]::new)); - //modJar.getPackages().stream().sorted().forEach(System.out::println); - mods.add(List.of(modJar.getRootPath())); - return mcFilter; + //modJar.getPackages().stream().sorted().forEach(System.out::println); + return modJar.getRootPath(); } - protected String[] getPackages() { - return new String[]{ "net/minecraftforge/", "META-INF/services/", "META-INF/coremods.json", "META-INF/mods.toml" }; + private static String[] getPackages() { + return new String[] { + "net/minecraftforge/", + "META-INF/services/", + "META-INF/coremods.json", + "META-INF/mods.toml" + }; } private static String getRandomNumbers(int length) { @@ -131,9 +119,70 @@ public abstract class CommonDevLaunchHandler extends CommonLaunchHandler { @Override protected ServiceRunner makeService(final String[] arguments, final ModuleLayer gameLayer) { - var args = preLaunch(arguments, gameLayer); - return ()->devService(args, gameLayer); + return super.makeService(preLaunch(arguments, gameLayer), gameLayer); } - abstract void devService(final String[] arguments, final ModuleLayer gameLayer) throws Throwable; + // TODO: Get rid of this string based classpath crap when I re-write mod loader + protected static Map> getModClasses() { + var modClasses = Optional.ofNullable(System.getenv("MOD_CLASSES")).orElse(""); + LOGGER.debug(LogMarkers.CORE, "Got mod coordinates {} from env", modClasses); + + /* + * So MOD_CLASSES at the end of the day is a Map> but because we want to shove that into a single string. + * And pass it in as an environment variable.. instead od using json, or a file path, or anything sane, cpw did hacky string stuff + * Basically what we want to do is split the string by File.pathSeperator to get each key-value pair. + * Then we find the magic string "%%" and split on that. Using the first half as the mod id and the second as the path. + * BUT the modID is optional, and if not specified {why wouldn't it be?} it uses "defaultmodid" + * Anyways, it was stream hell, but now it's simpler to debug/understand. + */ + Map> ret = new HashMap<>(); + var entries = modClasses.split(File.pathSeparator); + for (var entry : entries) { + var modid = "defaultmodid"; + var path = entry; + + int idx = entry.indexOf("%%"); + if (idx != -1) { + modid = entry.substring(0, idx); + path = entry.substring(idx + 2); + } + + var p = Paths.get(path); + var lst = ret.computeIfAbsent(modid, k -> new ArrayList<>()); + if (!lst.contains(p)) + lst.add(p); + } + + LOGGER.debug(LogMarkers.CORE, "Found supplied mod coordinates:"); + ret.forEach((k, v) -> { + if (v.size() == 1) + LOGGER.debug(LogMarkers.CORE, "\t{}: {}", k, v.get(0)); + else { + LOGGER.debug(LogMarkers.CORE, "\t{}:", k); + v.forEach(e -> LOGGER.debug("\t\t{}", e)); + } + }); + + return ret; + } + + protected static Path findJarOnClasspath(String[] classpath, String match) { + String ret = null; + + for (var entry : classpath) { + int idx = entry.lastIndexOf(File.separatorChar); + if (idx == -1) continue; + + var name = entry.substring(idx + 1); + if (name.startsWith(match)) { + ret = entry; + break; + } + } + + if (ret == null) + new IllegalStateException("Could not find " + match + " in classpath"); + + return Paths.get(ret); + } } diff --git a/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/CommonLaunchHandler.java b/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/CommonLaunchHandler.java index 2a9aaf95d3..13d7aa12c7 100644 --- a/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/CommonLaunchHandler.java +++ b/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/CommonLaunchHandler.java @@ -10,49 +10,52 @@ import cpw.mods.modlauncher.api.ILaunchHandlerService; import cpw.mods.modlauncher.api.ITransformingClassLoaderBuilder; import cpw.mods.modlauncher.api.ServiceRunner; import net.minecraftforge.fml.loading.FMLLoader; -import net.minecraftforge.fml.loading.LogMarkers; import net.minecraftforge.api.distmarker.Dist; import org.apache.logging.log4j.core.LoggerContext; import org.apache.logging.log4j.core.config.ConfigurationFactory; import org.apache.logging.log4j.core.config.ConfigurationSource; import org.apache.logging.log4j.core.config.Configurator; import org.slf4j.Logger; -import sun.misc.Unsafe; - -import java.io.File; import java.io.IOException; import java.net.URI; import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Arrays; import java.util.List; -import java.util.Map; -import java.util.Optional; import java.util.function.BiPredicate; -import java.util.stream.Collectors; +/** + * This is required by FMLLoader because ILaunchHandlerService doesn't have the context we need. + * I need to clean this up to make proper api. But that involves editing ModLauncher itself which i'm not gunna do right now. + * + * So until that happens, guess this is public api. + */ public abstract class CommonLaunchHandler implements ILaunchHandlerService { - public record LocatedPaths(List minecraftPaths, BiPredicate minecraftFilter, List> otherModPaths, List otherArtifacts) {} + public record LocatedPaths( + List minecraftPaths, + BiPredicate minecraftFilter, + List> otherModPaths, + List otherArtifacts + ) {} protected static final Logger LOGGER = LogUtils.getLogger(); - public abstract Dist getDist(); + private final LaunchType type; + private final String prefix; + protected CommonLaunchHandler(LaunchType type, String prefix) { + this.type = type; + this.prefix = prefix; + } + + @Override public String name() { return this.prefix + this.type.name(); } + public Dist getDist() { return this.type.dist(); } + public boolean isData() { return this.type.data(); } + public boolean isProduction() { return false; } public abstract String getNaming(); - public boolean isProduction() { - return false; - } - - public boolean isData() { - return false; - } - public abstract LocatedPaths getMinecraftPaths(); @Override public void configureTransformationClassLoader(final ITransformingClassLoaderBuilder builder) { - } protected String[] preLaunch(String[] arguments, ModuleLayer layer) { @@ -69,45 +72,23 @@ public abstract class CommonLaunchHandler implements ILaunchHandlerService { return arguments; } - protected final Map> getModClasses() { - final String modClasses = Optional.ofNullable(System.getenv("MOD_CLASSES")).orElse(""); - LOGGER.debug(LogMarkers.CORE, "Got mod coordinates {} from env", modClasses); - - record ExplodedModPath(String modid, Path path) {} - // "a/b/;c/d/;" -> "modid%%c:\fish\pepper;modid%%c:\fish2\pepper2\;modid2%%c:\fishy\bums;modid2%%c:\hmm" - final var modClassPaths = Arrays.stream(modClasses.split(File.pathSeparator)) - .map(inp -> inp.split("%%", 2)) - .map(splitString -> new ExplodedModPath(splitString.length == 1 ? "defaultmodid" : splitString[0], Paths.get(splitString[splitString.length - 1]))) - .collect(Collectors.groupingBy(ExplodedModPath::modid, Collectors.mapping(ExplodedModPath::path, Collectors.toList()))); - - LOGGER.debug(LogMarkers.CORE, "Found supplied mod coordinates [{}]", modClassPaths); - - //final var explodedTargets = ((Map>)arguments).computeIfAbsent("explodedTargets", a -> new ArrayList<>()); - //modClassPaths.forEach((modlabel,paths) -> explodedTargets.add(new ExplodedDirectoryLocator.ExplodedMod(modlabel, paths))); - return modClassPaths; - } - @Override public ServiceRunner launchService(final String[] arguments, final ModuleLayer gameLayer) { FMLLoader.beforeStart(gameLayer); return makeService(arguments, gameLayer); } - protected abstract ServiceRunner makeService(final String[] arguments, final ModuleLayer gameLayer); - - protected void clientService(final String[] arguments, final ModuleLayer layer) throws Throwable { - runTarget("net.minecraft.client.main.Main", arguments, layer); + protected ServiceRunner makeService(final String[] arguments, final ModuleLayer gameLayer) { + return () -> runTarget(this.type.module(), this.type.main(), arguments, gameLayer); } - protected void serverService(final String[] arguments, final ModuleLayer layer) throws Throwable { - runTarget("net.minecraft.server.Main", arguments, layer); - } + protected record LaunchType(String name, String module, String main, Dist dist, boolean data) {}; + protected static final LaunchType CLIENT = new LaunchType("client", "minecraft", "net.minecraft.client.main.Main", Dist.CLIENT, false); + protected static final LaunchType DATA = new LaunchType("data", "minecraft", "net.minecraft.data.Main", Dist.CLIENT, true); + protected static final LaunchType SERVER = new LaunchType("server", "minecraft", "net.minecraft.server.Main", Dist.DEDICATED_SERVER, false); + protected static final LaunchType SERVER_GAMETEST = new LaunchType("server_gametest", "forge", "net.minecratforge.gametest.GameTestMain", Dist.DEDICATED_SERVER, false); - protected void dataService(final String[] arguments, final ModuleLayer layer) throws Throwable { - runTarget("net.minecraft.data.Main", arguments, layer); - } - - protected void runTarget(final String target, final String[] arguments, final ModuleLayer layer) throws Throwable { - Class.forName(layer.findModule("minecraft").orElseThrow(),target).getMethod("main", String[].class).invoke(null, (Object)arguments); + protected void runTarget(String module, String target, final String[] arguments, final ModuleLayer layer) throws Throwable { + Class.forName(layer.findModule(module).orElseThrow(),target).getMethod("main", String[].class).invoke(null, (Object)arguments); } } diff --git a/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/CommonServerLaunchHandler.java b/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/CommonServerLaunchHandler.java deleted file mode 100644 index a041f63c47..0000000000 --- a/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/CommonServerLaunchHandler.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) Forge Development LLC and contributors - * SPDX-License-Identifier: LGPL-2.1-only - */ - -package net.minecraftforge.fml.loading.targets; - -import cpw.mods.jarhandling.SecureJar; -import cpw.mods.modlauncher.api.ServiceRunner; -import net.minecraftforge.fml.loading.FMLLoader; -import net.minecraftforge.fml.loading.LibraryFinder; -import net.minecraftforge.fml.loading.VersionInfo; -import net.minecraftforge.api.distmarker.Dist; - -import java.nio.file.Path; -import java.util.List; -import java.util.function.BiPredicate; -import java.util.stream.Stream; - -public abstract class CommonServerLaunchHandler extends CommonLaunchHandler { - @Override public Dist getDist() { return Dist.DEDICATED_SERVER; } - @Override public String getNaming() { return "srg"; } - @Override public boolean isProduction() { return true; } - - @Override - protected ServiceRunner makeService(String[] arguments, ModuleLayer layer) { - return () -> serverService(arguments, layer); - } - - @Override - public LocatedPaths getMinecraftPaths() { - final var vers = FMLLoader.versionInfo(); - var mc = LibraryFinder.findPathForMaven("net.minecraft", "server", "", "srg", vers.mcAndMCPVersion()); - var mcextra = LibraryFinder.findPathForMaven("net.minecraft", "server", "", "extra", vers.mcAndMCPVersion()); - var mcextra_filtered = SecureJar.from( // We only want it for it's resources. So filter everything else out. - (path, base) -> { - return path.equals("META-INF/versions/") || // This is required because it bypasses our filter for the manifest, and it's a multi-release jar. - (!path.endsWith(".class") && - !path.startsWith("META-INF/")); - }, mcextra - ); - - var mcstream = Stream.builder().add(mc).add(mcextra_filtered.getRootPath()); - var modstream = Stream.>builder(); - - BiPredicate filter = processMCStream(vers, mcstream, null, modstream); - - var fmlcore = LibraryFinder.findPathForMaven(vers.forgeGroup(), "fmlcore", "", "", vers.mcAndForgeVersion()); - var javafmllang = LibraryFinder.findPathForMaven(vers.forgeGroup(), "javafmllanguage", "", "", vers.mcAndForgeVersion()); - var lowcodelang = LibraryFinder.findPathForMaven(vers.forgeGroup(), "lowcodelanguage", "", "", vers.mcAndForgeVersion()); - var mclang = LibraryFinder.findPathForMaven(vers.forgeGroup(), "mclanguage", "", "", vers.mcAndForgeVersion()); - - return new LocatedPaths(mcstream.build().toList(), filter, modstream.build().toList(), List.of(fmlcore, javafmllang, lowcodelang, mclang)); - } - - protected abstract BiPredicate processMCStream(VersionInfo versionInfo, Stream.Builder mc, BiPredicate filter, Stream.Builder> mods); -} diff --git a/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/CommonUserdevLaunchHandler.java b/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/CommonUserdevLaunchHandler.java deleted file mode 100644 index cbc31398c2..0000000000 --- a/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/CommonUserdevLaunchHandler.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) Forge Development LLC and contributors - * SPDX-License-Identifier: LGPL-2.1-only - */ - -package net.minecraftforge.fml.loading.targets; - -import net.minecraftforge.fml.loading.FMLLoader; -import net.minecraftforge.fml.loading.VersionInfo; - -import java.io.File; -import java.nio.file.Path; -import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -public abstract class CommonUserdevLaunchHandler extends CommonDevLaunchHandler { - @Override - public LocatedPaths getMinecraftPaths() { - final var vers = FMLLoader.versionInfo(); - - // Minecraft is extra jar {resources} + forge jar {patches} - final var mcstream = Stream.builder(); - // Mod code is in exploded directories - final var modstream = Stream.>builder(); - - // The MC extra and forge jars are on the classpath, so try and pull them out - var legacyCP = Objects.requireNonNull(System.getProperty("legacyClassPath"), "Missing legacyClassPath, cannot find userdev jars").split(File.pathSeparator); - var extra = findJarOnClasspath(legacyCP, "client-extra"); - - processStreams(legacyCP, vers, mcstream, modstream); - getModClasses().forEach((modid, paths) -> modstream.add(paths)); - - var minecraft = mcstream.build().collect(Collectors.toList()); - var mcFilter = getMcFilter(extra, minecraft, modstream); - minecraft.add(extra); // Add extra late so the filter is made correctly - return new LocatedPaths(minecraft, mcFilter, modstream.build().toList(), getFmlStuff(legacyCP)); - } - - protected abstract void processStreams(String[] classpath, VersionInfo versionInfo, Stream.Builder mc, Stream.Builder> mods); -} diff --git a/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/ForgeClientDevLaunchHandler.java b/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/ForgeClientDevLaunchHandler.java deleted file mode 100644 index 7bae42b620..0000000000 --- a/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/ForgeClientDevLaunchHandler.java +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright (c) Forge Development LLC and contributors - * SPDX-License-Identifier: LGPL-2.1-only - */ - -package net.minecraftforge.fml.loading.targets; - -import net.minecraftforge.api.distmarker.Dist; - -public class ForgeClientDevLaunchHandler extends CommonDevLaunchHandler { - @Override public String name() { return "forgeclientdev"; } - @Override public Dist getDist() { return Dist.CLIENT; } - - @Override - public void devService(String[] arguments, ModuleLayer layer) throws Throwable { - clientService(arguments, layer); - } -} diff --git a/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/ForgeClientLaunchHandler.java b/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/ForgeClientLaunchHandler.java deleted file mode 100644 index bbc51f6a11..0000000000 --- a/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/ForgeClientLaunchHandler.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) Forge Development LLC and contributors - * SPDX-License-Identifier: LGPL-2.1-only - */ - -package net.minecraftforge.fml.loading.targets; - -import java.nio.file.Path; -import java.util.List; -import java.util.stream.Stream; - -import net.minecraftforge.fml.loading.LibraryFinder; -import net.minecraftforge.fml.loading.VersionInfo; - -public class ForgeClientLaunchHandler extends CommonClientLaunchHandler { - @Override public String name() { return "forgeclient"; } - - @Override - protected void processMCStream(VersionInfo versionInfo, Stream.Builder mc, Stream.Builder> mods) { - var forgepatches = LibraryFinder.findPathForMaven(versionInfo.forgeGroup(), "forge", "", "client", versionInfo.mcAndForgeVersion()); - var forgejar = LibraryFinder.findPathForMaven(versionInfo.forgeGroup(), "forge", "", "universal", versionInfo.mcAndForgeVersion()); - mc.add(forgepatches); - mods.add(List.of(forgejar)); - } -} diff --git a/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/ForgeClientUserdevLaunchHandler.java b/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/ForgeClientUserdevLaunchHandler.java deleted file mode 100644 index 08b8d90cc4..0000000000 --- a/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/ForgeClientUserdevLaunchHandler.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) Forge Development LLC and contributors - * SPDX-License-Identifier: LGPL-2.1-only - */ - -package net.minecraftforge.fml.loading.targets; - -import net.minecraftforge.api.distmarker.Dist; - -public class ForgeClientUserdevLaunchHandler extends ForgeUserdevLaunchHandler { - @Override - public String name() { return "forgeclientuserdev"; } - - @Override - public Dist getDist() { return Dist.CLIENT; } - - @Override - public void devService(String[] arguments, ModuleLayer layer) throws Throwable { - clientService(arguments, layer); - } -} diff --git a/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/ForgeDataDevLaunchHandler.java b/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/ForgeDataDevLaunchHandler.java deleted file mode 100644 index 307e09f5a0..0000000000 --- a/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/ForgeDataDevLaunchHandler.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (c) Forge Development LLC and contributors - * SPDX-License-Identifier: LGPL-2.1-only - */ - -package net.minecraftforge.fml.loading.targets; - -import net.minecraftforge.api.distmarker.Dist; - -public class ForgeDataDevLaunchHandler extends CommonDevLaunchHandler { - @Override public String name() { return "forgedatadev"; } - @Override public Dist getDist() { return Dist.CLIENT; } - @Override public boolean isData() { return true; } - - @Override - public void devService(String[] arguments, ModuleLayer layer) throws Throwable { - Class.forName(layer.findModule("minecraft").orElseThrow(), "net.minecraft.data.Main").getMethod("main", String[].class).invoke(null, (Object) arguments); - } -} diff --git a/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/ForgeDataUserdevLaunchHandler.java b/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/ForgeDataUserdevLaunchHandler.java deleted file mode 100644 index a5995577f1..0000000000 --- a/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/ForgeDataUserdevLaunchHandler.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) Forge Development LLC and contributors - * SPDX-License-Identifier: LGPL-2.1-only - */ - -package net.minecraftforge.fml.loading.targets; - -import net.minecraftforge.api.distmarker.Dist; - -public class ForgeDataUserdevLaunchHandler extends ForgeUserdevLaunchHandler { - @Override - public String name() { return "forgedatauserdev"; } - - @Override - public Dist getDist() { return Dist.CLIENT; } - - @Override - public boolean isData() { return true; } - - @Override - public void devService(String[] arguments, ModuleLayer layer) throws Throwable { - dataService(arguments, layer); - } -} diff --git a/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/ForgeDevLaunchHandler.java b/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/ForgeDevLaunchHandler.java new file mode 100644 index 0000000000..690ace158b --- /dev/null +++ b/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/ForgeDevLaunchHandler.java @@ -0,0 +1,295 @@ +/* + * Copyright (c) Forge Development LLC and contributors + * SPDX-License-Identifier: LGPL-2.1-only + */ + +package net.minecraftforge.fml.loading.targets; +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; +import java.nio.file.spi.FileSystemProvider; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Stream; + +import org.jetbrains.annotations.ApiStatus; +import org.objectweb.asm.AnnotationVisitor; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.Opcodes; +import com.electronwill.nightconfig.core.Config; +import com.electronwill.nightconfig.core.file.FileNotFoundAction; +import com.electronwill.nightconfig.core.io.WritingMode; +import com.electronwill.nightconfig.toml.TomlParser; +import com.electronwill.nightconfig.toml.TomlWriter; +import com.google.common.jimfs.Jimfs; + +import cpw.mods.niofs.union.UnionFileSystemProvider; + +@ApiStatus.Internal +abstract class ForgeDevLaunchHandler extends CommonDevLaunchHandler { + private static final String MODS_TOML = "META-INF/mods.toml"; + private static final String PACK_META = "pack.mcmeta"; + private static final UnionFileSystemProvider UFSP = (UnionFileSystemProvider)FileSystemProvider.installedProviders().stream().filter(fsp->fsp.getScheme().equals("union")).findFirst().orElseThrow(()->new IllegalStateException("Couldn't find UnionFileSystemProvider")); + + private ForgeDevLaunchHandler(LaunchType type) { + super(type, "forge_dev_"); + } + + @Override + public LocatedPaths getMinecraftPaths() { + // Our exploded directories in development include all mods and minecraft itself. + var mods = getModClasses(); + + // The extra jar is on the classpath, so try and pull it out of the legacy classpath + var legacyCP = Objects.requireNonNull(System.getProperty("legacyClassPath"), "Missing legacyClassPath, cannot find client-extra").split(File.pathSeparator); + var extra = findJarOnClasspath(legacyCP, "client-extra"); + + + // Minecraft is extra jar {resources} + our exploded directories in dev + var minecraft = mods.remove("minecraft"); + if (minecraft == null) + throw new IllegalStateException("Could not find 'minecraft' mod paths."); + var mcFilter = getMcFilter(extra, minecraft); + + // The MC code/Patcher edits are in exploded directories + var modstream = Stream.>builder(); + var forge = this.getForgeMod(minecraft); + modstream.add(List.of(forge)); + + // Explode our test mods into a framework that treats them all as separate jars. + var tests = mods.remove("tests"); + if (tests != null) + explodeTestMods(tests).forEach(modstream::add); + + mods.values().forEach(modstream::add); + + return new LocatedPaths( + Stream.concat(minecraft.stream(), List.of(extra).stream()).toList(), + mcFilter, + modstream.build().toList(), + getLibraries(legacyCP) + ); + } + + private List> explodeTestMods(List paths) { + var mod = new ArrayList>(); + var memory = Jimfs.newFileSystem(); + + // First lets find all class files, that have the @Mod annotation and map packages to modids. + var packages = findTestModPackages(paths); + for (var entry : packages.entrySet()) { + var pkg = entry.getKey(); + var modids = entry.getValue(); + + var resourcePaths = new LinkedHashSet(); + // Jump down into the package for resources + paths.stream() + .mapMulti((p, c) -> modids.forEach(id -> c.accept(p.resolve(id)))) + .filter(Files::exists).forEach(resourcePaths::add); + + var root = memory.getPath(modids.iterator().next()); // use the first modid as our root + buildModsToml(resourcePaths, modids, root); + buildPackMeta(resourcePaths, root); + + if (Files.exists(root)) + resourcePaths.add(root); + + // We want just the class files from the root of the input paths. So make a new union with a filter. + var classes = UFSP.newFileSystem( + (path, base) -> { + if (path.endsWith("/")) { + if (path.startsWith("/")) + path = path.substring(1); + return pkg.startsWith(path) || path.startsWith(pkg); + } + return path.endsWith(".class") && path.startsWith(pkg); + }, paths.toArray(Path[]::new)); + // And we want the resources, and none of the classes, just in case things get kinda fucky and somehow a package overlaps a sub package {shading?} + var resources = UFSP.newFileSystem((path, base) -> !path.endsWith(".class"), resourcePaths.toArray(Path[]::new)); + + mod.add(List.of(classes.getRoot(), resources.getRoot())); + } + + return mod; + } + + // Find all the @Mods so we can generate tomls, and so we can pick packages. Right now it doesn't allow mods in parent directories, + // I could make it merge all the way up, but I think this would be fine. + private Map> findTestModPackages(List paths) { + var mods = new HashMap>(); + for (var path : paths) { + try (var files = Files.walk(path)) { + var classes = files + .filter(Files::isRegularFile) + .filter(p -> p.getFileName().toString().endsWith(".class")) + .toList(); + + for (var cls : classes) { + try (var is = Files.newInputStream(cls)) { + var reader = new ClassReader(is); + reader.accept(new ClassVisitor(Opcodes.ASM9) { + private String clsName; + @Override + public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { + this.clsName = name; + super.visit(version, access, name, signature, superName, interfaces); + } + + @Override + public AnnotationVisitor visitAnnotation(String name, boolean runtime) { + if (!"Lnet/minecraftforge/fml/common/Mod;".equals(name)) + return super.visitAnnotation(name, runtime); + + return new AnnotationVisitor(Opcodes.ASM9) { + @Override + public void visit(String key, Object value) { + if ("value".equals(key)) { + int idx = clsName.lastIndexOf('/'); + var pkg = clsName.substring(0, idx); + mods.computeIfAbsent(pkg, k -> new HashSet<>()).add((String)value); + + idx = pkg.lastIndexOf('/'); + while (idx != -1) { + pkg = pkg.substring(0, idx); + idx = pkg.lastIndexOf('/'); + if (mods.containsKey(pkg)) + throw new IllegalStateException("Invalid ForgeDev test mod layout, conflicting packages: " + pkg + " for " + clsName); + } + } + } + }; + } + }, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES); + } + } + } catch (IOException e) { + sneak(e); + } + } + return mods; + } + + // Builds or update the mods.toml file for all @Mods in this package + private void buildModsToml(Set resources, Set modids, Path root) { + var toml = resources.stream() + .map(p -> p.resolve(MODS_TOML)) + .filter(Files::exists) + .findFirst() + .orElse(null); + + Config cfg = null; + + if (toml != null) + cfg = new TomlParser().parse(toml, FileNotFoundAction.READ_NOTHING); + else + cfg = Config.inMemory(); + + boolean modified = false; + var defaults = Map.of( + "modLoader", "javafml", + "loaderVersion", "[0,)", + "license", "Doesnt fucking matter" + ); + + for (var key : defaults.keySet()) { + if (!cfg.contains(key)) { + cfg.set(key, defaults.get(key)); + modified = true; + } + } + + var modlist = new ArrayList(); + if (cfg.contains("mods")) { + @SuppressWarnings("unchecked") + var existing = ((List)cfg.get("mods")); + modlist.addAll(existing); + } + + for (var modid : modids) { + if (!modlist.stream().anyMatch(c -> modid.equals(c.get("modId")))) { + modified = true; + var tmp = Config.inMemory(); + tmp.set("modId", modid); + modlist.add(tmp); + } + } + + cfg.set("mods", modlist); + + if (modified) { + var target = root.resolve(MODS_TOML); + try { + Files.createDirectories(target.getParent()); + new TomlWriter().write(cfg, target, WritingMode.REPLACE); + } catch (IOException e) { + throw new IllegalStateException("Failed to create in memory toml: " + target, e); + } + } + } + + // This is optional, it just hides a warning screen when starting up. I should probably remove this once I restructure how data gen for test mods work and make it generate there. + private void buildPackMeta(Set paths, Path root) { + var existing = paths.stream() + .map(p -> p.resolve(PACK_META)) + .filter(Files::exists) + .findFirst() + .orElse(null); + + if (existing != null) + return; + var target = root.resolve(PACK_META); + try { + Files.createDirectories(target.getParent()); + Files.writeString(target, + """ + { + "pack": { + "description": "doesn't matter", + "pack_format": 18 + } + } + """, StandardCharsets.UTF_8, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.CREATE); + } catch (IOException e) { + throw new IllegalStateException("Failed to make in memory pack.mcmeta: " + target, e); + } + } + + @SuppressWarnings("unchecked") + private static R sneak(Throwable e) throws E { + throw (E)e; + } + + public static class Client extends ForgeDevLaunchHandler { + public Client() { + super(CLIENT); + } + } + + public static class Data extends ForgeDevLaunchHandler { + public Data() { + super(DATA); + } + } + + public static class Server extends ForgeDevLaunchHandler { + public Server() { + super(SERVER); + } + } + + public static class ServerGameTest extends ForgeDevLaunchHandler { + public ServerGameTest() { + super(SERVER_GAMETEST); + } + } +} diff --git a/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/ForgeGametestDevLaunchHandler.java b/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/ForgeGametestDevLaunchHandler.java deleted file mode 100644 index 2ce9e8ea93..0000000000 --- a/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/ForgeGametestDevLaunchHandler.java +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright (c) Forge Development LLC and contributors - * SPDX-License-Identifier: LGPL-2.1-only - */ - -package net.minecraftforge.fml.loading.targets; - -import net.minecraftforge.api.distmarker.Dist; - -public class ForgeGametestDevLaunchHandler extends CommonDevLaunchHandler { - @Override public String name() { return "forgegametestserverdev"; } - @Override public Dist getDist() { return Dist.DEDICATED_SERVER; } - - @Override - public void devService(String[] arguments, ModuleLayer layer) throws Throwable { - Class.forName(layer.findModule("forge").orElseThrow(), "net.minecraftforge.gametest.GameTestMain").getMethod("main", String[].class).invoke(null, (Object)arguments); - } -} \ No newline at end of file diff --git a/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/ForgeGametestUserdevLaunchHandler.java b/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/ForgeGametestUserdevLaunchHandler.java deleted file mode 100644 index 3ada4f71da..0000000000 --- a/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/ForgeGametestUserdevLaunchHandler.java +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright (c) Forge Development LLC and contributors - * SPDX-License-Identifier: LGPL-2.1-only - */ - -package net.minecraftforge.fml.loading.targets; - -import net.minecraftforge.api.distmarker.Dist; - -public class ForgeGametestUserdevLaunchHandler extends ForgeUserdevLaunchHandler { - @Override public String name() { return "forgegametestserveruserdev"; } - @Override public Dist getDist() { return Dist.DEDICATED_SERVER; } - - @Override - public void devService(String[] arguments, ModuleLayer layer) throws Throwable { - Class.forName(layer.findModule("forge").orElseThrow(), "net.minecraftforge.gametest.GameTestMain").getMethod("main", String[].class).invoke(null, (Object)arguments); - } -} \ No newline at end of file diff --git a/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/ForgeProdLaunchHandler.java b/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/ForgeProdLaunchHandler.java new file mode 100644 index 0000000000..feac79b85d --- /dev/null +++ b/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/ForgeProdLaunchHandler.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) Forge Development LLC and contributors + * SPDX-License-Identifier: LGPL-2.1-only + */ + +package net.minecraftforge.fml.loading.targets; + +import java.nio.file.Path; +import java.util.List; +import java.util.function.BiPredicate; + +import org.jetbrains.annotations.ApiStatus; + +import cpw.mods.jarhandling.SecureJar; +import net.minecraftforge.fml.loading.FMLLoader; +import net.minecraftforge.fml.loading.LibraryFinder; +import net.minecraftforge.fml.loading.VersionInfo; + +@ApiStatus.Internal +abstract class ForgeProdLaunchHandler extends CommonLaunchHandler { + protected ForgeProdLaunchHandler(LaunchType type) { + super(type, "forge_"); + } + + @Override public String getNaming() { return "srg"; } + @Override public boolean isProduction() { return true; } + + protected Path mvn(VersionInfo info, String artifact) { + return mvn(info, artifact, ""); + } + protected Path mvn(VersionInfo info, String artifact, String classifier) { + return mvn(info.forgeGroup(), artifact, classifier, info.mcAndForgeVersion()); + } + protected Path mvn(String group, String artifact, String classifier, String version) { + return LibraryFinder.findPathForMaven(group, artifact, "", classifier, version); + } + + @Override + public LocatedPaths getMinecraftPaths() { + var vers = FMLLoader.versionInfo(); + + // Minecraft + var mc = getMCPaths(vers); + + // mods (Forge) + var forgejar = mvn(vers, "forge", "universal"); + + // Libraries + var fmlcore = mvn(vers, "fmlcore"); + var javafmllang = mvn(vers, "javafmllanguage"); + var lowcodelang = mvn(vers, "lowcodelanguage"); + var mclang = mvn(vers, "mclanguage"); + + return new LocatedPaths( + mc, + null, + List.of(List.of(forgejar)), + List.of(fmlcore, javafmllang, lowcodelang, mclang) + ); + } + + protected abstract List getMCPaths(VersionInfo vers); + + public static class Client extends ForgeProdLaunchHandler { + public Client() { + super(CLIENT); + } + + @Override + protected List getMCPaths(VersionInfo vers) { + var mc = mvn("net.minecraft", "client", "srg", vers.mcAndMCPVersion()); + var mcextra = mvn("net.minecraft", "client", "extra", vers.mcAndMCPVersion()); + var patches = mvn(vers, "forge", "client"); + return List.of(mc, mcextra, patches); + } + } + public static class Server extends ForgeProdLaunchHandler { + public Server() { + super(SERVER); + } + + @Override + protected List getMCPaths(VersionInfo vers) { + var mc = mvn("net.minecraft", "server", "srg", vers.mcAndMCPVersion()); + var mcextra = mvn("net.minecraft", "server", "extra", vers.mcAndMCPVersion()); + var patches = mvn(vers, "forge", "server"); + + // TODO: Get rid of this by filtering the file at install time. + // We only want it for it's resources. So filter everything else out. + BiPredicate filter = (path, base) -> { + return path.equals("META-INF/versions/") || // This is required because it bypasses our filter for the manifest, and it's a multi-release jar. + (!path.endsWith(".class") && !path.startsWith("META-INF/")); + }; + mcextra = SecureJar.from(filter, mcextra).getRootPath(); + + return List.of(mc, mcextra, patches); + } + } +} diff --git a/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/ForgeServerDevLaunchHandler.java b/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/ForgeServerDevLaunchHandler.java deleted file mode 100644 index 85f9fd9e84..0000000000 --- a/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/ForgeServerDevLaunchHandler.java +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright (c) Forge Development LLC and contributors - * SPDX-License-Identifier: LGPL-2.1-only - */ - -package net.minecraftforge.fml.loading.targets; - -import net.minecraftforge.api.distmarker.Dist; - -public class ForgeServerDevLaunchHandler extends CommonDevLaunchHandler { - @Override public String name() { return "forgeserverdev"; } - @Override public Dist getDist() { return Dist.DEDICATED_SERVER; } - - @Override - public void devService(String[] arguments, ModuleLayer layer) throws Throwable { - serverService(arguments, layer); - } -} \ No newline at end of file diff --git a/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/ForgeServerLaunchHandler.java b/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/ForgeServerLaunchHandler.java deleted file mode 100644 index a013f618b8..0000000000 --- a/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/ForgeServerLaunchHandler.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) Forge Development LLC and contributors - * SPDX-License-Identifier: LGPL-2.1-only - */ - -package net.minecraftforge.fml.loading.targets; - -import cpw.mods.modlauncher.api.ILaunchHandlerService; -import net.minecraftforge.fml.loading.LibraryFinder; -import net.minecraftforge.fml.loading.VersionInfo; - -import java.nio.file.Path; -import java.util.List; -import java.util.function.BiPredicate; -import java.util.stream.Stream; - -public class ForgeServerLaunchHandler extends CommonServerLaunchHandler implements ILaunchHandlerService { - @Override public String name() { return "forgeserver"; } - - @Override - protected BiPredicate processMCStream(VersionInfo versionInfo, Stream.Builder mc, BiPredicate filter, Stream.Builder> mods) { - var forgepatches = LibraryFinder.findPathForMaven(versionInfo.forgeGroup(), "forge", "", "server", versionInfo.mcAndForgeVersion()); - var forgejar = LibraryFinder.findPathForMaven(versionInfo.forgeGroup(), "forge", "", "universal", versionInfo.mcAndForgeVersion()); - mc.add(forgepatches); - mods.add(List.of(forgejar)); - return filter; - } -} diff --git a/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/ForgeServerUserdevLaunchHandler.java b/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/ForgeServerUserdevLaunchHandler.java deleted file mode 100644 index b33cc67f32..0000000000 --- a/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/ForgeServerUserdevLaunchHandler.java +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright (c) Forge Development LLC and contributors - * SPDX-License-Identifier: LGPL-2.1-only - */ - -package net.minecraftforge.fml.loading.targets; - -import net.minecraftforge.api.distmarker.Dist; - -public class ForgeServerUserdevLaunchHandler extends ForgeUserdevLaunchHandler { - @Override public String name() { return "forgeserveruserdev"; } - @Override public Dist getDist() { return Dist.DEDICATED_SERVER; } - - @Override - public void devService(String[] arguments, ModuleLayer layer) throws Throwable { - serverService(arguments, layer); - } -} \ No newline at end of file diff --git a/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/ForgeUserdevLaunchHandler.java b/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/ForgeUserdevLaunchHandler.java index 27925e9fa6..60b292348d 100644 --- a/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/ForgeUserdevLaunchHandler.java +++ b/fmlloader/src/main/java/net/minecraftforge/fml/loading/targets/ForgeUserdevLaunchHandler.java @@ -5,16 +5,70 @@ package net.minecraftforge.fml.loading.targets; -import net.minecraftforge.fml.loading.VersionInfo; - +import net.minecraftforge.fml.loading.FMLLoader; +import java.io.File; import java.nio.file.Path; import java.util.List; +import java.util.Objects; import java.util.stream.Stream; -public abstract class ForgeUserdevLaunchHandler extends CommonUserdevLaunchHandler { +import org.jetbrains.annotations.ApiStatus; + +@ApiStatus.Internal +abstract class ForgeUserdevLaunchHandler extends CommonDevLaunchHandler { + private ForgeUserdevLaunchHandler(LaunchType type) { + super(type, "forge_userdev_"); + } + @Override - protected void processStreams(String[] classpath, VersionInfo versionInfo, Stream.Builder mc, Stream.Builder> mods) { - var forge = findJarOnClasspath(classpath, "forge-" + versionInfo.mcAndForgeVersion()); - mc.add(forge); + public LocatedPaths getMinecraftPaths() { + var legacyCP = Objects.requireNonNull(System.getProperty("legacyClassPath"), "Missing legacyClassPath, cannot find userdev jars").split(File.pathSeparator); + var vers = FMLLoader.versionInfo(); + + // Minecraft is extra jar {resources} + forge jar {patches} + // The MC extra and forge jars are on the classpath, so try and pull them out + var extra = findJarOnClasspath(legacyCP, "client-extra"); + var forge = findJarOnClasspath(legacyCP, "forge-" + vers.mcAndForgeVersion()); + // We need to filter the forge jar to just MC code + var filter = getMcFilter(extra, List.of(forge)); + + // Mods is forge classes + anything from MOD_CLASSES + var modstream = Stream.>builder(); + // We want the forge as a seperate mod jar. + var forgemod = this.getForgeMod(List.of(forge)); + modstream.add(List.of(forgemod)); + // Mod code is in exploded directories + getModClasses().forEach((modid, paths) -> modstream.add(paths)); + + return new LocatedPaths( + List.of(forge, extra), + filter, + modstream.build().toList(), + getLibraries(legacyCP) + ); + } + + public static class Client extends ForgeUserdevLaunchHandler { + public Client() { + super(CLIENT); + } + } + + public static class Data extends ForgeUserdevLaunchHandler { + public Data() { + super(DATA); + } + } + + public static class Server extends ForgeUserdevLaunchHandler { + public Server() { + super(SERVER); + } + } + + public static class ServerGameTest extends ForgeUserdevLaunchHandler { + public ServerGameTest() { + super(SERVER_GAMETEST); + } } } diff --git a/fmlloader/src/main/java/net/minecraftforge/fml/loading/toposort/CyclePresentException.java b/fmlloader/src/main/java/net/minecraftforge/fml/loading/toposort/CyclePresentException.java index e3167e3f5f..31175f5e3c 100644 --- a/fmlloader/src/main/java/net/minecraftforge/fml/loading/toposort/CyclePresentException.java +++ b/fmlloader/src/main/java/net/minecraftforge/fml/loading/toposort/CyclePresentException.java @@ -11,6 +11,7 @@ import java.util.Set; * An exception thrown for graphs with cycles as an argument for topological sort. */ public final class CyclePresentException extends IllegalArgumentException { + private static final long serialVersionUID = -2609660010927054667L; private final Set> cycles; /** diff --git a/fmlloader/src/main/java/net/minecraftforge/fml/server/ServerMain.java b/fmlloader/src/main/java/net/minecraftforge/fml/server/ServerMain.java deleted file mode 100644 index 2cef0ac850..0000000000 --- a/fmlloader/src/main/java/net/minecraftforge/fml/server/ServerMain.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) Forge Development LLC and contributors - * SPDX-License-Identifier: LGPL-2.1-only - */ - -package net.minecraftforge.fml.server; - -import cpw.mods.modlauncher.InvalidLauncherSetupException; -import cpw.mods.modlauncher.Launcher; - -import java.io.File; -import java.io.IOException; -import java.net.URISyntaxException; -import java.net.URL; -import java.security.CodeSource; -import java.security.ProtectionDomain; -import java.util.Optional; -import java.util.jar.JarFile; -import java.util.jar.Manifest; - -public class ServerMain { - public static void main(String[] args) { - try { - Class.forName("cpw.mods.modlauncher.Launcher", false, ClassLoader.getSystemClassLoader()); - Class.forName("net.minecraftforge.forgespi.Environment", false, ClassLoader.getSystemClassLoader()); - } catch (ClassNotFoundException cnfe) { - System.err.println("FATAL ERROR, You need to run the installer. The libraries required to launch a server are missing"); - System.exit(1); - } - - final String launchArgs = Optional.ofNullable(ServerMain.class.getProtectionDomain()). - map(ProtectionDomain::getCodeSource). - map(CodeSource::getLocation). - map(ServerMain::urlToManifest). - map(Manifest::getMainAttributes). - map(a -> a.getValue("ServerLaunchArgs")). - orElseThrow(ServerMain::throwMissingManifest); - String[] defaultargs = launchArgs.split(" "); - String[] result = new String[args.length + defaultargs.length]; - System.arraycopy(defaultargs, 0, result, 0, defaultargs.length); - System.arraycopy(args, 0, result, defaultargs.length, args.length); - // separate class, so the exception can resolve - new Runner().runLauncher(result); - } - - private static class Runner { - private void runLauncher(final String[] result) { - try { - Launcher.main(result); - } catch (InvalidLauncherSetupException e) { - System.err.println("The server is missing critical libraries and cannot load. Please run the installer to correct this"); - System.exit(1); - } - } - } - private static Manifest urlToManifest(URL url) { - try { - return new JarFile(new File(url.toURI())).getManifest(); - } catch (URISyntaxException | IOException e) { - return null; - } - } - - private static RuntimeException throwMissingManifest() { - System.err.println("This is not being run from a valid JAR file, essential data is missing."); - return new RuntimeException("Missing the manifest"); - } -} diff --git a/fmlloader/src/main/resources/META-INF/services/cpw.mods.cl.ModularURLHandler.IURLProvider b/fmlloader/src/main/resources/META-INF/services/cpw.mods.cl.ModularURLHandler.IURLProvider deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/fmlloader/src/main/resources/META-INF/services/cpw.mods.modlauncher.api.ILaunchHandlerService b/fmlloader/src/main/resources/META-INF/services/cpw.mods.modlauncher.api.ILaunchHandlerService index f0cc3caef5..b4a3ffa7bc 100644 --- a/fmlloader/src/main/resources/META-INF/services/cpw.mods.modlauncher.api.ILaunchHandlerService +++ b/fmlloader/src/main/resources/META-INF/services/cpw.mods.modlauncher.api.ILaunchHandlerService @@ -1,10 +1,15 @@ -net.minecraftforge.fml.loading.targets.ForgeClientLaunchHandler -net.minecraftforge.fml.loading.targets.ForgeClientDevLaunchHandler -net.minecraftforge.fml.loading.targets.ForgeClientUserdevLaunchHandler -net.minecraftforge.fml.loading.targets.ForgeServerLaunchHandler -net.minecraftforge.fml.loading.targets.ForgeServerDevLaunchHandler -net.minecraftforge.fml.loading.targets.ForgeServerUserdevLaunchHandler -net.minecraftforge.fml.loading.targets.ForgeDataDevLaunchHandler -net.minecraftforge.fml.loading.targets.ForgeDataUserdevLaunchHandler -net.minecraftforge.fml.loading.targets.ForgeGametestDevLaunchHandler -net.minecraftforge.fml.loading.targets.ForgeGametestUserdevLaunchHandler +# Production +net.minecraftforge.fml.loading.targets.ForgeProdLaunchHandler$Client +net.minecraftforge.fml.loading.targets.ForgeProdLaunchHandler$Server + +# Mod Developers +net.minecraftforge.fml.loading.targets.ForgeUserdevLaunchHandler$Client +net.minecraftforge.fml.loading.targets.ForgeUserdevLaunchHandler$Data +net.minecraftforge.fml.loading.targets.ForgeUserdevLaunchHandler$Server +net.minecraftforge.fml.loading.targets.ForgeUserdevLaunchHandler$ServerGameTest + +#Working on Forge itself +net.minecraftforge.fml.loading.targets.ForgeDevLaunchHandler$Client +net.minecraftforge.fml.loading.targets.ForgeDevLaunchHandler$Data +net.minecraftforge.fml.loading.targets.ForgeDevLaunchHandler$Server +net.minecraftforge.fml.loading.targets.ForgeDevLaunchHandler$ServerGameTest diff --git a/src/generated_test/resources/EMPTY b/src/generated_test/resources/EMPTY deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/generated_test/resources/pack.mcmeta b/src/generated_test/resources/empty/pack.mcmeta similarity index 100% rename from src/generated_test/resources/pack.mcmeta rename to src/generated_test/resources/empty/pack.mcmeta diff --git a/src/generated_test/resources/data/forge/loot_modifiers/global_loot_modifiers.json b/src/generated_test/resources/global_loot_test/data/forge/loot_modifiers/global_loot_modifiers.json similarity index 100% rename from src/generated_test/resources/data/forge/loot_modifiers/global_loot_modifiers.json rename to src/generated_test/resources/global_loot_test/data/forge/loot_modifiers/global_loot_modifiers.json diff --git a/src/generated_test/resources/data/global_loot_test/loot_modifiers/bamboo_silk.json b/src/generated_test/resources/global_loot_test/data/global_loot_test/loot_modifiers/bamboo_silk.json similarity index 100% rename from src/generated_test/resources/data/global_loot_test/loot_modifiers/bamboo_silk.json rename to src/generated_test/resources/global_loot_test/data/global_loot_test/loot_modifiers/bamboo_silk.json diff --git a/src/generated_test/resources/data/global_loot_test/loot_modifiers/dungeon_loot.json b/src/generated_test/resources/global_loot_test/data/global_loot_test/loot_modifiers/dungeon_loot.json similarity index 100% rename from src/generated_test/resources/data/global_loot_test/loot_modifiers/dungeon_loot.json rename to src/generated_test/resources/global_loot_test/data/global_loot_test/loot_modifiers/dungeon_loot.json diff --git a/src/generated_test/resources/data/global_loot_test/loot_modifiers/smelting.json b/src/generated_test/resources/global_loot_test/data/global_loot_test/loot_modifiers/smelting.json similarity index 100% rename from src/generated_test/resources/data/global_loot_test/loot_modifiers/smelting.json rename to src/generated_test/resources/global_loot_test/data/global_loot_test/loot_modifiers/smelting.json diff --git a/src/generated_test/resources/data/global_loot_test/loot_modifiers/wheat_harvest.json b/src/generated_test/resources/global_loot_test/data/global_loot_test/loot_modifiers/wheat_harvest.json similarity index 100% rename from src/generated_test/resources/data/global_loot_test/loot_modifiers/wheat_harvest.json rename to src/generated_test/resources/global_loot_test/data/global_loot_test/loot_modifiers/wheat_harvest.json diff --git a/src/generated_mdk/resources/pack.mcmeta b/src/generated_test/resources/mdk_datagen/pack.mcmeta similarity index 79% rename from src/generated_mdk/resources/pack.mcmeta rename to src/generated_test/resources/mdk_datagen/pack.mcmeta index eca79ae4ae..2a62706c90 100644 --- a/src/generated_mdk/resources/pack.mcmeta +++ b/src/generated_test/resources/mdk_datagen/pack.mcmeta @@ -3,6 +3,6 @@ "description": { "text": "${mod_id} resources" }, - "pack_format": 15 + "pack_format": 18 } } \ No newline at end of file diff --git a/src/main/java/net/minecraftforge/client/ForgeHooksClient.java b/src/main/java/net/minecraftforge/client/ForgeHooksClient.java index a826efb21e..913ac60acb 100644 --- a/src/main/java/net/minecraftforge/client/ForgeHooksClient.java +++ b/src/main/java/net/minecraftforge/client/ForgeHooksClient.java @@ -20,7 +20,6 @@ import net.minecraft.FileUtil; import net.minecraft.client.Camera; import net.minecraft.client.KeyMapping; import net.minecraft.client.Minecraft; -import net.minecraft.client.MouseHandler; import net.minecraft.client.Options; import net.minecraft.client.color.block.BlockColors; import net.minecraft.client.color.item.ItemColors; @@ -60,7 +59,6 @@ import net.minecraft.client.renderer.texture.SpriteContents; import net.minecraft.client.renderer.texture.TextureAtlas; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.resources.language.I18n; -import net.minecraft.client.resources.metadata.animation.AnimationMetadataSection; import net.minecraft.client.resources.metadata.animation.FrameSize; import net.minecraft.client.resources.model.BakedModel; import net.minecraft.client.resources.model.Material; @@ -76,12 +74,10 @@ import net.minecraft.network.chat.ChatType; import net.minecraft.network.chat.ChatTypeDecoration; import net.minecraft.network.chat.CommonComponents; import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.ComponentContents; import net.minecraft.network.chat.FormattedText; import net.minecraft.network.chat.PlayerChatMessage; import net.minecraft.network.chat.Style; import net.minecraft.network.protocol.status.ServerStatus; -import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.packs.resources.ReloadableResourceManager; import net.minecraft.server.packs.resources.Resource; @@ -97,10 +93,8 @@ import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.ai.attributes.AttributeInstance; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.tooltip.TooltipComponent; -import net.minecraft.world.item.CreativeModeTab; import net.minecraft.world.item.ItemDisplayContext; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.ItemStackLinkedSet; import net.minecraft.world.item.crafting.RecipeManager; import net.minecraft.world.level.BlockAndTintGetter; import net.minecraft.world.level.GameType; @@ -151,12 +145,9 @@ import net.minecraftforge.client.model.data.ModelData; import net.minecraftforge.client.textures.ForgeTextureMetadata; import net.minecraftforge.client.textures.TextureAtlasSpriteLoaderManager; import net.minecraftforge.common.ForgeConfig; -import net.minecraftforge.common.ForgeHooks; import net.minecraftforge.common.ForgeI18n; import net.minecraftforge.common.ForgeMod; import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.common.util.MutableHashedLinkedMap; -import net.minecraftforge.event.BuildCreativeModeTabContentsEvent; import net.minecraftforge.eventbus.api.Event; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.IExtensionPoint; diff --git a/src/main/java/net/minecraftforge/client/gui/overlay/VanillaGuiOverlay.java b/src/main/java/net/minecraftforge/client/gui/overlay/VanillaGuiOverlay.java index 2de2168562..19011d0d4f 100644 --- a/src/main/java/net/minecraftforge/client/gui/overlay/VanillaGuiOverlay.java +++ b/src/main/java/net/minecraftforge/client/gui/overlay/VanillaGuiOverlay.java @@ -23,6 +23,7 @@ import org.lwjgl.opengl.GL11; /** * All the vanilla {@linkplain IGuiOverlay HUD overlays} in the order that they render. */ +@SuppressWarnings("resource") public enum VanillaGuiOverlay { VIGNETTE("vignette", (gui, guiGraphics, partialTick, screenWidth, screenHeight) -> { if (Minecraft.useFancyGraphics()) { diff --git a/src/main/java/net/minecraftforge/data/loading/DatagenModLoader.java b/src/main/java/net/minecraftforge/data/loading/DatagenModLoader.java index 7f49f3c437..ae0f138922 100644 --- a/src/main/java/net/minecraftforge/data/loading/DatagenModLoader.java +++ b/src/main/java/net/minecraftforge/data/loading/DatagenModLoader.java @@ -6,10 +6,10 @@ package net.minecraftforge.data.loading; import net.minecraft.Util; -import net.minecraft.core.HolderLookup; import net.minecraft.data.registries.VanillaRegistries; import net.minecraft.server.Bootstrap; import net.minecraftforge.common.data.ExistingFileHelper; +import net.minecraftforge.fml.ModList; import net.minecraftforge.fml.ModLoader; import net.minecraftforge.fml.ModWorkManager; import net.minecraftforge.data.event.GatherDataEvent; @@ -19,12 +19,13 @@ import org.apache.logging.log4j.Logger; import java.io.File; import java.nio.file.Path; import java.util.Collection; +import java.util.HashSet; import java.util.Set; import java.util.concurrent.CompletableFuture; +import java.util.regex.Pattern; public class DatagenModLoader { private static final Logger LOGGER = LogManager.getLogger(); - private static GatherDataEvent.DataGeneratorConfig dataGeneratorConfig; private static ExistingFileHelper existingFileHelper; private static boolean runningDataGen; @@ -32,25 +33,49 @@ public class DatagenModLoader { return runningDataGen; } - public static void begin(final Set mods, final Path path, final Collection inputs, Collection existingPacks, - Set existingMods, final boolean serverGenerators, final boolean clientGenerators, final boolean devToolGenerators, final boolean reportsGenerator, - final boolean structureValidator, final boolean flat, final String assetIndex, final File assetsDir) { - if (mods.contains("minecraft") && mods.size() == 1) + public static void begin( + Set patterns, Path output, Collection inputs, Collection existingPacks, Set existingMods, + boolean genServer, boolean genClient, boolean genDev, boolean genReports, + boolean validate, boolean flat, String assetIndex, File assetsDir + ) { + if (patterns.contains("minecraft") && patterns.size() == 1) return; - LOGGER.info("Initializing Data Gatherer for mods {}", mods); + runningDataGen = true; Bootstrap.bootStrap(); ModLoader.get().gatherAndInitializeMods(ModWorkManager.syncExecutor(), ModWorkManager.parallelExecutor(), ()->{}); - CompletableFuture lookupProvider = CompletableFuture.supplyAsync(VanillaRegistries::createLookup, Util.backgroundExecutor()); - dataGeneratorConfig = new GatherDataEvent.DataGeneratorConfig(mods, path, inputs, lookupProvider, serverGenerators, - clientGenerators, devToolGenerators, reportsGenerator, structureValidator, flat); + var lookupProvider = CompletableFuture.supplyAsync(VanillaRegistries::createLookup, Util.backgroundExecutor()); + + var mods = new HashSet(); + for (var pattern : patterns) { + if (pattern.indexOf('.') == -1) // No wildcard! + mods.add(pattern); + + var m = Pattern.compile('^' + pattern + '$'); + ModList.get().forEachModInOrder(mc -> { + var id = mc.getModId(); + if (!"forge".equals(id) && !"minecraft".equals(id) && m.matcher(id).matches()) + mods.add(id); + }); + } + LOGGER.info("Initializing Data Gatherer for mods {}", mods); + + var config = new GatherDataEvent.DataGeneratorConfig(mods, output, inputs, lookupProvider, genServer, + genClient, genDev, genReports, validate, flat); + if (!mods.contains("forge")) { // If we aren't generating data for forge, automatically add forge as an existing so mods can access forge's data existingMods.add("forge"); } - existingFileHelper = new ExistingFileHelper(existingPacks, existingMods, structureValidator, assetIndex, assetsDir); - ModLoader.get().runEventGenerator(mc -> new GatherDataEvent(mc, dataGeneratorConfig.makeGenerator(p -> dataGeneratorConfig.isFlat() ? p : p.resolve(mc.getModId()), - dataGeneratorConfig.getMods().contains(mc.getModId())), dataGeneratorConfig, existingFileHelper)); - dataGeneratorConfig.runAll(); + + existingFileHelper = new ExistingFileHelper(existingPacks, existingMods, validate, assetIndex, assetsDir); + ModLoader.get().runEventGenerator(mc -> new GatherDataEvent( + mc, + config.makeGenerator( + p -> config.isFlat() ? p : p.resolve(mc.getModId()), + config.getMods().contains(mc.getModId()) + ), config, existingFileHelper) + ); + config.runAll(); } } diff --git a/src/main/java/net/minecraftforge/event/AddReloadListenerEvent.java b/src/main/java/net/minecraftforge/event/AddReloadListenerEvent.java index 84e9f2bb85..d394fed423 100644 --- a/src/main/java/net/minecraftforge/event/AddReloadListenerEvent.java +++ b/src/main/java/net/minecraftforge/event/AddReloadListenerEvent.java @@ -27,14 +27,12 @@ import java.util.concurrent.Executor; * The event is fired on each reload and lets modders add their own ReloadListeners, for server-side resources. * The event is fired on the {@link MinecraftForge#EVENT_BUS} */ -public class AddReloadListenerEvent extends Event -{ +public class AddReloadListenerEvent extends Event { private final List listeners = new ArrayList<>(); private final ReloadableServerResources serverResources; private final RegistryAccess registryAccess; - public AddReloadListenerEvent(ReloadableServerResources serverResources, RegistryAccess registryAccess) - { + public AddReloadListenerEvent(ReloadableServerResources serverResources, RegistryAccess registryAccess) { this.serverResources = serverResources; this.registryAccess = registryAccess; } @@ -42,21 +40,18 @@ public class AddReloadListenerEvent extends Event /** * @param listener the listener to add to the ResourceManager on reload */ - public void addListener(PreparableReloadListener listener) - { + public void addListener(PreparableReloadListener listener) { listeners.add(new WrappedStateAwareListener(listener)); } - public List getListeners() - { + public List getListeners() { return ImmutableList.copyOf(listeners); } /** * @return The ReloableServerResources being reloaded. */ - public ReloadableServerResources getServerResources() - { + public ReloadableServerResources getServerResources() { return serverResources; } @@ -64,8 +59,7 @@ public class AddReloadListenerEvent extends Event * This context object holds data relevant to the current reload, such as staged tags. * @return The condition context for the currently active reload. */ - public ICondition.IContext getConditionContext() - { + public ICondition.IContext getConditionContext() { return serverResources.getConditionContext(); } @@ -74,8 +68,7 @@ public class AddReloadListenerEvent extends Event * All built-in and dynamic registries are loaded and frozen by this point. * @return The RegistryAccess context for the currently active reload. */ - public RegistryAccess getRegistryAccess() - { + public RegistryAccess getRegistryAccess() { return registryAccess; } diff --git a/src/test/java/net/minecraftforge/debug/CreativeModeTabTest.java b/src/test/java/net/minecraftforge/debug/creativetabs/CreativeModeTabTest.java similarity index 99% rename from src/test/java/net/minecraftforge/debug/CreativeModeTabTest.java rename to src/test/java/net/minecraftforge/debug/creativetabs/CreativeModeTabTest.java index dd3d4cc821..2033c0b745 100644 --- a/src/test/java/net/minecraftforge/debug/CreativeModeTabTest.java +++ b/src/test/java/net/minecraftforge/debug/creativetabs/CreativeModeTabTest.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: LGPL-2.1-only */ -package net.minecraftforge.debug; +package net.minecraftforge.debug.creativetabs; import java.util.List; import net.minecraft.core.registries.Registries; diff --git a/src/test/java/net/minecraftforge/debug/gameplay/loot/GlobalLootModifiersTest.java b/src/test/java/net/minecraftforge/debug/gameplay/loot/GlobalLootModifiersTest.java index c409a712da..ba2f14d752 100644 --- a/src/test/java/net/minecraftforge/debug/gameplay/loot/GlobalLootModifiersTest.java +++ b/src/test/java/net/minecraftforge/debug/gameplay/loot/GlobalLootModifiersTest.java @@ -90,7 +90,7 @@ public class GlobalLootModifiersTest { var entries = event.getEntries(); var vis = TabVisibility.PARENT_AND_SEARCH_TABS; if (event.getTabKey() == Empty.TAB) { - var smelt = new ItemStack(Items.SHEARS); + var smelt = new ItemStack(Items.IRON_AXE); EnchantmentHelper.setEnchantments(ImmutableMap.builder().put(SMELT.get(), 1).build(), smelt); entries.put(smelt, vis); } diff --git a/src/test_old/java/net/minecraftforge/mdk/MdkDatagen.java b/src/test/java/net/minecraftforge/mdk/Datagen.java similarity index 86% rename from src/test_old/java/net/minecraftforge/mdk/MdkDatagen.java rename to src/test/java/net/minecraftforge/mdk/Datagen.java index 63f820bfd7..c4535ac36a 100644 --- a/src/test_old/java/net/minecraftforge/mdk/MdkDatagen.java +++ b/src/test/java/net/minecraftforge/mdk/Datagen.java @@ -16,18 +16,15 @@ import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import java.util.Optional; -@Mod(MdkDatagen.MOD_ID) -public class MdkDatagen -{ +@Mod(Datagen.MOD_ID) +public class Datagen { static final String MOD_ID = "mdk_datagen"; - public MdkDatagen() - { - FMLJavaModLoadingContext.get().getModEventBus().addListener(MdkDatagen::gatherData); + public Datagen() { + FMLJavaModLoadingContext.get().getModEventBus().addListener(Datagen::gatherData); } - private static void gatherData(GatherDataEvent event) - { + private static void gatherData(GatherDataEvent event) { var gen = event.getGenerator(); var packOutput = gen.getPackOutput(); gen.addProvider(true, new PackMetadataGenerator(packOutput) diff --git a/src/test/resources/META-INF/mods.toml b/src/test/resources/global_loot_test/META-INF/mods.toml similarity index 52% rename from src/test/resources/META-INF/mods.toml rename to src/test/resources/global_loot_test/META-INF/mods.toml index 56730474a7..a7bf4e2486 100644 --- a/src/test/resources/META-INF/mods.toml +++ b/src/test/resources/global_loot_test/META-INF/mods.toml @@ -1,15 +1,3 @@ -modLoader="javafml" -loaderVersion="[28,)" -license="LGPL v2.1" - -[[mods]] -modId="empty" - -[[mods]] -modId="creative_mode_tab_test" - - - [[mods]] modId="global_loot_test" [[dependencies.global_loot_test]]