diff --git a/CHANGELOG.md b/CHANGELOG.md
index dd26a6e..41c55ab 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,17 @@ 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.1.0] - 2024-09-26
+### Added
+- Added `config reload` command for dynamic configuration updates
+- Added `refreshSkinOnJoin` config option (see [wiki](https://github.com/Suiranoil/SkinRestorer/wiki/Configuration#refreshskinonjoin))
+- Implemented caching for skin providers
+- Added provider configurations (see [wiki](https://github.com/Suiranoil/SkinRestorer/wiki/Configuration#providers))
+- Added username and url validation for requests
+### Fixed
+- Fixed old skin directory migration not working
+- Prevented overwriting existing skin files during migration
+
## [2.0.3] - 2024-08-20
### Added
- Added `firstJoinSkinProvider` config option (see [wiki](https://github.com/Suiranoil/SkinRestorer/wiki/Config#firstjoinskinprovider))
diff --git a/CHANGELOG_LATEST.md b/CHANGELOG_LATEST.md
index a253c55..9143cea 100644
--- a/CHANGELOG_LATEST.md
+++ b/CHANGELOG_LATEST.md
@@ -1,4 +1,9 @@
### Added
-- Added `firstJoinSkinProvider` config option (see [wiki](https://github.com/Suiranoil/SkinRestorer/wiki/Config#firstjoinskinprovider))
+- Added `config reload` command for dynamic configuration updates
+- Added `refreshSkinOnJoin` config option (see [wiki](https://github.com/Suiranoil/SkinRestorer/wiki/Configuration#refreshskinonjoin))
+- Implemented caching for skin providers
+- Added provider configurations (see [wiki](https://github.com/Suiranoil/SkinRestorer/wiki/Configuration#providers))
+- Added username and url validation for requests
### Fixed
-- Fixed ability to set config values to `null`
+- Fixed old skin directory migration not working
+- Prevented overwriting existing skin files during migration
diff --git a/README.md b/README.md
index 67e227a..e1e902e 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
# SkinRestorer
-
+
A server-side mod for managing and restoring player skins.
@@ -10,94 +10,25 @@ A server-side mod for managing and restoring player skins.
- **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)).
+- **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/Configuration)).
- **Singleplayer support**: Apply skins individually for each world.
- **Permissions API support**
## 📜 Command Usage Guide
-### Set Mojang skin
+For a detailed list of available commands and their usage, please visit the [commands wiki page](https://github.com/Suiranoil/SkinRestorer/wiki/Commands).
-Fetch and apply skins using a valid Minecraft username.
+## ❌ Known Incompatibilities
-```
-/skin set mojang []
-```
+- **[Arclight](https://github.com/IzzelAliz/Arclight) (<=1.20.1)**: Trials or older versions are not compatible due to mixin conflicts.
+ As an alternative, consider using the [SkinsRestorer](https://www.spigotmc.org/resources/skinsrestorer.2124/) plugin.
-- **Parameters**
- - ``: Minecraft username to fetch the skin from.
- - `[]`: (Optional, server operators only) Player(s) to apply the skin to.
+## 🪙 Donation
-### Set Ely.by skin
+If you enjoy using **SkinRestorer** and would like to support its development, you can contribute through cryptocurrency donations.
-Fetch and apply skins using a valid [Ely.by](https://ely.by/) username.
+Bitcoin (BTC): `1Ndbwny8pxdnWXFgadp95fp97y5JqMJKTX`\
+USDT (TRC20): `TGXn8wrqku5KLzwPWQAeH7wgnV4UzwHEae`\
+USDT (TON): `UQAQF18Xlmx-V1oZ90C2YOju5qI7q1LgrCP5QaIUhqIELmDS`
-```
-/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**
- - `(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.
-
-### 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**
- - `[]`: (Optional, server operators only) Player(s) to clear the skin for.
-
-### 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
-
-```
-/skin set mojang Notch
-/skin set web classic "https://example.com/skin.png"
-/skin clear @a
-```
+Thank you for your generosity!
diff --git a/common/src/main/java/net/lionarius/skinrestorer/SkinRestorer.java b/common/src/main/java/net/lionarius/skinrestorer/SkinRestorer.java
index 2518497..a324c84 100644
--- a/common/src/main/java/net/lionarius/skinrestorer/SkinRestorer.java
+++ b/common/src/main/java/net/lionarius/skinrestorer/SkinRestorer.java
@@ -20,6 +20,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.nio.file.Path;
+import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Optional;
@@ -71,7 +72,7 @@ public final class SkinRestorer {
var isDefaultName = config.name().equals(defaultName);
SkinRestorer.providersRegistry.register(defaultName, provider, config.enabled() && isDefaultName);
- if (!isDefaultName)
+ if (!isDefaultName && Arrays.stream(SkinProvider.BUILTIN_PROVIDER_NAMES).noneMatch(name -> name.equals(config.name())))
SkinRestorer.providersRegistry.register(config.name(), provider, config.enabled());
}
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 67a26f4..abd80df 100644
--- a/common/src/main/java/net/lionarius/skinrestorer/command/SkinCommand.java
+++ b/common/src/main/java/net/lionarius/skinrestorer/command/SkinCommand.java
@@ -49,7 +49,8 @@ public final class SkinCommand {
var providers = SkinRestorer.getProvidersRegistry().getPublicProviders();
for (var entry : providers)
set.then(buildSetSubcommand(entry.first(), entry.second()));
- base.then(set);
+ if (!providers.isEmpty())
+ base.then(set);
base.then(
literal("config")
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 030fdde..59e1017 100644
--- a/common/src/main/java/net/lionarius/skinrestorer/config/Config.java
+++ b/common/src/main/java/net/lionarius/skinrestorer/config/Config.java
@@ -14,7 +14,7 @@ public final class Config {
private String language = "en_us";
- private boolean refreshSkinOnJoin = false;
+ private boolean refreshSkinOnJoin = true;
private boolean fetchSkinOnFirstJoin = true;
diff --git a/common/src/main/java/net/lionarius/skinrestorer/skin/provider/SkinProvider.java b/common/src/main/java/net/lionarius/skinrestorer/skin/provider/SkinProvider.java
index 4df3b6a..86a5815 100644
--- a/common/src/main/java/net/lionarius/skinrestorer/skin/provider/SkinProvider.java
+++ b/common/src/main/java/net/lionarius/skinrestorer/skin/provider/SkinProvider.java
@@ -12,6 +12,8 @@ public interface SkinProvider {
ElyBySkinProvider ELY_BY = new ElyBySkinProvider();
MineskinSkinProvider MINESKIN = new MineskinSkinProvider();
+ String[] BUILTIN_PROVIDER_NAMES = new String[]{EmptySkinProvider.PROVIDER_NAME, MojangSkinProvider.PROVIDER_NAME, ElyBySkinProvider.PROVIDER_NAME, MineskinSkinProvider.PROVIDER_NAME};
+
String getArgumentName();
boolean hasVariantSupport();
diff --git a/gradle.properties b/gradle.properties
index 7802e33..dc1bbc5 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -8,9 +8,9 @@ minecraft_version_list=1.20,1.20.1
minecraft_version_range=[1.20, 1.20.1]
mod_id=skinrestorer
mod_name=SkinRestorer
-mod_version=2.0.3
+mod_version=2.1.0
mod_author=Lionarius
-mod_homepage=https://www.curseforge.com/minecraft/mc-mods/skinrestorer
+mod_homepage=https://modrinth.com/mod/skinrestorer
mod_sources=https://github.com/Suiranoil/SkinRestorer
mod_issues=https://github.com/Suiranoil/SkinRestorer/issues
license=MIT