diff --git a/.github/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yaml new file mode 100644 index 0000000..0bbbc3b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yaml @@ -0,0 +1,88 @@ +name: Bug Report +description: Report a bug encountered with SkinRestorer +title: "[Bug]: " +labels: ["bug"] +body: + - type: markdown + attributes: + value: | + 🐛 **Before submitting:** + - Ensure you're using the latest mod version + - Ensure this bug is reproducible consistently + - Check existing issues for duplicates + + - type: input + id: mod-version + attributes: + label: SkinRestorer Version + description: Exact version of the mod + placeholder: e.g., 2.2.1 + validations: + required: true + + - type: input + id: minecraft-version + attributes: + label: Minecraft Version + description: Full Minecraft version + placeholder: e.g., 1.21.4 + validations: + required: true + + - type: input + id: loader-version + attributes: + label: Mod Loader & Version + description: Fabric/Quilt/Forge/NeoForge version + placeholder: e.g., Fabric 0.15.7 + validations: + required: true + + - type: input + id: java-version + attributes: + label: Java Version + placeholder: e.g. 17, 21 + validations: + required: true + + - type: textarea + id: description + attributes: + label: Bug Description + description: What happened vs what you expected to happen + validations: + required: true + + - type: textarea + id: steps + attributes: + label: Reproduction Steps + placeholder: | + 1. + 2. + 3. + validations: + required: true + + - type: textarea + id: logs + attributes: + label: Relevant Logs + description: | + Please provide any relevant logs, especially error logs from your server console or `latest.log` file. + **Important**: Paste the FULL log content. Use a service like [mclo.gs](https://mclo.gs/). + render: shell + validations: + required: true + + - type: checkboxes + id: confirmations + attributes: + label: Confirmations + options: + - label: I've checked for existing issues + required: true + - label: This bug is reproducible consistently + required: true + - label: I've tested without other mods diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..0086358 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1 @@ +blank_issues_enabled: true diff --git a/.github/ISSUE_TEMPLATE/feature_request.yaml b/.github/ISSUE_TEMPLATE/feature_request.yaml new file mode 100644 index 0000000..0e9351e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yaml @@ -0,0 +1,52 @@ +name: Feature Request +description: Suggest a new feature for SkinRestorer +title: "[Feature Request]: " +labels: ["enhancement"] +body: + - type: markdown + attributes: + value: | + 💡 **Before submitting:** + - Check existing feature requests for duplicates + - Be clear and concise + - Explain the *why* and the *how* + + - type: textarea + id: description + attributes: + label: Feature Description + description: Detailed description of the feature + validations: + required: true + + - type: textarea + id: motivation + attributes: + label: Motivation + description: Why is this feature needed? What problem does it solve? + validations: + required: true + + - type: textarea + id: use-cases + attributes: + label: Use Cases + description: How would this feature be used and who would benefit? + validations: + required: true + + - type: textarea + id: implementation-ideas + attributes: + label: Implementation Ideas (Optional) + description: Any thoughts on how it could be implemented? + validations: + required: false + + - type: checkboxes + id: confirmations + attributes: + label: Confirmations + options: + - label: I've checked for existing feature requests + required: true diff --git a/README.md b/README.md index 50063e2..a7b6af3 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # SkinRestorer -Modrinth -CurseForge +Modrinth +CurseForge A server-side mod for managing and restoring player skins. @@ -33,7 +33,9 @@ the [commands wiki page](https://github.com/Suiranoil/SkinRestorer/wiki/Commands If you enjoy using **SkinRestorer** and would like to support its development, you can contribute through the following platforms: -[![Ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/lionarius) +Ko-fi + +Boosty Bitcoin (BTC): `1Ndbwny8pxdnWXFgadp95fp97y5JqMJKTX` USDT (TRC20): `TGXn8wrqku5KLzwPWQAeH7wgnV4UzwHEae` diff --git a/build.gradle b/build.gradle index c3dc515..36f20ad 100644 --- a/build.gradle +++ b/build.gradle @@ -1,15 +1,15 @@ plugins { // see https://fabricmc.net/develop/ for new versions - id 'fabric-loom' version '1.8-SNAPSHOT' apply false - // see https://projects.neoforged.net/neoforged/neogradle for new versions - id 'net.neoforged.gradle.userdev' version '7.0.153' apply false + id 'fabric-loom' version '1.10-SNAPSHOT' apply false + // see https://projects.neoforged.net/neoforged/moddevgradle for new versions + id 'net.neoforged.moddev' version '2.0.80' apply false // see https://files.minecraftforge.net/net/minecraftforge/gradle/ForgeGradle/ for new versions - id 'net.minecraftforge.gradle' version '6.0.29' apply false + id 'net.minecraftforge.gradle' version '6.0.35' apply false id 'org.parchmentmc.librarian.forgegradle' version '1.+' apply false id 'org.spongepowered.mixin' version '0.7-SNAPSHOT' apply false - id 'me.modmuss50.mod-publish-plugin' version '0.8.1' apply false + id 'me.modmuss50.mod-publish-plugin' version '0.8.4' apply false } allprojects { diff --git a/buildSrc/src/main/groovy/multiloader-publish.gradle b/buildSrc/src/main/groovy/multiloader-publish.gradle index f759713..8058a7a 100644 --- a/buildSrc/src/main/groovy/multiloader-publish.gradle +++ b/buildSrc/src/main/groovy/multiloader-publish.gradle @@ -5,6 +5,8 @@ plugins { publishMods { if (project.name == 'fabric') file = remapJar.archiveFile + else if (project.name == 'neoforge') + file = jar.archiveFile else file = tasks.named('jarJar').get().archiveFile diff --git a/common/src/main/java/net/lionarius/skinrestorer/command/SkinCommand.java b/common/src/main/java/net/lionarius/skinrestorer/command/SkinCommand.java index abd80df..8dd93ea 100644 --- a/common/src/main/java/net/lionarius/skinrestorer/command/SkinCommand.java +++ b/common/src/main/java/net/lionarius/skinrestorer/command/SkinCommand.java @@ -34,7 +34,7 @@ public final class SkinCommand { private SkinCommand() {} public static void register(CommandDispatcher dispatcher) { - LiteralArgumentBuilder base = + var base = literal("skin") .then(buildSetSubcommand("clear", SkinValue.EMPTY::toProviderContext)) .then(literal("reset") @@ -44,7 +44,7 @@ public final class SkinCommand { ))) .then(literal("refresh").executes(context -> refreshSubcommand(context.getSource()))); - LiteralArgumentBuilder set = literal("set"); + var set = literal("set"); var providers = SkinRestorer.getProvidersRegistry().getPublicProviders(); for (var entry : providers) @@ -92,7 +92,7 @@ public final class SkinCommand { Collection targets, boolean setByOperator ) { - Collection updatedPlayers = new HashSet<>(); + var updatedPlayers = new HashSet(); for (var profile : targets) { SkinValue skin = null; if (SkinRestorer.getSkinStorage().hasSavedSkin(profile.getId())) @@ -199,7 +199,7 @@ public final class SkinCommand { } private static LiteralArgumentBuilder buildSetSubcommand(String name, SkinProvider provider) { - LiteralArgumentBuilder action = literal(name); + var action = literal(name); if (provider.hasVariantSupport()) { for (SkinVariant variant : SkinVariant.values()) { diff --git a/common/src/main/java/net/lionarius/skinrestorer/compat/skinshuffle/SkinShuffleCompatibility.java b/common/src/main/java/net/lionarius/skinrestorer/compat/skinshuffle/SkinShuffleCompatibility.java index b535f0f..5c07460 100644 --- a/common/src/main/java/net/lionarius/skinrestorer/compat/skinshuffle/SkinShuffleCompatibility.java +++ b/common/src/main/java/net/lionarius/skinrestorer/compat/skinshuffle/SkinShuffleCompatibility.java @@ -5,6 +5,7 @@ import net.lionarius.skinrestorer.platform.Services; import net.lionarius.skinrestorer.skin.SkinValue; import net.lionarius.skinrestorer.skin.provider.SkinShuffleSkinProvider; import net.lionarius.skinrestorer.util.PlayerUtils; +import net.lionarius.skinrestorer.util.ServerUtils; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; @@ -40,7 +41,7 @@ public class SkinShuffleCompatibility { if (!property.hasSignature()) return; - server.execute(() -> { + ServerUtils.scheduleServerTask(server, () -> { SkinRestorer.applySkin( server, Collections.singleton(player.getGameProfile()), diff --git a/common/src/main/java/net/lionarius/skinrestorer/config/Config.java b/common/src/main/java/net/lionarius/skinrestorer/config/Config.java index c22f6bc..d8acb49 100644 --- a/common/src/main/java/net/lionarius/skinrestorer/config/Config.java +++ b/common/src/main/java/net/lionarius/skinrestorer/config/Config.java @@ -18,6 +18,8 @@ public final class Config implements GsonPostProcessable { private boolean refreshSkinOnJoin = true; + private int skinApplyDelayOnJoin = 0; + private boolean fetchSkinOnFirstJoin = true; private FirstJoinSkinProvider firstJoinSkinProvider = FirstJoinSkinProvider.MOJANG; @@ -37,6 +39,10 @@ public final class Config implements GsonPostProcessable { return this.refreshSkinOnJoin; } + public int skinApplyDelayOnJoin() { + return this.skinApplyDelayOnJoin; + } + public boolean fetchSkinOnFirstJoin() { return this.fetchSkinOnFirstJoin; } @@ -82,6 +88,11 @@ public final class Config implements GsonPostProcessable { this.language = "en_us"; } + if (this.skinApplyDelayOnJoin < 0) { + SkinRestorer.LOGGER.warn("SkinApplyDelayOnJoin config is less than 0, defaulting to 0"); + this.skinApplyDelayOnJoin = 0; + } + if (this.firstJoinSkinProvider == null) { SkinRestorer.LOGGER.warn("FirstJoinSkinProvider config is null, defaulting to MOJANG"); this.firstJoinSkinProvider = FirstJoinSkinProvider.MOJANG; diff --git a/common/src/main/java/net/lionarius/skinrestorer/config/provider/BuiltInProviderConfig.java b/common/src/main/java/net/lionarius/skinrestorer/config/provider/BuiltInProviderConfig.java index 198e9f1..c27e84c 100644 --- a/common/src/main/java/net/lionarius/skinrestorer/config/provider/BuiltInProviderConfig.java +++ b/common/src/main/java/net/lionarius/skinrestorer/config/provider/BuiltInProviderConfig.java @@ -1,10 +1,42 @@ package net.lionarius.skinrestorer.config.provider; -public interface BuiltInProviderConfig { +import net.lionarius.skinrestorer.SkinRestorer; +import net.lionarius.skinrestorer.util.gson.GsonPostProcessable; - boolean enabled(); - - String name(); - - CacheConfig cache(); +public abstract class BuiltInProviderConfig implements GsonPostProcessable { + protected boolean enabled; + protected String name; + protected CacheConfig cache; + + public BuiltInProviderConfig(String name, CacheConfig cache) { + this.enabled = true; + this.name = name; + this.cache = cache; + } + + public boolean enabled() { + return enabled; + } + + public String name() { + return name; + } + + public CacheConfig cache() { + return cache; + } + + protected void validate(String defaultName, CacheConfig defaultCache) { + if (this.name == null || this.name.isEmpty()) { + SkinRestorer.LOGGER.warn("Provider name is null or empty, defaulting to '{}'", defaultName); + this.name = defaultName; + } + + if (this.cache == null) { + SkinRestorer.LOGGER.warn("Provider cache is null, using default"); + this.cache = defaultCache; + } else { + this.cache.validate(defaultCache); + } + } } diff --git a/common/src/main/java/net/lionarius/skinrestorer/config/provider/ElyByProviderConfig.java b/common/src/main/java/net/lionarius/skinrestorer/config/provider/ElyByProviderConfig.java index c36caf8..e4a5dfa 100644 --- a/common/src/main/java/net/lionarius/skinrestorer/config/provider/ElyByProviderConfig.java +++ b/common/src/main/java/net/lionarius/skinrestorer/config/provider/ElyByProviderConfig.java @@ -1,46 +1,16 @@ package net.lionarius.skinrestorer.config.provider; -import net.lionarius.skinrestorer.SkinRestorer; import net.lionarius.skinrestorer.skin.provider.ElyBySkinProvider; -import net.lionarius.skinrestorer.util.gson.GsonPostProcessable; -public class ElyByProviderConfig implements BuiltInProviderConfig, GsonPostProcessable { +public final class ElyByProviderConfig extends BuiltInProviderConfig { private static final CacheConfig DEFAULT_CACHE_VALUE = new CacheConfig(true, 60); - private boolean enabled; - private String name; - private CacheConfig cache; - public ElyByProviderConfig() { - this.enabled = true; - this.name = ElyBySkinProvider.PROVIDER_NAME; - this.cache = DEFAULT_CACHE_VALUE; - } - - public boolean enabled() { - return enabled; - } - - public String name() { - return name; - } - - public CacheConfig cache() { - return cache; + super(ElyBySkinProvider.PROVIDER_NAME, DEFAULT_CACHE_VALUE); } @Override public void gsonPostProcess() { - if (this.name == null || this.name.isEmpty()) { - SkinRestorer.LOGGER.warn("Ely.By provider name is null or empty, defaulting to '{}'", ElyBySkinProvider.PROVIDER_NAME); - this.name = ElyBySkinProvider.PROVIDER_NAME; - } - - if (this.cache == null) { - SkinRestorer.LOGGER.warn("Ely.By provider cache is null, using default"); - this.cache = DEFAULT_CACHE_VALUE; - } else { - this.cache.validate(DEFAULT_CACHE_VALUE); - } + super.validate(ElyBySkinProvider.PROVIDER_NAME, DEFAULT_CACHE_VALUE); } } diff --git a/common/src/main/java/net/lionarius/skinrestorer/config/provider/MineskinProviderConfig.java b/common/src/main/java/net/lionarius/skinrestorer/config/provider/MineskinProviderConfig.java index b12ed30..ee7c05b 100644 --- a/common/src/main/java/net/lionarius/skinrestorer/config/provider/MineskinProviderConfig.java +++ b/common/src/main/java/net/lionarius/skinrestorer/config/provider/MineskinProviderConfig.java @@ -2,52 +2,25 @@ package net.lionarius.skinrestorer.config.provider; import net.lionarius.skinrestorer.SkinRestorer; import net.lionarius.skinrestorer.skin.provider.MineskinSkinProvider; -import net.lionarius.skinrestorer.util.gson.GsonPostProcessable; -public class MineskinProviderConfig implements BuiltInProviderConfig, GsonPostProcessable { +public final class MineskinProviderConfig extends BuiltInProviderConfig { private static final CacheConfig DEFAULT_CACHE_VALUE = new CacheConfig(true, 300); - private boolean enabled; - private String name; - private CacheConfig cache; private String apiKey; public MineskinProviderConfig() { - this.enabled = true; - this.name = MineskinSkinProvider.PROVIDER_NAME; - this.cache = DEFAULT_CACHE_VALUE; + super(MineskinSkinProvider.PROVIDER_NAME, DEFAULT_CACHE_VALUE); + this.apiKey = ""; } - public boolean enabled() { - return enabled; - } - - public String name() { - return name; - } - - public CacheConfig cache() { - return cache; - } - public String apiKey() { return apiKey; } @Override public void gsonPostProcess() { - if (this.name == null || this.name.isEmpty()) { - SkinRestorer.LOGGER.warn("Mineskin provider name is null or empty, defaulting to '{}'", MineskinSkinProvider.PROVIDER_NAME); - this.name = MineskinSkinProvider.PROVIDER_NAME; - } - - if (this.cache == null) { - SkinRestorer.LOGGER.warn("Mineskin cache is null, using default"); - this.cache = DEFAULT_CACHE_VALUE; - } else { - this.cache.validate(DEFAULT_CACHE_VALUE); - } + super.validate(MineskinSkinProvider.PROVIDER_NAME, DEFAULT_CACHE_VALUE); if (this.apiKey == null) { SkinRestorer.LOGGER.warn("Mineskin API key is null, defaulting to an empty string"); diff --git a/common/src/main/java/net/lionarius/skinrestorer/config/provider/MojangProviderConfig.java b/common/src/main/java/net/lionarius/skinrestorer/config/provider/MojangProviderConfig.java index 625a55e..20da780 100644 --- a/common/src/main/java/net/lionarius/skinrestorer/config/provider/MojangProviderConfig.java +++ b/common/src/main/java/net/lionarius/skinrestorer/config/provider/MojangProviderConfig.java @@ -1,46 +1,16 @@ package net.lionarius.skinrestorer.config.provider; -import net.lionarius.skinrestorer.SkinRestorer; import net.lionarius.skinrestorer.skin.provider.MojangSkinProvider; -import net.lionarius.skinrestorer.util.gson.GsonPostProcessable; -public class MojangProviderConfig implements BuiltInProviderConfig, GsonPostProcessable { +public final class MojangProviderConfig extends BuiltInProviderConfig { private static final CacheConfig DEFAULT_CACHE_VALUE = new CacheConfig(true, 60); - private boolean enabled; - private String name; - private CacheConfig cache; - public MojangProviderConfig() { - this.enabled = true; - this.name = MojangSkinProvider.PROVIDER_NAME; - this.cache = DEFAULT_CACHE_VALUE; - } - - public boolean enabled() { - return enabled; - } - - public String name() { - return name; - } - - public CacheConfig cache() { - return cache; + super(MojangSkinProvider.PROVIDER_NAME, DEFAULT_CACHE_VALUE); } @Override public void gsonPostProcess() { - if (this.name == null || this.name.isEmpty()) { - SkinRestorer.LOGGER.warn("Mojang provider name is null or empty, defaulting to '{}'", MojangSkinProvider.PROVIDER_NAME); - this.name = MojangSkinProvider.PROVIDER_NAME; - } - - if (this.cache == null) { - SkinRestorer.LOGGER.warn("Mojang provider cache is null, using default"); - this.cache = DEFAULT_CACHE_VALUE; - } else { - this.cache.validate(DEFAULT_CACHE_VALUE); - } + super.validate(MojangSkinProvider.PROVIDER_NAME, DEFAULT_CACHE_VALUE); } } diff --git a/common/src/main/java/net/lionarius/skinrestorer/mixin/PlayerListMixin.java b/common/src/main/java/net/lionarius/skinrestorer/mixin/PlayerListMixin.java index ec1f02e..4b02ac5 100644 --- a/common/src/main/java/net/lionarius/skinrestorer/mixin/PlayerListMixin.java +++ b/common/src/main/java/net/lionarius/skinrestorer/mixin/PlayerListMixin.java @@ -1,6 +1,7 @@ package net.lionarius.skinrestorer.mixin; import net.lionarius.skinrestorer.SkinRestorer; +import net.lionarius.skinrestorer.util.ServerUtils; import net.minecraft.network.Connection; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; @@ -9,6 +10,7 @@ import net.minecraft.server.players.PlayerList; 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; @@ -39,6 +41,22 @@ public abstract class PlayerListMixin { @Inject(method = "placeNewPlayer", at = @At("HEAD")) private void placeNewPlayer(Connection connection, ServerPlayer player, CommonListenerCookie cookie, CallbackInfo ci) { + var delay = SkinRestorer.getConfig().skinApplyDelayOnJoin(); + var uuid = player.getUUID(); + + if (delay <= 0) { + skinrestorer$tryApplySkin(server, player); + } else { + ServerUtils.scheduleServerTask(server, () -> { + var actualPlayer = server.getPlayerList().getPlayer(uuid); + if (actualPlayer != null) + skinrestorer$tryApplySkin(server, actualPlayer); + }, delay); + } + } + + @Unique + private static void skinrestorer$tryApplySkin(MinecraftServer server, ServerPlayer player) { if (SkinRestorer.getSkinStorage().hasSavedSkin(player.getUUID())) SkinRestorer.applySkin(server, Collections.singleton(player.getGameProfile()), SkinRestorer.getSkinStorage().getSkin(player.getUUID())); } diff --git a/common/src/main/java/net/lionarius/skinrestorer/util/ServerUtils.java b/common/src/main/java/net/lionarius/skinrestorer/util/ServerUtils.java new file mode 100644 index 0000000..a93de78 --- /dev/null +++ b/common/src/main/java/net/lionarius/skinrestorer/util/ServerUtils.java @@ -0,0 +1,37 @@ +package net.lionarius.skinrestorer.util; + +import net.minecraft.server.MinecraftServer; + +import java.util.function.Consumer; + +public class ServerUtils { + + private ServerUtils() {} + + public static void scheduleServerTask(MinecraftServer server, Consumer task) { + ServerUtils.scheduleServerTask(server, task, 0); + } + + public static void scheduleServerTask(MinecraftServer server, Runnable task) { + ServerUtils.scheduleServerTask(server, task, 0); + } + + public static void scheduleServerTask(MinecraftServer server, Consumer task, int tickDelay) { + server.execute(new ScheduledTickTask(server, task, server.getTickCount() + tickDelay)); + } + + public static void scheduleServerTask(MinecraftServer server, Runnable task, int tickDelay) { + server.execute(new ScheduledTickTask(server, _server -> task.run(), server.getTickCount() + tickDelay)); + } + + public record ScheduledTickTask(MinecraftServer server, Consumer task, + int tickTarget) implements Runnable { + @Override + public void run() { + if (this.server.getTickCount() >= this.tickTarget) + this.task.accept(this.server); + else + this.server.execute(this); + } + } +} diff --git a/forge/build.gradle b/forge/build.gradle index 08dc99b..9348289 100644 --- a/forge/build.gradle +++ b/forge/build.gradle @@ -40,7 +40,7 @@ minecraft { runs { client { - workingDirectory file('../run/client') + workingDirectory rootProject.file('run/client') ideaModule "${rootProject.name}.${project.name}.main" taskName 'Client' mods { @@ -51,7 +51,7 @@ minecraft { } server { - workingDirectory file('../run/server') + workingDirectory rootProject.file('run/server') ideaModule "${rootProject.name}.${project.name}.main" taskName 'Server' mods { diff --git a/gradle.properties b/gradle.properties index 2dabd06..3decee8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -17,6 +17,7 @@ license=MIT credits= description=A server-side mod for managing skins. +# Dependencies mineskin_client_version=3.0.1-SNAPSHOT # ParchmentMC mappings, see https://parchmentmc.org/docs/getting-started#choose-a-version for new versions diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 9355b41..e18bc25 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.10-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.12.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index f5feea6..f3b75f3 100644 --- a/gradlew +++ b/gradlew @@ -86,8 +86,7 @@ done # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s -' "$PWD" ) || exit +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum diff --git a/neoforge/build.gradle b/neoforge/build.gradle index 872c927..72eb58a 100644 --- a/neoforge/build.gradle +++ b/neoforge/build.gradle @@ -3,56 +3,58 @@ plugins { id 'idea' id 'eclipse' - id 'net.neoforged.gradle.userdev' + id 'net.neoforged.moddev' id 'multiloader-publish' } -// Automatically enable neoforge AccessTransformers if the file exists -def at = project(':common').file('src/main/resources/META-INF/accesstransformer.cfg') -if (at.exists()) { - minecraft.accessTransformers.file(at) -} - -jarJar.enable() - -tasks.named('jar') { - archiveClassifier = 'thin' -} - -tasks.named('jarJar') { - archiveClassifier = '' -} - -jar.finalizedBy('jarJar') - -dependencies { - implementation "net.neoforged:neoforge:${neoforge_version}" - - implementation(jarJar(group: 'org.mineskin', name: 'java-client', version: mineskin_client_version)) { - jarJar.ranged(it, "[${mineskin_client_version},)") +neoForge { + version = neoforge_version + + // Automatically enable neoforge AccessTransformers if the file exists + def at = project(':common').file('src/main/resources/META-INF/accesstransformer.cfg') + if (at.exists()) { + minecraft.accessTransformers.file(at) } -} -subsystems { parchment { minecraftVersion = parchment_minecraft mappingsVersion = parchment_version } -} -runs { - configureEach { - modSource project.sourceSets.main - systemProperty 'neoforge.enabledGameTestNamespaces', project.mod_id + runs { + configureEach { + ideName = "NeoForge ${it.name.capitalize()} (${project.path})" // Unify the run config names with fabric + } + + client { + client() + gameDirectory = rootProject.file('run/client') + } + + server { + server() + programArgument '--nogui' + gameDirectory = rootProject.file('run/server') + } } - client { - workingDirectory = file('../run/client') - } - - server { - programArgument '--nogui' - workingDirectory = file('../run/server') + mods { + "${mod_id}" { + sourceSet sourceSets.main + } } } + +dependencies { + implementation "net.neoforged:neoforge:${neoforge_version}" + + jarJar(implementation('org.mineskin:java-client')) { + version { + strictly "[${mineskin_client_version},)" + prefer mineskin_client_version + } + } + + additionalRuntimeClasspath "org.mineskin:java-client:${mineskin_client_version}" +}