feat: v1 prototype — core game systems #30

Merged
naomi merged 84 commits from feat/prototype into main 2026-03-08 15:53:39 -07:00
5 changed files with 60 additions and 1 deletions
Showing only changes of commit cb5ea9fee6 - Show all commits
+2 -1
View File
@@ -5,4 +5,5 @@ JWT_SECRET="op://Environment Variables - Naomi/Elysium/jwt secret"
DATABASE_URL="op://Environment Variables - Naomi/Elysium/mongo url"
ANTI_CHEAT_SECRET="op://Environment Variables - Naomi/Elysium/anti cheat secret"
PORT="op://Environment Variables - Naomi/Elysium/port"
CORS_ORIGIN="op://Environment Variables - Naomi/Elysium/origin"
CORS_ORIGIN="op://Environment Variables - Naomi/Elysium/origin"
DISCORD_MILESTONE_WEBHOOK="op://Environment Variables - Naomi/Elysium/discord milestone webhook"
+7
View File
@@ -7,6 +7,7 @@ import {
buildPostApotheosisState,
isEligibleForApotheosis,
} from "../services/apotheosis.js";
import { postMilestoneWebhook } from "../services/webhook.js";
export const apotheosisRouter = new Hono<HonoEnv>();
@@ -61,5 +62,11 @@ apotheosisRouter.post("/", async (context) => {
},
});
void postMilestoneWebhook(discordId, "apotheosis", {
prestige: newState.prestige.count,
transcendence: newState.transcendence?.count ?? 0,
apotheosis: newApotheosisData.count,
});
return context.json({ newApotheosisCount: newApotheosisData.count });
});
+7
View File
@@ -10,6 +10,7 @@ import {
computeRunestoneMultipliers,
isEligibleForPrestige,
} from "../services/prestige.js";
import { postMilestoneWebhook } from "../services/webhook.js";
export const prestigeRouter = new Hono<HonoEnv>();
@@ -87,6 +88,12 @@ prestigeRouter.post("/", async (context) => {
},
});
void postMilestoneWebhook(discordId, "prestige", {
prestige: newPrestigeData.count,
transcendence: newState.transcendence?.count ?? 0,
apotheosis: newState.apotheosis?.count ?? 0,
});
return context.json({
runestones: runestonesEarned,
newPrestigeCount: newPrestigeData.count,
+7
View File
@@ -9,6 +9,7 @@ import {
computeTranscendenceMultipliers,
isEligibleForTranscendence,
} from "../services/transcendence.js";
import { postMilestoneWebhook } from "../services/webhook.js";
export const transcendenceRouter = new Hono<HonoEnv>();
@@ -66,6 +67,12 @@ transcendenceRouter.post("/", async (context) => {
},
});
void postMilestoneWebhook(discordId, "transcendence", {
prestige: newState.prestige.count,
transcendence: newTranscendenceData.count,
apotheosis: newState.apotheosis?.count ?? 0,
});
return context.json({
echoes: echoesEarned,
newTranscendenceCount: newTranscendenceData.count,
+37
View File
@@ -0,0 +1,37 @@
type MilestoneType = "prestige" | "transcendence" | "apotheosis";
interface MilestoneCounts {
prestige: number;
transcendence: number;
apotheosis: number;
}
const MILESTONE_VERBS: Record<MilestoneType, string> = {
prestige: "prestiged",
transcendence: "transcended",
apotheosis: "reached apotheosis",
};
export const postMilestoneWebhook = async (
discordId: string,
milestone: MilestoneType,
counts: MilestoneCounts,
): Promise<void> => {
const webhookUrl = process.env["DISCORD_MILESTONE_WEBHOOK"];
if (!webhookUrl) {
return;
}
const verb = MILESTONE_VERBS[milestone];
const content = `<@${discordId}> has ${verb}~! They are now on Prestige ${counts.prestige}, Transcendence ${counts.transcendence}, Apotheosis ${counts.apotheosis}!`;
try {
await fetch(webhookUrl, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ content }),
});
} catch {
// Graceful degradation — webhook failure must not affect the game action
}
};