diff --git a/i18n/locales/en_us.json b/i18n/locales/en_us.json index 2356acb..993579e 100644 --- a/i18n/locales/en_us.json +++ b/i18n/locales/en_us.json @@ -308,8 +308,10 @@ "umuLauncherId": "UMU Launcher ID", "umuOverride": "Override UMU Launcher Game ID", "umuOverrideDesc": "By default, Drop uses a non-ID when launching with UMU Launcher. In order to get the right patches for some games, you may have to manually set this field.", - "updateMode": "Update mode", + "updateMode": "Update/delta mode", "updateModeDesc": "When enabled, these files will be installed on top of (overwriting) the previous version's. If multiple \"update modes\" are chained together, they are applied in order.", + "hide": "Hide version", + "hideDesc": "Hide version so clients cannot install it. Useful if you are using delta versions to save space, but don't want to allow users to install partial games.", "version": "Select version to import" }, "withoutMetadata": "Import without metadata" diff --git a/pages/admin/library/[id]/import.vue b/pages/admin/library/[id]/import.vue index 485a57c..11d5711 100644 --- a/pages/admin/library/[id]/import.vue +++ b/pages/admin/library/[id]/import.vue @@ -398,6 +398,36 @@ /> + + + + {{ $t("library.admin.import.version.hide") }} + {{ + $t("library.admin.import.version.hideDesc") + }} + + + + +
({ +const versionSettings = ref>({ platform: undefined, launch: "", launchArgs: "", @@ -581,6 +601,7 @@ const versionSettings = ref<{ delta: false, onlySetup: false, umuId: "", + hide: false, }); const versionGuesses = diff --git a/prisma/migrations/20250819062913_add_hidden_field_to_versions/migration.sql b/prisma/migrations/20250819062913_add_hidden_field_to_versions/migration.sql new file mode 100644 index 0000000..24df7d6 --- /dev/null +++ b/prisma/migrations/20250819062913_add_hidden_field_to_versions/migration.sql @@ -0,0 +1,8 @@ +-- DropIndex +DROP INDEX "GameTag_name_idx"; + +-- AlterTable +ALTER TABLE "GameVersion" ADD COLUMN "hidden" BOOLEAN NOT NULL DEFAULT false; + +-- CreateIndex +CREATE INDEX "GameTag_name_idx" ON "GameTag" USING GIST ("name" gist_trgm_ops(siglen=32)); diff --git a/prisma/models/content.prisma b/prisma/models/content.prisma index 3ab28be..7f00d68 100644 --- a/prisma/models/content.prisma +++ b/prisma/models/content.prisma @@ -56,12 +56,11 @@ model GameTag { id String @id @default(uuid()) name String @unique - games Game[] + games Game[] @@index([name(ops: raw("gist_trgm_ops(siglen=32)"))], type: Gist) } - model GameRating { id String @id @default(uuid()) @@ -95,6 +94,7 @@ model GameVersion { setupCommand String @default("") // Command to setup game (dependencies and such) setupArgs String[] onlySetup Boolean @default(false) + hidden Boolean @default(false) umuIdOverride String? diff --git a/server/api/v1/admin/import/version/index.post.ts b/server/api/v1/admin/import/version/index.post.ts index ab9ad1c..fabf682 100644 --- a/server/api/v1/admin/import/version/index.post.ts +++ b/server/api/v1/admin/import/version/index.post.ts @@ -1,20 +1,25 @@ import { type } from "arktype"; +import { PlatformClient } from "~/composables/types"; import { readDropValidatedBody, throwingArktype } from "~/server/arktype"; import aclManager from "~/server/internal/acls"; import prisma from "~/server/internal/db/database"; import libraryManager from "~/server/internal/library"; -import { parsePlatform } from "~/server/internal/utils/parseplatform"; -const ImportVersion = type({ +export const ImportVersion = type({ id: "string", version: "string", - platform: "string", + platform: type.valueOf(PlatformClient), + launch: "string = ''", launchArgs: "string = ''", + setup: "string = ''", setupArgs: "string = ''", + onlySetup: "boolean = false", + hide: "boolean = false", + delta: "boolean = false", umuId: "string = ''", }).configure(throwingArktype); @@ -34,15 +39,12 @@ export default defineEventHandler(async (h3) => { onlySetup, delta, umuId, + hide, } = await readDropValidatedBody(h3, ImportVersion); - const platformParsed = parsePlatform(platform); - if (!platformParsed) - throw createError({ statusCode: 400, statusMessage: "Invalid platform." }); - if (delta) { const validOverlayVersions = await prisma.gameVersion.count({ - where: { gameId: id, platform: platformParsed, delta: false }, + where: { gameId: id, platform, delta: false }, }); if (validOverlayVersions == 0) throw createError({ @@ -75,6 +77,7 @@ export default defineEventHandler(async (h3) => { launchArgs, setup, setupArgs, + hide, umuId, delta, diff --git a/server/api/v1/client/game/version.get.ts b/server/api/v1/client/game/version.get.ts index e9cf38e..37af994 100644 --- a/server/api/v1/client/game/version.get.ts +++ b/server/api/v1/client/game/version.get.ts @@ -17,6 +17,7 @@ export default defineClientEventHandler(async (h3) => { gameId: id, versionName: version, }, + hidden: false, }, }); diff --git a/server/api/v1/client/game/versions.get.ts b/server/api/v1/client/game/versions.get.ts index fab014a..1ac4b55 100644 --- a/server/api/v1/client/game/versions.get.ts +++ b/server/api/v1/client/game/versions.get.ts @@ -13,6 +13,7 @@ export default defineClientEventHandler(async (h3) => { const versions = await prisma.gameVersion.findMany({ where: { gameId: id, + hidden: false, }, orderBy: { versionIndex: "desc", // Latest one first diff --git a/server/internal/library/index.ts b/server/internal/library/index.ts index 0a74dfe..4285e86 100644 --- a/server/internal/library/index.ts +++ b/server/internal/library/index.ts @@ -15,6 +15,7 @@ import { GameNotFoundError, type LibraryProvider } from "./provider"; import { logger } from "../logging"; import type { GameModel } from "~/prisma/client/models"; import { createHash } from "node:crypto"; +import type { ImportVersion } from "~/server/api/v1/admin/import/version/index.post"; export function createGameImportTaskId(libraryId: string, libraryPath: string) { return createHash("md5") @@ -231,18 +232,7 @@ class LibraryManager { async importVersion( gameId: string, versionName: string, - metadata: { - platform: string; - onlySetup: boolean; - - setup: string; - setupArgs: string; - launch: string; - launchArgs: string; - delta: boolean; - - umuId: string; - }, + metadata: Omit, ) { const taskId = createVersionImportTaskId(gameId, versionName); @@ -286,41 +276,24 @@ class LibraryManager { }); // Then, create the database object - if (metadata.onlySetup) { - await prisma.gameVersion.create({ - data: { - gameId: gameId, - versionName: versionName, - dropletManifest: manifest, - versionIndex: currentIndex, - delta: metadata.delta, - umuIdOverride: metadata.umuId, - platform: platform, + await prisma.gameVersion.create({ + data: { + gameId: gameId, + versionName: versionName, + dropletManifest: manifest, + versionIndex: currentIndex, + delta: metadata.delta, + umuIdOverride: metadata.umuId, + platform: platform, - onlySetup: true, - setupCommand: metadata.setup, - setupArgs: metadata.setupArgs.split(" "), - }, - }); - } else { - await prisma.gameVersion.create({ - data: { - gameId: gameId, - versionName: versionName, - dropletManifest: manifest, - versionIndex: currentIndex, - delta: metadata.delta, - umuIdOverride: metadata.umuId, - platform: platform, - - onlySetup: false, - setupCommand: metadata.setup, - setupArgs: metadata.setupArgs.split(" "), - launchCommand: metadata.launch, - launchArgs: metadata.launchArgs.split(" "), - }, - }); - } + hidden: metadata.hide, + onlySetup: metadata.onlySetup, + setupCommand: metadata.setup, + setupArgs: metadata.setupArgs.split(" "), + launchCommand: metadata.launch, + launchArgs: metadata.launchArgs.split(" "), + }, + }); logger.info("Successfully created version!");