game version re-ordering

This commit is contained in:
DecDuck
2024-10-14 20:34:23 +11:00
parent 8674ac7211
commit 329c74d3ce
18 changed files with 354 additions and 50 deletions
+13
View File
@@ -16,6 +16,19 @@ export default defineEventHandler(async (h3) => {
where: {
id: gameId,
},
include: {
versions: {
orderBy: {
versionIndex: "asc",
},
select: {
versionIndex: true,
versionName: true,
platform: true,
delta: true,
}
},
},
});
if (!game)
@@ -0,0 +1,26 @@
import prisma from "~/server/internal/db/database";
export default defineEventHandler(async (h3) => {
const user = await h3.context.session.getAdminUser(h3);
if (!user) throw createError({ statusCode: 403 });
const body = await readBody(h3);
const gameId = body.id.toString();
const version = body.versionName.toString();
if (!gameId || !version)
throw createError({
statusCode: 400,
statusMessage: "Missing ID or versionName in body",
});
await prisma.gameVersion.delete({
where: {
gameId_versionName: {
gameId: gameId,
versionName: version,
},
},
});
return {};
});
+40
View File
@@ -0,0 +1,40 @@
import prisma from "~/server/internal/db/database";
export default defineEventHandler(async (h3) => {
const user = await h3.context.session.getAdminUser(h3);
if (!user) throw createError({ statusCode: 403 });
const body = await readBody(h3);
const gameId = body.id?.toString();
// We expect an array of the version names for this game
const versions: string[] | undefined = body.versions;
if (!gameId || !versions || !Array.isArray(versions))
throw createError({
statusCode: 400,
statusMessage: "Missing id, versions or versions is not an array",
});
const newVersions = await prisma.$transaction(
versions.map((versionName, versionIndex) =>
prisma.gameVersion.update({
where: {
gameId_versionName: {
gameId: gameId,
versionName: versionName,
},
},
data: {
versionIndex: versionIndex,
},
select: {
versionIndex: true,
versionName: true,
platform: true,
delta: true,
}
})
)
);
return newVersions;
});
@@ -10,23 +10,24 @@ export default defineEventHandler(async (h3) => {
const platform = body.platform;
const startup = body.startup;
const setup = body.setup ?? "";
if (
!gameId ||
!versionName ||
!platform ||
!startup
)
const delta = body.delta ?? false;
if (!gameId || !versionName || !platform || (!delta && !startup))
throw createError({
statusCode: 400,
statusMessage:
"Missing id, version, platform, setup or startup from body",
});
const taskId = await libraryManager.importVersion(gameId, versionName, {
platform,
startup,
setup,
});
const taskId = await libraryManager.importVersion(
gameId,
versionName,
{
platform,
startup,
setup,
},
delta
);
if (!taskId)
throw createError({
statusCode: 400,
@@ -0,0 +1,12 @@
import { defineClientEventHandler } from "~/server/internal/clients/event-handler";
export default defineClientEventHandler(async (h3) => {
const query = getQuery(h3);
const id = query.id?.toString();
const version = query.version?.toString();
if (!id || !version)
throw createError({
statusCode: 400,
statusMessage: "Missing id or version in query",
});
});
@@ -14,6 +14,14 @@ export default defineClientEventHandler(async (h3, {}) => {
where: {
gameId: id,
},
select: {
versionIndex: true,
versionName: true,
platform: true,
setupCommand: true,
launchCommand: true,
delta: true,
}
});
return versions;
@@ -1,8 +1,16 @@
# Drop Download System
Drop downloads come in two types:
# Drop P2P System
Drop clients have a variety of P2P or P2P-like methods of data transfer available
## Public (not quite) HTTPS downloads endpoints
These use public HTTPS certificate, and while are authenticated, are 'public' in the sense that they aren't P2P; anyone can connect to them
## Private mTLS P2P endpoints
Drop clients use P2P mTLS aided by the P2P co-ordinator to transfer chunks between themselves.
Drop clients use P2P mTLS aided by the P2P co-ordinator to transfer chunks between themselves. This happens over HTTP.
## Private mTLS Wireguard tunnels
Drop clients can establish P2P Wireguard
+52
View File
@@ -0,0 +1,52 @@
export type DropChunk = {
permissions: number;
ids: string[];
checksums: string[];
lengths: string[];
};
export type DropManifest = {
[key: string]: DropChunk;
};
export type DropManifestMetadata = {
manifest: DropManifest;
versionName: string;
};
export type DropGeneratedManifest = DropManifest & {
[key: string]: { versionName: string };
};
class ManifestGenerator {
static generateManifest(
rootManifest: DropManifestMetadata,
...overlays: DropManifestMetadata[]
): DropGeneratedManifest {
if (overlays.length == 0) {
return Object.fromEntries(
Object.entries(rootManifest.manifest).map(([key, value]) => [
key,
Object.assign({}, value, { versionName: rootManifest.versionName }),
])
);
}
// Recurse in verse order through versions, skipping files that already exist.
const versions = [...overlays.reverse(), rootManifest];
const manifest: DropGeneratedManifest = {};
for (const version of versions) {
for (const [filename, chunk] of Object.entries(version.manifest)) {
if (manifest[filename]) continue;
manifest[filename] = Object.assign({}, chunk, {
versionName: version.versionName,
});
}
}
return manifest;
}
}
export const manifestGenerator = new ManifestGenerator();
export default manifestGenerator;
+8 -1
View File
@@ -195,7 +195,8 @@ class LibraryManager {
async importVersion(
gameId: string,
versionName: string,
metadata: { platform: string; setup: string; startup: string }
metadata: { platform: string; setup: string; startup: string },
delta = false
) {
const taskId = `import:${gameId}:${versionName}`;
@@ -238,6 +239,10 @@ class LibraryManager {
log("Created manifest successfully!");
const currentIndex = await prisma.gameVersion.count({
where: { gameId: gameId },
});
// Then, create the database object
const version = await prisma.gameVersion.create({
data: {
@@ -247,6 +252,8 @@ class LibraryManager {
setupCommand: metadata.setup,
launchCommand: metadata.startup,
dropletManifest: manifest,
versionIndex: currentIndex,
delta: delta,
},
});