From efb1b64fc162e3cf9b29bfe6f9b2e50fdb903964 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Mon, 11 Nov 2024 16:48:47 -0800 Subject: [PATCH 01/11] fix: work on re-enabling spongeforge for 1.21.3 --- forge/gradle.properties | 2 +- .../spongepowered/forge/SpongeForgeMod.java | 8 +- .../server/level/ServerPlayerMixin_Forge.java | 7 +- ...rverGamePacketListenerImplMixin_Forge.java | 25 ++- .../world/entity/LivingEntityMixin_Forge.java | 12 +- .../world/entity/vehicle/BoatMixin_Forge.java | 12 +- ...rverPlayerGameModeMixin_Forge_Tracker.java | 2 +- .../BlockBehaviorMixin_Forge_Tracker.java | 2 +- gradle/verification-metadata.xml | 159 ++++++++++++++++++ 9 files changed, 202 insertions(+), 27 deletions(-) diff --git a/forge/gradle.properties b/forge/gradle.properties index acc83580cf4..f3f921aae37 100644 --- a/forge/gradle.properties +++ b/forge/gradle.properties @@ -2,7 +2,7 @@ name=SpongeForge implementation=Forge description=The SpongeAPI implementation for MinecraftForge -forgeVersion=52.0.3 +forgeVersion=53.0.25 loom.platform=forge fabric.loom.dontRemap=true mixinConfigs=mixins.spongeforge.accessors.json,mixins.spongeforge.api.json,mixins.spongeforge.inventory.json,mixins.spongeforge.inventory.shared.json,mixins.spongeforge.core.json,mixins.spongeforge.core.shared.json,mixins.spongeforge.tracker.json \ No newline at end of file diff --git a/forge/src/main/java/org/spongepowered/forge/SpongeForgeMod.java b/forge/src/main/java/org/spongepowered/forge/SpongeForgeMod.java index 200740664e5..3cccd1d9797 100644 --- a/forge/src/main/java/org/spongepowered/forge/SpongeForgeMod.java +++ b/forge/src/main/java/org/spongepowered/forge/SpongeForgeMod.java @@ -25,6 +25,8 @@ package org.spongepowered.forge; import net.minecraft.client.Minecraft; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.MobCategory; import net.minecraftforge.common.MinecraftForge; @@ -64,10 +66,10 @@ public final class SpongeForgeMod { private final Logger logger = LogManager.getLogger("spongeforge"); - public SpongeForgeMod() { + public SpongeForgeMod(FMLJavaModLoadingContext ctx) { // WorldPersistenceHooks.addHook(SpongeLevelDataPersistence.INSTANCE); // TODO SF 1.19.4 - final IEventBus modBus = FMLJavaModLoadingContext.get().getModEventBus(); + final IEventBus modBus = ctx.getModEventBus(); // modBus: add all FML events with it modBus.addListener(this::onCommonSetup); @@ -144,7 +146,7 @@ public void onRegister(RegisterEvent event) { .sized(0.6F, 1.8F) .clientTrackingRange(org.spongepowered.common.util.Constants.Entity.Player.TRACKING_RANGE) .updateInterval(2) - .build("sponge:human") + .build(ResourceKey.create(ForgeRegistries.Keys.ENTITY_TYPES, ResourceLocation.parse("sponge:human"))) ; event.register(ForgeRegistries.Keys.ENTITY_TYPES, helper -> helper.register(HumanEntity.KEY, SpongeEntityTypes.HUMAN)); diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/server/level/ServerPlayerMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/server/level/ServerPlayerMixin_Forge.java index b06f9cb2cce..25f11215d82 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/server/level/ServerPlayerMixin_Forge.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/server/level/ServerPlayerMixin_Forge.java @@ -24,8 +24,10 @@ */ package org.spongepowered.forge.mixin.core.server.level; +import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.common.event.tracking.PhaseContext; import org.spongepowered.common.event.tracking.PhaseTracker; @@ -37,10 +39,13 @@ @Mixin(ServerPlayer.class) public abstract class ServerPlayerMixin_Forge extends LivingEntityMixin_Forge { + @Shadow public abstract ServerLevel shadow$serverLevel(); + // override from LivingEntityMixin_Forge @Override protected void forge$onElytraUse(final CallbackInfo ci) { - final PhaseContext context = PhaseTracker.SERVER.getPhaseContext(); + final ServerLevel level = this.shadow$serverLevel(); + final PhaseContext context = PhaseTracker.getWorldInstance(level).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); final net.minecraft.server.level.ServerPlayer player = (net.minecraft.server.level.ServerPlayer) (Object) this; try (final EffectTransactor ignored = transactor.logPlayerInventoryChangeWithEffect(player, PlayerInventoryTransaction.EventCreator.STANDARD)) { diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/server/network/ServerGamePacketListenerImplMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/server/network/ServerGamePacketListenerImplMixin_Forge.java index f8e9a9a30af..f3c363bcbec 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/server/network/ServerGamePacketListenerImplMixin_Forge.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/server/network/ServerGamePacketListenerImplMixin_Forge.java @@ -25,6 +25,8 @@ package org.spongepowered.forge.mixin.core.server.network; import net.minecraft.network.protocol.game.ServerGamePacketListener; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.network.ServerGamePacketListenerImpl; import net.minecraft.world.inventory.RecipeBookMenu; import net.minecraft.world.item.crafting.RecipeHolder; @@ -33,6 +35,7 @@ import org.spongepowered.api.item.inventory.crafting.CraftingInventory; import org.spongepowered.api.item.inventory.query.QueryTypes; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.common.SpongeCommon; @@ -44,23 +47,29 @@ @Mixin(ServerGamePacketListenerImpl.class) public abstract class ServerGamePacketListenerImplMixin_Forge implements ServerGamePacketListener { - @SuppressWarnings({"unchecked", "rawtypes"}) - @Redirect(method = "lambda$handlePlaceRecipe$10", - at = @At(value = "INVOKE", target = "Lnet/minecraft/world/inventory/RecipeBookMenu;handlePlacement(ZLnet/minecraft/world/item/crafting/RecipeHolder;Lnet/minecraft/server/level/ServerPlayer;)V")) - private void forge$onPlaceRecipe(final RecipeBookMenu recipeBookMenu, final boolean shift, final RecipeHolder recipe, final net.minecraft.server.level.ServerPlayer player) { - final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext(); + @Shadow public ServerPlayer player; + + @Redirect(method = "handlePlaceRecipe", + at = @At(value = "INVOKE", target = "net/minecraft/world/inventory/RecipeBookMenu.handlePlacement(ZZLnet/minecraft/world/item/crafting/RecipeHolder;Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/player/Inventory;)Lnet/minecraft/world/inventory/RecipeBookMenu$PostPlaceAction;")) + private RecipeBookMenu.PostPlaceAction forge$onPlaceRecipe( + final RecipeBookMenu recipeBookMenu, final boolean shift, final boolean isCreative, final RecipeHolder recipe, + final ServerLevel serverLevel, final net.minecraft.world.entity.player.Inventory inventory) { + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(this.player.serverLevel()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); + final var player = this.player; final Inventory craftInv = ((Inventory) player.containerMenu).query(QueryTypes.INVENTORY_TYPE.get().of(CraftingInventory.class)); + final RecipeBookMenu.PostPlaceAction result; if (!(craftInv instanceof CraftingInventory)) { - recipeBookMenu.handlePlacement(shift, recipe, player); + result = recipeBookMenu.handlePlacement(shift,isCreative, recipe, serverLevel, inventory); SpongeCommon.logger().warn("Detected crafting without a InventoryCrafting!? Crafting Event will not fire."); - return; + return result; } try (final EffectTransactor ignored = transactor.logPlaceRecipe(shift, recipe, player, (CraftingInventory) craftInv)) { - recipeBookMenu.handlePlacement(shift, recipe, player); + result = recipeBookMenu.handlePlacement(shift,isCreative, recipe, serverLevel, inventory); player.containerMenu.broadcastChanges(); } + return result; } } diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/LivingEntityMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/LivingEntityMixin_Forge.java index 050c899e5cc..a91a34fa01e 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/LivingEntityMixin_Forge.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/LivingEntityMixin_Forge.java @@ -34,12 +34,12 @@ public abstract class LivingEntityMixin_Forge { @Inject( - method = "updateFallFlying", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/world/item/ItemStack;elytraFlightTick(Lnet/minecraft/world/entity/LivingEntity;I)Z", - shift = At.Shift.AFTER - ) + method = "updateFallFlying", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/world/item/ItemStack;hurtAndBreak(ILnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/entity/EquipmentSlot;)V", + shift = At.Shift.AFTER + ) ) protected void forge$onElytraUse(final CallbackInfo ci) { } diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/vehicle/BoatMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/vehicle/BoatMixin_Forge.java index f00eb8a1c45..e52b4a69c3c 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/vehicle/BoatMixin_Forge.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/entity/vehicle/BoatMixin_Forge.java @@ -26,21 +26,21 @@ import net.minecraft.core.BlockPos; import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.vehicle.Boat; +import net.minecraft.world.entity.vehicle.AbstractBoat; import net.minecraft.world.level.LevelReader; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.state.BlockState; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.common.bridge.world.entity.vehicle.BoatBridge; +import org.spongepowered.common.bridge.world.entity.vehicle.AbstractBoatBridge; -@Mixin(Boat.class) -public abstract class BoatMixin_Forge implements BoatBridge { +@Mixin(AbstractBoat.class) +public abstract class BoatMixin_Forge implements AbstractBoatBridge { @Redirect(method = "getGroundFriction", at = @At( - value = "INVOKE", - target = "Lnet/minecraft/world/level/block/state/BlockState;getFriction(Lnet/minecraft/world/level/LevelReader;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/entity/Entity;)F") + value = "INVOKE", + target = "Lnet/minecraft/world/level/block/state/BlockState;getFriction(Lnet/minecraft/world/level/LevelReader;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/entity/Entity;)F") ) private float forge$getBlockFrictionIfBoatIsNotOverridingMovingOnLand(BlockState caller, LevelReader level, BlockPos pos, Entity entity) { final boolean movesOnLand = this.bridge$getMoveOnLand(); diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/tracker/server/level/ServerPlayerGameModeMixin_Forge_Tracker.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/tracker/server/level/ServerPlayerGameModeMixin_Forge_Tracker.java index b3f8c60f891..0b0b2dd3e13 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/tracker/server/level/ServerPlayerGameModeMixin_Forge_Tracker.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/tracker/server/level/ServerPlayerGameModeMixin_Forge_Tracker.java @@ -63,7 +63,7 @@ public abstract class ServerPlayerGameModeMixin_Forge_Tracker { final ItemStack itemStack, final Level level, final BlockState state, final BlockPos pos, final Player player ) { - final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext(); + final PhaseContext<@NonNull ?> context = PhaseTracker.getWorldInstance(player.level()).getPhaseContext(); final TransactionalCaptureSupplier transactor = context.getTransactor(); // Log the prepare drops here because Forge rewrites // this method to call mine block before calling destroy block diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/tracker/world/level/block/state/BlockBehaviorMixin_Forge_Tracker.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/tracker/world/level/block/state/BlockBehaviorMixin_Forge_Tracker.java index 8784263a379..973df0af53f 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/tracker/world/level/block/state/BlockBehaviorMixin_Forge_Tracker.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/tracker/world/level/block/state/BlockBehaviorMixin_Forge_Tracker.java @@ -42,7 +42,7 @@ public abstract class BlockBehaviorMixin_Forge_Tracker { method = "getLootTable", at = @At( value = "FIELD", - target = "Lnet/minecraft/world/level/block/state/BlockBehaviour;lootTableSupplier:Ljava/util/function/Supplier;", + target = "Lnet/minecraft/world/level/block/state/BlockBehaviour;drops:Ljava/util/Optional;", remap = false ) ) diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 4046353e1be..7f3a0944ff0 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -1699,6 +1699,14 @@ + + + + + + + + @@ -2964,6 +2972,14 @@ + + + + + + + + @@ -3036,6 +3052,22 @@ + + + + + + + + + + + + + + + + @@ -3084,6 +3116,22 @@ + + + + + + + + + + + + + + + + @@ -3132,6 +3180,22 @@ + + + + + + + + + + + + + + + + @@ -3216,6 +3280,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -3232,6 +3324,14 @@ + + + + + + + + @@ -3288,6 +3388,22 @@ + + + + + + + + + + + + + + + + @@ -3336,6 +3452,22 @@ + + + + + + + + + + + + + + + + @@ -3384,6 +3516,22 @@ + + + + + + + + + + + + + + + + @@ -3430,6 +3578,14 @@ + + + + + + + + @@ -3461,6 +3617,9 @@ + + + From 6ad95591066b60bab3ba9de709c5198e48eed7da Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sat, 21 Dec 2024 13:18:06 +0100 Subject: [PATCH 02/11] WIP Replace arch-loom with ForgeGradle --- bootstrap-dev/build.gradle.kts | 3 + bootstrap-dev/src/main/java/module-info.java | 6 + .../spongepowered/bootstrap/dev/Multimap.java | 36 ++++ .../bootstrap/dev}/SourceSet.java | 2 +- .../dev}/SpongeDevClasspathFixer.java | 47 ++--- ...e.bootstrap.api.BootstrapClasspathModifier | 1 + .../impl/SpongeImplementationExtension.java | 104 ++++++++-- forge/build.gradle.kts | 160 +++++++-------- gradle/libs.versions.toml | 4 +- gradle/verification-metadata.xml | 186 ++++++++++++++++++ neoforge/build.gradle.kts | 2 +- settings.gradle.kts | 1 + vanilla/build.gradle.kts | 43 ++-- vanilla/src/devlaunch/java/module-info.java | 6 - ...e.bootstrap.api.BootstrapClasspathModifier | 1 - 15 files changed, 426 insertions(+), 176 deletions(-) create mode 100644 bootstrap-dev/build.gradle.kts create mode 100644 bootstrap-dev/src/main/java/module-info.java create mode 100644 bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/Multimap.java rename {vanilla/src/devlaunch/java/org/spongepowered/vanilla/devlaunch => bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev}/SourceSet.java (98%) rename {vanilla/src/devlaunch/java/org/spongepowered/vanilla/devlaunch => bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev}/SpongeDevClasspathFixer.java (84%) create mode 100644 bootstrap-dev/src/main/resources/META-INF/services/net.minecraftforge.bootstrap.api.BootstrapClasspathModifier delete mode 100644 vanilla/src/devlaunch/java/module-info.java delete mode 100644 vanilla/src/devlaunch/resources/META-INF/services/net.minecraftforge.bootstrap.api.BootstrapClasspathModifier diff --git a/bootstrap-dev/build.gradle.kts b/bootstrap-dev/build.gradle.kts new file mode 100644 index 00000000000..408470bf53e --- /dev/null +++ b/bootstrap-dev/build.gradle.kts @@ -0,0 +1,3 @@ +dependencies { + api(libs.bootstrap.api) +} diff --git a/bootstrap-dev/src/main/java/module-info.java b/bootstrap-dev/src/main/java/module-info.java new file mode 100644 index 00000000000..c46b80848e7 --- /dev/null +++ b/bootstrap-dev/src/main/java/module-info.java @@ -0,0 +1,6 @@ +module org.spongepowered.boostrap.dev { + requires net.minecraftforge.bootstrap.api; + exports org.spongepowered.bootstrap.dev; + + provides net.minecraftforge.bootstrap.api.BootstrapClasspathModifier with org.spongepowered.bootstrap.dev.SpongeDevClasspathFixer; +} diff --git a/bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/Multimap.java b/bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/Multimap.java new file mode 100644 index 00000000000..e56fa029fdd --- /dev/null +++ b/bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/Multimap.java @@ -0,0 +1,36 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.bootstrap.dev; + +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; + +public class Multimap extends HashMap> { + + public void add(K key, V value) { + this.computeIfAbsent(key, k -> new LinkedList<>()).add(value); + } +} diff --git a/vanilla/src/devlaunch/java/org/spongepowered/vanilla/devlaunch/SourceSet.java b/bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/SourceSet.java similarity index 98% rename from vanilla/src/devlaunch/java/org/spongepowered/vanilla/devlaunch/SourceSet.java rename to bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/SourceSet.java index a4fa3b1b537..540c752afcc 100644 --- a/vanilla/src/devlaunch/java/org/spongepowered/vanilla/devlaunch/SourceSet.java +++ b/bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/SourceSet.java @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.vanilla.devlaunch; +package org.spongepowered.bootstrap.dev; import java.nio.file.Files; import java.nio.file.Path; diff --git a/vanilla/src/devlaunch/java/org/spongepowered/vanilla/devlaunch/SpongeDevClasspathFixer.java b/bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/SpongeDevClasspathFixer.java similarity index 84% rename from vanilla/src/devlaunch/java/org/spongepowered/vanilla/devlaunch/SpongeDevClasspathFixer.java rename to bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/SpongeDevClasspathFixer.java index 47c8f979594..7e4e7b8ec5a 100644 --- a/vanilla/src/devlaunch/java/org/spongepowered/vanilla/devlaunch/SpongeDevClasspathFixer.java +++ b/bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/SpongeDevClasspathFixer.java @@ -22,17 +22,15 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -package org.spongepowered.vanilla.devlaunch; +package org.spongepowered.bootstrap.dev; import net.minecraftforge.bootstrap.api.BootstrapClasspathModifier; +import java.io.File; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedList; import java.util.List; -import java.util.Map; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; @@ -51,11 +49,12 @@ public String name() { */ @Override public boolean process(final List classpath) { - final Set bootLibs = Set.of(System.getProperty("sponge.dev.boot").split(";")); - final Set gameShadedLibs = Set.of(System.getProperty("sponge.dev.gameShaded").split(";")); + final Set ignoredLibs = Set.of("bootstrap-dev.jar"); + final Set bootLibs = Set.of(System.getProperty("sponge.dev.boot").split(File.pathSeparator)); + final Set gameShadedLibs = Set.of(System.getProperty("sponge.dev.gameShaded").split(File.pathSeparator)); - final Map> bootSourceSets = new HashMap<>(); - final Map> unknownProjects = new HashMap<>(); + final Multimap bootSourceSets = new Multimap<>(); + final Multimap unknownProjects = new Multimap<>(); final List spongeImplUnion = new ArrayList<>(); final List gameLibs = new ArrayList<>(); @@ -75,8 +74,11 @@ public boolean process(final List classpath) { } switch (sourceSet.project()) { - case "modlauncher-transformers": - bootSourceSets.computeIfAbsent("transformers", k -> new LinkedList<>()).add(path); + case "bootstrap-dev": + // ignore + break; + case "modlauncher-transformers", "library-manager": + bootSourceSets.add(sourceSet.project(), path); break; case "SpongeAPI": switch (sourceSet.name()) { @@ -91,21 +93,15 @@ public boolean process(final List classpath) { break; } break; - case "Sponge", "vanilla": - switch (sourceSet.name()) { - case "devlaunch": - // ignore - break; - case "applaunch": - bootSourceSets.computeIfAbsent("applaunch", k -> new LinkedList<>()).add(path); - break; - default: - spongeImplUnion.add(path); - break; + case "Sponge", "vanilla", "forge": + if (sourceSet.name().equals("applaunch")) { + bootSourceSets.add("applaunch", path); + } else { + spongeImplUnion.add(path); } break; default: - unknownProjects.computeIfAbsent(sourceSet.project(), k -> new LinkedList<>()).add(path); + unknownProjects.add(sourceSet.project(), path); break; } return true; @@ -113,6 +109,13 @@ public boolean process(final List classpath) { final String fileName = path.getFileName().toString(); + if (ignoredLibs.contains(fileName)) { + if (DEBUG) { + System.out.println("Ignored: " + path); + } + return true; + } + if (bootLibs.contains(fileName)) { if (DEBUG) { System.out.println("Boot: " + path); diff --git a/bootstrap-dev/src/main/resources/META-INF/services/net.minecraftforge.bootstrap.api.BootstrapClasspathModifier b/bootstrap-dev/src/main/resources/META-INF/services/net.minecraftforge.bootstrap.api.BootstrapClasspathModifier new file mode 100644 index 00000000000..32a491ef8a6 --- /dev/null +++ b/bootstrap-dev/src/main/resources/META-INF/services/net.minecraftforge.bootstrap.api.BootstrapClasspathModifier @@ -0,0 +1 @@ +org.spongepowered.bootstrap.dev.SpongeDevClasspathFixer diff --git a/build-logic/src/main/java/org/spongepowered/gradle/impl/SpongeImplementationExtension.java b/build-logic/src/main/java/org/spongepowered/gradle/impl/SpongeImplementationExtension.java index 09dc131237a..7881f2a2d2b 100644 --- a/build-logic/src/main/java/org/spongepowered/gradle/impl/SpongeImplementationExtension.java +++ b/build-logic/src/main/java/org/spongepowered/gradle/impl/SpongeImplementationExtension.java @@ -37,6 +37,7 @@ import javax.annotation.Nullable; import javax.inject.Inject; +import java.io.File; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -44,6 +45,8 @@ import java.util.Map; import java.util.Objects; import java.util.Set; +import java.util.StringJoiner; +import java.util.function.Predicate; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -60,33 +63,100 @@ public SpongeImplementationExtension(final Project project, final Logger logger) this.logger = logger; } - public void copyModulesExcludingProvided(final Configuration source, final Configuration provided, final Configuration target) { - final DependencyHandler deps = this.project.getDependencies(); + private record Module(ModuleIdentifier id, String classifier) {} + + public String buildRuntimeFileNames(final Configuration config) { + final Configuration runtimeConfig = this.project.getConfigurations().getByName("runtimeClasspath"); + + final Map runtimeFileNames = new HashMap<>(); + for (final ResolvedArtifact artifact : runtimeConfig.getResolvedConfiguration().getResolvedArtifacts()) { + final ComponentIdentifier id = artifact.getId().getComponentIdentifier(); + if (id instanceof ModuleComponentIdentifier moduleId) { + runtimeFileNames.put(new Module(moduleId.getModuleIdentifier(), artifact.getClassifier()), artifact.getFile().getName()); + } + } + + final StringJoiner joiner = new StringJoiner(File.pathSeparator); + + for (final ResolvedArtifact artifact : config.getResolvedConfiguration().getResolvedArtifacts()) { + final ComponentIdentifier id = artifact.getId().getComponentIdentifier(); + + String fileName = null; + if (id instanceof ModuleComponentIdentifier moduleId) { + fileName = runtimeFileNames.get(new Module(moduleId.getModuleIdentifier(), artifact.getClassifier())); + } + + if (fileName == null) { + fileName = artifact.getFile().getName(); + } + + joiner.add(fileName); + } + + return joiner.toString(); + } + private String buildDependencyNotation(final ModuleComponentIdentifier moduleId, final String classifier) { + final ModuleIdentifier module = moduleId.getModuleIdentifier(); + String notation = module.getGroup() + ":" + module.getName() + ":" + moduleId.getVersion(); + if (classifier != null) { + notation += ":" + classifier; + } + return notation; + } + + public void copyModulesExcludingProvided(final Configuration source, final Configuration provided, final Configuration target) { final Map providedModuleVersions = new HashMap<>(); - for (ResolvedArtifact artifact : provided.getResolvedConfiguration().getResolvedArtifacts()) { + for (final ResolvedArtifact artifact : provided.getResolvedConfiguration().getResolvedArtifacts()) { final ComponentIdentifier id = artifact.getId().getComponentIdentifier(); - if (id instanceof ModuleComponentIdentifier) { - final ModuleComponentIdentifier moduleId = (ModuleComponentIdentifier) id; + if (id instanceof ModuleComponentIdentifier moduleId) { providedModuleVersions.put(moduleId.getModuleIdentifier(), moduleId.getVersion()); } } + this.copyModulesExcludingPredicate(source, (moduleId) -> { + final ModuleIdentifier module = moduleId.getModuleIdentifier(); + final String version = moduleId.getVersion(); + + final String providedVersion = providedModuleVersions.get(module); + if (providedVersion == null) { + return false; + } + + if (!providedVersion.equals(version)) { + this.logger.warn("Version mismatch for module {}. {} expects {} but {} has {}.", module, source.getName(), version, provided.getName(), providedVersion); + } + return true; + }, target); + } + + public void copyModulesExcludingPrefix(final Configuration source, final String group, final String namePrefix, final Configuration target) { + this.copyModulesExcludingPredicate(source, (moduleId) -> { + final ModuleIdentifier module = moduleId.getModuleIdentifier(); + return module.getGroup().equals(group) && module.getName().startsWith(namePrefix); + }, target); + } + + public void copyModulesExcludingExact(final Configuration source, final String group, final String name, final Configuration target) { + this.copyModulesExcludingPredicate(source, (moduleId) -> { + final ModuleIdentifier module = moduleId.getModuleIdentifier(); + return module.getGroup().equals(group) && module.getName().equals(name); + }, target); + } + + private void copyModulesExcludingPredicate(final Configuration source, final Predicate predicate, final Configuration target) { + final DependencyHandler deps = this.project.getDependencies(); + for (ResolvedArtifact artifact : source.getResolvedConfiguration().getResolvedArtifacts()) { final ComponentIdentifier id = artifact.getId().getComponentIdentifier(); - if (id instanceof ModuleComponentIdentifier) { - final ModuleComponentIdentifier moduleId = (ModuleComponentIdentifier) id; - final ModuleIdentifier module = moduleId.getModuleIdentifier(); - final String version = moduleId.getVersion(); - - final String providedVersion = providedModuleVersions.get(module); - if (providedVersion == null) { - ModuleDependency dep = (ModuleDependency) deps.create(module.getGroup() + ":" + module.getName() + ":" + version); - dep.setTransitive(false); - target.getDependencies().add(dep); - } else if (!providedVersion.equals(version)) { - this.logger.warn("Version mismatch for module {}. {} expects {} but {} has {}.", module, source.getName(), version, provided.getName(), providedVersion); + if (id instanceof ModuleComponentIdentifier moduleId) { + if (predicate.test(moduleId)) { + continue; } + + final ModuleDependency dep = (ModuleDependency) deps.create(this.buildDependencyNotation(moduleId, artifact.getClassifier())); + dep.setTransitive(false); + target.getDependencies().add(dep); } // projects are not copied because we cannot always recreate properly a project dependency from the resolved artefact diff --git a/forge/build.gradle.kts b/forge/build.gradle.kts index 7aeb4a2e696..1a4feb36864 100644 --- a/forge/build.gradle.kts +++ b/forge/build.gradle.kts @@ -1,12 +1,12 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar -import net.fabricmc.loom.api.LoomGradleExtensionAPI +import net.minecraftforge.gradle.userdev.UserDevExtension buildscript { repositories { maven("https://repo.spongepowered.org/repository/maven-public") { name = "sponge" } - maven("https://maven.architectury.dev/") + maven("https://maven.minecraftforge.net/") } } @@ -14,10 +14,11 @@ plugins { alias(libs.plugins.shadow) id("implementation-structure") alias(libs.plugins.blossom) - id("dev.architectury.loom") version "1.6.411" + id("net.minecraftforge.gradle") version "[6.0.24,6.2)" } val commonProject = parent!! +val bootstrapDevProject = commonProject.project(":bootstrap-dev") val transformersProject = commonProject.project(":modlauncher-transformers") val libraryManagerProject = commonProject.project(":library-manager") val testPluginsProject: Project? = rootProject.subprojects.find { "testplugins" == it.name } @@ -38,6 +39,11 @@ repositories { } // SpongeForge libraries +val bootLibrariesConfig: NamedDomainObjectProvider = configurations.register("bootLibraries") { + // Ideally we would filter minecraft itself and only keep its dependencies for this layer, + // but I couldn't find a way to do it without breaking ForgeGradle. + extendsFrom(configurations.minecraft.get()) +} val serviceLibrariesConfig: NamedDomainObjectProvider = configurations.register("serviceLibraries") val gameLibrariesConfig: NamedDomainObjectProvider = configurations.register("gameLibraries") @@ -46,28 +52,21 @@ val gameManagedLibrariesConfig: NamedDomainObjectProvider = confi val serviceShadedLibrariesConfig: NamedDomainObjectProvider = configurations.register("serviceShadedLibraries") val gameShadedLibrariesConfig: NamedDomainObjectProvider = configurations.register("gameShadedLibraries") -val runTaskOnlyConfig: NamedDomainObjectProvider = configurations.register("runTaskOnly") - -configurations.named("forgeRuntimeLibrary") { - extendsFrom(serviceLibrariesConfig.get()) -} - // ModLauncher layers +val bootLayerConfig: NamedDomainObjectProvider = configurations.register("bootLayer") { + extendsFrom(bootLibrariesConfig.get()) +} val serviceLayerConfig: NamedDomainObjectProvider = configurations.register("serviceLayer") { + extendsFrom(bootLayerConfig.get()) extendsFrom(serviceLibrariesConfig.get()) - extendsFrom(configurations.getByName("forgeDependencies")) } val langLayerConfig: NamedDomainObjectProvider = configurations.register("langLayer") { - extendsFrom(configurations.getByName("forgeDependencies")) + extendsFrom(bootLayerConfig.get()) } val gameLayerConfig: NamedDomainObjectProvider = configurations.register("gameLayer") { extendsFrom(serviceLayerConfig.get()) extendsFrom(langLayerConfig.get()) extendsFrom(gameLibrariesConfig.get()) - - afterEvaluate { - extendsFrom(configurations.getByName("minecraftNamedCompile")) - } } // SpongeCommon source sets @@ -141,6 +140,10 @@ val forgeMain by sourceSets.named("main") { configurations.named(implementationConfigurationName) { extendsFrom(gameLayerConfig.get()) } + + // The rest of the project because we want everything in the initial classpath + spongeImpl.addDependencyToRuntimeOnly(mixins.get(), this) + spongeImpl.addDependencyToRuntimeOnly(forgeMixins, this) } configurations.configureEach { @@ -155,48 +158,8 @@ configurations.configureEach { } } -extensions.configure(LoomGradleExtensionAPI::class) { - silentMojangMappingsLicense() - accessWidenerPath.set(file("../src/main/resources/common.accesswidener")) - - mixin { - useLegacyMixinAp.set(false) - } - - forge { - useCustomMixin.set(false) - } - - mods { - named("main") { - sourceSet(forgeMixins) - sourceSet(forgeAccessors) - sourceSet(forgeLaunch) - - sourceSet(main.get(), commonProject) - sourceSet(mixins.get(), commonProject) - sourceSet(accessors.get(), commonProject) - sourceSet(launch.get(), commonProject) - - configuration(gameManagedLibrariesConfig.get()) - configuration(gameShadedLibrariesConfig.get()) - } - } - - // Arch-loom bug, skip broken union-relauncher - runs.forEach { - it.mainClass.set("net.minecraftforge.bootstrap.ForgeBootstrap") - } -} - dependencies { - "minecraft"("com.mojang:minecraft:${minecraftVersion}") - "forge"("net.minecraftforge:forge:$minecraftVersion-$forgeVersion") - "mappings"(loom.layered { - officialMojangMappings { - nameSyntheticMembers = true - } - }) + "minecraft"("net.minecraftforge:forge:$minecraftVersion-$forgeVersion") val service = serviceLibrariesConfig.name service(apiLibs.pluginSpi) @@ -231,13 +194,56 @@ dependencies { gameShadedLibraries("org.spongepowered:spongeapi:$apiVersion") { isTransitive = false } afterEvaluate { - spongeImpl.copyModulesExcludingProvided(serviceLibrariesConfig.get(), configurations.getByName("forgeDependencies"), serviceShadedLibrariesConfig.get()) + spongeImpl.copyModulesExcludingProvided(serviceLibrariesConfig.get(), bootLayerConfig.get(), serviceShadedLibrariesConfig.get()) spongeImpl.copyModulesExcludingProvided(gameLibrariesConfig.get(), serviceLayerConfig.get(), gameManagedLibrariesConfig.get()) } - val runTaskOnly = runTaskOnlyConfig.name - // Arch-loom bug, fix support of MOD_CLASSES - runTaskOnly("net.minecraftforge:bootstrap-dev:2.1.3") + runtimeOnly(project(bootstrapDevProject.path)) +} + +val mixinConfigs: MutableSet = spongeImpl.mixinConfigurations + +extensions.configure(UserDevExtension::class) { + mappings("official", "1.21.3") + // accessWidenerPath.set(file("../src/main/resources/common.accesswidener")) TODO + + reobf = false + + runs { + configureEach { + ideaModule("Sponge.SpongeForge.main") + + property("forge.logging.markers", "REGISTRIES") + property("forge.logging.console.level", "debug") + + // jvmArgs("-Dbsl.debug=true") // Uncomment to debug bootstrap classpath + + args(mixinConfigs.flatMap { sequenceOf("--mixin.config", it) }) + + environment("MOD_CLASSES", "nop") + } + + create("client") { + workingDirectory(file("run/client")) + } + + create("server") { + workingDirectory(file("run/client")) + args("--nogui") + } + } +} + +afterEvaluate { + extensions.configure(UserDevExtension::class) { + // Configure bootstrap-dev + val bootFileNames = spongeImpl.buildRuntimeFileNames(serviceLayerConfig.get()) // service in boot during dev + val gameShadedFileNames = spongeImpl.buildRuntimeFileNames(gameShadedLibrariesConfig.get()) + runs.configureEach { + jvmArgs("-Dsponge.dev.boot=$bootFileNames") + jvmArgs("-Dsponge.dev.gameShaded=$gameShadedFileNames") + } + } } val forgeManifest = java.manifest { @@ -254,8 +260,6 @@ val forgeManifest = java.manifest { System.getenv()["GIT_BRANCH"]?.apply { attributes("Git-Branch" to this) } } -val mixinConfigs: MutableSet = spongeImpl.mixinConfigurations - tasks { jar { manifest.from(forgeManifest) @@ -306,38 +310,6 @@ tasks { duplicatesStrategy = DuplicatesStrategy.WARN } - afterEvaluate { - withType(net.fabricmc.loom.task.AbstractRunTask::class) { - // Default classpath is a mess, we better start a new one from scratch - classpath = files( - configurations.getByName("forgeRuntimeLibrary"), - forgeServicesJar, forgeLangJar, runTaskOnlyConfig - ) - - testPluginsProject?.also { - val testPluginsOutput = it.sourceSets.getByName("main").output - val dirs: MutableList = mutableListOf() - dirs.add(testPluginsOutput.resourcesDir!!) - dirs.addAll(testPluginsOutput.classesDirs) - environment["SPONGE_PLUGINS"] = dirs.joinToString("&") - - dependsOn(it.tasks.classes) - } - - argumentProviders += CommandLineArgumentProvider { - mixinConfigs.asSequence() - .flatMap { sequenceOf("--mixin.config", it) } - .toList() - } - - // jvmArguments.add("-Dbsl.debug=true") // Uncomment to debug bootstrap classpath - - sourceSets.forEach { - dependsOn(it.classesTaskName) - } - } - } - val installerResources = project.layout.buildDirectory.dir("generated/resources/installer") forgeAppLaunch.resources.srcDir(installerResources) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 867ada7f2fe..cbc47e0b08d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -8,8 +8,8 @@ asm = "9.7" log4j = "2.22.1" forgeAutoRenamingTool = "1.0.6" mixin = "0.8.7" -bootstrap = "2.1.1" -modlauncher = "10.2.1" +bootstrap = "2.1.3" +modlauncher = "10.2.2" neo-modlauncher = "11.0.3" securemodules = "2.2.20" jarjar = "0.3.26" diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 7f3a0944ff0..328daf4d49e 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -168,6 +168,9 @@ + + + @@ -208,6 +211,9 @@ + + + @@ -1523,6 +1529,14 @@ + + + + + + + + @@ -1715,6 +1729,14 @@ + + + + + + + + @@ -2046,6 +2068,9 @@ + + + @@ -2773,6 +2798,14 @@ + + + + + + + + @@ -2811,18 +2844,40 @@ + + + + + + + + + + + + + + + + + + + + + + @@ -2847,10 +2902,21 @@ + + + + + + + + + + + @@ -2890,6 +2956,9 @@ + + + @@ -2925,6 +2994,9 @@ + + + @@ -2976,6 +3048,9 @@ + + + @@ -3000,6 +3075,9 @@ + + + @@ -3064,6 +3142,9 @@ + + + @@ -3128,6 +3209,9 @@ + + + @@ -3192,6 +3276,9 @@ + + + @@ -3308,6 +3395,14 @@ + + + + + + + + @@ -3328,6 +3423,9 @@ + + + @@ -3400,6 +3498,9 @@ + + + @@ -3464,6 +3565,9 @@ + + + @@ -3528,6 +3632,9 @@ + + + @@ -3582,6 +3689,9 @@ + + + @@ -3669,6 +3779,14 @@ + + + + + + + + @@ -3680,6 +3798,19 @@ + + + + + + + + + + + + + @@ -4191,6 +4322,14 @@ + + + + + + + + @@ -4206,6 +4345,11 @@ + + + + + @@ -4313,11 +4457,24 @@ + + + + + + + + + + + + + @@ -4763,6 +4920,11 @@ + + + + + @@ -4787,6 +4949,14 @@ + + + + + + + + @@ -4810,6 +4980,11 @@ + + + + + @@ -4972,6 +5147,9 @@ + + + @@ -5337,6 +5515,14 @@ + + + + + + + + diff --git a/neoforge/build.gradle.kts b/neoforge/build.gradle.kts index a7b86632259..9cd699e0d03 100644 --- a/neoforge/build.gradle.kts +++ b/neoforge/build.gradle.kts @@ -312,7 +312,7 @@ tasks { .toList() } - jvmArguments.add("-Dbsl.debug=true") // Uncomment to debug bootstrap classpath + // jvmArguments.add("-Dbsl.debug=true") // Uncomment to debug bootstrap classpath sourceSets.forEach { dependsOn(it.classesTaskName) diff --git a/settings.gradle.kts b/settings.gradle.kts index 00d638da944..6202443c650 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -70,6 +70,7 @@ includeBuild("SpongeAPI") { } include("modlauncher-transformers") include("library-manager") +include("bootstrap-dev") include("generator") // Optional projects diff --git a/vanilla/build.gradle.kts b/vanilla/build.gradle.kts index b936a70281c..00ac01e6f6c 100644 --- a/vanilla/build.gradle.kts +++ b/vanilla/build.gradle.kts @@ -9,6 +9,7 @@ plugins { } val commonProject = parent!! +val bootstrapDevProject = commonProject.project(":bootstrap-dev") val transformersProject = commonProject.project(":modlauncher-transformers") val libraryManagerProject = commonProject.project(":library-manager") val testPluginsProject: Project? = rootProject.subprojects.find { "testplugins" == it.name } @@ -23,7 +24,6 @@ description = "The SpongeAPI implementation for Vanilla Minecraft" version = spongeImpl.generatePlatformBuildVersionString(apiVersion, minecraftVersion, recommendedVersion) // SpongeVanilla libraries -val devlaunchLibrariesConfig: NamedDomainObjectProvider = configurations.register("devlaunchLibraries") val installerLibrariesConfig: NamedDomainObjectProvider = configurations.register("installerLibraries") val initLibrariesConfig: NamedDomainObjectProvider = configurations.register("initLibraries") // JVM initial classpath val bootLibrariesConfig: NamedDomainObjectProvider = configurations.register("bootLibraries") @@ -54,13 +54,6 @@ val mixins: NamedDomainObjectProvider = commonProject.sourceSets.name val main: NamedDomainObjectProvider = commonProject.sourceSets.named("main") // SpongeVanilla source sets -// Dev launch -val vanillaDevLaunch by sourceSets.register("devlaunch") { - configurations.named(implementationConfigurationName) { - extendsFrom(devlaunchLibrariesConfig.get()) - } -} - // Prod launch val vanillaInstaller by sourceSets.register("installer") { configurations.named(implementationConfigurationName) { @@ -126,12 +119,7 @@ val vanillaMain by sourceSets.named("main") { // The rest of the project because we want everything in the initial classpath spongeImpl.addDependencyToRuntimeOnly(mixins.get(), this) - spongeImpl.addDependencyToRuntimeOnly(vanillaDevLaunch, this) spongeImpl.addDependencyToRuntimeOnly(vanillaMixins, this) - - configurations.named(runtimeOnlyConfigurationName) { - extendsFrom(devlaunchLibrariesConfig.get()) - } } val superclassConfigs = spongeImpl.getNamedConfigurations("superClassChanges") @@ -157,9 +145,6 @@ configurations.configureEach { } dependencies { - val devlaunch = devlaunchLibrariesConfig.name - devlaunch(libs.bootstrap.api) - val installer = installerLibrariesConfig.name installer(apiLibs.gson) installer(platform(apiLibs.configurate.bom)) @@ -233,17 +218,8 @@ dependencies { exclude(group = "org.checkerframework", module = "checker-qual") } - // All minecraft deps except itself - configurations.minecraft.get().resolvedConfiguration.resolvedArtifacts - .map { - var id = it.id.componentIdentifier.toString() - if (it.classifier != null) { - id += ":" + it.classifier - } - id - } - .filter { !it.startsWith("net.minecraft:joined") } - .forEach { boot(it) { isTransitive = false } } + // All minecraft dependencies except itself + spongeImpl.copyModulesExcludingPrefix(configurations.minecraft.get(), "net.minecraft", "joined", bootLibrariesConfig.get()) boot(project(transformersProject.path)) { exclude(group = "cpw.mods", module = "modlauncher") @@ -271,9 +247,9 @@ dependencies { spongeImpl.copyModulesExcludingProvided(gameLibrariesConfig.get(), bootLayerConfig.get(), gameManagedLibrariesConfig.get()) - val runOnly = vanillaMain.runtimeOnlyConfigurationName + runtimeOnly(project(bootstrapDevProject.path)) testPluginsProject?.also { - runOnly(project(it.path)) + runtimeOnly(project(it.path)) } } @@ -295,6 +271,10 @@ minecraft { args("--launchTarget", "sponge_client_it") } + // Configure bootstrap-dev + val bootFileNames = spongeImpl.buildRuntimeFileNames(bootLayerConfig.get()) + val gameShadedFileNames = spongeImpl.buildRuntimeFileNames(gameShadedLibrariesConfig.get()) + configureEach { targetVersion(apiJavaTarget.toInt()) workingDirectory(project.file("run/")) @@ -328,9 +308,8 @@ minecraft { // jvmArgs("-Dbsl.debug=true") // Uncomment to debug bootstrap classpath mainClass("net.minecraftforge.bootstrap.ForgeBootstrap") - // Configure resources - jvmArgs("-Dsponge.dev.boot=" + bootLayerConfig.get().resolvedConfiguration.resolvedArtifacts.joinToString(";") { it.file.name }) - jvmArgs("-Dsponge.dev.gameShaded=" + gameShadedLibrariesConfig.get().resolvedConfiguration.resolvedArtifacts.joinToString(";") { it.file.name }) + jvmArgs("-Dsponge.dev.boot=$bootFileNames") + jvmArgs("-Dsponge.dev.gameShaded=$gameShadedFileNames") } } } diff --git a/vanilla/src/devlaunch/java/module-info.java b/vanilla/src/devlaunch/java/module-info.java deleted file mode 100644 index 3328ffb314e..00000000000 --- a/vanilla/src/devlaunch/java/module-info.java +++ /dev/null @@ -1,6 +0,0 @@ -module org.spongepowered.vanilla.devlaunch { - requires net.minecraftforge.bootstrap.api; - exports org.spongepowered.vanilla.devlaunch; - - provides net.minecraftforge.bootstrap.api.BootstrapClasspathModifier with org.spongepowered.vanilla.devlaunch.SpongeDevClasspathFixer; -} diff --git a/vanilla/src/devlaunch/resources/META-INF/services/net.minecraftforge.bootstrap.api.BootstrapClasspathModifier b/vanilla/src/devlaunch/resources/META-INF/services/net.minecraftforge.bootstrap.api.BootstrapClasspathModifier deleted file mode 100644 index 8351cd09f4e..00000000000 --- a/vanilla/src/devlaunch/resources/META-INF/services/net.minecraftforge.bootstrap.api.BootstrapClasspathModifier +++ /dev/null @@ -1 +0,0 @@ -org.spongepowered.vanilla.devlaunch.SpongeDevClasspathFixer From a35bb81e20591d87d199defbc4a09da5be8d619b Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sat, 21 Dec 2024 16:43:27 +0100 Subject: [PATCH 03/11] Rework SpongeForge mod locators and load resources in dev --- .../dev/SpongeDevClasspathFixer.java | 18 ++--- forge/build.gradle.kts | 5 +- .../moddiscovery/AbstractModProvider.java | 80 +++++++++++++++++++ .../moddiscovery/PluginFileParser.java | 75 ++++++++++++++--- .../SpongeForgeDependencyLocator.java | 17 +--- .../moddiscovery/SpongeForgeModLocator.java | 21 ++++- .../locator/EnvironmentPluginLocator.java | 14 +--- .../locator/PluginsDirectoryLocator.java | 10 +-- ...java => SpongePropertyLocatorService.java} | 9 ++- ...owered.plugin.PluginResourceLocatorService | 2 +- .../vanilla/installer/InstallerMain.java | 9 ++- 11 files changed, 192 insertions(+), 68 deletions(-) create mode 100644 forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/AbstractModProvider.java rename vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/locator/{GameResourceLocatorService.java => SpongePropertyLocatorService.java} (93%) diff --git a/bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/SpongeDevClasspathFixer.java b/bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/SpongeDevClasspathFixer.java index 7e4e7b8ec5a..e1630913203 100644 --- a/bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/SpongeDevClasspathFixer.java +++ b/bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/SpongeDevClasspathFixer.java @@ -161,26 +161,26 @@ public boolean process(final List classpath) { }); } - final StringBuilder gameResourcesEnvBuilder = new StringBuilder(); + final StringBuilder resourcesEnvBuilder = new StringBuilder(); for (final Path resource : gameLibs) { - gameResourcesEnvBuilder.append(resource).append(';'); + resourcesEnvBuilder.append(resource).append(File.pathSeparator); } for (final List project : unknownProjects.values()) { for (final Path resource : project) { - gameResourcesEnvBuilder.append(resource).append('&'); + resourcesEnvBuilder.append(resource).append('&'); } - gameResourcesEnvBuilder.setCharAt(gameResourcesEnvBuilder.length() - 1, ';'); + resourcesEnvBuilder.setCharAt(resourcesEnvBuilder.length() - 1, File.pathSeparatorChar); } for (final Path resource : spongeImplUnion) { - gameResourcesEnvBuilder.append(resource).append('&'); + resourcesEnvBuilder.append(resource).append('&'); } - gameResourcesEnvBuilder.setLength(gameResourcesEnvBuilder.length() - 1); - final String gameResourcesEnv = gameResourcesEnvBuilder.toString(); + resourcesEnvBuilder.setLength(resourcesEnvBuilder.length() - 1); + final String resourcesEnv = resourcesEnvBuilder.toString(); if (DEBUG) { - System.out.println("Game resources env: " + gameResourcesEnv); + System.out.println("Resources env: " + resourcesEnv); } - System.setProperty("sponge.gameResources", gameResourcesEnv); + System.setProperty("sponge.resources", resourcesEnv); return true; } } diff --git a/forge/build.gradle.kts b/forge/build.gradle.kts index 1a4feb36864..99f42629fcd 100644 --- a/forge/build.gradle.kts +++ b/forge/build.gradle.kts @@ -223,12 +223,9 @@ extensions.configure(UserDevExtension::class) { environment("MOD_CLASSES", "nop") } - create("client") { - workingDirectory(file("run/client")) - } + create("client") create("server") { - workingDirectory(file("run/client")) args("--nogui") } } diff --git a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/AbstractModProvider.java b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/AbstractModProvider.java new file mode 100644 index 00000000000..5b71dde2099 --- /dev/null +++ b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/AbstractModProvider.java @@ -0,0 +1,80 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.forge.applaunch.loading.moddiscovery; + +import cpw.mods.jarhandling.SecureJar; +import net.minecraftforge.forgespi.locating.IModFile; +import net.minecraftforge.forgespi.locating.IModProvider; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Map; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Consumer; +import java.util.stream.Stream; + +public abstract class AbstractModProvider implements IModProvider { + private static final Logger LOGGER = LogManager.getLogger(); + + @Override + public boolean isValid(final IModFile modFile) { + return true; + } + + @Override + public void initArguments(final Map arguments) { + } + + @Override + public void scanFile(final IModFile file, final Consumer pathConsumer) { + LOGGER.debug("Scan started: {}", file); + final SecureJar jar = file.getSecureJar(); + + Consumer consumer = pathConsumer; + final AtomicReference minStatus = new AtomicReference<>(SecureJar.Status.NONE); + if (jar.hasSecurityData()) { + minStatus.set(SecureJar.Status.VERIFIED); + consumer = path -> { + pathConsumer.accept(path); + SecureJar.Status status = jar.verifyPath(path); + if (status.ordinal() < minStatus.get().ordinal()) + minStatus.set(status); + }; + } + + try (final Stream files = Files.walk(jar.getRootPath())) { + files.filter(p -> p.toString().endsWith(".class")).forEach(consumer); + } catch (IOException e) { + LOGGER.debug("Scan failed: {}", file); + minStatus.set(SecureJar.Status.NONE); + } + + file.setSecurityStatus(minStatus.get()); + LOGGER.debug("Scan finished: {}", file); + } +} diff --git a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/PluginFileParser.java b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/PluginFileParser.java index 9102910689f..f63dfb7c498 100644 --- a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/PluginFileParser.java +++ b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/PluginFileParser.java @@ -24,14 +24,16 @@ */ package org.spongepowered.forge.applaunch.loading.moddiscovery; +import cpw.mods.jarhandling.JarMetadata; import cpw.mods.jarhandling.SecureJar; +import net.minecraftforge.fml.loading.moddiscovery.AbstractModProvider; import net.minecraftforge.fml.loading.moddiscovery.ModFile; import net.minecraftforge.fml.loading.moddiscovery.ModFileInfo; +import net.minecraftforge.fml.loading.moddiscovery.ModFileParser; import net.minecraftforge.fml.loading.moddiscovery.ModJarMetadata; import net.minecraftforge.forgespi.language.IModFileInfo; import net.minecraftforge.forgespi.locating.IModFile; -import net.minecraftforge.forgespi.locating.IModLocator; -import net.minecraftforge.forgespi.locating.ModFileFactory; +import net.minecraftforge.forgespi.locating.IModProvider; import org.spongepowered.common.applaunch.AppLaunch; import org.spongepowered.common.applaunch.metadata.PluginMetadataFixer; import org.spongepowered.common.applaunch.plugin.PluginPlatformConstants; @@ -46,7 +48,11 @@ import java.nio.file.Path; import java.util.List; +@SuppressWarnings("UnstableApiUsage") public final class PluginFileParser { + private static final String MODS_TOML = "META-INF/mods.toml"; + private static final String MODULE_INFO = "module-info.class"; + private static Constructor modJarMetadataConstructor; static { @@ -58,7 +64,7 @@ public final class PluginFileParser { } } - private static IModFileInfo parsePluginMetadata(final IModFile iModFile) { + private static IModFileInfo parsePluginFileInfo(final IModFile iModFile) { final ModFile modFile = (ModFile) iModFile; AppLaunch.logger().debug("Considering plugin file candidate {}", modFile.getFilePath()); @@ -82,6 +88,14 @@ private static IModFileInfo parsePluginMetadata(final IModFile iModFile) { } } + private static IModFileInfo parseModFileInfo(final IModFile iModFile) { + return ModFileParser.modsTomlParser(iModFile); + } + + private static IModFileInfo parseLibraryFileInfo(final IModFile iModFile) { + return DummyModProvider.INSTANCE.manifestParser(iModFile); + } + private static ModJarMetadata newModJarMetadata() { try { return modJarMetadataConstructor.newInstance(); @@ -90,13 +104,56 @@ private static ModJarMetadata newModJarMetadata() { } } - public static ModFile newPluginInstance(final IModLocator locator, final Path... path) { - ModJarMetadata mjm = newModJarMetadata(); - ModFile modFile = (ModFile) ModFileFactory.FACTORY.build(SecureJar.from(jar -> mjm, path), locator, PluginFileParser::parsePluginMetadata); - mjm.setModFile(modFile); - return modFile; + private static boolean useModJarMetadata(final SecureJar jar) { + final SecureJar.ModuleDataProvider data = jar.moduleDataProvider(); + if (data.findFile(PluginFileParser.MODULE_INFO).isPresent()) { + return false; + } + return data.findFile(PluginFileParser.MODS_TOML).isPresent() || data.findFile(PluginPlatformConstants.METADATA_FILE_LOCATION).isPresent(); + } + + public static ModFile newModFile(final IModProvider provider, boolean allowUnknown, final Path... paths) { + final ModJarMetadata mjm = newModJarMetadata(); + final SecureJar jar = SecureJar.from(j -> useModJarMetadata(j) ? mjm : JarMetadata.from(j, paths), paths); + + final SecureJar.ModuleDataProvider data = jar.moduleDataProvider(); + final String type = data.getManifest().getMainAttributes().getValue("FMLModType"); + + if (data.findFile(PluginFileParser.MODS_TOML).isPresent()) { + ModFile modFile = new ModFile(jar, provider, PluginFileParser::parseModFileInfo, type == null ? "MOD" : type); + mjm.setModFile(modFile); + return modFile; + } + + if (data.findFile(PluginPlatformConstants.METADATA_FILE_LOCATION).isPresent()) { + ModFile modFile = new ModFile(jar, provider, PluginFileParser::parsePluginFileInfo, type == null ? "MOD" : type); + mjm.setModFile(modFile); + return modFile; + } + + if (!allowUnknown && type == null) { + throw new IllegalArgumentException("Unknown mod file type"); + } + + return new ModFile(jar, provider, PluginFileParser::parseLibraryFileInfo, type == null ? "GAMELIBRARY" : type); + } + + public static ModFile newLibraryFile(final IModProvider provider, final Path... paths) { + final SecureJar jar = SecureJar.from(paths); + return new ModFile(jar, provider, PluginFileParser::parseLibraryFileInfo, "GAMELIBRARY"); } - private PluginFileParser() { + private static class DummyModProvider extends AbstractModProvider { + private static final DummyModProvider INSTANCE = new DummyModProvider(); + + @Override + public String name() { + return "dummy"; + } + + @Override + public IModFileInfo manifestParser(IModFile mod) { + return super.manifestParser(mod); + } } } diff --git a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/SpongeForgeDependencyLocator.java b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/SpongeForgeDependencyLocator.java index b73e593f3c6..4fa07561fdd 100644 --- a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/SpongeForgeDependencyLocator.java +++ b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/SpongeForgeDependencyLocator.java @@ -27,10 +27,8 @@ import cpw.mods.modlauncher.Environment; import cpw.mods.modlauncher.Launcher; import net.minecraftforge.fml.loading.FMLEnvironment; -import net.minecraftforge.fml.loading.moddiscovery.AbstractModProvider; import net.minecraftforge.forgespi.locating.IDependencyLocator; import net.minecraftforge.forgespi.locating.IModFile; -import net.minecraftforge.forgespi.locating.IModLocator; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.spongepowered.forge.applaunch.loading.moddiscovery.library.Log4JLogger; @@ -42,14 +40,13 @@ import java.util.List; import java.util.Map; -// works with ForgeProductionBootstrap to make this whole thing go public class SpongeForgeDependencyLocator extends AbstractModProvider implements IDependencyLocator { private static final Logger LOGGER = LogManager.getLogger(); private LibraryManager libraryManager; @Override - public List scanMods(Iterable loadedMods) { + public List scanMods(final Iterable loadedMods) { final List modFiles = new ArrayList<>(); // Add Sponge-specific libraries @@ -64,23 +61,13 @@ public List scanMods(Iterable loadedMods) { for (final LibraryManager.Library library : this.libraryManager.getAll("main")) { final Path path = library.file(); SpongeForgeDependencyLocator.LOGGER.debug("Proposing jar {} as a game library", path); - - final IModLocator.ModFileOrException fileOrException = createMod(path); - if (fileOrException.ex() != null) { - throw fileOrException.ex(); - } - modFiles.add(fileOrException.file()); + modFiles.add(PluginFileParser.newLibraryFile(this, path)); } } return modFiles; } - @Override - protected String getDefaultJarModType() { - return IModFile.Type.GAMELIBRARY.name(); - } - @Override public String name() { return "spongeforge"; diff --git a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/SpongeForgeModLocator.java b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/SpongeForgeModLocator.java index e7c704b506b..841f97069a7 100644 --- a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/SpongeForgeModLocator.java +++ b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/SpongeForgeModLocator.java @@ -28,20 +28,23 @@ import cpw.mods.modlauncher.Environment; import cpw.mods.modlauncher.Launcher; import net.minecraftforge.fml.loading.FMLEnvironment; -import net.minecraftforge.fml.loading.moddiscovery.AbstractModProvider; import net.minecraftforge.forgespi.locating.IModLocator; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.spongepowered.forge.applaunch.plugin.ForgePluginPlatform; +import java.io.File; import java.net.URI; import java.net.URL; import java.nio.file.FileSystem; import java.nio.file.FileSystems; import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.stream.Stream; public final class SpongeForgeModLocator extends AbstractModProvider implements IModLocator { private static final Logger LOGGER = LogManager.getLogger(); @@ -49,7 +52,19 @@ public final class SpongeForgeModLocator extends AbstractModProvider implements @Override public List scanMods() { if (!FMLEnvironment.production) { - return List.of(); + final List resources = new ArrayList<>(); + final String resourcesProp = System.getProperty("sponge.resources"); + if (resourcesProp != null) { + for (final String entry : resourcesProp.split(File.pathSeparator)) { + if (entry.isBlank()) { + continue; + } + + final Path[] paths = Stream.of(entry.split("&")).map(Path::of).toArray(Path[]::new); + resources.add(new ModFileOrException(PluginFileParser.newModFile(this, true, paths), null)); + } + } + return resources; } try { @@ -66,7 +81,7 @@ public List scanMods() { } catch (Exception e) { throw new RuntimeException(e); } - }).map(this::createMod).toList(); + }).map((path -> new ModFileOrException(PluginFileParser.newModFile(this, false, path), null))).toList(); } catch (Exception e) { LOGGER.error("Failed to scan mod candidates", e); } diff --git a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/locator/EnvironmentPluginLocator.java b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/locator/EnvironmentPluginLocator.java index e2903123f0d..a76911d39dd 100644 --- a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/locator/EnvironmentPluginLocator.java +++ b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/locator/EnvironmentPluginLocator.java @@ -24,15 +24,14 @@ */ package org.spongepowered.forge.applaunch.loading.moddiscovery.locator; -import net.minecraftforge.fml.loading.moddiscovery.AbstractModProvider; import net.minecraftforge.forgespi.locating.IModLocator; +import org.spongepowered.forge.applaunch.loading.moddiscovery.AbstractModProvider; import org.spongepowered.forge.applaunch.loading.moddiscovery.PluginFileParser; import java.nio.file.Path; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.Map; import java.util.stream.Stream; public final class EnvironmentPluginLocator extends AbstractModProvider implements IModLocator { @@ -41,25 +40,16 @@ public final class EnvironmentPluginLocator extends AbstractModProvider implemen public List scanMods() { final List modFiles = new ArrayList<>(); for (final Path[] paths : EnvironmentPluginLocator.getPluginsPaths()) { - modFiles.add(new ModFileOrException(PluginFileParser.newPluginInstance(this, paths), null)); + modFiles.add(new ModFileOrException(PluginFileParser.newModFile(this, false, paths), null)); } return modFiles; } - @Override - protected ModFileOrException createMod(Path path) { - return new ModFileOrException(PluginFileParser.newPluginInstance(this, path), null); - } - @Override public String name() { return "environment plugin"; } - @Override - public void initArguments(final Map arguments) { - } - private static List getPluginsPaths() { final String env = System.getenv("SPONGE_PLUGINS"); if (env == null) { diff --git a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/locator/PluginsDirectoryLocator.java b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/locator/PluginsDirectoryLocator.java index 4202f337b93..e0ed9845745 100644 --- a/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/locator/PluginsDirectoryLocator.java +++ b/forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/locator/PluginsDirectoryLocator.java @@ -27,12 +27,12 @@ import cpw.mods.modlauncher.api.LamdbaExceptionUtils; import net.minecraftforge.fml.loading.ModDirTransformerDiscoverer; import net.minecraftforge.fml.loading.StringUtils; -import net.minecraftforge.fml.loading.moddiscovery.AbstractModProvider; import net.minecraftforge.fml.loading.moddiscovery.ModFile; import net.minecraftforge.forgespi.locating.IModLocator; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.spongepowered.common.applaunch.AppLaunch; +import org.spongepowered.forge.applaunch.loading.moddiscovery.AbstractModProvider; import org.spongepowered.forge.applaunch.loading.moddiscovery.PluginFileParser; import java.nio.file.Files; @@ -40,7 +40,6 @@ import java.util.ArrayList; import java.util.Comparator; import java.util.List; -import java.util.Map; import java.util.stream.Stream; public final class PluginsDirectoryLocator extends AbstractModProvider implements IModLocator { @@ -60,12 +59,13 @@ public List scanMods() { return modFiles; } + @SuppressWarnings("UnstableApiUsage") private Stream scanForPluginsIn(final Path pluginsDirectory) { final List excluded = ModDirTransformerDiscoverer.allExcluded(); return LamdbaExceptionUtils.uncheck(() -> Files.list(pluginsDirectory)) .filter((p) -> !excluded.contains(p) && StringUtils.toLowerCase(p.getFileName().toString()).endsWith(".jar")) .sorted(Comparator.comparing((path) -> StringUtils.toLowerCase(path.getFileName().toString()))) - .map((p) -> PluginFileParser.newPluginInstance(this, p)) + .map((p) -> PluginFileParser.newModFile(this, false, p)) .filter(ModFile::identifyMods); } @@ -73,8 +73,4 @@ private Stream scanForPluginsIn(final Path pluginsDirectory) { public String name() { return "plugins directory"; } - - @Override - public void initArguments(final Map arguments) { - } } diff --git a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/locator/GameResourceLocatorService.java b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/locator/SpongePropertyLocatorService.java similarity index 93% rename from vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/locator/GameResourceLocatorService.java rename to vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/locator/SpongePropertyLocatorService.java index 0a1791fb459..19e5d2e8b4e 100644 --- a/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/locator/GameResourceLocatorService.java +++ b/vanilla/src/applaunch/java/org/spongepowered/vanilla/applaunch/plugin/locator/SpongePropertyLocatorService.java @@ -28,6 +28,7 @@ import org.spongepowered.plugin.builtin.jvm.JVMPluginResource; import org.spongepowered.plugin.builtin.jvm.locator.JVMPluginResourceLocatorService; +import java.io.File; import java.net.URI; import java.nio.file.FileSystem; import java.nio.file.FileSystems; @@ -37,11 +38,11 @@ import java.util.Set; import java.util.stream.Stream; -public final class GameResourceLocatorService implements JVMPluginResourceLocatorService { +public final class SpongePropertyLocatorService implements JVMPluginResourceLocatorService { @Override public String name() { - return "game"; + return "sponge_resources"; } @Override @@ -49,9 +50,9 @@ public Set locatePluginResources(final Environment environmen environment.logger().info("Locating '{}' resources...", this.name()); final Set resources = new HashSet<>(); - final String resourcesProp = System.getProperty("sponge.gameResources"); + final String resourcesProp = System.getProperty("sponge.resources"); if (resourcesProp != null) { - for (final String entry : resourcesProp.split(";")) { + for (final String entry : resourcesProp.split(File.pathSeparator)) { if (entry.isBlank()) { continue; } diff --git a/vanilla/src/applaunch/resources/META-INF/services/org.spongepowered.plugin.PluginResourceLocatorService b/vanilla/src/applaunch/resources/META-INF/services/org.spongepowered.plugin.PluginResourceLocatorService index 330fcb92be8..cf8cd29b6e7 100644 --- a/vanilla/src/applaunch/resources/META-INF/services/org.spongepowered.plugin.PluginResourceLocatorService +++ b/vanilla/src/applaunch/resources/META-INF/services/org.spongepowered.plugin.PluginResourceLocatorService @@ -1 +1 @@ -org.spongepowered.vanilla.applaunch.plugin.locator.GameResourceLocatorService \ No newline at end of file +org.spongepowered.vanilla.applaunch.plugin.locator.SpongePropertyLocatorService \ No newline at end of file diff --git a/vanilla/src/installer/java/org/spongepowered/vanilla/installer/InstallerMain.java b/vanilla/src/installer/java/org/spongepowered/vanilla/installer/InstallerMain.java index 9c36b84dd5e..370e4c18036 100644 --- a/vanilla/src/installer/java/org/spongepowered/vanilla/installer/InstallerMain.java +++ b/vanilla/src/installer/java/org/spongepowered/vanilla/installer/InstallerMain.java @@ -42,6 +42,7 @@ import org.spongepowered.vanilla.installer.model.mojang.VersionManifest; import org.tinylog.Logger; +import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -68,6 +69,7 @@ import java.util.Map; import java.util.Optional; import java.util.Set; +import java.util.StringJoiner; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.jar.JarFile; @@ -177,12 +179,11 @@ public void downloadAndRun() throws Exception { } } - final StringBuilder gameLibsEnv = new StringBuilder(); + final StringJoiner resourcesEnv = new StringJoiner(File.pathSeparator); for (final Path lib : gameLibs) { - gameLibsEnv.append(lib.toAbsolutePath()).append(';'); + resourcesEnv.add(lib.toAbsolutePath().toString()); } - gameLibsEnv.setLength(gameLibsEnv.length() - 1); - System.setProperty("sponge.gameResources", gameLibsEnv.toString()); + System.setProperty("sponge.resources", resourcesEnv.toString()); final List gameArgs = new ArrayList<>(LauncherCommandLine.remainingArgs); gameArgs.add("--launchTarget"); From 061dfd0e19f85cddb1b237e662c448696cdd4a87 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sat, 21 Dec 2024 21:24:52 +0100 Subject: [PATCH 04/11] Fix SpongeForge attack and furnace mixins --- ...AbstractFurnaceBlockEntityMixin_Forge.java | 24 ++++++++++--------- .../entity/LivingEntityMixin_Attack_Impl.java | 11 +++------ 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Forge.java index 34cab814694..5a8394cd809 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Forge.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/world/level/block/entity/AbstractFurnaceBlockEntityMixin_Forge.java @@ -27,10 +27,11 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.NonNullList; import net.minecraft.core.RegistryAccess; +import net.minecraft.server.level.ServerLevel; import net.minecraft.util.Mth; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.RecipeHolder; -import net.minecraft.world.level.Level; +import net.minecraft.world.item.crafting.SingleRecipeInput; import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity; import net.minecraft.world.level.block.state.BlockState; import org.objectweb.asm.Opcodes; @@ -69,7 +70,7 @@ public abstract class AbstractFurnaceBlockEntityMixin_Forge implements AbstractF // @formatter:off @Shadow protected NonNullList items; @Shadow int cookingProgress; - @Shadow private boolean shadow$canBurn(RegistryAccess registryAccess, @Nullable RecipeHolder recipe, NonNullList slots, int maxStackSize) { + @Shadow private boolean shadow$canBurn(RegistryAccess registryAccess, @Nullable RecipeHolder recipe, SingleRecipeInput input, NonNullList slots, int maxStackSize) { throw new UnsupportedOperationException("Shadowed canBurn"); } // @formatter:on @@ -79,15 +80,16 @@ public abstract class AbstractFurnaceBlockEntityMixin_Forge implements AbstractF // Tick up and Start @Redirect(method = "serverTick", at = @At(value = "INVOKE", - target = "Lnet/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity;canBurn(Lnet/minecraft/core/RegistryAccess;Lnet/minecraft/world/item/crafting/RecipeHolder;Lnet/minecraft/core/NonNullList;I)Z", + target = "Lnet/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity;canBurn(Lnet/minecraft/core/RegistryAccess;Lnet/minecraft/world/item/crafting/RecipeHolder;Lnet/minecraft/world/item/crafting/SingleRecipeInput;Lnet/minecraft/core/NonNullList;I)Z", ordinal = 1)) private static boolean forge$checkIfCanSmelt(final AbstractFurnaceBlockEntity entityIn, - final RegistryAccess registryAccess, - final RecipeHolder recipe, - final NonNullList slots, - final int maxStackSize) { + final RegistryAccess registryAccess, + final RecipeHolder recipe, + final SingleRecipeInput input, + final NonNullList slots, + final int maxStackSize) { final var entity = (AbstractFurnaceBlockEntityMixin_Forge) (Object) (entityIn); - if (!entity.shadow$canBurn(registryAccess, recipe, slots, maxStackSize)) { + if (!entity.shadow$canBurn(registryAccess, recipe, input, slots, maxStackSize)) { return false; } @@ -111,7 +113,7 @@ public abstract class AbstractFurnaceBlockEntityMixin_Forge implements AbstractF // Tick down @Redirect(method = "serverTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/Mth;clamp(III)I")) private static int forge$resetCookTimeIfCancelled(final int newCookTime, final int zero, final int totalCookTime, - final Level level, final BlockPos entityPos, final BlockState state, final AbstractFurnaceBlockEntity entityIn) { + final ServerLevel level, final BlockPos entityPos, final BlockState state, final AbstractFurnaceBlockEntity entityIn) { final int clampedCookTime = Mth.clamp(newCookTime, zero, totalCookTime); final var entity = (AbstractFurnaceBlockEntityMixin_Forge) (Object) entityIn; final ItemStackSnapshot fuel = ItemStackUtil.snapshotOf(entity.items.get(1)); @@ -133,7 +135,7 @@ public abstract class AbstractFurnaceBlockEntityMixin_Forge implements AbstractF slice = @Slice( from = @At(value = "FIELD", target = "Lnet/minecraft/world/level/block/Blocks;WET_SPONGE:Lnet/minecraft/world/level/block/Block;", opcode = Opcodes.GETSTATIC) )) - private void forge$captureBucketFill(final RegistryAccess registryAccess, final RecipeHolder recipe, final NonNullList slots, final int maxStackSize, final CallbackInfoReturnable cir) { + private void forge$captureBucketFill(final RegistryAccess registryAccess, final RecipeHolder recipe, final SingleRecipeInput input, final NonNullList slots, final int maxStackSize, final CallbackInfoReturnable cir) { this.forge$filledWaterBucket = true; } @@ -142,7 +144,7 @@ public abstract class AbstractFurnaceBlockEntityMixin_Forge implements AbstractF locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;shrink(I)V")) private void forge$afterSmeltItem( - final RegistryAccess registryAccess, final RecipeHolder recipe, + final RegistryAccess registryAccess, final RecipeHolder recipe, final SingleRecipeInput input, final NonNullList slots, final int maxStackSize, final CallbackInfoReturnable cir, final ItemStack itemIn, final ItemStack recipeResult, final ItemStack itemOut diff --git a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java index 8bce4b1a806..0835f4869de 100644 --- a/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java +++ b/src/mixins/java/org/spongepowered/common/mixin/core/world/entity/LivingEntityMixin_Attack_Impl.java @@ -43,7 +43,6 @@ import org.spongepowered.asm.mixin.injection.*; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import org.spongepowered.common.SpongeCommon; import org.spongepowered.common.bridge.world.entity.LivingEntityBridge; import org.spongepowered.common.event.tracking.PhaseTracker; @@ -170,14 +169,10 @@ public abstract class LivingEntityMixin_Attack_Impl extends EntityMixin implemen * After calling #actuallyHurt (even when invulnerable), if cancelled return early or is still invulnerable * and reset {@link #lastHurt} and {@link #invulnerableTime} */ - @Inject(method = "hurtServer", locals = LocalCapture.CAPTURE_FAILHARD, cancellable = true, + @Inject(method = "hurtServer", cancellable = true, at = @At(value = "INVOKE", shift = At.Shift.AFTER, ordinal = 0, target = "Lnet/minecraft/world/entity/LivingEntity;actuallyHurt(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;F)V")) - private void attackImpl$afterActuallyHurt1( - final ServerLevel level, final DamageSource source, final float damageTaken, - final CallbackInfoReturnable cir, final float dealtDamage, final boolean isBlocked, - float $$5, boolean wasHurt - ) { + private void attackImpl$afterActuallyHurt1(final ServerLevel level, final DamageSource source, final float damageTaken, final CallbackInfoReturnable cir) { if (this.attackImpl$actuallyHurtCancelled || damageTaken <= this.lastHurt) { this.invulnerableTime = this.attackImpl$InvulnerableTime; this.lastHurt = this.attackImpl$lastHurt; @@ -189,7 +184,7 @@ public abstract class LivingEntityMixin_Attack_Impl extends EntityMixin implemen * After calling #actuallyHurt, if cancelled return early * Also reset values */ - @Inject(method = "hurtServer",cancellable = true, + @Inject(method = "hurtServer", cancellable = true, at = @At(value = "INVOKE", shift = At.Shift.AFTER, ordinal = 1, target = "Lnet/minecraft/world/entity/LivingEntity;actuallyHurt(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;F)V")) private void attackImpl$afterActuallyHurt2(ServerLevel $$0, DamageSource $$1, float $$2, CallbackInfoReturnable cir) { From c644444f3b55c5cb1785060f3b9cead39d03c90f Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sun, 22 Dec 2024 17:28:39 +0100 Subject: [PATCH 05/11] Convert AW to AT for ForgeGradle --- build-logic/build.gradle | 5 + build-logic/settings.gradle | 9 +- .../gradle/impl/ConvertAWToAT.java | 109 ++++++++++++++++++ build.gradle.kts | 11 +- forge/build.gradle.kts | 12 +- generator/build.gradle.kts | 7 +- gradle/libs.versions.toml | 1 + neoforge/build.gradle.kts | 2 +- vanilla/build.gradle.kts | 11 +- 9 files changed, 140 insertions(+), 27 deletions(-) create mode 100644 build-logic/src/main/java/org/spongepowered/gradle/impl/ConvertAWToAT.java diff --git a/build-logic/build.gradle b/build-logic/build.gradle index 5cabd817724..1539cbfb1a6 100644 --- a/build-logic/build.gradle +++ b/build-logic/build.gradle @@ -13,6 +13,11 @@ indra { dependencies { api(apiLibs.gson) implementation("gradle.plugin.org.jetbrains.gradle.plugin.idea-ext:gradle-idea-ext:${apiLibs.versions.ideaExt.get()}") + implementation(libs.at) + implementation(libs.accessWidener) + + // arch-loom is used by SpongeNeo but must be declared here to avoid a classloader conflict with its transitive dependencies + api("dev.architectury:architectury-loom:1.6.411") } indraSpotlessLicenser { diff --git a/build-logic/settings.gradle b/build-logic/settings.gradle index 9e7a64e236c..3e53ae9cde4 100644 --- a/build-logic/settings.gradle +++ b/build-logic/settings.gradle @@ -9,7 +9,14 @@ pluginManagement { dependencyResolutionManagement { repositoriesMode = RepositoriesMode.FAIL_ON_PROJECT_REPOS - repositories { pluginManagement.repositories.each { add(it) } } + repositories { + pluginManagement.repositories.each { add(it) } + maven { + url = "https://maven.architectury.dev/" + name = "architectury" + } + } + versionCatalogs { libs { from files("../gradle/libs.versions.toml") diff --git a/build-logic/src/main/java/org/spongepowered/gradle/impl/ConvertAWToAT.java b/build-logic/src/main/java/org/spongepowered/gradle/impl/ConvertAWToAT.java new file mode 100644 index 00000000000..d3f1e05193d --- /dev/null +++ b/build-logic/src/main/java/org/spongepowered/gradle/impl/ConvertAWToAT.java @@ -0,0 +1,109 @@ +/* + * This file is part of Sponge, licensed under the MIT License (MIT). + * + * Copyright (c) SpongePowered + * Copyright (c) contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package org.spongepowered.gradle.impl; + +import dev.architectury.at.AccessChange; +import dev.architectury.at.AccessTransform; +import dev.architectury.at.AccessTransformSet; +import dev.architectury.at.ModifierChange; +import dev.architectury.at.io.AccessTransformFormats; +import net.fabricmc.accesswidener.AccessWidenerReader; +import net.fabricmc.accesswidener.AccessWidenerVisitor; +import org.cadixdev.bombe.type.signature.MethodSignature; +import org.gradle.api.DefaultTask; +import org.gradle.api.GradleException; +import org.gradle.api.file.ConfigurableFileCollection; +import org.gradle.api.file.RegularFileProperty; +import org.gradle.api.tasks.InputFiles; +import org.gradle.api.tasks.OutputFile; +import org.gradle.api.tasks.TaskAction; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.util.Set; + +public abstract class ConvertAWToAT extends DefaultTask { + + @InputFiles + public abstract ConfigurableFileCollection getAccessWideners(); + + public void accessWideners(Object... paths) { + this.getAccessWideners().from(paths); + } + + @OutputFile + public abstract RegularFileProperty getAccessTransformer(); + + @TaskAction + public void convert() { + final Set awFiles = this.getAccessWideners().getFiles(); + final File atFile = this.getAccessTransformer().get().getAsFile(); + + final AccessTransformSet at = AccessTransformSet.create(); + + for (final File awFile : awFiles) { + try (final BufferedReader reader = Files.newBufferedReader(awFile.toPath())) { + ConvertAWToAT.convert(reader, at); + } catch (final IOException e) { + throw new GradleException("Failed to read access widener: " + awFile, e); + } + } + + try (final BufferedWriter writer = Files.newBufferedWriter(atFile.toPath())) { + AccessTransformFormats.FML.write(writer, at); + } catch (IOException e) { + throw new GradleException("Failed to write access transformer: " + atFile, e); + } + } + + public static void convert(final BufferedReader reader, final AccessTransformSet at) throws IOException { + new AccessWidenerReader(new AccessWidenerVisitor() { + @Override + public void visitClass(final String name, final AccessWidenerReader.AccessType access, final boolean transitive) { + at.getOrCreateClass(name).merge(ConvertAWToAT.convertEntry(access)); + } + + @Override + public void visitMethod(final String owner, final String name, final String descriptor, final AccessWidenerReader.AccessType access, final boolean transitive) { + at.getOrCreateClass(owner).mergeMethod(MethodSignature.of(name, descriptor), ConvertAWToAT.convertEntry(access)); + } + + @Override + public void visitField(final String owner, final String name, final String descriptor, final AccessWidenerReader.AccessType access, final boolean transitive) { + at.getOrCreateClass(owner).mergeField(name, ConvertAWToAT.convertEntry(access)); + } + }).read(reader); + } + + public static AccessTransform convertEntry(final AccessWidenerReader.AccessType access) { + return switch (access) { + case ACCESSIBLE -> AccessTransform.of(AccessChange.PUBLIC); + case EXTENDABLE, MUTABLE -> AccessTransform.of(AccessChange.PUBLIC, ModifierChange.REMOVE); + }; + } +} diff --git a/build.gradle.kts b/build.gradle.kts index 936320ff20b..85ce26ad312 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -176,6 +176,10 @@ dependencies { } } +minecraft { + accessWideners(main.resources.filter { it.name.endsWith(".accesswidener") }) +} + allprojects { configurations.configureEach { resolutionStrategy.dependencySubstitution { @@ -199,13 +203,6 @@ allprojects { minecraft { version(minecraftVersion) injectRepositories(false) - project.sourceSets["main"].resources - .filter { it.name.endsWith(".accesswidener") } - .files - .forEach { - accessWideners(it) - parent?.minecraft?.accessWideners(it) - } } dependencies { diff --git a/forge/build.gradle.kts b/forge/build.gradle.kts index 99f42629fcd..3394d182ff7 100644 --- a/forge/build.gradle.kts +++ b/forge/build.gradle.kts @@ -1,5 +1,6 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar import net.minecraftforge.gradle.userdev.UserDevExtension +import org.spongepowered.gradle.impl.ConvertAWToAT buildscript { repositories { @@ -201,11 +202,17 @@ dependencies { runtimeOnly(project(bootstrapDevProject.path)) } +val convertAWToAT = tasks.register("convertAWToAT", ConvertAWToAT::class) { + accessWideners(main.get().resources.filter { it.name.endsWith(".accesswidener") }) + accessWideners(forgeMain.resources.filter { it.name.endsWith(".accesswidener") }) + accessTransformer.set(project.layout.buildDirectory.file("generated/resources/at.cfg")) +} + val mixinConfigs: MutableSet = spongeImpl.mixinConfigurations extensions.configure(UserDevExtension::class) { mappings("official", "1.21.3") - // accessWidenerPath.set(file("../src/main/resources/common.accesswidener")) TODO + accessTransformers.from(convertAWToAT.flatMap { it.accessTransformer }) reobf = false @@ -213,8 +220,7 @@ extensions.configure(UserDevExtension::class) { configureEach { ideaModule("Sponge.SpongeForge.main") - property("forge.logging.markers", "REGISTRIES") - property("forge.logging.console.level", "debug") + // property("forge.logging.console.level", "debug") // jvmArgs("-Dbsl.debug=true") // Uncomment to debug bootstrap classpath diff --git a/generator/build.gradle.kts b/generator/build.gradle.kts index 6481b69c15c..da7ca6bedc2 100644 --- a/generator/build.gradle.kts +++ b/generator/build.gradle.kts @@ -5,12 +5,7 @@ plugins { description = "Code generator for automatically producing API catalog classes based off of Vanilla MC data" minecraft { - rootProject.sourceSets["main"].resources - .filter { it.name.endsWith(".accesswidener") } - .files - .forEach { - accessWideners(it) - } + accessWideners(rootProject.sourceSets["main"].resources.filter { it.name.endsWith(".accesswidener") }) } configurations.configureEach { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index cbc47e0b08d..d2eca4aaf9b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -68,6 +68,7 @@ terminalConsoleAppender = { module = "net.minecrell:terminalconsoleappender", ve # buildtime-only vineflower = { module = "org.vineflower:vineflower", version.ref = "vineflower" } +at = { module = "dev.architectury:at", version = "1.0.1" } [plugins] blossom = { id = "net.kyori.blossom", version = "2.1.0" } diff --git a/neoforge/build.gradle.kts b/neoforge/build.gradle.kts index 9cd699e0d03..96e95d67d69 100644 --- a/neoforge/build.gradle.kts +++ b/neoforge/build.gradle.kts @@ -14,7 +14,7 @@ plugins { alias(libs.plugins.shadow) id("implementation-structure") alias(libs.plugins.blossom) - id("dev.architectury.loom") version "1.6.411" + id("dev.architectury.loom") } val commonProject = parent!! diff --git a/vanilla/build.gradle.kts b/vanilla/build.gradle.kts index 00ac01e6f6c..90595bb3a29 100644 --- a/vanilla/build.gradle.kts +++ b/vanilla/build.gradle.kts @@ -126,15 +126,8 @@ val superclassConfigs = spongeImpl.getNamedConfigurations("superClassChanges") val mixinConfigs = spongeImpl.mixinConfigurations minecraft { - main.get().resources - .filter { it.name.endsWith(".accesswidener") } - .files - .forEach { accessWideners(it) } - - vanillaMain.resources - .filter { it.name.endsWith(".accesswidener") } - .files - .forEach { accessWideners(it) } + accessWideners(main.get().resources.filter { it.name.endsWith(".accesswidener") }) + accessWideners(vanillaMain.resources.filter { it.name.endsWith(".accesswidener") }) } configurations.configureEach { From cd0ea4ab3ec705e9629887e8130a5e8b421472a7 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sun, 22 Dec 2024 20:10:34 +0100 Subject: [PATCH 06/11] Load test plugins on SpongeForge --- .../dev/SpongeDevClasspathFixer.java | 44 ++++++++++--------- forge/build.gradle.kts | 18 ++------ .../applaunch/resources/META-INF/MANIFEST.MF | 1 + forge/src/lang/resources/META-INF/MANIFEST.MF | 2 + library-manager/build.gradle.kts | 8 ++++ .../src/main/resources/META-INF/MANIFEST.MF | 1 + modlauncher-transformers/build.gradle.kts | 2 +- .../src/main/resources/META-INF/MANIFEST.MF | 2 +- 8 files changed, 42 insertions(+), 36 deletions(-) create mode 100644 forge/src/applaunch/resources/META-INF/MANIFEST.MF create mode 100644 forge/src/lang/resources/META-INF/MANIFEST.MF create mode 100644 library-manager/src/main/resources/META-INF/MANIFEST.MF diff --git a/bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/SpongeDevClasspathFixer.java b/bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/SpongeDevClasspathFixer.java index e1630913203..1fc983100b0 100644 --- a/bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/SpongeDevClasspathFixer.java +++ b/bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/SpongeDevClasspathFixer.java @@ -53,11 +53,12 @@ public boolean process(final List classpath) { final Set bootLibs = Set.of(System.getProperty("sponge.dev.boot").split(File.pathSeparator)); final Set gameShadedLibs = Set.of(System.getProperty("sponge.dev.gameShaded").split(File.pathSeparator)); - final Multimap bootSourceSets = new Multimap<>(); - final Multimap unknownProjects = new Multimap<>(); + // boot layer + final Multimap bootUnions = new Multimap<>(); - final List spongeImplUnion = new ArrayList<>(); - final List gameLibs = new ArrayList<>(); + // game or plugin layer + final Multimap unions = new Multimap<>(); + final List libs = new ArrayList<>(); final AtomicBoolean hasAPISourceSet = new AtomicBoolean(false); @@ -78,7 +79,7 @@ public boolean process(final List classpath) { // ignore break; case "modlauncher-transformers", "library-manager": - bootSourceSets.add(sourceSet.project(), path); + bootUnions.add(sourceSet.project(), path); break; case "SpongeAPI": switch (sourceSet.name()) { @@ -89,19 +90,25 @@ public boolean process(final List classpath) { hasAPISourceSet.set(true); // no break default: - spongeImplUnion.add(path); + unions.add("sponge", path); break; } break; case "Sponge", "vanilla", "forge": - if (sourceSet.name().equals("applaunch")) { - bootSourceSets.add("applaunch", path); - } else { - spongeImplUnion.add(path); + switch (sourceSet.name()) { + case "applaunch": + bootUnions.add("applaunch", path); + break; + case "lang": + unions.add("lang", path); + break; + default: + unions.add("sponge", path); + break; } break; default: - unknownProjects.add(sourceSet.project(), path); + unions.add(sourceSet.project(), path); break; } return true; @@ -127,14 +134,14 @@ public boolean process(final List classpath) { if (DEBUG) { System.out.println("Sponge: " + path); } - spongeImplUnion.add(path); + unions.add("sponge", path); return true; } if (DEBUG) { System.out.println("Game: " + path); } - gameLibs.add(path); + libs.add(path); return true; }); @@ -142,12 +149,12 @@ public boolean process(final List classpath) { return false; } - for (final List sourceSets : bootSourceSets.values()) { + for (final List sourceSets : bootUnions.values()) { classpath.add(sourceSets.toArray(Path[]::new)); } if (hasAPISourceSet.get()) { - spongeImplUnion.removeIf((path) -> { + unions.get("sponge").removeIf((path) -> { if (Files.isRegularFile(path)) { final String fileName = path.getFileName().toString(); if (fileName.startsWith("spongeapi") && fileName.endsWith(".jar")) { @@ -162,18 +169,15 @@ public boolean process(final List classpath) { } final StringBuilder resourcesEnvBuilder = new StringBuilder(); - for (final Path resource : gameLibs) { + for (final Path resource : libs) { resourcesEnvBuilder.append(resource).append(File.pathSeparator); } - for (final List project : unknownProjects.values()) { + for (final List project : unions.values()) { for (final Path resource : project) { resourcesEnvBuilder.append(resource).append('&'); } resourcesEnvBuilder.setCharAt(resourcesEnvBuilder.length() - 1, File.pathSeparatorChar); } - for (final Path resource : spongeImplUnion) { - resourcesEnvBuilder.append(resource).append('&'); - } resourcesEnvBuilder.setLength(resourcesEnvBuilder.length() - 1); final String resourcesEnv = resourcesEnvBuilder.toString(); diff --git a/forge/build.gradle.kts b/forge/build.gradle.kts index 3394d182ff7..b3a90619a7b 100644 --- a/forge/build.gradle.kts +++ b/forge/build.gradle.kts @@ -145,6 +145,7 @@ val forgeMain by sourceSets.named("main") { // The rest of the project because we want everything in the initial classpath spongeImpl.addDependencyToRuntimeOnly(mixins.get(), this) spongeImpl.addDependencyToRuntimeOnly(forgeMixins, this) + spongeImpl.addDependencyToRuntimeOnly(forgeLang, this) } configurations.configureEach { @@ -200,6 +201,9 @@ dependencies { } runtimeOnly(project(bootstrapDevProject.path)) + testPluginsProject?.also { + runtimeOnly(project(it.path)) + } } val convertAWToAT = tasks.register("convertAWToAT", ConvertAWToAT::class) { @@ -299,20 +303,6 @@ tasks { from(forgeLang.output) } - val forgeServicesJar by registering(Jar::class) { - archiveClassifier.set("services") - - manifest { - from(forgeManifest) - attributes("Automatic-Module-Name" to "spongeforge.services") - } - - from(commonProject.sourceSets.named("applaunch").map { it.output }) - from(forgeAppLaunch.output) - - duplicatesStrategy = DuplicatesStrategy.WARN - } - val installerResources = project.layout.buildDirectory.dir("generated/resources/installer") forgeAppLaunch.resources.srcDir(installerResources) diff --git a/forge/src/applaunch/resources/META-INF/MANIFEST.MF b/forge/src/applaunch/resources/META-INF/MANIFEST.MF new file mode 100644 index 00000000000..c54a634b615 --- /dev/null +++ b/forge/src/applaunch/resources/META-INF/MANIFEST.MF @@ -0,0 +1 @@ +Automatic-Module-Name: spongeforge.services diff --git a/forge/src/lang/resources/META-INF/MANIFEST.MF b/forge/src/lang/resources/META-INF/MANIFEST.MF new file mode 100644 index 00000000000..8e85d7c5e2a --- /dev/null +++ b/forge/src/lang/resources/META-INF/MANIFEST.MF @@ -0,0 +1,2 @@ +Automatic-Module-Name: spongeforge.lang +FMLModType: LANGPROVIDER diff --git a/library-manager/build.gradle.kts b/library-manager/build.gradle.kts index e2a23945059..11fc683e50f 100644 --- a/library-manager/build.gradle.kts +++ b/library-manager/build.gradle.kts @@ -1,3 +1,11 @@ dependencies { implementation(apiLibs.gson) } + +tasks { + jar { + manifest { + attributes("Automatic-Module-Name" to "sponge.library_manager") + } + } +} diff --git a/library-manager/src/main/resources/META-INF/MANIFEST.MF b/library-manager/src/main/resources/META-INF/MANIFEST.MF new file mode 100644 index 00000000000..68336aaf212 --- /dev/null +++ b/library-manager/src/main/resources/META-INF/MANIFEST.MF @@ -0,0 +1 @@ +Automatic-Module-Name: sponge.library_manager diff --git a/modlauncher-transformers/build.gradle.kts b/modlauncher-transformers/build.gradle.kts index 390fab762bd..ab8303b3673 100644 --- a/modlauncher-transformers/build.gradle.kts +++ b/modlauncher-transformers/build.gradle.kts @@ -31,7 +31,7 @@ dependencies { tasks { jar { manifest { - attributes("Automatic-Module-Name" to "sponge.modlauncher.transformers") + attributes("Automatic-Module-Name" to "sponge.modlauncher_transformers") } } } diff --git a/modlauncher-transformers/src/main/resources/META-INF/MANIFEST.MF b/modlauncher-transformers/src/main/resources/META-INF/MANIFEST.MF index 0a1e1f7343d..8e5fb5b07e5 100644 --- a/modlauncher-transformers/src/main/resources/META-INF/MANIFEST.MF +++ b/modlauncher-transformers/src/main/resources/META-INF/MANIFEST.MF @@ -1 +1 @@ -Automatic-Module-Name: sponge.modlauncher.transformers +Automatic-Module-Name: sponge.modlauncher_transformers From fe195a7911ce2a22bc9a65e0d051039898c850ba Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sun, 22 Dec 2024 20:11:41 +0100 Subject: [PATCH 07/11] Fix branding mixin on Forge --- .../internal/BrandingControlMixin_Forge.java | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/internal/BrandingControlMixin_Forge.java b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/internal/BrandingControlMixin_Forge.java index 841f6ba78ea..c92ec5c3b54 100644 --- a/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/internal/BrandingControlMixin_Forge.java +++ b/forge/src/mixins/java/org/spongepowered/forge/mixin/core/minecraftforge/internal/BrandingControlMixin_Forge.java @@ -36,16 +36,7 @@ public abstract class BrandingControlMixin_Forge { * @reason This is also not Kansas anymore */ @Overwrite - public static String getClientBranding() { - return "forge/spongeforge"; - } - - /** - * @author Zidane - * @reason What that said above - */ - @Overwrite - public static String getServerBranding() { + public static String getBranding() { return "forge/spongeforge"; } } From 2321a693d786747780c78a6289c5f2b1c84e1aeb Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Sun, 22 Dec 2024 20:30:09 +0100 Subject: [PATCH 08/11] Update verification metadata --- gradle/verification-metadata.xml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 328daf4d49e..2cf4b8bf80a 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -6,6 +6,7 @@ + @@ -2286,6 +2287,14 @@ + + + + + + + + From 52c4d263c6063fcbdcae78e6948df97cb1c343d6 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Mon, 23 Dec 2024 22:24:11 +0100 Subject: [PATCH 09/11] Fix dev classpath when root directory is not "Sponge" --- .../bootstrap/dev/SourceSet.java | 30 ++++--- .../dev/SpongeDevClasspathFixer.java | 89 +++++++++++-------- forge/build.gradle.kts | 1 + vanilla/build.gradle.kts | 1 + 4 files changed, 68 insertions(+), 53 deletions(-) diff --git a/bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/SourceSet.java b/bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/SourceSet.java index 540c752afcc..badeb5407dc 100644 --- a/bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/SourceSet.java +++ b/bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/SourceSet.java @@ -29,7 +29,7 @@ import java.util.ArrayList; import java.util.List; -public record SourceSet(String project, String name, String format) { +public record SourceSet(Path project, String name, String format) { @Override public String toString() { @@ -57,32 +57,34 @@ public static SourceSet identify(Path path) { } // from right to left - final List parts = new ArrayList<>(); + final List names = new ArrayList<>(); + final List paths = new ArrayList<>(); while (path != null) { - parts.add(path.getFileName().toString()); - if (parts.size() >= 5) { + names.add(path.getFileName().toString()); + paths.add(path); + if (names.size() >= 5) { break; } path = path.getParent(); } - if (parts.size() >= 4 && (parts.get(0).equals("classes") || parts.get(0).equals("resources"))) { - final String name = parts.get(1); - return new SourceSet(parts.get(3), name.equals("production") ? "main" : name, "IntelliJ"); + if (names.size() >= 4 && (names.get(0).equals("classes") || names.get(0).equals("resources"))) { + final String name = names.get(1); + return new SourceSet(paths.get(3), name.equals("production") ? "main" : name, "IntelliJ"); } - if (parts.size() >= 4 && (parts.get(1).equals("resources") || parts.get(1).equals("generated"))) { - return new SourceSet(parts.get(3), parts.get(0), "Gradle"); + if (names.size() >= 4 && (names.get(1).equals("resources") || names.get(1).equals("generated"))) { + return new SourceSet(paths.get(3), names.get(0), "Gradle"); } - if (parts.size() >= 5 && parts.get(2).equals("classes")) { - return new SourceSet(parts.get(4), parts.get(0), "Gradle"); + if (names.size() >= 5 && names.get(2).equals("classes")) { + return new SourceSet(paths.get(4), names.get(0), "Gradle"); } - if (parts.size() >= 3 && parts.get(1).equals("bin")) { - return new SourceSet(parts.get(2), parts.get(0), "Eclipse"); + if (names.size() >= 3 && names.get(1).equals("bin")) { + return new SourceSet(paths.get(2), names.get(0), "Eclipse"); } - return new SourceSet("", parts.get(0), "Unknown"); + return new SourceSet(paths.get(0), "?", "Unknown"); } } diff --git a/bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/SpongeDevClasspathFixer.java b/bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/SpongeDevClasspathFixer.java index 1fc983100b0..ab566c5f915 100644 --- a/bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/SpongeDevClasspathFixer.java +++ b/bootstrap-dev/src/main/java/org/spongepowered/bootstrap/dev/SpongeDevClasspathFixer.java @@ -29,6 +29,7 @@ import java.io.File; import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; import java.util.Set; @@ -49,6 +50,7 @@ public String name() { */ @Override public boolean process(final List classpath) { + final Path spongeRoot = Paths.get(System.getProperty("sponge.dev.root")).toAbsolutePath(); final Set ignoredLibs = Set.of("bootstrap-dev.jar"); final Set bootLibs = Set.of(System.getProperty("sponge.dev.boot").split(File.pathSeparator)); final Set gameShadedLibs = Set.of(System.getProperty("sponge.dev.gameShaded").split(File.pathSeparator)); @@ -70,46 +72,55 @@ public boolean process(final List classpath) { final Path path = paths[0]; final SourceSet sourceSet = SourceSet.identify(path); if (sourceSet != null) { - if (DEBUG) { - System.out.println("SourceSet (" + sourceSet + "): " + path); - } + if (sourceSet.project().startsWith(spongeRoot)) { + if (DEBUG) { + System.out.println("Sponge SourceSet (" + sourceSet + "): " + path); + } - switch (sourceSet.project()) { - case "bootstrap-dev": - // ignore - break; - case "modlauncher-transformers", "library-manager": - bootUnions.add(sourceSet.project(), path); - break; - case "SpongeAPI": - switch (sourceSet.name()) { - case "ap": - // ignore - break; - case "main": - hasAPISourceSet.set(true); - // no break - default: - unions.add("sponge", path); - break; - } - break; - case "Sponge", "vanilla", "forge": - switch (sourceSet.name()) { - case "applaunch": - bootUnions.add("applaunch", path); - break; - case "lang": - unions.add("lang", path); - break; - default: - unions.add("sponge", path); - break; - } - break; - default: - unions.add(sourceSet.project(), path); - break; + final String projectName = spongeRoot.relativize(sourceSet.project()).toString(); + switch (projectName) { + case "bootstrap-dev": + // ignore + break; + case "modlauncher-transformers", "library-manager": + bootUnions.add(projectName, path); + break; + case "SpongeAPI": + switch (sourceSet.name()) { + case "ap": + // ignore + break; + case "main": + hasAPISourceSet.set(true); + // no break + default: + unions.add("sponge", path); + break; + } + break; + case "", "vanilla", "forge": + switch (sourceSet.name()) { + case "applaunch": + bootUnions.add("applaunch", path); + break; + case "lang": + unions.add("lang", path); + break; + default: + unions.add("sponge", path); + break; + } + break; + default: + unions.add(projectName, path); + break; + } + } else { + if (DEBUG) { + System.out.println("External SourceSet (" + sourceSet + "): " + path); + } + + unions.add(sourceSet.project().toString(), path); } return true; } diff --git a/forge/build.gradle.kts b/forge/build.gradle.kts index b3a90619a7b..c973f13168e 100644 --- a/forge/build.gradle.kts +++ b/forge/build.gradle.kts @@ -247,6 +247,7 @@ afterEvaluate { val bootFileNames = spongeImpl.buildRuntimeFileNames(serviceLayerConfig.get()) // service in boot during dev val gameShadedFileNames = spongeImpl.buildRuntimeFileNames(gameShadedLibrariesConfig.get()) runs.configureEach { + jvmArgs("-Dsponge.dev.root=" + project.rootDir) jvmArgs("-Dsponge.dev.boot=$bootFileNames") jvmArgs("-Dsponge.dev.gameShaded=$gameShadedFileNames") } diff --git a/vanilla/build.gradle.kts b/vanilla/build.gradle.kts index 90595bb3a29..27fc697f86c 100644 --- a/vanilla/build.gradle.kts +++ b/vanilla/build.gradle.kts @@ -301,6 +301,7 @@ minecraft { // jvmArgs("-Dbsl.debug=true") // Uncomment to debug bootstrap classpath mainClass("net.minecraftforge.bootstrap.ForgeBootstrap") + jvmArgs("-Dsponge.dev.root=" + project.rootDir) jvmArgs("-Dsponge.dev.boot=$bootFileNames") jvmArgs("-Dsponge.dev.gameShaded=$gameShadedFileNames") } From cd1052a11acbd12097c8c28fcc6b16ee53ffc565 Mon Sep 17 00:00:00 2001 From: Yeregorix Date: Tue, 24 Dec 2024 22:24:22 +0100 Subject: [PATCH 10/11] Generate access transformer during Gradle configuration phase --- .../impl/{ConvertAWToAT.java => AWToAT.java} | 42 +++++++------------ forge/build.gradle.kts | 15 +++---- 2 files changed, 19 insertions(+), 38 deletions(-) rename build-logic/src/main/java/org/spongepowered/gradle/impl/{ConvertAWToAT.java => AWToAT.java} (72%) diff --git a/build-logic/src/main/java/org/spongepowered/gradle/impl/ConvertAWToAT.java b/build-logic/src/main/java/org/spongepowered/gradle/impl/AWToAT.java similarity index 72% rename from build-logic/src/main/java/org/spongepowered/gradle/impl/ConvertAWToAT.java rename to build-logic/src/main/java/org/spongepowered/gradle/impl/AWToAT.java index d3f1e05193d..da782c13dc6 100644 --- a/build-logic/src/main/java/org/spongepowered/gradle/impl/ConvertAWToAT.java +++ b/build-logic/src/main/java/org/spongepowered/gradle/impl/AWToAT.java @@ -32,43 +32,27 @@ import net.fabricmc.accesswidener.AccessWidenerReader; import net.fabricmc.accesswidener.AccessWidenerVisitor; import org.cadixdev.bombe.type.signature.MethodSignature; -import org.gradle.api.DefaultTask; import org.gradle.api.GradleException; -import org.gradle.api.file.ConfigurableFileCollection; -import org.gradle.api.file.RegularFileProperty; -import org.gradle.api.tasks.InputFiles; -import org.gradle.api.tasks.OutputFile; -import org.gradle.api.tasks.TaskAction; +import org.gradle.api.logging.Logger; +import org.gradle.api.logging.Logging; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.IOException; import java.nio.file.Files; -import java.util.Set; -public abstract class ConvertAWToAT extends DefaultTask { +public class AWToAT { + private static final Logger logger = Logging.getLogger(AWToAT.class); - @InputFiles - public abstract ConfigurableFileCollection getAccessWideners(); - - public void accessWideners(Object... paths) { - this.getAccessWideners().from(paths); - } - - @OutputFile - public abstract RegularFileProperty getAccessTransformer(); - - @TaskAction - public void convert() { - final Set awFiles = this.getAccessWideners().getFiles(); - final File atFile = this.getAccessTransformer().get().getAsFile(); + public static void convert(final Iterable awFiles, final File atFile) { + AWToAT.logger.lifecycle("Converting AWs {} to AT {} ...", awFiles, atFile); final AccessTransformSet at = AccessTransformSet.create(); for (final File awFile : awFiles) { try (final BufferedReader reader = Files.newBufferedReader(awFile.toPath())) { - ConvertAWToAT.convert(reader, at); + AWToAT.convert(reader, at); } catch (final IOException e) { throw new GradleException("Failed to read access widener: " + awFile, e); } @@ -79,28 +63,30 @@ public void convert() { } catch (IOException e) { throw new GradleException("Failed to write access transformer: " + atFile, e); } + + AWToAT.logger.lifecycle("Converted AWs to AT."); } - public static void convert(final BufferedReader reader, final AccessTransformSet at) throws IOException { + private static void convert(final BufferedReader reader, final AccessTransformSet at) throws IOException { new AccessWidenerReader(new AccessWidenerVisitor() { @Override public void visitClass(final String name, final AccessWidenerReader.AccessType access, final boolean transitive) { - at.getOrCreateClass(name).merge(ConvertAWToAT.convertEntry(access)); + at.getOrCreateClass(name).merge(AWToAT.convertEntry(access)); } @Override public void visitMethod(final String owner, final String name, final String descriptor, final AccessWidenerReader.AccessType access, final boolean transitive) { - at.getOrCreateClass(owner).mergeMethod(MethodSignature.of(name, descriptor), ConvertAWToAT.convertEntry(access)); + at.getOrCreateClass(owner).mergeMethod(MethodSignature.of(name, descriptor), AWToAT.convertEntry(access)); } @Override public void visitField(final String owner, final String name, final String descriptor, final AccessWidenerReader.AccessType access, final boolean transitive) { - at.getOrCreateClass(owner).mergeField(name, ConvertAWToAT.convertEntry(access)); + at.getOrCreateClass(owner).mergeField(name, AWToAT.convertEntry(access)); } }).read(reader); } - public static AccessTransform convertEntry(final AccessWidenerReader.AccessType access) { + private static AccessTransform convertEntry(final AccessWidenerReader.AccessType access) { return switch (access) { case ACCESSIBLE -> AccessTransform.of(AccessChange.PUBLIC); case EXTENDABLE, MUTABLE -> AccessTransform.of(AccessChange.PUBLIC, ModifierChange.REMOVE); diff --git a/forge/build.gradle.kts b/forge/build.gradle.kts index c973f13168e..34ba73d2a51 100644 --- a/forge/build.gradle.kts +++ b/forge/build.gradle.kts @@ -1,6 +1,6 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar import net.minecraftforge.gradle.userdev.UserDevExtension -import org.spongepowered.gradle.impl.ConvertAWToAT +import org.spongepowered.gradle.impl.AWToAT buildscript { repositories { @@ -206,18 +206,15 @@ dependencies { } } -val convertAWToAT = tasks.register("convertAWToAT", ConvertAWToAT::class) { - accessWideners(main.get().resources.filter { it.name.endsWith(".accesswidener") }) - accessWideners(forgeMain.resources.filter { it.name.endsWith(".accesswidener") }) - accessTransformer.set(project.layout.buildDirectory.file("generated/resources/at.cfg")) -} +val awFiles: Set = files(main.get().resources, forgeMain.resources).filter { it.name.endsWith(".accesswidener") }.files +val atFile = project.layout.buildDirectory.file("generated/resources/at.cfg").get().asFile +AWToAT.convert(awFiles, atFile) val mixinConfigs: MutableSet = spongeImpl.mixinConfigurations extensions.configure(UserDevExtension::class) { mappings("official", "1.21.3") - accessTransformers.from(convertAWToAT.flatMap { it.accessTransformer }) - + accessTransformers.from(atFile) reobf = false runs { @@ -225,11 +222,9 @@ extensions.configure(UserDevExtension::class) { ideaModule("Sponge.SpongeForge.main") // property("forge.logging.console.level", "debug") - // jvmArgs("-Dbsl.debug=true") // Uncomment to debug bootstrap classpath args(mixinConfigs.flatMap { sequenceOf("--mixin.config", it) }) - environment("MOD_CLASSES", "nop") } From 88778c3405ec9e8f902f96dfc5bbe27a55e74d28 Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Wed, 25 Dec 2024 22:31:30 -0800 Subject: [PATCH 11/11] feat: enable forge 1.21.3 --- .github/workflows/deploy.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml index 5b6b154fd91..dc10e45473e 100644 --- a/.github/workflows/deploy.yaml +++ b/.github/workflows/deploy.yaml @@ -29,13 +29,13 @@ jobs: matrix: project: - vanilla -# - forge + - forge - neoforge include: - project: vanilla gradleProject: SpongeVanilla -# - project: forge -# gradleProject: SpongeForge + - project: forge + gradleProject: SpongeForge - project: neoforge gradleProject: SpongeNeo steps: