Files
the-nexus/modules/portals.js
Alexander Whitestone aa65e39bfe
Some checks failed
CI / validate (pull_request) Failing after 14s
CI / auto-merge (pull_request) Has been skipped
feat: wire effects/ modules into app.js via globalTicker (Refs #413)
- init all 6 effects modules in app.js (matrix-rain, lightning, energy-beam, rune-ring, gravity-zones, shockwave)
- subscribe each to globalTicker; tick() called in the RAF loop
- add subscribe() named export to core/ticker.js for panels compatibility
- bridge data to core/state.js: zoneIntensity from heatmap.js, activeAgentCount + commitHashes from data/gitea.js, portals from portals.js
- update portals.js and weather.js to use new effects/rune-ring and effects/gravity-zones instead of legacy effects.js

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-24 18:17:37 -04:00

66 lines
2.1 KiB
JavaScript

// === PORTALS ===
import * as THREE from 'three';
import { scene } from './scene-setup.js';
import { rebuild as rebuildRuneRing } from './effects/rune-ring.js';
import { setPortalsRefAudio, startPortalHums } from './audio.js';
import { S } from './state.js';
import { state } from './core/state.js';
import { fetchPortals as fetchPortalData } from './data/loaders.js';
export const portalGroup = new THREE.Group();
scene.add(portalGroup);
export let portals = [];
function createPortals() {
const portalGeo = new THREE.TorusGeometry(3.0, 0.2, 16, 100);
portals.forEach(portal => {
const isOnline = portal.status === 'online';
const portalMat = new THREE.MeshBasicMaterial({
color: new THREE.Color(portal.color).convertSRGBToLinear(),
transparent: true,
opacity: isOnline ? 0.7 : 0.15,
blending: THREE.AdditiveBlending,
side: THREE.DoubleSide,
});
const portalMesh = new THREE.Mesh(portalGeo, portalMat);
portalMesh.position.set(portal.position.x, portal.position.y + 0.5, portal.position.z);
portalMesh.rotation.y = portal.rotation.y;
portalMesh.rotation.x = Math.PI / 2;
portalMesh.name = `portal-${portal.id}`;
portalMesh.userData.destinationUrl = portal.destination?.url || null;
portalMesh.userData.portalColor = new THREE.Color(portal.color).convertSRGBToLinear();
portalGroup.add(portalMesh);
});
}
// rebuildGravityZones forward ref
let _rebuildGravityZonesFn = null;
export function setRebuildGravityZonesFn(fn) { _rebuildGravityZonesFn = fn; }
// runPortalHealthChecks forward ref
let _runPortalHealthChecksFn = null;
export function setRunPortalHealthChecksFn(fn) { _runPortalHealthChecksFn = fn; }
export async function loadPortals() {
try {
portals = await fetchPortalData();
state.portals = portals;
console.log('Loaded portals:', portals);
setPortalsRefAudio(portals);
createPortals();
rebuildRuneRing();
if (_rebuildGravityZonesFn) _rebuildGravityZonesFn();
startPortalHums();
if (_runPortalHealthChecksFn) _runPortalHealthChecksFn();
} catch (error) {
console.error('Failed to load portals:', error);
}
}