diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c47320..dd26a6e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2.0.3] - 2024-08-20 +### Added +- Added `firstJoinSkinProvider` config option (see [wiki](https://github.com/Suiranoil/SkinRestorer/wiki/Config#firstjoinskinprovider)) +### Fixed +- Fixed ability to set config values to `null` + ## [2.0.2] - 2024-08-04 ### Added - Backported to minecraft 1.20-1.20.2 diff --git a/CHANGELOG_LATEST.md b/CHANGELOG_LATEST.md index 4b6fca1..a253c55 100644 --- a/CHANGELOG_LATEST.md +++ b/CHANGELOG_LATEST.md @@ -1,5 +1,4 @@ ### Added -- Backported to minecraft 1.20-1.20.2 -- [Forge] Added support for Forge -### Changed -- Changed minimum java version to 17 for minecraft 1.20-1.20.4 +- Added `firstJoinSkinProvider` config option (see [wiki](https://github.com/Suiranoil/SkinRestorer/wiki/Config#firstjoinskinprovider)) +### Fixed +- Fixed ability to set config values to `null` diff --git a/README.md b/README.md index b6a8be3..67e227a 100644 --- a/README.md +++ b/README.md @@ -1,55 +1,100 @@ # SkinRestorer -![a](https://cf.way2muchnoise.eu/versions/skinrestorer.svg) -![Enviroment](https://img.shields.io/badge/enviroment-server-orangered) -[![CurseForge Downloads](https://cf.way2muchnoise.eu/skinrestorer.svg)](https://www.curseforge.com/minecraft/mc-mods/skinrestorer) -[![Modrinth Downloads](https://img.shields.io/modrinth/dt/skinrestorer?logo=modrinth&label=&suffix=%20&style=flat&color=242629&labelColor=5ca424&logoColor=1c1c1c)](https://modrinth.com/mod/skinrestorer) +CurseForge +Modrinth -SkinRestorer is a **server-side** only mod for Fabric that allows players to use and change skins on servers running in -offline/insecure mode. +A server-side mod for managing and restoring player skins. -## Features +## ✨ Features -- **Set Skins from Mojang Account**: Fetch and apply skins using a valid Minecraft account name. -- **Set Skins from URL**: Apply skins from any image URL, supporting both classic (Steve) and slim (Alex) skin models. +- **Set skins from Mojang Account**: Fetch and apply skins using a valid Minecraft username. +- **Set skins from Ely.by**: Fetch and apply skins using a valid [Ely.by](https://ely.by/) username. +- **Set skins from URL**: Fetch and apply skins from any image URL, supporting both classic (Steve) and slim (Alex) skin models. +- **Automatic skin fetching**: Automatically fetch skin from Mojang/Ely.by when a player joins the server running in offline/insecure mode ([configurable](https://github.com/Suiranoil/SkinRestorer/wiki/Config)). +- **Singleplayer support**: Apply skins individually for each world. +- **Permissions API support** -## Command Usage Guide +## 📜 Command Usage Guide -### Set Mojang Skin +### Set Mojang skin + +Fetch and apply skins using a valid Minecraft username. ``` /skin set mojang [] ``` -- **Parameters:** - - ``: Minecraft account name to fetch the skin from. +- **Parameters** + - ``: Minecraft username to fetch the skin from. - `[]`: (Optional, server operators only) Player(s) to apply the skin to. -### Set Web Skin +### Set Ely.by skin + +Fetch and apply skins using a valid [Ely.by](https://ely.by/) username. + +``` +/skin set ely.by [] +``` + +- **Parameters** + - ``: Ely.by username to fetch the skin from. + - `[]`: (Optional, server operators only) Player(s) to apply the skin to. + +### Set Web skin + +Fetch and apply skins from any image URL, supporting both classic (Steve) and slim (Alex) skin models. + +Uses [mineskin api](https://mineskin.org/) under the hood. ``` /skin set web (classic|slim) "" [] ``` -- **Parameters:** +- **Parameters** - `(classic|slim)`: Type of the skin model (`classic` for Steve model, `slim` for Alex model). - `""`: URL pointing to the skin image file (ensure it follows Minecraft's skin size and format requirements). - `[]`: (Optional, server operators only) Player(s) to apply the skin to. -### Clear Skin +### Refresh skin + +Refetch and reapply the currently applied skins. + +``` +/skin refresh [] +``` + +- **Parameters** + - `[]`: (Optional, server operators only) Player(s) to refresh the skin for. + +### Clear skin + +Remove the currently applied skins. ``` /skin clear [] ``` -- **Parameters:** +- **Parameters** - `[]`: (Optional, server operators only) Player(s) to clear the skin for. -### Notes: +### Reset skin + +Reset to the default skin or remove any custom skin. + +If [automatic skin fetching](https://github.com/Suiranoil/SkinRestorer/wiki/Config#fetchskinonfirstjoin) is enabled, a new skin will be fetched when the player rejoins the server. + +``` +/skin reset [] +``` + +- **Parameters** + - `[]`: (Optional, server operators only) Player(s) to reset the skin for. + +### Notes - If `targets` is not specified, the command will apply to the player executing the command. -### Examples: +### Examples ``` /skin set mojang Notch 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 91d0acd..3366568 100644 --- a/common/src/main/java/net/lionarius/skinrestorer/config/Config.java +++ b/common/src/main/java/net/lionarius/skinrestorer/config/Config.java @@ -15,6 +15,8 @@ public final class Config { private boolean fetchSkinOnFirstJoin = true; + private FirstJoinSkinProvider firstJoinSkinProvider = FirstJoinSkinProvider.MOJANG; + private String proxy = ""; private long requestTimeout = 10; @@ -27,6 +29,10 @@ public final class Config { return this.fetchSkinOnFirstJoin; } + public FirstJoinSkinProvider getFirstJoinSkinProvider() { + return this.firstJoinSkinProvider; + } + public String getProxy() { return this.proxy; } @@ -48,8 +54,24 @@ public final class Config { if (config == null) config = new Config(); + config.verifyAndFix(); + FileUtils.writeFile(path.resolve(Config.CONFIG_FILENAME), JsonUtils.toJson(config)); return config; } + + private void verifyAndFix() { + if (this.language == null || this.language.isEmpty()) + this.language = "en_us"; + + if (this.firstJoinSkinProvider == null) + this.firstJoinSkinProvider = FirstJoinSkinProvider.MOJANG; + + if (this.proxy == null) + this.proxy = ""; + + if (this.requestTimeout <= 0) + this.requestTimeout = 10; + } } diff --git a/common/src/main/java/net/lionarius/skinrestorer/config/FirstJoinSkinProvider.java b/common/src/main/java/net/lionarius/skinrestorer/config/FirstJoinSkinProvider.java new file mode 100644 index 0000000..120f8de --- /dev/null +++ b/common/src/main/java/net/lionarius/skinrestorer/config/FirstJoinSkinProvider.java @@ -0,0 +1,22 @@ +package net.lionarius.skinrestorer.config; + +import com.google.gson.annotations.SerializedName; +import net.lionarius.skinrestorer.skin.provider.ElyBySkinProvider; +import net.lionarius.skinrestorer.skin.provider.MojangSkinProvider; + +public enum FirstJoinSkinProvider { + @SerializedName(value = "MOJANG", alternate = {"mojang"}) + MOJANG(MojangSkinProvider.PROVIDER_NAME), + @SerializedName(value = "ELY.BY", alternate = {"ely.by", "ELY_BY", "ely_by"}) + ELY_BY(ElyBySkinProvider.PROVIDER_NAME); + + private final String name; + + FirstJoinSkinProvider(String name) { + this.name = name; + } + + public String getName() { + return this.name; + } +} diff --git a/common/src/main/java/net/lionarius/skinrestorer/mixin/ServerLoginPacketListenerImplMixin.java b/common/src/main/java/net/lionarius/skinrestorer/mixin/ServerLoginPacketListenerImplMixin.java index 59d772d..c607893 100644 --- a/common/src/main/java/net/lionarius/skinrestorer/mixin/ServerLoginPacketListenerImplMixin.java +++ b/common/src/main/java/net/lionarius/skinrestorer/mixin/ServerLoginPacketListenerImplMixin.java @@ -3,7 +3,6 @@ package net.lionarius.skinrestorer.mixin; import com.mojang.authlib.GameProfile; import net.lionarius.skinrestorer.SkinRestorer; import net.lionarius.skinrestorer.skin.SkinValue; -import net.lionarius.skinrestorer.skin.provider.MojangSkinProvider; import net.lionarius.skinrestorer.skin.provider.SkinProviderContext; import net.lionarius.skinrestorer.util.PlayerUtils; import net.lionarius.skinrestorer.util.Result; @@ -48,7 +47,11 @@ public abstract class ServerLoginPacketListenerImplMixin { if (originalSkin == null && SkinRestorer.getConfig().fetchSkinOnFirstJoin()) { SkinRestorer.LOGGER.debug("Fetching {}'s skin", authenticatedProfile.getName()); - var context = new SkinProviderContext(MojangSkinProvider.PROVIDER_NAME, authenticatedProfile.getName(), null); + var context = new SkinProviderContext( + SkinRestorer.getConfig().getFirstJoinSkinProvider().getName(), + authenticatedProfile.getName(), + null + ); var result = SkinRestorer.getProvider(context.name()).map( provider -> provider.getSkin(context.argument(), context.variant()) ).orElse(Result.ofNullable(null)); diff --git a/gradle.properties b/gradle.properties index 956b603..84772a9 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ minecraft_version_list=1.20.2 minecraft_version_range=1.20.2 mod_id=skinrestorer mod_name=SkinRestorer -mod_version=2.0.2 +mod_version=2.0.3 mod_author=Lionarius mod_homepage=https://www.curseforge.com/minecraft/mc-mods/skinrestorer mod_sources=https://github.com/Suiranoil/SkinRestorer