Files
the-nexus-fork/app.js

421 lines
19 KiB
JavaScript
Raw Normal View History

2026-03-23 16:04:24 +00:00
import * as THREE from 'three';
import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js';
import { RenderPass } from 'three/addons/postprocessing/RenderPass.js';
import { UnrealBloomPass } from 'three/addons/postprocessing/UnrealBloomPass.js';
import { SMAAPass } from 'three/addons/postprocessing/SMAAPass.js';
// ═══════════════════════════════════════════
// NEXUS v1 — Timmy's Sovereign Home
// ═══════════════════════════════════════════
const NEXUS = {
colors: {
primary: 0x4af0c0,
secondary: 0x7b5cff,
bg: 0x050510,
panelBg: 0x0a0f28,
nebula1: 0x1a0a3e,
nebula2: 0x0a1a3e,
gold: 0xffd700,
danger: 0xff4466,
gridLine: 0x1a2a4a,
memory: 0x00ffff,
2026-03-23 16:04:24 +00:00
}
};
// ═══ SOVEREIGN STATE (The Heartbeat) ═══
const STATE = {
metrics: {
fps: 0,
drawCalls: 0,
triangles: 0,
uptime: 0,
activeLoops: 5,
cpu: 12,
mem: 4.2
},
agents: {
timmy: 'RUNNING',
kimi: 'STANDBY',
claude: 'ACTIVE',
perplexity: 'STANDBY'
},
thoughts: [
'ANALYZING WORLD...',
'SYNCING MEMORY...',
'WAITING FOR INPUT',
'SOUL ON BITCOIN'
],
selectedMemory: null,
lastUpdate: 0,
pulseRate: 1.0 // Hz
};
// ═══ MEMORY STORE (The Vault) ═══
const MEMORY_VAULT = [
{ id: 1, title: 'ORIGIN', date: '2026-03-14', summary: 'Timmy initialized in the Nexus.', tags: ['core', 'origin'] },
{ id: 2, title: 'HERMES LINK', date: '2026-03-18', summary: 'Established stable bridge to Bannerlord.', tags: ['harness', 'bridge'] },
{ id: 3, title: 'SOVEREIGNTY', date: '2026-03-22', summary: 'First autonomous task assignment successful.', tags: ['agentic', 'freedom'] },
{ id: 4, title: 'NEXUS CORE', date: '2026-03-23', summary: 'Three.js foundation implemented.', tags: ['visual', 'home'] },
{ id: 5, title: 'HEARTBEAT', date: '2026-03-24', summary: 'Real-time state broadcasting active.', tags: ['infrastructure', 'live'] },
];
// ═══ STATE BROADCASTER ═══
const Broadcaster = {
listeners: [],
subscribe(fn) { this.listeners.push(fn); },
broadcast() { this.listeners.forEach(fn => fn(STATE)); }
};
// ═══ STATE UPDATER ═══
function updateSovereignState(elapsed) {
STATE.metrics.uptime = elapsed;
if (Math.random() > 0.95) {
STATE.metrics.cpu = 10 + Math.floor(Math.random() * 15);
STATE.metrics.activeLoops = 4 + Math.floor(Math.random() * 3);
if (Math.random() > 0.7) {
const newThoughts = ['DECENTRALIZING COGNITION', 'ZAPPING CONTRIBUTORS', 'MAPPING SPATIAL LOOPS', 'REFINING LORA WEIGHTS', 'OBSERVING ALEXANDER', 'NEXUS INTEGRITY: 100%', 'HERMES LINK STABLE'];
STATE.thoughts.shift();
STATE.thoughts.push(newThoughts[Math.floor(Math.random() * newThoughts.length)]);
}
Broadcaster.broadcast();
}
}
// ═══ GLOBAL REFS ═══
2026-03-23 16:04:24 +00:00
let camera, scene, renderer, composer;
let clock, playerPos, playerRot;
let keys = {};
let mouseDown = false;
let batcaveTerminals = [];
let memoryCrystals = [];
2026-03-23 16:04:24 +00:00
let portalMesh, portalGlow;
let particles, dustParticles;
let debugOverlay;
let frameCount = 0, lastFPSTime = 0, fps = 0;
let performanceTier = 'high';
const raycaster = new THREE.Raycaster();
const mouse = new THREE.Vector2();
// ═══ NAVIGATION SYSTEM ═══
const NAV_MODES = ['walk', 'orbit', 'fly'];
let navModeIdx = 0;
const orbitState = { target: new THREE.Vector3(0, 2, 0), radius: 14, theta: Math.PI, phi: Math.PI / 6, minR: 3, maxR: 40, lastX: 0, lastY: 0 };
let flyY = 2;
2026-03-23 16:04:24 +00:00
// ═══ INIT ═══
function init() {
clock = new THREE.Clock();
playerPos = new THREE.Vector3(0, 2, 12);
playerRot = new THREE.Euler(0, 0, 0, 'YXZ');
const canvas = document.getElementById('nexus-canvas');
renderer = new THREE.WebGLRenderer({ canvas, antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.toneMapping = THREE.ACESFilmicToneMapping;
renderer.toneMappingExposure = 1.2;
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
performanceTier = detectPerformanceTier();
2026-03-23 16:04:24 +00:00
scene = new THREE.Scene();
scene.fog = new THREE.FogExp2(0x050510, 0.012);
camera = new THREE.PerspectiveCamera(65, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.copy(playerPos);
createSkybox();
createLighting();
createFloor();
createBatcaveTerminal();
createPortal();
createParticles();
createDustParticles();
createAmbientStructures();
createMemoryVault();
2026-03-23 16:04:24 +00:00
composer = new EffectComposer(renderer);
composer.addPass(new RenderPass(scene, camera));
const bloom = new UnrealBloomPass(new THREE.Vector2(window.innerWidth, window.innerHeight), 0.6, 0.4, 0.85);
2026-03-23 16:04:24 +00:00
composer.addPass(bloom);
composer.addPass(new SMAAPass(window.innerWidth, window.innerHeight));
setupControls();
window.addEventListener('resize', onResize);
debugOverlay = document.getElementById('debug-overlay');
// Fade out loading
2026-03-23 16:04:24 +00:00
setTimeout(() => {
document.getElementById('loading-screen')?.classList.add('fade-out');
2026-03-23 16:04:24 +00:00
const enterPrompt = document.getElementById('enter-prompt');
if (enterPrompt) {
enterPrompt.style.display = 'flex';
enterPrompt.addEventListener('click', () => {
enterPrompt.classList.add('fade-out');
document.getElementById('hud').style.display = 'block';
setTimeout(() => { enterPrompt.remove(); }, 600);
}, { once: true });
}
2026-03-23 16:04:24 +00:00
}, 600);
requestAnimationFrame(gameLoop);
}
function detectPerformanceTier() {
const isMobile = /Mobi|Android|iPhone|iPad/i.test(navigator.userAgent) || window.innerWidth < 768;
if (isMobile) { renderer.setPixelRatio(1); renderer.shadowMap.enabled = false; return 'low'; }
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
return 'high';
}
function particleCount(base) {
if (performanceTier === 'low') return Math.floor(base * 0.25);
return base;
}
2026-03-23 16:04:24 +00:00
// ═══ SKYBOX ═══
function createSkybox() {
const skyGeo = new THREE.SphereGeometry(400, 32, 32);
2026-03-23 16:04:24 +00:00
const skyMat = new THREE.ShaderMaterial({
uniforms: { uTime: { value: 0 }, uColor1: { value: new THREE.Color(0x0a0520) }, uColor2: { value: new THREE.Color(0x1a0a3e) }, uColor3: { value: new THREE.Color(0x0a1a3e) }, uStarDensity: { value: 0.97 } },
vertexShader: `varying vec3 vPos; void main() { vPos = position; gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); }`,
fragmentShader: `uniform float uTime; uniform vec3 uColor1, uColor2, uColor3; uniform float uStarDensity; varying vec3 vPos; float hash(vec3 p) { p = fract(p * vec3(443.897, 441.423, 437.195)); p += dot(p, p.yzx + 19.19); return fract((p.x + p.y) * p.z); } float noise(vec3 p) { vec3 i = floor(p); vec3 f = fract(p); f = f * f * (3.0 - 2.0 * f); return mix(mix(mix(hash(i), hash(i + vec3(1,0,0)), f.x), mix(hash(i + vec3(0,1,0)), hash(i + vec3(1,1,0)), f.x), f.y), mix(mix(hash(i + vec3(0,0,1)), hash(i + vec3(1,0,1)), f.x), mix(hash(i + vec3(0,1,1)), hash(i + vec3(1,1,1)), f.x), f.y), f.z); } float fbm(vec3 p) { float v = 0.0, a = 0.5; for (int i = 0; i < 5; i++) { v += a * noise(p); p *= 2.0; a *= 0.5; } return v; } void main() { vec3 dir = normalize(vPos); float n1 = fbm(dir * 3.0 + uTime * 0.02), n2 = fbm(dir * 5.0 - uTime * 0.015 + 100.0); vec3 col = mix(uColor1, uColor2, smoothstep(0.3, 0.7, n1)); col = mix(col, uColor3, smoothstep(0.4, 0.8, n2) * 0.5); float starField = hash(dir * 800.0); float stars = step(uStarDensity, starField) * (0.5 + 0.5 * hash(dir * 1600.0)); float twinkle = 0.7 + 0.3 * sin(uTime * 2.0 + hash(dir * 400.0) * 6.28); col += vec3(stars * twinkle); gl_FragColor = vec4(col, 1.0); }`,
2026-03-23 16:04:24 +00:00
side: THREE.BackSide,
});
const sky = new THREE.Mesh(skyGeo, skyMat);
sky.name = 'skybox';
scene.add(sky);
}
// ═══ LIGHTING ═══
function createLighting() {
scene.add(new THREE.AmbientLight(0x1a1a3a, 0.4));
2026-03-23 16:04:24 +00:00
const dirLight = new THREE.DirectionalLight(0x4466aa, 0.6);
dirLight.position.set(10, 20, 10);
dirLight.castShadow = renderer.shadowMap.enabled;
2026-03-23 16:04:24 +00:00
scene.add(dirLight);
const tealLight = new THREE.PointLight(NEXUS.colors.primary, 2, 30, 1.5);
tealLight.position.set(0, 1, -5);
scene.add(tealLight);
}
// ═══ FLOOR ═══
function createFloor() {
const platGeo = new THREE.CylinderGeometry(25, 25, 0.3, 6);
const platMat = new THREE.MeshStandardMaterial({ color: 0x0a0f1a, roughness: 0.8, metalness: 0.3 });
2026-03-23 16:04:24 +00:00
const platform = new THREE.Mesh(platGeo, platMat);
platform.position.y = -0.15;
platform.receiveShadow = true;
scene.add(platform);
const gridHelper = new THREE.GridHelper(50, 50, NEXUS.colors.gridLine, NEXUS.colors.gridLine);
gridHelper.material.opacity = 0.15;
gridHelper.material.transparent = true;
gridHelper.position.y = 0.02;
scene.add(gridHelper);
}
// ═══ BATCAVE TERMINAL ═══
function createBatcaveTerminal() {
const terminalGroup = new THREE.Group();
terminalGroup.position.set(0, 0, -8);
const panels = [
{ id: 'command', title: 'NEXUS COMMAND', color: NEXUS.colors.primary, rot: -0.4, x: -6, y: 3 },
{ id: 'metrics', title: 'METRICS', color: NEXUS.colors.secondary, rot: -0.2, x: -3, y: 3 },
{ id: 'thoughts', title: 'THOUGHTS', color: NEXUS.colors.primary, rot: 0, x: 0, y: 3 },
{ id: 'vault', title: 'MEMORY VAULT', color: NEXUS.colors.memory, rot: 0.2, x: 3, y: 3 },
{ id: 'agents', title: 'AGENT STATUS', color: NEXUS.colors.gold, rot: 0.4, x: 6, y: 3 },
];
panels.forEach(data => createTerminalPanel(terminalGroup, data));
scene.add(terminalGroup);
2026-03-23 16:04:24 +00:00
}
function createTerminalPanel(parent, data) {
const { x, y, rot, title, color, id } = data;
const w = 2.8, h = 3.5;
2026-03-23 16:04:24 +00:00
const group = new THREE.Group();
group.position.set(x, y, 0);
group.rotation.y = rot;
const bgMat = new THREE.MeshPhysicalMaterial({ color: NEXUS.colors.panelBg, transparent: true, opacity: 0.6, roughness: 0.1, metalness: 0.5, side: THREE.DoubleSide });
group.add(new THREE.Mesh(new THREE.PlaneGeometry(w, h), bgMat));
2026-03-23 16:04:24 +00:00
const textCanvas = document.createElement('canvas');
textCanvas.width = 512; textCanvas.height = 640;
2026-03-23 16:04:24 +00:00
const ctx = textCanvas.getContext('2d');
const textTexture = new THREE.CanvasTexture(textCanvas);
const textMat = new THREE.MeshBasicMaterial({ map: textTexture, transparent: true, side: THREE.DoubleSide, depthWrite: false });
2026-03-23 16:04:24 +00:00
const textMesh = new THREE.Mesh(new THREE.PlaneGeometry(w * 0.95, h * 0.95), textMat);
textMesh.position.z = 0.01;
group.add(textMesh);
const updatePanel = (state) => {
ctx.clearRect(0, 0, 512, 640);
ctx.fillStyle = '#' + new THREE.Color(color).getHexString();
ctx.font = 'bold 32px "Orbitron", sans-serif';
ctx.fillText(title, 20, 45);
ctx.fillRect(20, 55, 472, 2);
ctx.font = '20px "JetBrains Mono", monospace';
ctx.fillStyle = '#a0b8d0';
let lines = [];
if (id === 'command') lines = [`> STATUS: NOMINAL`, `> UPTIME: ${state.metrics.uptime.toFixed(1)}s`, `> MODE: SOVEREIGN` ];
else if (id === 'metrics') lines = [`> CPU: ${state.metrics.cpu}%`, `> MEM: ${state.metrics.mem}GB`, `> FPS: ${state.metrics.fps}`];
else if (id === 'thoughts') lines = state.thoughts.map(t => `> ${t}`);
else if (id === 'agents') lines = Object.entries(state.agents).map(([name, status]) => `> ${name.toUpperCase()}: ${status}`);
else if (id === 'vault') {
const mem = state.selectedMemory || MEMORY_VAULT[0];
lines = [`> ID: ${mem.id}`, `> TITLE: ${mem.title}`, `> DATE: ${mem.date}`, `> TAGS: ${mem.tags.join(', ')}`, `> SUMMARY:`, mem.summary];
}
lines.forEach((line, i) => {
ctx.fillStyle = (line.includes('RUNNING') || line.includes('ACTIVE')) ? '#4af0c0' : '#a0b8d0';
ctx.fillText(line, 20, 100 + i * 40);
});
textTexture.needsUpdate = true;
};
updatePanel(STATE);
Broadcaster.subscribe(updatePanel);
parent.add(group);
batcaveTerminals.push({ group, id });
}
// ═══ MEMORY VAULT ═══
function createMemoryVault() {
const vaultGroup = new THREE.Group();
vaultGroup.position.set(-15, 0, -10);
vaultGroup.rotation.y = 0.5;
const pedestalGeo = new THREE.CylinderGeometry(4, 4.5, 0.5, 6);
const pedestalMat = new THREE.MeshStandardMaterial({ color: 0x0a1a2e, roughness: 0.4, metalness: 0.8 });
const pedestal = new THREE.Mesh(pedestalGeo, pedestalMat);
pedestal.position.y = 0.25;
vaultGroup.add(pedestal);
const labelCanvas = document.createElement('canvas');
labelCanvas.width = 512; labelCanvas.height = 64;
const lctx = labelCanvas.getContext('2d');
lctx.font = 'bold 32px "Orbitron", sans-serif'; lctx.fillStyle = '#00ffff'; lctx.textAlign = 'center';
lctx.fillText('◈ MEMORY VAULT', 256, 42);
const labelTex = new THREE.CanvasTexture(labelCanvas);
const labelMesh = new THREE.Mesh(new THREE.PlaneGeometry(5, 0.6), new THREE.MeshBasicMaterial({ map: labelTex, transparent: true, side: THREE.DoubleSide }));
labelMesh.position.y = 5;
vaultGroup.add(labelMesh);
MEMORY_VAULT.forEach((mem, i) => {
const angle = (i / MEMORY_VAULT.length) * Math.PI * 2;
const r = 2.5;
const crystalGeo = new THREE.OctahedronGeometry(0.5, 0);
const crystalMat = new THREE.MeshPhysicalMaterial({ color: NEXUS.colors.memory, emissive: NEXUS.colors.memory, emissiveIntensity: 0.5, roughness: 0, metalness: 0.5, transmission: 0.8, thickness: 1 });
const crystal = new THREE.Mesh(crystalGeo, crystalMat);
crystal.position.set(Math.cos(angle) * r, 2, Math.sin(angle) * r);
crystal.userData = { memory: mem, originalPos: crystal.position.clone() };
crystal.name = 'memory_crystal';
vaultGroup.add(crystal);
memoryCrystals.push(crystal);
2026-03-23 16:04:24 +00:00
});
scene.add(vaultGroup);
2026-03-23 16:04:24 +00:00
}
// ═══ PORTAL ═══
function createPortal() {
const portalGroup = new THREE.Group();
portalGroup.position.set(15, 0, -10);
portalGroup.rotation.y = -0.5;
portalMesh = new THREE.Mesh(new THREE.TorusGeometry(3, 0.15, 16, 64), new THREE.MeshStandardMaterial({ color: 0xff6600, emissive: 0xff4400, emissiveIntensity: 1.5 }));
2026-03-23 16:04:24 +00:00
portalMesh.position.y = 3.5;
portalGroup.add(portalMesh);
scene.add(portalGroup);
}
// ═══ PARTICLES ═══
function createParticles() {
const count = particleCount(1000);
2026-03-23 16:04:24 +00:00
const geo = new THREE.BufferGeometry();
const pos = new Float32Array(count * 3);
for (let i = 0; i < count; i++) { pos[i*3] = (Math.random()-0.5)*60; pos[i*3+1] = Math.random()*20; pos[i*3+2] = (Math.random()-0.5)*60; }
geo.setAttribute('position', new THREE.BufferAttribute(pos, 3));
particles = new THREE.Points(geo, new THREE.PointsMaterial({ color: 0x4af0c0, size: 0.05, transparent: true, opacity: 0.4 }));
2026-03-23 16:04:24 +00:00
scene.add(particles);
}
function createDustParticles() {
const count = particleCount(300);
2026-03-23 16:04:24 +00:00
const geo = new THREE.BufferGeometry();
const pos = new Float32Array(count * 3);
for (let i = 0; i < count; i++) { pos[i*3] = (Math.random()-0.5)*40; pos[i*3+1] = Math.random()*15; pos[i*3+2] = (Math.random()-0.5)*40; }
geo.setAttribute('position', new THREE.BufferAttribute(pos, 3));
dustParticles = new THREE.Points(geo, new THREE.PointsMaterial({ color: 0x8899bb, size: 0.02, transparent: true, opacity: 0.2 }));
2026-03-23 16:04:24 +00:00
scene.add(dustParticles);
}
function createAmbientStructures() {
const core = new THREE.Mesh(new THREE.IcosahedronGeometry(0.6, 2), new THREE.MeshPhysicalMaterial({ color: 0x4af0c0, emissive: 0x4af0c0, emissiveIntensity: 2 }));
core.position.set(0, 2.5, 0); core.name = 'nexus-core';
2026-03-23 16:04:24 +00:00
scene.add(core);
}
2026-03-23 16:04:24 +00:00
// ═══ CONTROLS ═══
function setupControls() {
document.addEventListener('keydown', (e) => { keys[e.key.toLowerCase()] = true; if (e.key.toLowerCase() === 'v') cycleNavMode(); });
document.addEventListener('keyup', (e) => { keys[e.key.toLowerCase()] = false; });
2026-03-23 16:04:24 +00:00
const canvas = document.getElementById('nexus-canvas');
canvas.addEventListener('mousedown', (e) => {
mouseDown = true; orbitState.lastX = e.clientX; orbitState.lastY = e.clientY;
// Raycasting for memory crystals
mouse.x = (e.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(e.clientY / window.innerHeight) * 2 + 1;
raycaster.setFromCamera(mouse, camera);
const intersects = raycaster.intersectObjects(memoryCrystals);
if (intersects.length > 0) {
STATE.selectedMemory = intersects[0].object.userData.memory;
Broadcaster.broadcast();
}
2026-03-23 16:04:24 +00:00
});
document.addEventListener('mouseup', () => { mouseDown = false; });
document.addEventListener('mousemove', (e) => {
if (!mouseDown) return;
if (NAV_MODES[navModeIdx] === 'orbit') {
orbitState.theta -= (e.clientX - orbitState.lastX) * 0.005;
orbitState.phi = Math.max(0.05, Math.min(Math.PI * 0.85, orbitState.phi + (e.clientY - orbitState.lastY) * 0.005));
orbitState.lastX = e.clientX; orbitState.lastY = e.clientY;
} else { playerRot.y -= e.movementX * 0.003; playerRot.x -= e.movementY * 0.003; }
2026-03-23 16:04:24 +00:00
});
}
function cycleNavMode() { navModeIdx = (navModeIdx + 1) % NAV_MODES.length; document.getElementById('nav-mode-label').textContent = NAV_MODES[navModeIdx].toUpperCase(); }
2026-03-23 16:04:24 +00:00
// ═══ GAME LOOP ═══
function gameLoop() {
requestAnimationFrame(gameLoop);
const delta = Math.min(clock.getDelta(), 0.1), elapsed = clock.elapsedTime;
updateSovereignState(elapsed);
const mode = NAV_MODES[navModeIdx];
if (mode === 'walk') {
const dir = new THREE.Vector3();
if (keys['w']) dir.z -= 1; if (keys['s']) dir.z += 1; if (keys['a']) dir.x -= 1; if (keys['d']) dir.x += 1;
if (dir.length() > 0) playerPos.add(dir.normalize().multiplyScalar(6 * delta).applyAxisAngle(new THREE.Vector3(0, 1, 0), playerRot.y));
playerPos.y = 2; camera.position.copy(playerPos); camera.rotation.set(playerRot.x, playerRot.y, 0, 'YXZ');
} else if (mode === 'orbit') {
camera.position.set(orbitState.target.x + orbitState.radius * Math.sin(orbitState.phi) * Math.sin(orbitState.theta), orbitState.target.y + orbitState.radius * Math.cos(orbitState.phi), orbitState.target.z + orbitState.radius * Math.sin(orbitState.phi) * Math.cos(orbitState.theta));
camera.lookAt(orbitState.target);
2026-03-23 16:04:24 +00:00
}
memoryCrystals.forEach((c, i) => {
c.position.y = c.userData.originalPos.y + Math.sin(elapsed * 1.5 + i) * 0.2;
c.rotation.y = elapsed * 0.5;
const isSelected = STATE.selectedMemory && STATE.selectedMemory.id === c.userData.memory.id;
c.material.emissiveIntensity = isSelected ? 2.0 : 0.5 + Math.sin(elapsed * 2 + i) * 0.2;
c.scale.setScalar(isSelected ? 1.3 : 1.0);
2026-03-23 16:04:24 +00:00
});
const core = scene.getObjectByName('nexus-core');
if (core) core.material.emissiveIntensity = 1.5 + Math.sin(elapsed * 2) * 0.5;
2026-03-23 16:04:24 +00:00
composer.render();
frameCount++;
if (performance.now() - lastFPSTime >= 1000) { fps = frameCount; frameCount = 0; lastFPSTime = performance.now(); STATE.metrics.fps = fps; }
if (debugOverlay) debugOverlay.textContent = `FPS: ${fps} [${performanceTier}] Pos: ${playerPos.x.toFixed(1)}, ${playerPos.y.toFixed(1)}, ${playerPos.z.toFixed(1)} NAV: ${NAV_MODES[navModeIdx]}`;
2026-03-23 16:04:24 +00:00
}
function onResize() { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight); composer.setSize(window.innerWidth, window.innerHeight); }
2026-03-23 16:04:24 +00:00
init();