import { RedisClient } from "bun"; const redis = new RedisClient("redis://localhost:40379"); const colors = { reset: "\x1b[0m", cyan: "\x1b[36m", green: "\x1b[32m", yellow: "\x1b[33m", magenta: "\x1b[35m", red: "\x1b[31m", gray: "\x1b[90m", bold: "\x1b[1m", }; let totalRequests = 0; function log(msg: string, color: string = colors.reset) { const timestamp = new Date().toISOString().split('T')[1].slice(0, -1); console.log(`${colors.gray}[${timestamp}]${colors.reset} ${color}${msg}${colors.reset}`); } const introMessage = "Starting Ringstats Desktop Application..."; log(introMessage, colors.cyan); const pingStart = performance.now(); await redis.ping(); totalRequests++; log(`Connected to Ringstats Database successfully. (Reqs: 1 | Total: ${totalRequests} | Time: ${(performance.now() - pingStart).toFixed(2)}ms)`, colors.green); log("Looking for Elden Ring process...", colors.gray); await Bun.sleep(1500); log("Found Elden Ring process!", colors.green); log("Equipping initial gear...", colors.gray); await redis.del("player:1:weapon", "player:1:armor", "player:1:talisman"); await redis.sadd("player:1:weapon", "1"); await redis.sadd("player:1:armor", "11"); await redis.sadd("player:1:talisman", "26"); totalRequests += 4; let playerHealth = 100; let playerStamina = 100; let playerLevel = 1; let currentRegionId = 1; const CHANCE_LEVEL_UP = 0.10; const CHANCE_FAST_TRAVEL = 0.15; const CHANCE_GEAR_SWAP = 0.10; const CHANCE_TARGET_LOCK = 0.30; log("Entering live sync loop (press Ctrl+C to exit)...", colors.gray); while (true) { try { // 1. Lebens- und Ausdauerwerte simulieren playerHealth = Math.floor(Math.max(10, playerHealth - (Math.random() * 10) + 5)); playerStamina = Math.floor(Math.max(10, playerStamina - (Math.random() * 20) + 10)); if (Math.random() < CHANCE_LEVEL_UP) { playerLevel += 1; } // 2. Zufälliges Event: Schnellreise in eine andere Region if (Math.random() < CHANCE_FAST_TRAVEL) { currentRegionId = Math.floor(Math.random() * 16) + 1; const startTravel = performance.now(); const regionName = await redis.hget(`region:${currentRegionId}`, "name"); const regionEnemiesIds = await redis.smembers(`region:${currentRegionId}:enemies`); const regionItemsIds = await redis.smembers(`region:${currentRegionId}:items`); const enemyNames = await Promise.all(regionEnemiesIds.map(id => redis.hget(`enemy:${id}`, "name"))); const itemNames = await Promise.all(regionItemsIds.map(id => redis.hget(`item:${id}`, "name"))); const queries = 3 + regionEnemiesIds.length + regionItemsIds.length; totalRequests += queries; const travelTime = (performance.now() - startTravel).toFixed(2); console.log(); log(`>>> Fast Traveled to: [ID: ${currentRegionId}] ${regionName} <<<`, colors.magenta + colors.bold); log(`[Region Data] Enemies nearby: ${enemyNames.join(", ") || "None"}`, colors.magenta); log(`[Region Data] Items nearby: ${itemNames.join(", ") || "None"}`, colors.magenta); log(`[Stats] Query Time: ${travelTime}ms | Reqs in Block: ${queries} | Total Reqs: ${totalRequests}`, colors.gray); console.log(); } // 3. Zufälliges Event: Ausrüstung wechseln if (Math.random() < CHANCE_GEAR_SWAP) { const newWeaponId = Math.floor(Math.random() * 10) + 1; // 1 to 10 const newArmorId = Math.floor(Math.random() * 10) + 11; // 11 to 20 const newTalismanId = Math.floor(Math.random() * 5) + 26; // 26 to 30 const startSwap = performance.now(); await redis.del("player:1:weapon", "player:1:armor", "player:1:talisman"); await redis.sadd("player:1:weapon", newWeaponId.toString()); await redis.sadd("player:1:armor", newArmorId.toString()); await redis.sadd("player:1:talisman", newTalismanId.toString()); const weaponName = await redis.hget(`item:${newWeaponId}`, "name"); const armorName = await redis.hget(`item:${newArmorId}`, "name"); const talismanName = await redis.hget(`item:${newTalismanId}`, "name"); totalRequests += 7; // 1 del + 3 sadd + 3 hget const swapTime = (performance.now() - startSwap).toFixed(2); console.log(); log(`>>> Gear Swapped <<<`, colors.cyan + colors.bold); log(`Equipped: ${weaponName} | ${armorName} | ${talismanName}`, colors.cyan); log(`[Stats] Query Time: ${swapTime}ms | Reqs in Block: 7 | Total Reqs: ${totalRequests}`, colors.gray); console.log(); } // 4. Aktuelle Spielerdaten an Redis senden const startSync = performance.now(); await redis.hset("player:1", { id: 1, name: "Jonas", health: playerHealth, stamina: playerStamina, level: playerLevel, region_id: currentRegionId }); totalRequests += 1; const syncTime = (performance.now() - startSync).toFixed(2); log(`[Live Sync] [ID: 1] Jonas - Lvl: ${playerLevel} | HP: ${playerHealth} | Stamina: ${playerStamina}`, colors.green); log(`[Stats] Query Time: ${syncTime}ms | Reqs in Block: 1 | Total Reqs: ${totalRequests}`, colors.gray); // 5. Zufälliges Event: Gegner anvisieren if (Math.random() < CHANCE_TARGET_LOCK) { const startLock = performance.now(); const randomEnemyId = await redis.srandmember(`region:${currentRegionId}:enemies`); totalRequests += 1; if (randomEnemyId) { console.log(); log("--- Target Lock Detected ---", colors.red + colors.bold); const enemyInfo = await redis.hgetall(`enemy:${randomEnemyId}`); const dropItemIds = await redis.smembers(`enemy:${randomEnemyId}:items`); const dropItemNames = await Promise.all(dropItemIds.map(id => redis.hget(`item:${id}`, "name"))); const queries = 2 + dropItemIds.length; totalRequests += queries; const lockTime = (performance.now() - startLock).toFixed(2); log(`Overlay -> [ID: ${enemyInfo.id}] ${enemyInfo.name} | Lvl: ${enemyInfo.level} | HP: ${enemyInfo.health} | DMG: ${enemyInfo.damage}`, colors.yellow); log(`Drops -> ${dropItemNames.length > 0 ? dropItemNames.join(", ") : "None"}`, colors.yellow); log(`[Stats] Query Time: ${lockTime}ms | Reqs in Block: ${queries + 1} | Total Reqs: ${totalRequests}`, colors.gray); console.log(); } } } catch (error) { log("Datenbankfehler! Verbindung zu Redis unterbrochen.", colors.red); console.error(error); } await Bun.sleep(2000); }