diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8fc3827..405c477 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -4,26 +4,52 @@ # against bad commits. name: build -on: [pull_request, push] + +on: + pull_request: + paths: &build_paths + - '.github/workflows/build.yml' + - 'build.gradle' + - 'gradle.properties' + - 'gradle/**' + - 'gradlew' + - 'gradlew.bat' + - 'settings.gradle' + - 'src/**' + + push: + branches: [main] + paths: *build_paths + +concurrency: + group: "java-build-${{ github.ref }}" + cancel-in-progress: true jobs: build: - runs-on: ubuntu-24.04 + strategy: + matrix: + # Use these Java versions + java: [ + 25, # Current Java LTS + ] + runs-on: ubuntu-latest steps: - name: checkout repository uses: actions/checkout@v4 - name: validate gradle wrapper - uses: gradle/actions/wrapper-validation@v4 - - name: setup jdk + uses: gradle/wrapper-validation-action@v2 + - name: setup jdk ${{ matrix.java }} uses: actions/setup-java@v4 with: - java-version: '21' + java-version: ${{ matrix.java }} distribution: 'microsoft' - name: make gradle wrapper executable run: chmod +x ./gradlew - name: build run: ./gradlew build - name: capture build artifacts + if: ${{ matrix.java == '25' }} # Only upload artefacts built from latest java uses: actions/upload-artifact@v4 with: name: Artifacts diff --git a/build.gradle b/build.gradle index b81a0e2..92cd4c7 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ plugins { - id 'fabric-loom' version "${loom_version}" + id 'net.fabricmc.fabric-loom' version "${loom_version}" id 'maven-publish' } @@ -21,11 +21,11 @@ repositories { dependencies { // To change the versions see the gradle.properties file minecraft "com.mojang:minecraft:${project.minecraft_version}" - mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" - modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" + implementation "net.fabricmc:fabric-loader:${project.loader_version}" // Fabric API. This is technically optional, but you probably want it anyway. - modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" + // NOTE: Not all projects use Fabric API, but there's no telling that we won't need it later. + implementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_api_version}" } @@ -38,17 +38,14 @@ processResources { } tasks.withType(JavaCompile).configureEach { - it.options.release = 21 + it.options.release = 25 } java { - // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task - // if it is present. - // If you remove this line, sources will not be generated. withSourcesJar() - sourceCompatibility = JavaVersion.VERSION_21 - targetCompatibility = JavaVersion.VERSION_21 + sourceCompatibility = JavaVersion.VERSION_25 + targetCompatibility = JavaVersion.VERSION_25 } jar { @@ -68,11 +65,7 @@ publishing { } } - // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing. repositories { // Add repositories to publish to here. - // Notice: This block does NOT have the same function as the block in the top level. - // The repositories here will be used for publishing your artifact, not for - // retrieving dependencies. } } \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index b695fa3..66092a5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,21 +1,18 @@ -# Done to increase the memory available to gradle. -org.gradle.jvmargs=-Xmx1G +# Done to increase the memory available to Gradle. +org.gradle.jvmargs=-Xmx2G org.gradle.parallel=true -# IntelliJ IDEA is not yet fully compatible with configuration cache, see: https://github.com/FabricMC/fabric-loom/issues/1349 -org.gradle.configuration-cache=false - # Fabric Properties # check these on https://fabricmc.net/develop -minecraft_version=1.21.10 -yarn_mappings=1.21.10+build.2 -loader_version=0.17.3 -loom_version=1.12-SNAPSHOT + +minecraft_version=26.1-snapshot-6 +loader_version=0.18.4 +loom_version=1.15-SNAPSHOT # Mod Properties -mod_version=1.0.0+1.21.10 +mod_version=1.0.1-beta+26.1-snapshots_fabric maven_group=me.imgalvin archives_base_name=auto-lan # Dependencies -fabric_version=0.137.0+1.21.10 \ No newline at end of file +fabric_api_version=0.143.2+26.1 \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index d4081da..19a6bde 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.0-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/src/main/java/me/imgalvin/Autolan.java b/src/main/java/me/imgalvin/Autolan.java index f2cd263..98ee6a5 100644 --- a/src/main/java/me/imgalvin/Autolan.java +++ b/src/main/java/me/imgalvin/Autolan.java @@ -1,29 +1,16 @@ package me.imgalvin; import net.fabricmc.api.ClientModInitializer; -import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; -import net.minecraft.server.integrated.IntegratedServer; -import net.minecraft.text.Text; -import net.minecraft.world.GameMode; -import static net.minecraft.util.NetworkUtils.findLocalPort; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class Autolan implements ClientModInitializer { - private boolean opened = false; + public static final String MOD_ID = "AutoLan"; + public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID); @Override public void onInitializeClient() { - ClientTickEvents.END_CLIENT_TICK.register(client -> { - if (!opened && client.player != null && client.getServer() != null) { - IntegratedServer server = client.getServer(); - - if (server.isSingleplayer()) { - int port = findLocalPort(); - server.openToLan(GameMode.CREATIVE, true, port); - client.player.sendMessage(Text.of("§aOpened to LAN on port " + port), false); - opened = true; - } - } - }); + LOGGER.info("AutoLan initialized!"); } } diff --git a/src/main/java/me/imgalvin/Mixin/PublishLANServerMixin.java b/src/main/java/me/imgalvin/Mixin/PublishLANServerMixin.java new file mode 100644 index 0000000..2b002a4 --- /dev/null +++ b/src/main/java/me/imgalvin/Mixin/PublishLANServerMixin.java @@ -0,0 +1,68 @@ +package me.imgalvin.Mixin; + +import net.minecraft.client.Minecraft; +import net.minecraft.network.chat.Component; +import net.minecraft.server.MinecraftServer; +import net.minecraft.util.HttpUtil; +import net.minecraft.world.level.GameType; +import org.jspecify.annotations.Nullable; +import org.slf4j.Logger; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +@Mixin(MinecraftServer.class) +public abstract class PublishLANServerMixin { + @Shadow + public abstract boolean publishServer(@Nullable GameType gameMode, boolean allowCommands, int port); + + @Shadow + @Final + private static Logger LOGGER; + // Scheduler to check for connection readiness without blocking the main thread + @Unique + private static final ScheduledExecutorService SCHEDULER = Executors.newSingleThreadScheduledExecutor(); + + // Inject at the end of loadLevel + @Inject(at = @At("TAIL"), method = "loadLevel") + private void init(CallbackInfo info) { + MinecraftServer server = (MinecraftServer) (Object) this; + attemptLanPublish(server); + } + + @Unique + private void attemptLanPublish(MinecraftServer server) { + // Schedule a check every 500ms + SCHEDULER.scheduleAtFixedRate(() -> { + // Check if the connection is ready + if (Minecraft.getInstance().getConnection() != null) { + // Back to the main server thread for the actual logic + server.execute(() -> { + int port = HttpUtil.getAvailablePort(); + boolean success = publishServer(GameType.CREATIVE, true, port); + + if (success) { + server.getPlayerList().broadcastSystemMessage( + Component.literal("§aOpened to LAN on port " + port), false); + LOGGER.info("Successfully opened to LAN on port {}", port); + } else { + server.getPlayerList().broadcastSystemMessage( + Component.literal("§cFailed to open to LAN!"), false); + LOGGER.error("Failed to open to LAN on port {}", port); + } + }); + + // End scheduler + throw new RuntimeException("attemptLanPublish Complete"); + } + }, 0, 500, TimeUnit.MILLISECONDS); + } +} \ No newline at end of file diff --git a/src/main/resources/autolan.client.mixins.json b/src/main/resources/autolan.client.mixins.json new file mode 100644 index 0000000..50065f6 --- /dev/null +++ b/src/main/resources/autolan.client.mixins.json @@ -0,0 +1,11 @@ +{ + "required": true, + "package": "me.imgalvin.Mixin", + "compatibilityLevel": "JAVA_25", + "client": [ + "PublishLANServerMixin" + ], + "injectors": { + "defaultRequire": 1 + } +} \ No newline at end of file diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 14f2516..c6cd631 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -22,8 +22,11 @@ }, "depends": { "fabricloader": ">=0.16", - "minecraft": "1.21.10", - "java": ">=21", + "minecraft": "26.1-alpha.6", + "java": ">=25", "fabric-api": "*" - } + }, + "mixins": [ + "autolan.client.mixins.json" + ] } \ No newline at end of file