Allow beta-typed Modrinth builds for EasyAuth (easyauth:beta)
EasyAuth publishes its 26.x builds as beta on Modrinth, and the itzg resolver only accepts release-typed versions by default, so the mc container failed to start. Pin easyauth:beta in the default mod list and teach the panel's mod manager to compare entries by base slug so version qualifiers don't break protected/duplicate checks. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
279d137ce5
commit
795c2af50b
6 files changed
+32
-11
No files matched your search
+3
-1
@@ -24,7 +24,9 @@ MC_SEED=
|
|||||||
|
|
||||||
# Server-side mods (Modrinth project slugs, comma-separated).
|
# Server-side mods (Modrinth project slugs, comma-separated).
|
||||||
# Auto-resolved to the newest compatible release on every container start.
|
# Auto-resolved to the newest compatible release on every container start.
|
||||||
MODRINTH_PROJECTS=fabric-api,easyauth,spark,lithium,ferrite-core
|
# Append ":beta" to allow beta-typed builds for a project (EasyAuth ships
|
||||||
|
# its 26.x builds as beta on Modrinth).
|
||||||
|
MODRINTH_PROJECTS=fabric-api,easyauth:beta,spark,lithium,ferrite-core
|
||||||
# To run a full modpack instead, set its Modrinth slug (e.g. adrenaline)
|
# To run a full modpack instead, set its Modrinth slug (e.g. adrenaline)
|
||||||
# and see docs/mods-and-modpacks.md before enabling.
|
# and see docs/mods-and-modpacks.md before enabling.
|
||||||
MODRINTH_MODPACK=
|
MODRINTH_MODPACK=
|
||||||
|
|||||||
@@ -31,6 +31,10 @@ type SearchHit = {
|
|||||||
|
|
||||||
const PROTECTED = new Set(["fabric-api", "easyauth"]);
|
const PROTECTED = new Set(["fabric-api", "easyauth"]);
|
||||||
|
|
||||||
|
// Managed entries may carry a version qualifier ("easyauth:beta") — compare
|
||||||
|
// by the base slug.
|
||||||
|
const baseSlug = (entry: string) => entry.split(":")[0].toLowerCase();
|
||||||
|
|
||||||
export default function ModsPage() {
|
export default function ModsPage() {
|
||||||
const { data, refresh } = useApi<ModsData>("/api/mods", 0);
|
const { data, refresh } = useApi<ModsData>("/api/mods", 0);
|
||||||
const [query, setQuery] = useState("");
|
const [query, setQuery] = useState("");
|
||||||
@@ -82,7 +86,7 @@ export default function ModsPage() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const managedSet = new Set((data?.managed ?? []).map((s) => s.toLowerCase()));
|
const managedSet = new Set((data?.managed ?? []).map(baseSlug));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
@@ -121,7 +125,7 @@ export default function ModsPage() {
|
|||||||
)}
|
)}
|
||||||
{hits?.length === 0 && <p className="py-6 text-center text-xs text-muted">No compatible mods found.</p>}
|
{hits?.length === 0 && <p className="py-6 text-center text-xs text-muted">No compatible mods found.</p>}
|
||||||
{hits?.map((h) => {
|
{hits?.map((h) => {
|
||||||
const already = managedSet.has(h.slug.toLowerCase());
|
const already = managedSet.has(baseSlug(h.slug));
|
||||||
return (
|
return (
|
||||||
<div key={h.slug} className="flex items-center gap-3 rounded-lg border border-border bg-surface2 p-2.5">
|
<div key={h.slug} className="flex items-center gap-3 rounded-lg border border-border bg-surface2 p-2.5">
|
||||||
{h.icon_url ? (
|
{h.icon_url ? (
|
||||||
@@ -166,13 +170,13 @@ export default function ModsPage() {
|
|||||||
{(data?.managed ?? []).map((slug) => (
|
{(data?.managed ?? []).map((slug) => (
|
||||||
<li key={slug} className="flex items-center gap-2 rounded-lg border border-border bg-surface2 px-3 py-2">
|
<li key={slug} className="flex items-center gap-2 rounded-lg border border-border bg-surface2 px-3 py-2">
|
||||||
<span className="font-mono text-sm">{slug}</span>
|
<span className="font-mono text-sm">{slug}</span>
|
||||||
{PROTECTED.has(slug.toLowerCase()) && (
|
{PROTECTED.has(baseSlug(slug)) && (
|
||||||
<Badge color="info">
|
<Badge color="info">
|
||||||
<Lock size={9} /> required
|
<Lock size={9} /> required
|
||||||
</Badge>
|
</Badge>
|
||||||
)}
|
)}
|
||||||
<span className="ml-auto">
|
<span className="ml-auto">
|
||||||
{!PROTECTED.has(slug.toLowerCase()) && (
|
{!PROTECTED.has(baseSlug(slug)) && (
|
||||||
<Button
|
<Button
|
||||||
size="sm"
|
size="sm"
|
||||||
variant="danger"
|
variant="danger"
|
||||||
|
|||||||
@@ -40,6 +40,10 @@ export async function searchMods(query: string): Promise<ModSearchResult[]> {
|
|||||||
return data.hits;
|
return data.hits;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Entries may carry a version qualifier after a colon (e.g. "easyauth:beta"
|
||||||
|
* allows beta-typed builds); comparisons always use the base slug.
|
||||||
|
*/
|
||||||
export function managedSlugs(): string[] {
|
export function managedSlugs(): string[] {
|
||||||
return (readEnvFile()["MODRINTH_PROJECTS"] ?? "")
|
return (readEnvFile()["MODRINTH_PROJECTS"] ?? "")
|
||||||
.split(",")
|
.split(",")
|
||||||
@@ -47,22 +51,26 @@ export function managedSlugs(): string[] {
|
|||||||
.filter(Boolean);
|
.filter(Boolean);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function baseSlug(entry: string): string {
|
||||||
|
return entry.split(":")[0].toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
const PROTECTED_SLUGS = new Set(["fabric-api", "easyauth"]);
|
const PROTECTED_SLUGS = new Set(["fabric-api", "easyauth"]);
|
||||||
|
|
||||||
export function addManagedMod(slug: string): string[] {
|
export function addManagedMod(slug: string): string[] {
|
||||||
if (!/^[a-z0-9][a-z0-9\-_]{0,63}$/i.test(slug)) throw new Error("Invalid Modrinth slug");
|
if (!/^[a-z0-9][a-z0-9\-_]{0,63}$/i.test(slug)) throw new Error("Invalid Modrinth slug");
|
||||||
const slugs = managedSlugs();
|
const slugs = managedSlugs();
|
||||||
if (slugs.some((s) => s.toLowerCase() === slug.toLowerCase())) return slugs;
|
if (slugs.some((s) => baseSlug(s) === slug.toLowerCase())) return slugs;
|
||||||
const next = [...slugs, slug.toLowerCase()];
|
const next = [...slugs, slug.toLowerCase()];
|
||||||
writeEnvFile({ MODRINTH_PROJECTS: next.join(",") });
|
writeEnvFile({ MODRINTH_PROJECTS: next.join(",") });
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function removeManagedMod(slug: string): string[] {
|
export function removeManagedMod(slug: string): string[] {
|
||||||
if (PROTECTED_SLUGS.has(slug.toLowerCase())) {
|
if (PROTECTED_SLUGS.has(baseSlug(slug))) {
|
||||||
throw new Error(`${slug} is required by the panel (auth/loader) and can't be removed here`);
|
throw new Error(`${slug} is required by the panel (auth/loader) and can't be removed here`);
|
||||||
}
|
}
|
||||||
const next = managedSlugs().filter((s) => s.toLowerCase() !== slug.toLowerCase());
|
const next = managedSlugs().filter((s) => baseSlug(s) !== baseSlug(slug));
|
||||||
writeEnvFile({ MODRINTH_PROJECTS: next.join(",") });
|
writeEnvFile({ MODRINTH_PROJECTS: next.join(",") });
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-2
@@ -33,8 +33,10 @@ services:
|
|||||||
ENABLE_RCON: "true"
|
ENABLE_RCON: "true"
|
||||||
RCON_PASSWORD: ${RCON_PASSWORD:?generate with scripts/setup.sh}
|
RCON_PASSWORD: ${RCON_PASSWORD:?generate with scripts/setup.sh}
|
||||||
|
|
||||||
# Server-side mods, auto-resolved for the current MC version on every start
|
# Server-side mods, auto-resolved for the current MC version on every start.
|
||||||
MODRINTH_PROJECTS: ${MODRINTH_PROJECTS:-fabric-api,easyauth,spark,lithium,ferrite-core}
|
# ":beta" allows beta-typed builds for that project (EasyAuth publishes
|
||||||
|
# its 26.x builds as beta).
|
||||||
|
MODRINTH_PROJECTS: ${MODRINTH_PROJECTS:-fabric-api,easyauth:beta,spark,lithium,ferrite-core}
|
||||||
MODRINTH_DOWNLOAD_DEPENDENCIES: required
|
MODRINTH_DOWNLOAD_DEPENDENCIES: required
|
||||||
|
|
||||||
# Modpack support (leave empty for lean Fabric; see docs/mods-and-modpacks.md)
|
# Modpack support (leave empty for lean Fabric; see docs/mods-and-modpacks.md)
|
||||||
|
|||||||
@@ -36,9 +36,13 @@ restart the server.
|
|||||||
Managed mods are pinned by *project slug*, not version, in `.env`:
|
Managed mods are pinned by *project slug*, not version, in `.env`:
|
||||||
|
|
||||||
```
|
```
|
||||||
MODRINTH_PROJECTS=fabric-api,easyauth,spark,lithium,ferrite-core
|
MODRINTH_PROJECTS=fabric-api,easyauth:beta,spark,lithium,ferrite-core
|
||||||
```
|
```
|
||||||
|
|
||||||
|
A `:beta` (or `:alpha`) suffix widens which release types are accepted for that
|
||||||
|
project — EasyAuth publishes its 26.x builds as beta on Modrinth, so it needs the
|
||||||
|
suffix. Without one, only release-typed builds are considered.
|
||||||
|
|
||||||
Every time the server container (re)starts, the itzg image resolves each slug to the
|
Every time the server container (re)starts, the itzg image resolves each slug to the
|
||||||
**newest release compatible with your Minecraft version** and downloads it. So:
|
**newest release compatible with your Minecraft version** and downloads it. So:
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
|---|---|
|
|---|---|
|
||||||
| `EULA` complaints | `EULA=TRUE` is set by compose — make sure you didn't override it |
|
| `EULA` complaints | `EULA=TRUE` is set by compose — make sure you didn't override it |
|
||||||
| A mod failed to resolve for your version | Remove that slug on the Mods page, Apply. (New MC version + mod hasn't updated yet.) |
|
| A mod failed to resolve for your version | Remove that slug on the Mods page, Apply. (New MC version + mod hasn't updated yet.) |
|
||||||
|
| `No candidate versions of '<mod>' … matched versionType=release` | The mod only ships beta builds for this MC version — append `:beta` to its entry in `MODRINTH_PROJECTS` (e.g. `easyauth:beta`) and `docker compose up -d mc` |
|
||||||
| `OutOfMemoryError` | Lower `MC_VIEW_DISTANCE`, or raise `MC_MEMORY`/`MC_CONTAINER_MEM_LIMIT` if the host has headroom |
|
| `OutOfMemoryError` | Lower `MC_VIEW_DISTANCE`, or raise `MC_MEMORY`/`MC_CONTAINER_MEM_LIMIT` if the host has headroom |
|
||||||
| Port already in use | Something else on 25565 — change `MC_PORT` in `.env` |
|
| Port already in use | Something else on 25565 — change `MC_PORT` in `.env` |
|
||||||
| Crash right after "Done" | A mod conflict — disable recently added jars (Mods page → power icon) |
|
| Crash right after "Done" | A mod conflict — disable recently added jars (Mods page → power icon) |
|
||||||
|
|||||||
Reference in new issue
Block a user