Restore RemotePackSync plugin identity
This commit is contained in:
@@ -10,7 +10,7 @@ permissions:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
release:
|
release:
|
||||||
name: Build and publish LexianDEV
|
name: Build and publish RemotePackSync
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
@@ -36,5 +36,5 @@ jobs:
|
|||||||
uses: softprops/action-gh-release@v2
|
uses: softprops/action-gh-release@v2
|
||||||
with:
|
with:
|
||||||
generate_release_notes: false
|
generate_release_notes: false
|
||||||
files: target/LexianDEV.jar
|
files: target/RemotePackSync.jar
|
||||||
fail_on_unmatched_files: true
|
fail_on_unmatched_files: true
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
# LexianDEV
|
# RemotePackSync
|
||||||
|
|
||||||
Official website: <https://lexian.dev>
|
Created by **LexianDEV** · Official website: <https://lexian.dev>
|
||||||
|
|
||||||
LexianDEV is a lightweight **Spigot 26.2** plugin that keeps Java Edition resource packs synchronized with a remotely hosted SHA-1 checksum and optionally serves a local Bedrock Edition pack to players connecting through **GeyserMC**. It uses only public Bukkit/Spigot and Geyser APIs, so it runs on **Spigot, Paper, Purpur, Bukkit-compatible servers, and current GeyserMC**.
|
RemotePackSync is a lightweight **Spigot 26.2** plugin that keeps Java Edition resource packs synchronized with a remotely hosted SHA-1 checksum and optionally serves a local Bedrock Edition pack to players connecting through **GeyserMC**. It uses only public Bukkit/Spigot and Geyser APIs, so it runs on **Spigot, Paper, Purpur, Bukkit-compatible servers, and current GeyserMC**.
|
||||||
|
|
||||||
No NMS, packet libraries, or server-fork-specific APIs are used.
|
No NMS, packet libraries, or server-fork-specific APIs are used.
|
||||||
|
|
||||||
@@ -20,15 +20,15 @@ mvn clean package
|
|||||||
The ready-to-install plugin is written to:
|
The ready-to-install plugin is written to:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
target/LexianDEV.jar
|
target/RemotePackSync.jar
|
||||||
```
|
```
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
1. Copy `LexianDEV.jar` into the server's `plugins/` directory.
|
1. Copy `RemotePackSync.jar` into the server's `plugins/` directory.
|
||||||
2. Start the server once. LexianDEV writes `plugins/LexianDEV/config.yml` automatically.
|
2. Start the server once. RemotePackSync writes `plugins/RemotePackSync/config.yml` automatically.
|
||||||
3. Configure the resource-pack and SHA-1 URLs.
|
3. Configure the resource-pack and SHA-1 URLs.
|
||||||
4. Restart the server, or run `/lexiandev reload` as an operator.
|
4. Restart the server, or run `/remotepacksync reload` as an operator.
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
@@ -48,7 +48,7 @@ refreshInterval: 300
|
|||||||
bedrockResourcePackUrl: "https://example.com/packs/server-pack.mcpack"
|
bedrockResourcePackUrl: "https://example.com/packs/server-pack.mcpack"
|
||||||
|
|
||||||
# Optional local alternative; use only when bedrockResourcePackUrl is blank.
|
# Optional local alternative; use only when bedrockResourcePackUrl is blank.
|
||||||
# Relative paths are resolved from plugins/LexianDEV/.
|
# Relative paths are resolved from plugins/RemotePackSync/.
|
||||||
bedrockResourcePack: "bedrock/server-pack.mcpack"
|
bedrockResourcePack: "bedrock/server-pack.mcpack"
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -66,7 +66,7 @@ The SHA-1 response must contain a 40-character hexadecimal SHA-1. Both of these
|
|||||||
|
|
||||||
### Java Edition
|
### Java Edition
|
||||||
|
|
||||||
- On startup and at every refresh interval, LexianDEV fetches only the SHA-1 file asynchronously.
|
- On startup and at every refresh interval, RemotePackSync fetches only the SHA-1 file asynchronously.
|
||||||
- When the SHA-1 changes, it sends the configured resource-pack URL and new hash to every online player.
|
- When the SHA-1 changes, it sends the configured resource-pack URL and new hash to every online player.
|
||||||
- Players joining after a successful SHA-1 fetch receive the current resource pack.
|
- Players joining after a successful SHA-1 fetch receive the current resource pack.
|
||||||
- A failed request leaves the last known-good SHA-1 active, so a brief CDN outage does not interrupt existing pack delivery.
|
- A failed request leaves the last known-good SHA-1 active, so a brief CDN outage does not interrupt existing pack delivery.
|
||||||
@@ -74,24 +74,24 @@ The SHA-1 response must contain a 40-character hexadecimal SHA-1. Both of these
|
|||||||
|
|
||||||
### Bedrock Edition through GeyserMC
|
### Bedrock Edition through GeyserMC
|
||||||
|
|
||||||
- Preferred remote mode: set `bedrockResourcePackUrl` to a direct `.mcpack` or `.zip` download URL. LexianDEV creates a Geyser `UrlPackCodec` and registers it through the public `SessionLoadResourcePacksEvent` API, so Geyser supplies the URL to connecting Bedrock clients.
|
- Preferred remote mode: set `bedrockResourcePackUrl` to a direct `.mcpack` or `.zip` download URL. RemotePackSync creates a Geyser `UrlPackCodec` and registers it through the public `SessionLoadResourcePacksEvent` API, so Geyser supplies the URL to connecting Bedrock clients.
|
||||||
- The remote server must return `Content-Type: application/zip` and an exact `Content-Length`. LexianDEV verifies those headers (following redirects) before registering the URL; a provider that returns `application/octet-stream` is not compatible with Bedrock URL packs. Redirects are allowed only when they ultimately resolve to a valid direct download. The URL should be stable and should expose a changed ETag or URL when the pack changes.
|
- The remote server must return `Content-Type: application/zip` and an exact `Content-Length`. RemotePackSync verifies those headers (following redirects) before registering the URL; a provider that returns `application/octet-stream` is not compatible with Bedrock URL packs. Redirects are allowed only when they ultimately resolve to a valid direct download. The URL should be stable and should expose a changed ETag or URL when the pack changes.
|
||||||
- Geyser validates/downloads remote URL packs during its lifecycle. Use `/lexiandev reload` after changing the URL or after replacing a pack at the same URL; players already connected must reconnect.
|
- Geyser validates/downloads remote URL packs during its lifecycle. Use `/remotepacksync reload` after changing the URL or after replacing a pack at the same URL; players already connected must reconnect.
|
||||||
- Local alternative: set `bedrockResourcePack` to a `.mcpack` or `.zip` file. The source is checked asynchronously at `refreshInterval`; changes receive a deterministic manifest UUID and are managed under `plugins/LexianDEV/bedrock-managed/`.
|
- Local alternative: set `bedrockResourcePack` to a `.mcpack` or `.zip` file. The source is checked asynchronously at `refreshInterval`; changes receive a deterministic manifest UUID and are managed under `plugins/RemotePackSync/bedrock-managed/`.
|
||||||
- The original configured local pack is never modified.
|
- The original configured local pack is never modified.
|
||||||
- Every new Geyser Bedrock connection receives the latest successfully registered pack.
|
- Every new Geyser Bedrock connection receives the latest successfully registered pack.
|
||||||
- The pack must be a valid Bedrock pack containing `manifest.json` at the archive root. Geyser does **not** convert Java packs into Bedrock packs.
|
- The pack must be a valid Bedrock pack containing `manifest.json` at the archive root. Geyser does **not** convert Java packs into Bedrock packs.
|
||||||
- Bedrock's protocol only negotiates packs while a client connects. Players already connected when the file changes must reconnect to receive the new version; LexianDEV cannot hot-push a replacement to an active Bedrock session.
|
- Bedrock's protocol only negotiates packs while a client connects. Players already connected when the file changes must reconnect to receive the new version; RemotePackSync cannot hot-push a replacement to an active Bedrock session.
|
||||||
- If Geyser is absent, Java Edition resource-pack operation continues normally and Bedrock delivery stays disabled.
|
- If Geyser is absent, Java Edition resource-pack operation continues normally and Bedrock delivery stays disabled.
|
||||||
|
|
||||||
## Commands and permissions
|
## Commands and permissions
|
||||||
|
|
||||||
- `/lexiandev reload` (alias: `/ldev reload`) reloads `config.yml` and begins a fresh asynchronous SHA-1 refresh.
|
- `/remotepacksync reload` (alias: `/rps reload`) reloads `config.yml` and begins a fresh asynchronous SHA-1 refresh.
|
||||||
- Permission: `lexiandev.reload` (default: `op`).
|
- Permission: `remotepacksync.reload` (default: `op`).
|
||||||
|
|
||||||
## Compatibility
|
## Compatibility
|
||||||
|
|
||||||
LexianDEV compiles against `org.spigotmc:spigot-api:26.2-R0.1-SNAPSHOT` and Geyser API `2.11.0-SNAPSHOT`, targeting Java 25 as required by Minecraft/Spigot 26.2. Java packs are sent through Bukkit's stable `Player#setResourcePack(String, byte[])` API; Bedrock packs use Geyser's public `UrlPackCodec`/pack-session API. Geyser is a soft dependency, so Java-only servers remain supported.
|
RemotePackSync compiles against `org.spigotmc:spigot-api:26.2-R0.1-SNAPSHOT` and Geyser API `2.11.0-SNAPSHOT`, targeting Java 25 as required by Minecraft/Spigot 26.2. Java packs are sent through Bukkit's stable `Player#setResourcePack(String, byte[])` API; Bedrock packs use Geyser's public `UrlPackCodec`/pack-session API. Geyser is a soft dependency, so Java-only servers remain supported.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
|||||||
@@ -5,9 +5,9 @@
|
|||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
<groupId>dev.lexian</groupId>
|
<groupId>dev.lexian</groupId>
|
||||||
<artifactId>lexiandev</artifactId>
|
<artifactId>remotepacksync</artifactId>
|
||||||
<version>v1.0.0</version>
|
<version>v1.0.0</version>
|
||||||
<name>LexianDEV</name>
|
<name>RemotePackSync</name>
|
||||||
<description>Synchronizes a server resource-pack SHA-1 from a remote URL.</description>
|
<description>Synchronizes a server resource-pack SHA-1 from a remote URL.</description>
|
||||||
<url>https://lexian.dev</url>
|
<url>https://lexian.dev</url>
|
||||||
|
|
||||||
@@ -50,7 +50,7 @@
|
|||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<finalName>LexianDEV</finalName>
|
<finalName>RemotePackSync</finalName>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
|||||||
+4
-4
@@ -1,4 +1,4 @@
|
|||||||
package dev.lexian.lexiandev;
|
package dev.lexian.remotepacksync;
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
@@ -102,7 +102,7 @@ public final class BedrockPackManager {
|
|||||||
}
|
}
|
||||||
if (Bukkit.getPluginManager().getPlugin("Geyser-Spigot") == null) {
|
if (Bukkit.getPluginManager().getPlugin("Geyser-Spigot") == null) {
|
||||||
plugin.getLogger().warning("bedrockResourcePack is configured, but Geyser-Spigot is not installed; "
|
plugin.getLogger().warning("bedrockResourcePack is configured, but Geyser-Spigot is not installed; "
|
||||||
+ "the Bedrock pack will not be sent until Geyser is available and LexianDEV is reloaded.");
|
+ "the Bedrock pack will not be sent until Geyser is available and RemotePackSync is reloaded.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,8 +215,8 @@ public final class BedrockPackManager {
|
|||||||
String extension = sourceName.endsWith(".mcpack") ? ".mcpack" : ".zip";
|
String extension = sourceName.endsWith(".mcpack") ? ".mcpack" : ".zip";
|
||||||
Path directory = plugin.getDataFolder().toPath().resolve("bedrock-managed");
|
Path directory = plugin.getDataFolder().toPath().resolve("bedrock-managed");
|
||||||
Files.createDirectories(directory);
|
Files.createDirectories(directory);
|
||||||
Path target = directory.resolve("LexianDEV-Bedrock" + extension);
|
Path target = directory.resolve("RemotePackSync-Bedrock" + extension);
|
||||||
Path temporary = Files.createTempFile(directory, "LexianDEV-Bedrock-", extension);
|
Path temporary = Files.createTempFile(directory, "RemotePackSync-Bedrock-", extension);
|
||||||
UUID cacheBustingUuid = UUID.nameUUIDFromBytes(sourceSha256);
|
UUID cacheBustingUuid = UUID.nameUUIDFromBytes(sourceSha256);
|
||||||
|
|
||||||
boolean foundManifest = false;
|
boolean foundManifest = false;
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package dev.lexian.lexiandev;
|
package dev.lexian.remotepacksync;
|
||||||
|
|
||||||
import org.bukkit.configuration.file.FileConfiguration;
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
|
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package dev.lexian.lexiandev;
|
package dev.lexian.remotepacksync;
|
||||||
|
|
||||||
import org.geysermc.geyser.api.event.EventRegistrar;
|
import org.geysermc.geyser.api.event.EventRegistrar;
|
||||||
|
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package dev.lexian.lexiandev;
|
package dev.lexian.remotepacksync;
|
||||||
|
|
||||||
import org.bukkit.configuration.file.FileConfiguration;
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
|
|
||||||
+7
-7
@@ -1,4 +1,4 @@
|
|||||||
package dev.lexian.lexiandev;
|
package dev.lexian.remotepacksync;
|
||||||
|
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
import org.bukkit.command.CommandExecutor;
|
import org.bukkit.command.CommandExecutor;
|
||||||
@@ -15,8 +15,8 @@ import java.util.Collections;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
/** Entry point for LexianDEV. Uses only stable Bukkit/Spigot APIs. */
|
/** Entry point for RemotePackSync. Uses only stable Bukkit/Spigot APIs. */
|
||||||
public final class LexianDEVPlugin extends JavaPlugin implements Listener, CommandExecutor, TabCompleter {
|
public final class RemotePackSyncPlugin extends JavaPlugin implements Listener, CommandExecutor, TabCompleter {
|
||||||
private ResourcePackManager resourcePackManager;
|
private ResourcePackManager resourcePackManager;
|
||||||
private BedrockPackManager bedrockPackManager;
|
private BedrockPackManager bedrockPackManager;
|
||||||
|
|
||||||
@@ -30,7 +30,7 @@ public final class LexianDEVPlugin extends JavaPlugin implements Listener, Comma
|
|||||||
resourcePackManager = new ResourcePackManager(this);
|
resourcePackManager = new ResourcePackManager(this);
|
||||||
getServer().getPluginManager().registerEvents(this, this);
|
getServer().getPluginManager().registerEvents(this, this);
|
||||||
|
|
||||||
PluginCommand command = getCommand("lexiandev");
|
PluginCommand command = getCommand("remotepacksync");
|
||||||
if (command != null) {
|
if (command != null) {
|
||||||
command.setExecutor(this);
|
command.setExecutor(this);
|
||||||
command.setTabCompleter(this);
|
command.setTabCompleter(this);
|
||||||
@@ -60,13 +60,13 @@ public final class LexianDEVPlugin extends JavaPlugin implements Listener, Comma
|
|||||||
sender.sendMessage("§eUsage: /" + label + " reload");
|
sender.sendMessage("§eUsage: /" + label + " reload");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (!sender.hasPermission("lexiandev.reload")) {
|
if (!sender.hasPermission("remotepacksync.reload")) {
|
||||||
sender.sendMessage("§cYou do not have permission to reload LexianDEV.");
|
sender.sendMessage("§cYou do not have permission to reload RemotePackSync.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
reloadPackConfiguration();
|
reloadPackConfiguration();
|
||||||
sender.sendMessage("§aLexianDEV configuration reloaded.");
|
sender.sendMessage("§aRemotePackSync configuration reloaded.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
+2
-2
@@ -1,4 +1,4 @@
|
|||||||
package dev.lexian.lexiandev;
|
package dev.lexian.remotepacksync;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
@@ -26,7 +26,7 @@ public final class RemoteSha1Fetcher {
|
|||||||
.GET()
|
.GET()
|
||||||
.timeout(REQUEST_TIMEOUT)
|
.timeout(REQUEST_TIMEOUT)
|
||||||
.header("Accept", "text/plain, text/*;q=0.9, */*;q=0.1")
|
.header("Accept", "text/plain, text/*;q=0.9, */*;q=0.1")
|
||||||
.header("User-Agent", "LexianDEV/v1.0.0")
|
.header("User-Agent", "RemotePackSync/v1.0.0")
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
HttpResponse<byte[]> response = client.send(request, HttpResponse.BodyHandlers.ofByteArray());
|
HttpResponse<byte[]> response = client.send(request, HttpResponse.BodyHandlers.ofByteArray());
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package dev.lexian.lexiandev;
|
package dev.lexian.remotepacksync;
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
resourcePackUrl: ""
|
resourcePackUrl: ""
|
||||||
|
|
||||||
# Direct URL to a text file containing the SHA-1 of the resource pack.
|
# Direct URL to a text file containing the SHA-1 of the resource pack.
|
||||||
# LexianDEV accepts a 40-character hexadecimal SHA-1 anywhere in the response,
|
# RemotePackSync accepts a 40-character hexadecimal SHA-1 anywhere in the response,
|
||||||
# so standard '<hash> filename.zip' checksum files are supported.
|
# so standard '<hash> filename.zip' checksum files are supported.
|
||||||
sha1Url: ""
|
sha1Url: ""
|
||||||
|
|
||||||
@@ -16,5 +16,5 @@ refreshInterval: 300
|
|||||||
bedrockResourcePackUrl: ""
|
bedrockResourcePackUrl: ""
|
||||||
|
|
||||||
# Optional local alternative. Configure this only when bedrockResourcePackUrl is blank.
|
# Optional local alternative. Configure this only when bedrockResourcePackUrl is blank.
|
||||||
# Relative paths are resolved from plugins/LexianDEV/.
|
# Relative paths are resolved from plugins/RemotePackSync/.
|
||||||
bedrockResourcePack: ""
|
bedrockResourcePack: ""
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
name: LexianDEV
|
name: RemotePackSync
|
||||||
version: 'v1.0.0'
|
version: 'v1.0.0'
|
||||||
main: dev.lexian.lexiandev.LexianDEVPlugin
|
main: dev.lexian.remotepacksync.RemotePackSyncPlugin
|
||||||
api-version: '26.2'
|
api-version: '26.2'
|
||||||
description: Synchronizes a server resource-pack SHA-1 from a remote URL.
|
description: Synchronizes a server resource-pack SHA-1 from a remote URL.
|
||||||
author: LexianDEV
|
author: LexianDEV
|
||||||
website: https://lexian.dev
|
website: https://lexian.dev
|
||||||
softdepend: [Geyser-Spigot]
|
softdepend: [Geyser-Spigot]
|
||||||
commands:
|
commands:
|
||||||
lexiandev:
|
remotepacksync:
|
||||||
description: Reload LexianDEV configuration and SHA-1 data.
|
description: Reload RemotePackSync configuration and SHA-1 data.
|
||||||
usage: /lexiandev reload
|
usage: /remotepacksync reload
|
||||||
aliases: [ldev]
|
aliases: [rps]
|
||||||
permissions:
|
permissions:
|
||||||
lexiandev.reload:
|
remotepacksync.reload:
|
||||||
description: Allows reloading LexianDEV.
|
description: Allows reloading RemotePackSync.
|
||||||
default: op
|
default: op
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package dev.lexian.lexiandev;
|
package dev.lexian.remotepacksync;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
Reference in New Issue
Block a user