Harden onion boot flow and deepen site surfaces
Add persistent onion key backup and restore, improve startup resilience, and flesh out the major site verticals with richer navigation, search coverage, and operator documentation. Made-with: Cursor
This commit is contained in:
75
app/game/page.tsx
Normal file
75
app/game/page.tsx
Normal file
@@ -0,0 +1,75 @@
|
||||
"use client";
|
||||
|
||||
import { useState, useEffect, useRef } from "react";
|
||||
|
||||
export default function DarknetPingPong() {
|
||||
const [ballPos, setBallPos] = useState({ x: 50, y: 50 });
|
||||
const [isHaunted, setIsHaunted] = useState(false);
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
// Simulate shared state with a simple interval or WebSocket-like behavior
|
||||
// In a real app, this would use Pusher, Socket.io, or a backend
|
||||
useEffect(() => {
|
||||
const interval = setInterval(() => {
|
||||
// Random "haunted" movement to simulate other users or ghosts
|
||||
if (Math.random() > 0.95) {
|
||||
setBallPos(prev => ({
|
||||
x: Math.max(10, Math.min(90, prev.x + (Math.random() - 0.5) * 20)),
|
||||
y: Math.max(10, Math.min(90, prev.y + (Math.random() - 0.5) * 20)),
|
||||
}));
|
||||
setIsHaunted(true);
|
||||
setTimeout(() => setIsHaunted(false), 500);
|
||||
}
|
||||
}, 2000);
|
||||
|
||||
return () => clearInterval(interval);
|
||||
}, []);
|
||||
|
||||
const handleBallClick = (e: React.MouseEvent) => {
|
||||
if (!containerRef.current) return;
|
||||
|
||||
const rect = containerRef.current.getBoundingClientRect();
|
||||
const x = ((e.clientX - rect.left) / rect.width) * 100;
|
||||
const y = ((e.clientY - rect.top) / rect.height) * 100;
|
||||
|
||||
// Move ball to click position
|
||||
setBallPos({ x, y });
|
||||
|
||||
// In a real app, you'd emit this to a server:
|
||||
// socket.emit('move_ball', { x, y });
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={containerRef}
|
||||
className="relative w-full h-[600px] bg-[url('https://images.unsplash.com/photo-1533090161767-e6ffed986c88?q=80&w=2069&auto=format&fit=crop')] bg-cover bg-center border-8 border-[#3d2b1f] shadow-2xl overflow-hidden cursor-crosshair"
|
||||
style={{ backgroundColor: "#1a1a1a" }}
|
||||
>
|
||||
<div className="absolute inset-0 bg-black/40 pointer-events-none" />
|
||||
|
||||
{/* The Haunted Ball */}
|
||||
<div
|
||||
onClick={handleBallClick}
|
||||
className={`absolute w-16 h-16 rounded-full cursor-pointer transition-all duration-500 ease-out
|
||||
${isHaunted ? "scale-125 blur-sm" : "scale-100"}
|
||||
shadow-[0_0_30px_rgba(255,255,255,0.3)]
|
||||
`}
|
||||
style={{
|
||||
left: `${ballPos.x}%`,
|
||||
top: `${ballPos.y}%`,
|
||||
transform: "translate(-50%, -50%)",
|
||||
background: "radial-gradient(circle at 30% 30%, #555, #000)",
|
||||
border: "2px solid rgba(255,255,255,0.1)"
|
||||
}}
|
||||
>
|
||||
<div className="absolute inset-0 flex items-center justify-center opacity-20">
|
||||
<span className="text-white text-[10px] uppercase tracking-widest">void</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="absolute bottom-4 left-4 text-white/50 font-mono text-xs uppercase tracking-widest">
|
||||
Shared Entity #001 - Darknet Ping Pong
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user