Minegame.exe

This commit is contained in:
MD1125 2025-06-12 22:35:54 +02:00
parent 7b11266f72
commit 11197d1382
6 changed files with 979 additions and 5 deletions

View file

@ -0,0 +1,74 @@
import { auth } from '$lib/auth';
import { error, json } from '@sveltejs/kit';
import { db } from '$lib/server/db';
import { user } from '$lib/server/db/schema';
import { eq } from 'drizzle-orm';
import { activeGames } from '$lib/server/games/mines';
import type { RequestHandler } from './$types';
export const POST: RequestHandler = async ({ request }) => {
const session = await auth.api.getSession({
headers: request.headers
});
if (!session?.user) {
throw error(401, 'Not authenticated');
}
try {
const { sessionToken } = await request.json();
const game = activeGames.get(sessionToken);
const userId = Number(session.user.id);
if (!game) {
return json({ error: 'Invalid session' }, { status: 400 });
}
const result = await db.transaction(async (tx) => {
const [userData] = await tx
.select({ baseCurrencyBalance: user.baseCurrencyBalance })
.from(user)
.where(eq(user.id, userId))
.for('update')
.limit(1);
const currentBalance = Number(userData.baseCurrencyBalance);
let payout: number;
let newBalance: number;
// If no tiles revealed, treat as abort and return full bet. This could be changed later to keep the initial bet on the Server
if (game.revealedTiles.length === 0) {
payout = game.betAmount;
newBalance = Math.round((currentBalance + payout) * 100000000) / 100000000;
} else {
// Calculate payout
payout = game.betAmount * game.currentMultiplier;
const roundedPayout = Math.round(payout * 100000000) / 100000000;
newBalance = Math.round((currentBalance + roundedPayout) * 100000000) / 100000000;
}
await tx
.update(user)
.set({
baseCurrencyBalance: newBalance.toFixed(8),
updatedAt: new Date()
})
.where(eq(user.id, userId));
activeGames.delete(sessionToken);
return {
newBalance,
payout,
amountWagered: game.betAmount,
isAbort: game.revealedTiles.length === 0
};
});
return json(result);
} catch (e) {
console.error('Mines cashout error:', e);
const errorMessage = e instanceof Error ? e.message : 'Internal server error';
return json({ error: errorMessage }, { status: 400 });
}
};

View file

@ -0,0 +1,81 @@
import { auth } from '$lib/auth';
import { error, json } from '@sveltejs/kit';
import { activeGames, calculateMultiplier } from '$lib/server/games/mines';
import type { RequestHandler } from './$types';
import { db } from '$lib/server/db';
import { user } from '$lib/server/db/schema';
import { eq } from 'drizzle-orm';
export const POST: RequestHandler = async ({ request }) => {
const session = await auth.api.getSession({
headers: request.headers
});
if (!session?.user) {
throw error(401, 'Not authenticated');
}
try {
const { sessionToken, tileIndex } = await request.json();
const game = activeGames.get(sessionToken);
if (!game) {
return json({ error: 'Invalid session' }, { status: 400 });
}
if (game.revealedTiles.includes(tileIndex)) {
return json({ error: 'Tile already revealed' }, { status: 400 });
}
// Update last activity time
game.lastActivity = Date.now();
// Check if hit mine
if (game.minePositions.includes(tileIndex)) {
game.status = 'lost';
const minePositions = game.minePositions;
// Fetch user balance to return after loss
const userId = Number(session.user.id);
const [userData] = await db
.select({ baseCurrencyBalance: user.baseCurrencyBalance })
.from(user)
.where(eq(user.id, userId))
.limit(1);
activeGames.delete(sessionToken);
return json({
hitMine: true,
minePositions,
newBalance: Number(userData.baseCurrencyBalance),
status: 'lost'
});
}
// Safe tile
game.revealedTiles.push(tileIndex);
game.currentMultiplier = calculateMultiplier(
game.revealedTiles.length,
game.mineCount,
game.betAmount
);
// Check if all safe tiles are revealed. Crazy when you get this :)
if (game.revealedTiles.length === 25 - game.mineCount) {
game.status = 'won';
}
return json({
hitMine: false,
currentMultiplier: game.currentMultiplier,
status: game.status
});
} catch (e) {
console.error('Mines reveal error:', e);
const errorMessage = e instanceof Error ? e.message : 'Internal server error';
return json({ error: errorMessage }, { status: 400 });
}
};

View file

@ -0,0 +1,100 @@
import { auth } from '$lib/auth';
import { error, json } from '@sveltejs/kit';
import { db } from '$lib/server/db';
import { user } from '$lib/server/db/schema';
import { eq } from 'drizzle-orm';
import { activeGames } from '$lib/server/games/mines';
import type { RequestHandler } from './$types';
export const POST: RequestHandler = async ({ request }) => {
const session = await auth.api.getSession({
headers: request.headers
});
if (!session?.user) {
throw error(401, 'Not authenticated');
}
try {
const { betAmount, mineCount } = await request.json();
const userId = Number(session.user.id);
if (!betAmount || !mineCount || mineCount < 3 || mineCount > 24) {
return json({ error: 'Invalid bet amount or mine count' }, { status: 400 });
}
if (betAmount > 1000000) {
return json({ error: 'Bet amount too large' }, { status: 400 });
}
const result = await db.transaction(async (tx) => {
const [userData] = await tx
.select({ baseCurrencyBalance: user.baseCurrencyBalance })
.from(user)
.where(eq(user.id, userId))
.for('update')
.limit(1);
const currentBalance = Number(userData.baseCurrencyBalance);
const roundedAmount = Math.round(betAmount * 100000000) / 100000000;
const roundedBalance = Math.round(currentBalance * 100000000) / 100000000;
if (roundedAmount > roundedBalance) {
throw new Error(`Insufficient funds. You need *${roundedAmount.toFixed(2)} but only have *${roundedBalance.toFixed(2)}`);
}
// Generate mine positions
const positions = new Set<number>();
while (positions.size < mineCount) {
positions.add(Math.floor(Math.random() * 25));
}
const safePositions = [];
for (let i = 0; i < 25; i++) {
if (!positions.has(i)) safePositions.push(i);
}
console.log(positions)
console.log('Safe positions:', safePositions);
// transaction token for authentication
const randomBytes = new Uint8Array(8);
crypto.getRandomValues(randomBytes);
const sessionToken = Array.from(randomBytes)
.map(b => b.toString(16).padStart(2, '0'))
.join('');
const now = Date.now();
// Create session
activeGames.set(sessionToken, {
sessionToken,
betAmount: roundedAmount,
mineCount,
minePositions: Array.from(positions),
revealedTiles: [],
startTime: now,
lastActivity: now,
currentMultiplier: 1,
status: 'active',
userId
});
// Hold bet amount on server to prevent the user from like sending it to another account and farming money without a risk
await tx
.update(user)
.set({
baseCurrencyBalance: (roundedBalance - roundedAmount).toFixed(8),
updatedAt: new Date()
})
.where(eq(user.id, userId));
return { sessionToken };
});
return json(result);
} catch (e) {
console.error('Mines start error:', e);
const errorMessage = e instanceof Error ? e.message : 'Internal server error';
return json({ error: errorMessage }, { status: 400 });
}
};