Windows-GPU-UNLOCK
RTX3090 UEFI 포트, 한국어 무리셋 윈도우 부팅 가이드, 검증된 소스와 벤치마크 제공
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
Fully on-chain multiplayer Pac-Man built with BOLT ECS (MagicBlock) + Ephemeral Rollups for real-time gameplay on Solana.
• Entity — just an ID (a PDA on Solana). No data, no logic.
• Component — pure data struct (= a Solana account). Position, health, score, etc.
• System — a Solana program that contains the logic. Receives components, modifies them, returns them.
Each element in the game (player, map, monster) is an Entity with Components attached. The World program handles PDA derivation, account routing, and component lifecycle — you just declare what components your system needs.README 전문 보기 ↗Fully on-chain multiplayer Pac-Man built with BOLT ECS (MagicBlock) + Ephemeral Rollups for real-time gameplay on Solana.
| Layer | Tech |
|---|---|
| On-chain framework | BOLT ECS (extends Anchor) |
| Real-time engine | Ephemeral Rollups (MagicBlock) |
| Language | Rust (programs) / TypeScript (frontend) |
| Frontend | Next.js 16 + React 19 + Tailwind 4 |
Each element in the game (player, map, monster) is an Entity with Components attached. The World program handles PDA derivation, account routing, and component lifecycle — you just declare what components your system needs.
A temporary mini-Solana dedicated to the game session.
eu.magicblock.app), US (us.magicblock.app), Asia (as.magicblock.app)All 5 components use #[component(delegate)] for ER support.
1. INIT (L1)
Create World + map entity + 5 components
init-map: spawn snake at random bottom corner, 3 ghosts at other corners, set status Playing
2. DELEGATE (L1 → ER)
DelegateComponent for all 5 component PDAs (2 batches)
Accounts locked on L1, cloned into ER
3. GAMEPLAY (ER — all gasless, ~50ms)
move-player: wall check, snake body block, coin pickup, kill check, anti-teleport, spawn lock
move-monster: BFS pathfinding (snake + 3 ghosts), ghost wander, kill check
Session keys: wallet signs once, then moves auto-sign (no popup)
4. END GAME (ER → L1)
end-game system checks: timeout / all coins / no players
Commit & Undelegate → final scores permanent on Solana L1
Every frontend connects to the ER via WebSocket (onAccountChange). When any account changes (player moves, coin collected, monster moves), all connected clients receive the update instantly. No game server needed.
| Component | Fields | Description |
|---|---|---|
Position | x (i64), y (i64), spawn_x (i64), spawn_y (i64), orientation (u16), sprinting (bool) | Player/entity position + spawn point. Coords x100 (1300 = tile 13, 1350 = tile 13 right quadrant) |
PlayerState | authority (Pubkey), alive (bool), spawn_time (i64), locked (bool), lock_time (i64), coins_saved (u16), respawn_time (i64) | Player stats, life status, spawn lock, respawn timer |
CollectedCoins | bits ([u8; 421]), count (u16) | Per-player coin bitset — 4 coins per tile (1 per quadrant), 841 tiles × 4 = 3364 bits |
MapConfig | seed (u64), width (u16), height (u16), active_players (u8), total_coins (u16), start_time (i64), status (GameStatus) | Map metadata + game state (Waiting/Playing/Finished) |
PlayerRegistry | players ([[u8;32]; 10]), player_states ([[u8;32]; 10]), count (u8) | Registry of active players (Position + PlayerState PDAs). Max 10 |
Monster | x (i64), y (i64), direction (u16), body ([i64; 12]), ghosts ([i64; 6]), ghosts_dir ([u16; 3]) | Snake head (centered, +50) + 6 body segments + 3 ghost positions + ghost directions. All coords x100 |
| System | Input Components | Description |
|---|---|---|
init-map | MapConfig, Monster | Parse totalCoins from args. Snake spawns at random bottom corner (start_time % 2), 3 ghosts at other 3 corners. Init snake body. Set status to Playing |
spawn-player | Position, PlayerState, MapConfig, PlayerRegistry | Spawn player in ghost house center (10 predefined positions in x=12-16, y=12-16). Init alive=true, coins zeroed, locked=false. Register in PlayerRegistry. Increment active_players |
move-player | Position, CollectedCoins, MapConfig, Monster, PlayerState | Sub-tile movement (0.25 tile per move). Wall check. Snake body block. Per-quadrant coin pickup. Rectangle kill check (snake) + quadrant kill check (ghosts). Spawn lock (5s + coin reset) |
move-monster | Monster, MapConfig, Position, PlayerState, CollectedCoins + remaining_accounts | Snake: BFS + 25 unit/tick smooth movement, body shifts on tile change. Ghosts: BFS to tile, sub-tile chase on same tile (targets exact player position). Random wander when no target. Respawn check (revives dead players after 15s). Kill check vs all players |
end-game | MapConfig, PlayerState | Check 3 end conditions: all coins collected, no active players, timeout (50 min) |
SnakeCollision error)All monsters have a 20-tile Manhattan distance detection range. Beyond that, they wander randomly. This means you can avoid monsters by staying far enough away, but they'll chase you aggressively once you're in range.
The frontend sends a moveMonster transaction every 400ms via session key. The on-chain system moves all 4 monsters in a single transaction (400k CU budget).
When a player dies (monster kill), they are teleported to their spawn point and must wait 15 seconds before respawning. The respawn is handled by move-monster (runs every 400ms even when dead). On death, collected coins are reset (bitset cleared). coins_saved is preserved.
When a player enters the safe zone (ghost house) from outside:
coins_saved += collected_coins.count → score is banked permanentlylocked = true, lock_time = now + 5 secondsDuring the lock:
lock_time expires (on-chain Locked error)Fixed 29x29 Pac-Man layout with ghost house safe zone.
libs/map-utils/src/bsp.rs) and TypeScript (app/frontend/app/lib/map-gen.ts)All validation is on-chain — the frontend is untrusted.
Instead of failing transactions on invalid moves, move-player uses a desync flag. When a validation fails (wall, teleport, snake body), the transaction still confirms but player_state.desync = true is set and the move is rejected silently. While desync:
desync = false and the player can move againThis prevents tx failures from causing SOL loss and keeps the client synchronized.
| Check | Behavior |
|---|---|
| Anti-teleport (max 25 units walk / 50 sprint) | Sets desync = true |
| Wall collision | Sets desync = true |
| Snake body collision | Sets desync = true |
| Spawn lock (can't exit safe zone during cooldown) | Move silently ignored (no desync) |
| Game must be Playing | require! — tx fails |
| Player must be alive | require! — tx fails |
| Snake kill (centered rectangle — player inside 100x100 box centered on snake head) | Sets alive = false |
| Ghost kill (same tile + same quadrant) | Sets alive = false |
| Spawn position validation | require! — tx fails |
move-monster uses a slot-based rate limit (last_monster_slot in MapConfig). Monsters only move if current_slot >= last_slot + 3 (~150ms on ER). Multiple clients calling moveMonster in the same window only results in one move. Kill check and respawn always run regardless of rate limit.
CUBE3D/
├── programs-ecs/
│ ├── components/
│ │ ├── position/ # x, y, orientation, sprinting
│ │ ├── player-state/ # authority, alive, locked, coins_saved, respawn_time
│ │ ├── collected-coins/ # per-player coin bitset (4 coins/tile, 421 bytes)
│ │ ├── map-config/ # seed, width, height, total_coins, status
│ │ ├── player-registry/ # Position + PlayerState PDAs, max 10 players
│ │ └── monster/ # snake (head + body) + 3 ghosts (positions + directions)
│ └── systems/
│ ├── init-map/ # Spawn monsters at corners, set Playing
│ ├── spawn-player/ # Register player in ghost house
│ ├── move-player/ # Movement + coins + anti-teleport + kill check + spawn lock
│ ├── move-monster/ # BFS pathfinding + ghost wander + anti-collision + kill
│ └── end-game/ # Check win/lose/timeout conditions
├── libs/
│ └── map-utils/ # Shared map bitset, coin detection, PRNG (Rust)
├── app/
│ └── frontend/ # Next.js 16 + React 19 + Tailwind 4 (see frontend/README.md)
├── tests/ # E2E tests
├── docs/ # Architecture & decisions
├── patches/ # session-keys custom lib
└── Anchor.toml
# Terminal 1 — L1 (Surfpool)
surfpool start --rpc-url 'https://devnet.helius-rpc.com/?api-key=YOUR_KEY'
# Terminal 2 — Ephemeral Rollup
ephemeral-validator --remotes "http://localhost:8899" --remotes "ws://localhost:8900" -l "7799" --lifecycle ephemeral
bolt build
anchor deploy --provider.cluster http://localhost:8899
Important: After redeploying, restart the ER validator and delete
magicblock-test-storage/for a clean start. The ER caches program binaries.
cd app/frontend
npm install
npm run dev
Open http://localhost:3000, connect a Solana wallet (Phantom on localhost).
bolt build
anchor deploy --provider.cluster 'https://devnet.helius-rpc.com/?api-key=YOUR_KEY'
| Program | ID |
|---|---|
| position | D6arufzkdPfmne2TrUGaMSA73HEQvSMpSpW81EtrpfEg |
| player-state | 3R6wE1awZdKHDSGchGhS2xHKKB2QSR1xQfCB9GgagZah |
| map-config | 4tNjQVh1bSjqMYNRoWK8jpgvBr1suSjX7adpt6vrgsLV |
| player-registry | 3KYSbQkcqDoRdRUbyT6HGU8a67VCzuhKkfQTUHLDmKLL |
| monster | 8xPThZpo5mJf9avTuGbgDnLKojHxuGF5V53iiUUn6yT2 |
| init-map | 5CB1AR5p23rHraxA367Rt2cyFC3kLRxDga8nywY5dNEV |
| spawn-player | 62SXEXeaqYAQ4PTL3Vgu5LU1bt5iwCYwPvkjmVWUWKnE |
| move-player | GX7dFnXqthzMkBdsvEwsqtprcaPLHUVbxkC2G2j4L8Ap |
| move-monster | EJYmw1gd3eq6ig6aDMAqNfvN3ZiFqsGo5FCCWZrtCok |
| end-game | DNPfzbrCvfodqjTzqgcRYRSfxVyivvZ3BoThcNXoPXgM |
These constraints shaped the architecture:
Vec, no heap allocations. All arrays are stack-allocated ([u8; 106], [u16; MAX_TILES])execute() and passed by reference to bfs_direction(). Cannot call BFS as a function with its own stack arrays 4 timesmove-monster needs 400k CU (4 BFS pathfinding calls). Set via ComputeBudgetProgram.setComputeUnitLimit() — free on ER{"x":300,"y":100}). On-chain systems parse with custom stack-only JSON parsers (no serde, no heap)