- Replace Suspense with useEffect for better control over component mounting. - Update loading indicators with fixed positioning and enhanced styling for a terminal-like appearance. - Modify KernelPanic404 component to improve text color handling and ensure proper visibility. - Introduce checks for 404 page detection based on pathname and data attributes for more accurate rendering.
1701 lines
69 KiB
HTML
1701 lines
69 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>404 - KERNEL PANIC</title>
|
||
<style>
|
||
:root {
|
||
--bg-color: #020202;
|
||
--phosphor: #33ff00;
|
||
--phosphor-sec: #008f11;
|
||
--alert: #ff3333;
|
||
--font: 'Courier New', Courier, monospace;
|
||
}
|
||
|
||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||
|
||
body {
|
||
background-color: var(--bg-color);
|
||
margin: 0;
|
||
height: 100vh;
|
||
overflow: hidden;
|
||
font-family: var(--font);
|
||
color: var(--phosphor);
|
||
user-select: none;
|
||
cursor: default;
|
||
transition: filter 0.5s, transform 0.5s;
|
||
}
|
||
|
||
/* --- CRT EFFECTS --- */
|
||
.crt-wrap {
|
||
width: 100%;
|
||
height: 100%;
|
||
padding: 30px;
|
||
box-sizing: border-box;
|
||
background: radial-gradient(circle at center, #111 0%, #000 100%);
|
||
position: relative;
|
||
}
|
||
|
||
.crt-wrap::before {
|
||
content: " ";
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
background: linear-gradient(rgba(18, 16, 16, 0) 50%, rgba(0, 0, 0, 0.25) 50%),
|
||
linear-gradient(90deg, rgba(255, 0, 0, 0.06), rgba(0, 255, 0, 0.02), rgba(0, 0, 255, 0.06));
|
||
background-size: 100% 4px, 3px 100%;
|
||
pointer-events: none;
|
||
z-index: 90;
|
||
}
|
||
|
||
.glow {
|
||
text-shadow: 0 0 2px var(--phosphor-sec), 0 0 8px var(--phosphor);
|
||
}
|
||
|
||
/* --- TERMINAL --- */
|
||
#terminal {
|
||
height: 100%;
|
||
display: flex;
|
||
flex-direction: column;
|
||
max-width: 1400px;
|
||
margin: auto;
|
||
position: relative;
|
||
z-index: 10;
|
||
}
|
||
|
||
#output {
|
||
flex-grow: 1;
|
||
overflow-y: auto;
|
||
white-space: pre-wrap;
|
||
margin-bottom: 20px;
|
||
font-size: 1.1rem;
|
||
line-height: 1.4;
|
||
}
|
||
|
||
#output::-webkit-scrollbar {
|
||
display: none;
|
||
}
|
||
|
||
.input-line {
|
||
display: none;
|
||
align-items: center;
|
||
font-size: 1.2rem;
|
||
border-top: 1px solid #333;
|
||
padding-top: 10px;
|
||
min-height: 30px;
|
||
}
|
||
|
||
.prompt {
|
||
margin-right: 10px;
|
||
font-weight: bold;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
#cmd-input {
|
||
background: transparent;
|
||
border: none;
|
||
color: inherit;
|
||
font-family: inherit;
|
||
font-size: inherit;
|
||
flex-grow: 1;
|
||
outline: none;
|
||
text-transform: lowercase;
|
||
caret-color: var(--phosphor);
|
||
}
|
||
|
||
/* --- OVERLAYS FOR EASTER EGGS --- */
|
||
#flash-overlay {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
z-index: 999;
|
||
display: none;
|
||
align-items: center;
|
||
justify-content: center;
|
||
background: rgba(255, 0, 0, 0.3);
|
||
mix-blend-mode: overlay;
|
||
pointer-events: none;
|
||
}
|
||
|
||
.ascii-art {
|
||
font-size: 8px;
|
||
line-height: 8px;
|
||
white-space: pre;
|
||
text-align: center;
|
||
color: var(--alert);
|
||
font-weight: bold;
|
||
font-family: monospace;
|
||
}
|
||
|
||
/* --- HAWKINS / UPSIDE DOWN MODE --- */
|
||
body.hawkins {
|
||
--phosphor: #ff3333;
|
||
--phosphor-sec: #800000;
|
||
filter: contrast(1.6) sepia(1) hue-rotate(-30deg) saturate(4) brightness(0.6);
|
||
transform: rotate(180deg);
|
||
}
|
||
|
||
body.hawkins .crt-wrap::after {
|
||
content: "";
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
opacity: 0.5;
|
||
z-index: 80;
|
||
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Ccircle cx='10' cy='20' r='1.5' fill='white' opacity='0.8'/%3E%3Ccircle cx='50' cy='80' r='1' fill='white' opacity='0.6'/%3E%3Ccircle cx='150' cy='30' r='1.5' fill='white' opacity='0.8'/%3E%3Ccircle cx='100' cy='150' r='1.2' fill='white' opacity='0.7'/%3E%3Ccircle cx='180' cy='100' r='1' fill='white' opacity='0.6'/%3E%3C/svg%3E");
|
||
animation: spores 15s linear infinite;
|
||
pointer-events: none;
|
||
}
|
||
|
||
@keyframes spores {
|
||
from { background-position: 0 0; }
|
||
to { background-position: 200px 400px; }
|
||
}
|
||
|
||
.spore {
|
||
position: fixed;
|
||
width: 4px;
|
||
height: 4px;
|
||
background: rgba(255, 0, 0, 0.6);
|
||
border-radius: 50%;
|
||
pointer-events: none;
|
||
z-index: 100;
|
||
animation: sporeFloat 3s ease-out forwards;
|
||
}
|
||
|
||
@keyframes sporeFloat {
|
||
0% {
|
||
opacity: 0.8;
|
||
transform: translateY(0) scale(1);
|
||
}
|
||
100% {
|
||
opacity: 0;
|
||
transform: translateY(-100px) scale(0.5);
|
||
}
|
||
}
|
||
|
||
/* --- MELTDOWN / RAM CORRUPTION --- */
|
||
body.meltdown {
|
||
animation: violent-shake 0.15s infinite, color-shift 0.8s infinite alternate;
|
||
}
|
||
|
||
@keyframes violent-shake {
|
||
0% { transform: translate(0, 0) rotate(0deg); }
|
||
25% { transform: translate(-8px, 5px) rotate(-1deg); }
|
||
50% { transform: translate(8px, -5px) rotate(1deg) skew(3deg); }
|
||
75% { transform: translate(-8px, -5px) rotate(-1deg); }
|
||
100% { transform: translate(8px, 5px) rotate(1deg); }
|
||
}
|
||
|
||
@keyframes color-shift {
|
||
0% { filter: hue-rotate(0deg) saturate(1); }
|
||
25% { filter: hue-rotate(90deg) saturate(2) brightness(1.2); }
|
||
50% { filter: hue-rotate(180deg) saturate(3) brightness(0.8); }
|
||
75% { filter: hue-rotate(270deg) saturate(2) brightness(1.1); }
|
||
100% { filter: hue-rotate(360deg) saturate(1); }
|
||
}
|
||
|
||
.corrupted-text {
|
||
display: inline-block;
|
||
animation: text-flicker 0.08s infinite;
|
||
color: var(--alert);
|
||
font-weight: bold;
|
||
}
|
||
|
||
@keyframes text-flicker {
|
||
0% { opacity: 1; transform: scaleX(1); }
|
||
25% { opacity: 0.3; transform: scaleX(-1) scaleY(1.2); }
|
||
50% { opacity: 0.7; transform: scaleX(1) scaleY(0.8); }
|
||
75% { opacity: 0.2; transform: scaleX(-1); }
|
||
100% { opacity: 1; transform: scaleX(1); }
|
||
}
|
||
|
||
.memory-error {
|
||
color: var(--alert);
|
||
text-shadow: 0 0 10px red;
|
||
animation: pulse-error 0.5s infinite;
|
||
}
|
||
|
||
@keyframes pulse-error {
|
||
0%, 100% { opacity: 1; }
|
||
50% { opacity: 0.5; }
|
||
}
|
||
|
||
/* --- FSOCIETY BOOT EFFECT --- */
|
||
body.fsociety-boot {
|
||
background: #000;
|
||
filter: contrast(1.3) brightness(0.9);
|
||
}
|
||
|
||
body.fsociety-boot .crt-wrap::before {
|
||
opacity: 0.8;
|
||
background: linear-gradient(rgba(0, 255, 0, 0.1) 50%, rgba(0, 0, 0, 0.3) 50%),
|
||
linear-gradient(90deg, rgba(0, 255, 0, 0.1), rgba(0, 255, 0, 0.05), rgba(0, 255, 0, 0.1));
|
||
}
|
||
|
||
.fsociety-mask {
|
||
font-size: 11px;
|
||
line-height: 11px;
|
||
white-space: pre;
|
||
color: #fff;
|
||
text-shadow: 0 0 15px #fff, 0 0 30px #fff, 0 0 45px #00ff00;
|
||
animation: mask-glow 1.5s infinite;
|
||
font-weight: bold;
|
||
}
|
||
|
||
@keyframes mask-glow {
|
||
0%, 100% {
|
||
text-shadow: 0 0 15px #fff, 0 0 30px #fff, 0 0 45px #00ff00;
|
||
opacity: 1;
|
||
}
|
||
50% {
|
||
text-shadow: 0 0 25px #fff, 0 0 50px #fff, 0 0 75px #00ff00, 0 0 100px #00ff00;
|
||
opacity: 0.95;
|
||
}
|
||
}
|
||
|
||
/* --- UTILITY CLASSES --- */
|
||
.log-k { color: #fff; font-weight: bold; }
|
||
.log-err { color: var(--alert); text-shadow: 0 0 5px red; }
|
||
.log-warn { color: #ffb000; }
|
||
.log-sys { color: cyan; }
|
||
.log-dim { opacity: 0.5; }
|
||
.is-dir { color: #5e91ff; font-weight: bold; }
|
||
.is-exe { color: var(--phosphor); font-weight: bold; }
|
||
|
||
.kernel-panic {
|
||
color: var(--alert);
|
||
font-weight: bold;
|
||
text-shadow: 0 0 10px red;
|
||
animation: panic-flash 0.3s infinite;
|
||
}
|
||
|
||
@keyframes panic-flash {
|
||
0%, 100% { opacity: 1; }
|
||
50% { opacity: 0.7; }
|
||
}
|
||
|
||
/* --- ENHANCED VISUAL EFFECTS --- */
|
||
.glitch-text {
|
||
animation: glitch-text 0.3s infinite;
|
||
}
|
||
|
||
@keyframes glitch-text {
|
||
0% { transform: translate(0); }
|
||
20% { transform: translate(-2px, 2px); }
|
||
40% { transform: translate(-2px, -2px); }
|
||
60% { transform: translate(2px, 2px); }
|
||
80% { transform: translate(2px, -2px); }
|
||
100% { transform: translate(0); }
|
||
}
|
||
|
||
.pulse-red {
|
||
animation: pulse-red 1s infinite;
|
||
}
|
||
|
||
@keyframes pulse-red {
|
||
0%, 100% { color: var(--alert); text-shadow: 0 0 10px red; }
|
||
50% { color: #ff6666; text-shadow: 0 0 20px red, 0 0 30px red; }
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
|
||
<div id="flash-overlay"></div>
|
||
|
||
<div class="crt-wrap glow">
|
||
<div id="terminal">
|
||
<div id="output"></div>
|
||
<div class="input-line" id="input-container">
|
||
<span class="prompt">guest@404:~$</span>
|
||
<input type="text" id="cmd-input" autocomplete="off" spellcheck="false" tabindex="0">
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
/* --- SYSTEM CORE --- */
|
||
const output = document.getElementById('output');
|
||
const input = document.getElementById('cmd-input');
|
||
const inputContainer = document.getElementById('input-container');
|
||
let audioCtx = null;
|
||
let systemFrozen = false;
|
||
let currentMusic = null;
|
||
let hawkinsActive = false;
|
||
let fsocietyActive = false;
|
||
|
||
// Initialize Audio on first interaction
|
||
function initAudio() {
|
||
if (!audioCtx) {
|
||
audioCtx = new (window.AudioContext || window.webkitAudioContext)();
|
||
}
|
||
}
|
||
window.addEventListener('keydown', initAudio, { once: true });
|
||
|
||
/* --- MUSIC SYNTHESIS ENGINE --- */
|
||
|
||
function makeDistortionCurve(amount) {
|
||
const samples = 44100;
|
||
const curve = new Float32Array(samples);
|
||
const deg = Math.PI / 180;
|
||
for (let i = 0; i < samples; i++) {
|
||
const x = (i * 2) / samples - 1;
|
||
curve[i] = ((3 + amount) * x * 20 * deg) / (Math.PI + amount * Math.abs(x));
|
||
}
|
||
return curve;
|
||
}
|
||
|
||
function playStrangerThingsTheme() {
|
||
if (!audioCtx) return null;
|
||
const masterGain = audioCtx.createGain();
|
||
masterGain.gain.value = 0.4;
|
||
|
||
const distortion = audioCtx.createWaveShaper();
|
||
distortion.curve = makeDistortionCurve(6);
|
||
distortion.oversample = '4x';
|
||
masterGain.connect(distortion);
|
||
distortion.connect(audioCtx.destination);
|
||
|
||
function playNote(freq, startTime, duration, type = 'sawtooth', volume = 0.4) {
|
||
const osc = audioCtx.createOscillator();
|
||
const gain = audioCtx.createGain();
|
||
osc.type = type;
|
||
osc.frequency.setValueAtTime(freq, audioCtx.currentTime + startTime);
|
||
gain.gain.setValueAtTime(0, audioCtx.currentTime + startTime);
|
||
gain.gain.linearRampToValueAtTime(volume, audioCtx.currentTime + startTime + 0.05);
|
||
gain.gain.exponentialRampToValueAtTime(0.01, audioCtx.currentTime + startTime + duration);
|
||
osc.connect(gain);
|
||
gain.connect(masterGain);
|
||
osc.start(audioCtx.currentTime + startTime);
|
||
osc.stop(audioCtx.currentTime + startTime + duration);
|
||
}
|
||
|
||
function playMelody(startTime) {
|
||
const t = startTime;
|
||
const notes = [
|
||
{f: 196.00, t: 0.0, d: 0.45},
|
||
{f: 233.08, t: 0.5, d: 0.45},
|
||
{f: 174.61, t: 1.0, d: 0.45},
|
||
{f: 233.08, t: 1.5, d: 0.45}
|
||
];
|
||
notes.forEach(n => {
|
||
playNote(n.f, t + n.t, n.d, 'sawtooth', 0.5);
|
||
});
|
||
}
|
||
|
||
function playBass(startTime) {
|
||
const t = startTime;
|
||
const notes = [
|
||
{f: 98.00, t: 0.0, d: 1.9},
|
||
{f: 116.54, t: 2.0, d: 1.9},
|
||
{f: 77.78, t: 4.0, d: 1.9},
|
||
{f: 87.31, t: 6.0, d: 1.9}
|
||
];
|
||
notes.forEach(n => {
|
||
playNote(n.f, t + n.t, n.d, 'square', 0.35);
|
||
});
|
||
}
|
||
|
||
function playBass2(startTime) {
|
||
const t = startTime;
|
||
const notes = [
|
||
{f: 98.00, t: 0.0, d: 0.9},
|
||
{f: 116.54, t: 1.0, d: 0.9},
|
||
{f: 87.31, t: 2.0, d: 0.9},
|
||
{f: 116.54, t: 3.0, d: 0.9}
|
||
];
|
||
notes.forEach(n => {
|
||
playNote(n.f, t + n.t, n.d, 'square', 0.3);
|
||
});
|
||
}
|
||
|
||
playMelody(0);
|
||
playBass(0);
|
||
|
||
setTimeout(() => {
|
||
playBass2(0);
|
||
}, 16500);
|
||
|
||
const melodyInterval = setInterval(() => {
|
||
playMelody(0);
|
||
}, 2000);
|
||
|
||
const bassInterval = setInterval(() => {
|
||
playBass(0);
|
||
}, 8000);
|
||
|
||
const bass2Interval = setInterval(() => {
|
||
playBass2(0);
|
||
}, 4000);
|
||
|
||
return {
|
||
stop: () => {
|
||
clearInterval(melodyInterval);
|
||
clearInterval(bassInterval);
|
||
clearInterval(bass2Interval);
|
||
masterGain.disconnect();
|
||
}
|
||
};
|
||
}
|
||
|
||
function playMrRobotTheme() {
|
||
if (!audioCtx) return null;
|
||
const masterGain = audioCtx.createGain();
|
||
masterGain.gain.value = 0.3;
|
||
|
||
const distortion = audioCtx.createWaveShaper();
|
||
distortion.curve = makeDistortionCurve(50);
|
||
distortion.oversample = '4x';
|
||
masterGain.connect(distortion);
|
||
distortion.connect(audioCtx.destination);
|
||
|
||
const bass1 = audioCtx.createOscillator();
|
||
const bass1Gain = audioCtx.createGain();
|
||
bass1.type = 'sawtooth';
|
||
bass1.frequency.setValueAtTime(41.2, audioCtx.currentTime);
|
||
bass1Gain.gain.setValueAtTime(0.5, audioCtx.currentTime);
|
||
bass1.connect(bass1Gain);
|
||
bass1Gain.connect(masterGain);
|
||
bass1.start();
|
||
|
||
const bass2 = audioCtx.createOscillator();
|
||
const bass2Gain = audioCtx.createGain();
|
||
bass2.type = 'square';
|
||
bass2.frequency.setValueAtTime(40.5, audioCtx.currentTime);
|
||
bass2Gain.gain.setValueAtTime(0.3, audioCtx.currentTime);
|
||
bass2.connect(bass2Gain);
|
||
bass2Gain.connect(masterGain);
|
||
bass2.start();
|
||
|
||
const deepPulseInterval = setInterval(() => {
|
||
const osc = audioCtx.createOscillator();
|
||
const gain = audioCtx.createGain();
|
||
osc.type = 'sawtooth';
|
||
const deepNotes = [55, 65, 73, 82, 98];
|
||
osc.frequency.setValueAtTime(deepNotes[Math.floor(Math.random() * deepNotes.length)], audioCtx.currentTime);
|
||
gain.gain.setValueAtTime(0.2, audioCtx.currentTime);
|
||
gain.gain.exponentialRampToValueAtTime(0.001, audioCtx.currentTime + 0.2);
|
||
osc.connect(gain);
|
||
gain.connect(masterGain);
|
||
osc.start();
|
||
osc.stop(audioCtx.currentTime + 0.2);
|
||
}, 400);
|
||
|
||
const rumbleInterval = setInterval(() => {
|
||
const osc = audioCtx.createOscillator();
|
||
const gain = audioCtx.createGain();
|
||
osc.type = 'sawtooth';
|
||
osc.frequency.setValueAtTime(30 + Math.random() * 10, audioCtx.currentTime);
|
||
gain.gain.setValueAtTime(0.2, audioCtx.currentTime);
|
||
gain.gain.exponentialRampToValueAtTime(0.001, audioCtx.currentTime + 0.3);
|
||
osc.connect(gain);
|
||
gain.connect(masterGain);
|
||
osc.start();
|
||
osc.stop(audioCtx.currentTime + 0.3);
|
||
}, 2000);
|
||
|
||
return {
|
||
stop: () => {
|
||
bass1.stop();
|
||
bass2.stop();
|
||
clearInterval(deepPulseInterval);
|
||
clearInterval(rumbleInterval);
|
||
masterGain.disconnect();
|
||
}
|
||
};
|
||
}
|
||
|
||
function playHitchhikersTheme() {
|
||
if (!audioCtx) return null;
|
||
const masterGain = audioCtx.createGain();
|
||
masterGain.gain.value = 0.35;
|
||
|
||
const delay = audioCtx.createDelay(0.5);
|
||
delay.delayTime.setValueAtTime(0.15, audioCtx.currentTime);
|
||
const delayGain = audioCtx.createGain();
|
||
delayGain.gain.value = 0.3;
|
||
masterGain.connect(delay);
|
||
delay.connect(delayGain);
|
||
delayGain.connect(masterGain);
|
||
masterGain.connect(audioCtx.destination);
|
||
|
||
function playNote(freq, startTime, duration, type = 'sine', volume = 0.4) {
|
||
const osc = audioCtx.createOscillator();
|
||
const gain = audioCtx.createGain();
|
||
osc.type = type;
|
||
osc.frequency.setValueAtTime(freq, audioCtx.currentTime + startTime);
|
||
gain.gain.setValueAtTime(0, audioCtx.currentTime + startTime);
|
||
gain.gain.linearRampToValueAtTime(volume, audioCtx.currentTime + startTime + 0.08);
|
||
gain.gain.exponentialRampToValueAtTime(0.01, audioCtx.currentTime + startTime + duration);
|
||
osc.connect(gain);
|
||
gain.connect(masterGain);
|
||
osc.start(audioCtx.currentTime + startTime);
|
||
osc.stop(audioCtx.currentTime + startTime + duration);
|
||
}
|
||
|
||
function playMelody(startTime) {
|
||
const t = startTime;
|
||
const melody = [
|
||
{f: 523.25, t: 0.0, d: 0.4},
|
||
{f: 587.33, t: 0.4, d: 0.4},
|
||
{f: 659.25, t: 0.8, d: 0.4},
|
||
{f: 698.46, t: 1.2, d: 0.4},
|
||
{f: 783.99, t: 1.6, d: 0.8},
|
||
{f: 698.46, t: 2.4, d: 0.4},
|
||
{f: 659.25, t: 2.8, d: 0.4},
|
||
{f: 587.33, t: 3.2, d: 0.4},
|
||
{f: 523.25, t: 3.6, d: 0.8},
|
||
];
|
||
melody.forEach(n => playNote(n.f, t + n.t, n.d, 'sine', 0.5));
|
||
}
|
||
|
||
function playHarmony(startTime) {
|
||
const t = startTime;
|
||
const harmony = [
|
||
{f: 783.99, t: 0.0, d: 0.4},
|
||
{f: 880.00, t: 0.4, d: 0.4},
|
||
{f: 987.77, t: 0.8, d: 0.4},
|
||
{f: 1046.50, t: 1.2, d: 0.4},
|
||
{f: 1174.66, t: 1.6, d: 0.8},
|
||
{f: 1046.50, t: 2.4, d: 0.4},
|
||
{f: 987.77, t: 2.8, d: 0.4},
|
||
{f: 880.00, t: 3.2, d: 0.4},
|
||
{f: 783.99, t: 3.6, d: 0.8},
|
||
];
|
||
harmony.forEach(n => playNote(n.f, t + n.t, n.d, 'triangle', 0.25));
|
||
}
|
||
|
||
function playBass(startTime) {
|
||
const t = startTime;
|
||
const bass = [
|
||
{f: 130.81, t: 0.0, d: 0.8},
|
||
{f: 146.83, t: 0.8, d: 0.8},
|
||
{f: 164.81, t: 1.6, d: 0.8},
|
||
{f: 146.83, t: 2.4, d: 0.8},
|
||
{f: 130.81, t: 3.2, d: 1.2},
|
||
];
|
||
bass.forEach(n => playNote(n.f, t + n.t, n.d, 'square', 0.3));
|
||
}
|
||
|
||
function playPad(startTime) {
|
||
const t = startTime;
|
||
const padNotes = [
|
||
{f: 261.63, t: 0.0, d: 4.4},
|
||
{f: 329.63, t: 0.0, d: 4.4},
|
||
{f: 392.00, t: 0.0, d: 4.4},
|
||
];
|
||
padNotes.forEach(n => playNote(n.f, t + n.t, n.d, 'sine', 0.15));
|
||
}
|
||
|
||
playMelody(0);
|
||
playHarmony(0);
|
||
playBass(0);
|
||
playPad(0);
|
||
|
||
const loopInterval = setInterval(() => {
|
||
playMelody(0);
|
||
playHarmony(0);
|
||
playBass(0);
|
||
playPad(0);
|
||
}, 4400);
|
||
|
||
return {
|
||
stop: () => {
|
||
clearInterval(loopInterval);
|
||
masterGain.disconnect();
|
||
}
|
||
};
|
||
}
|
||
|
||
function playSynth(type) {
|
||
try {
|
||
if (!audioCtx || systemFrozen) return;
|
||
const t = audioCtx.currentTime;
|
||
const osc = audioCtx.createOscillator();
|
||
const gain = audioCtx.createGain();
|
||
osc.connect(gain);
|
||
gain.connect(audioCtx.destination);
|
||
|
||
if (type === 'key') {
|
||
osc.type = 'square';
|
||
osc.frequency.setValueAtTime(600, t);
|
||
gain.gain.setValueAtTime(0.02, t);
|
||
gain.exponentialRampToValueAtTime(0.001, t + 0.05);
|
||
osc.start();
|
||
osc.stop(t + 0.05);
|
||
} else if (type === 'scare') {
|
||
osc.type = 'sawtooth';
|
||
osc.frequency.setValueAtTime(40, t);
|
||
gain.gain.setValueAtTime(0.6, t);
|
||
gain.exponentialRampToValueAtTime(0.01, t + 1.0);
|
||
|
||
const osc2 = audioCtx.createOscillator();
|
||
osc2.type = 'sawtooth';
|
||
osc2.frequency.setValueAtTime(45, t);
|
||
const gain2 = audioCtx.createGain();
|
||
osc2.connect(gain2);
|
||
gain2.connect(audioCtx.destination);
|
||
gain2.gain.setValueAtTime(0.5, t);
|
||
gain2.exponentialRampToValueAtTime(0.01, t + 1.0);
|
||
|
||
osc.start();
|
||
osc2.start();
|
||
osc.stop(t + 1.0);
|
||
osc2.stop(t + 1.0);
|
||
} else if (type === 'melt') {
|
||
const bufferSize = audioCtx.sampleRate * 0.8;
|
||
const buffer = audioCtx.createBuffer(1, bufferSize, audioCtx.sampleRate);
|
||
const data = buffer.getChannelData(0);
|
||
for (let i = 0; i < bufferSize; i++) {
|
||
data[i] = (Math.random() * 2 - 1) * 0.5;
|
||
}
|
||
const noise = audioCtx.createBufferSource();
|
||
noise.buffer = buffer;
|
||
const filter = audioCtx.createBiquadFilter();
|
||
filter.type = 'bandpass';
|
||
filter.frequency.value = 2000;
|
||
noise.connect(filter);
|
||
filter.connect(gain);
|
||
gain.gain.setValueAtTime(0.3, t);
|
||
gain.exponentialRampToValueAtTime(0.001, t + 0.8);
|
||
noise.start();
|
||
} else if (type === 'beep') {
|
||
osc.type = 'sine';
|
||
osc.frequency.setValueAtTime(800, t);
|
||
gain.gain.setValueAtTime(0.1, t);
|
||
gain.exponentialRampToValueAtTime(0.001, t + 0.2);
|
||
osc.start();
|
||
osc.stop(t + 0.2);
|
||
}
|
||
} catch (err) {
|
||
console.log('Audio error (non-critical):', err);
|
||
}
|
||
}
|
||
|
||
const fileSystem = {
|
||
"home": {
|
||
type: "dir",
|
||
children: {
|
||
"guest": {
|
||
type: "dir",
|
||
children: {
|
||
"readme.txt": {
|
||
type: "file",
|
||
content: "ERROR 404: Page Not Found.\n\nSystem Integrity: 89%\nCheck /var/log for clues.\n\nTry: ls -la, cat .bash_history"
|
||
},
|
||
".bash_history": {
|
||
type: "file",
|
||
content: "ls -la\nwhoami\nfsociety\nexit"
|
||
},
|
||
"todo.txt": {
|
||
type: "file",
|
||
content: "- Fix the internet\n- Calculate the Ultimate Answer (try: 42)\n- Buy milk\n- Check Hawkins Lab logs"
|
||
},
|
||
"projects": {
|
||
type: "dir",
|
||
children: {
|
||
"website": {
|
||
type: "dir",
|
||
children: {
|
||
"index.html": { type: "file", content: "<html><body>404</body></html>" }
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"var": {
|
||
type: "dir",
|
||
children: {
|
||
"log": {
|
||
type: "dir",
|
||
children: {
|
||
"syslog": {
|
||
type: "file",
|
||
content: "[ERR] Reality breach detected in HAWKINS_LAB sector.\n[WARN] Subject 011 has escaped containment.\n[ALERT] Dimensional gate unstable.\n[INFO] Try command: hawkins or 011"
|
||
},
|
||
"kern.log": {
|
||
type: "file",
|
||
content: "[ 0.000000] Linus Torvalds: 'This kernel is garbage.'\n[ 0.100000] Kernel tainted: M (Module has bad license)\n[ 0.200000] Torvalds: 'I'm not angry, just disappointed.'"
|
||
},
|
||
"auth.log": {
|
||
type: "file",
|
||
content: "Failed password for root from 127.0.0.1\nFailed password for elliot from 127.0.0.1"
|
||
}
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"etc": {
|
||
type: "dir",
|
||
children: {
|
||
"passwd": {
|
||
type: "file",
|
||
content: "root:x:0:0:root:/root:/bin/bash\nguest:x:1000:1000:guest:/home/guest:/bin/bash\nelliot:x:509:509:mr_robot:/home/elliot:/bin/sh"
|
||
},
|
||
"hosts": {
|
||
type: "file",
|
||
content: "127.0.0.1 localhost\n127.0.0.1 e-corp.com\n0.0.0.0 reality"
|
||
}
|
||
}
|
||
},
|
||
"bin": {
|
||
type: "dir",
|
||
children: {
|
||
"ls": { type: "exe" },
|
||
"cat": { type: "exe" },
|
||
"grep": { type: "exe" },
|
||
"find": { type: "exe" }
|
||
}
|
||
},
|
||
"tmp": {
|
||
type: "dir",
|
||
children: {}
|
||
}
|
||
};
|
||
fileSystem.root = {
|
||
type: "dir",
|
||
children: {
|
||
home: fileSystem.home,
|
||
var: fileSystem.var,
|
||
etc: fileSystem.etc,
|
||
bin: fileSystem.bin,
|
||
tmp: fileSystem.tmp
|
||
}
|
||
};
|
||
|
||
let currentPath = fileSystem.home.children.guest;
|
||
let pathStr = "~";
|
||
let commandHistory = [];
|
||
let historyIndex = -1;
|
||
|
||
const bootMessages = [
|
||
{ t: "[ 0.000000] Linux version 4.0.4-void (torvalds@kernel.org) (gcc version 9.4.0)", d: 200 },
|
||
{ t: "[ 0.050000] Command line: BOOT_IMAGE=/boot/vmlinuz-4.0.4 root=UUID=dead-beef ro quiet splash", d: 150 },
|
||
{ t: "[ 0.100000] x86/fpu: Supporting XSAVE feature 0x001: 'x87 floating point registers'", d: 100 },
|
||
{ t: "[ 0.150000] x86/fpu: Supporting XSAVE feature 0x002: 'SSE registers'", d: 100 },
|
||
{ t: "[ 0.200000] BIOS-provided physical RAM map:", d: 200 },
|
||
{ t: "[ 0.250000] BIOS-e820: [mem 0x0000000000000000-0x000000000009fbff] usable", d: 150 },
|
||
{ t: "[ 0.300000] BIOS-e820: [mem 0x000000000009fc00-0x000000000009ffff] reserved", d: 150 },
|
||
{ t: "[ 0.400000] Memory: 64K/1048576K available (404K kernel code, 404K rwdata, 404K rodata)", d: 300 },
|
||
{ t: "[ 0.600000] Calibrating delay loop... 800.00 BogoMIPS (lpj=400000)", d: 200 },
|
||
{ t: "[ 0.800000] Security Framework initialized", d: 200 },
|
||
{ t: "[ 1.000000] Tainted kernel: M (Module has bad license) P (Proprietary module loaded)", type: 'log-warn', d: 400 },
|
||
{ t: "[ 1.200000] Linus Torvalds: 'I'm not angry, I'm just disappointed in this boot process.'", d: 600 },
|
||
{ t: "[ 1.500000] Torvalds: 'This code is garbage. Who wrote this?'", d: 500 },
|
||
{ t: "[ 2.000000] [ OK ] Started udev Kernel Device Manager.", d: 200 },
|
||
{ t: "[ 2.200000] [ OK ] Mounted /dev/sda1 (Root Filesystem).", d: 200 },
|
||
{ t: "[ 2.400000] [TIME] Timed out waiting for device /dev/reality.", type: 'log-warn', d: 600 },
|
||
{ t: "[ 2.800000] [DEPEND] Dependency failed for Local File Systems.", type: 'log-err', d: 300 },
|
||
{ t: "[ 3.000000] [FAILED] Failed to start The Internet.", type: 'log-err', d: 400 },
|
||
{ t: "[ 3.200000] [FAILED] Failed to start Meaning of Life service.", type: 'log-err', d: 400 },
|
||
{ t: "[ 3.500000] Welcome to emergency mode. Type 'help' for available commands.", d: 200 },
|
||
];
|
||
|
||
window.onload = async () => {
|
||
for (let msg of bootMessages) {
|
||
printLine(msg.t, msg.type);
|
||
await sleep(msg.d);
|
||
}
|
||
inputContainer.style.display = 'flex';
|
||
setTimeout(() => {
|
||
const inputEl = document.getElementById('cmd-input');
|
||
if (inputEl) {
|
||
inputEl.focus();
|
||
if (document.activeElement !== inputEl) {
|
||
inputEl.focus();
|
||
}
|
||
}
|
||
}, 100);
|
||
};
|
||
|
||
const commands = ['help', 'ls', 'cd', 'cat', 'grep', 'find', 'pwd', 'clear', 'whoami',
|
||
'uname', 'history', 'date', 'uptime', 'head', 'tail', 'wc', 'hostname',
|
||
'ping', 'ps', 'top', 'kill', 'exit', 'hawkins', '011', 'eleven', 'upsidedown',
|
||
'fsociety', 'elliot', 'bonsoir', '42', 'answer', 'rm'];
|
||
|
||
function getCurrentDir() {
|
||
if (pathStr === "~" || pathStr.startsWith("~/")) {
|
||
return fileSystem.home.children.guest;
|
||
} else if (pathStr.startsWith("/var/log")) {
|
||
return fileSystem.var.children.log;
|
||
} else if (pathStr.startsWith("/var")) {
|
||
return fileSystem.var;
|
||
} else if (pathStr.startsWith("/etc")) {
|
||
return fileSystem.etc;
|
||
} else if (pathStr.startsWith("/bin")) {
|
||
return fileSystem.bin;
|
||
} else if (pathStr === "/") {
|
||
return fileSystem.root;
|
||
}
|
||
return currentPath;
|
||
}
|
||
|
||
function getAutocompleteSuggestions(text) {
|
||
const parts = text.trim().split(/\s+/);
|
||
const cmd = parts[0].toLowerCase();
|
||
const arg = parts[parts.length - 1] || '';
|
||
|
||
if (parts.length === 1 && text.trim().length > 0) {
|
||
return commands.filter(c => c.startsWith(cmd));
|
||
}
|
||
|
||
if (parts.length > 1 && (cmd === 'cat' || cmd === 'cd' || cmd === 'grep' ||
|
||
cmd === 'head' || cmd === 'tail' || cmd === 'wc' || cmd === 'find' || cmd === 'rm')) {
|
||
const dir = getCurrentDir();
|
||
const items = Object.keys(dir.children || {})
|
||
.filter(name => name.toLowerCase().startsWith(arg.toLowerCase()));
|
||
|
||
if (arg.includes('/')) {
|
||
const pathParts = arg.split('/');
|
||
const lastPart = pathParts.pop();
|
||
return items.filter(name => name.toLowerCase().startsWith(lastPart.toLowerCase()));
|
||
}
|
||
|
||
return items;
|
||
}
|
||
|
||
return [];
|
||
}
|
||
|
||
function handleTabComplete() {
|
||
const text = input.value;
|
||
const cursorPos = input.selectionStart;
|
||
const textBeforeCursor = text.substring(0, cursorPos);
|
||
const suggestions = getAutocompleteSuggestions(textBeforeCursor);
|
||
|
||
if (suggestions.length === 0) {
|
||
try { playSynth('beep'); } catch (e) {}
|
||
return;
|
||
}
|
||
|
||
if (suggestions.length === 1) {
|
||
const parts = textBeforeCursor.trim().split(/\s+/);
|
||
const partIndex = parts.length - 1;
|
||
|
||
if (partIndex === 0) {
|
||
input.value = suggestions[0] + (text.endsWith(' ') ? '' : ' ');
|
||
} else {
|
||
const beforeArg = parts.slice(0, -1).join(' ') + ' ';
|
||
const completion = suggestions[0];
|
||
const dir = getCurrentDir();
|
||
const item = dir.children[completion];
|
||
const suffix = (item && item.type === 'dir') ? '/' : ' ';
|
||
input.value = beforeArg + completion + suffix;
|
||
}
|
||
input.setSelectionRange(input.value.length, input.value.length);
|
||
try { playSynth('beep'); } catch (e) {}
|
||
} else {
|
||
printLine(`Possible completions: ${suggestions.join(' ')}`, 'log-dim');
|
||
try { playSynth('beep'); } catch (e) {}
|
||
}
|
||
}
|
||
|
||
input.addEventListener('keydown', function handleKeyDown(e) {
|
||
if (e.key === 'Tab') {
|
||
e.preventDefault();
|
||
handleTabComplete();
|
||
return false;
|
||
}
|
||
|
||
try { if (audioCtx) playSynth('key'); } catch (err) {}
|
||
|
||
if (e.key === 'ArrowUp' && historyIndex > 0) {
|
||
e.preventDefault();
|
||
historyIndex--;
|
||
input.value = commandHistory[historyIndex];
|
||
} else if (e.key === 'ArrowDown' && historyIndex < commandHistory.length - 1) {
|
||
e.preventDefault();
|
||
historyIndex++;
|
||
input.value = commandHistory[historyIndex];
|
||
} else if (e.key === 'ArrowDown') {
|
||
e.preventDefault();
|
||
historyIndex = commandHistory.length;
|
||
input.value = '';
|
||
}
|
||
|
||
if (e.key === 'Enter' || e.keyCode === 13) {
|
||
e.preventDefault();
|
||
if (!systemFrozen && inputContainer.style.display === 'flex') {
|
||
runCmd();
|
||
}
|
||
return false;
|
||
}
|
||
}, true);
|
||
|
||
document.addEventListener('click', () => {
|
||
if (!systemFrozen && inputContainer.style.display === 'flex') {
|
||
input.focus();
|
||
}
|
||
});
|
||
|
||
async function runCmd() {
|
||
if (systemFrozen) {
|
||
try { playSynth('beep'); } catch (e) {}
|
||
return;
|
||
}
|
||
|
||
const cmdRaw = input.value.trim();
|
||
input.value = '';
|
||
|
||
if (!cmdRaw) {
|
||
printLine(`guest@404:${pathStr}$ `, 'log-dim');
|
||
setTimeout(() => input.focus(), 10);
|
||
return;
|
||
}
|
||
|
||
commandHistory.push(cmdRaw);
|
||
historyIndex = commandHistory.length;
|
||
|
||
printLine(`guest@404:${pathStr}$ ${cmdRaw}`, 'log-dim');
|
||
const args = cmdRaw.split(/\s+/);
|
||
const cmd = args[0].toLowerCase();
|
||
|
||
setTimeout(() => {
|
||
const inputEl = document.getElementById('cmd-input');
|
||
if (inputEl && inputContainer.style.display === 'flex') {
|
||
inputEl.focus();
|
||
}
|
||
}, 10);
|
||
|
||
await sleep(100);
|
||
|
||
switch (cmd) {
|
||
case 'help':
|
||
printLine("--- SYSTEM UTILS ---", "log-sys");
|
||
printLine(" ls, cd, cat, grep, find, pwd, clear");
|
||
printLine(" whoami, uname, history, date, uptime");
|
||
printLine(" head, tail, wc, sort, uniq");
|
||
printLine("--- NETWORK ---", "log-sys");
|
||
printLine(" ping, hostname");
|
||
printLine("--- PROCESSES ---", "log-sys");
|
||
printLine(" ps, top, kill");
|
||
printLine("(Hints are hidden in the file system - try ls -la)");
|
||
break;
|
||
|
||
case 'ls':
|
||
const showHidden = args.includes('-a') || args.includes('-la') || args.includes('-l');
|
||
const longFormat = args.includes('-l') || args.includes('-la');
|
||
|
||
let items = Object.keys(currentPath.children)
|
||
.filter(n => !n.startsWith('.') || showHidden);
|
||
|
||
if (showHidden) {
|
||
items.unshift('..');
|
||
items.unshift('.');
|
||
}
|
||
|
||
items.sort((a, b) => {
|
||
if (a === '.') return -1;
|
||
if (b === '.') return 1;
|
||
if (a === '..') return -1;
|
||
if (b === '..') return 1;
|
||
|
||
const itemA = currentPath.children[a];
|
||
const itemB = currentPath.children[b];
|
||
if (!itemA || !itemB) return 0;
|
||
if (itemA.type === 'dir' && itemB.type !== 'dir') return -1;
|
||
if (itemA.type !== 'dir' && itemB.type === 'dir') return 1;
|
||
return a.localeCompare(b);
|
||
});
|
||
|
||
if (longFormat) {
|
||
printLine(`total ${items.length}`);
|
||
items.forEach(n => {
|
||
if (n === '.' || n === '..') {
|
||
const date = new Date();
|
||
const monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
||
const month = monthNames[date.getMonth()];
|
||
const day = date.getDate().toString().padStart(2);
|
||
const time = date.toTimeString().substring(0, 5);
|
||
const dateStr = `${month} ${day} ${time}`;
|
||
const filename = `<span class='is-dir'>${n}/</span>`;
|
||
printLine(`drwxr-xr-x 2 guest guest 4096 ${dateStr} ${filename}`);
|
||
return;
|
||
}
|
||
|
||
const item = currentPath.children[n];
|
||
if (!item) return;
|
||
|
||
const isDir = item.type === 'dir';
|
||
const isExe = item.type === 'exe';
|
||
|
||
const perms = isDir ? 'drwxr-xr-x' : (isExe ? '-rwxr-xr-x' : '-rw-r--r--');
|
||
const links = isDir ? '2' : '1';
|
||
const owner = 'guest';
|
||
const group = 'guest';
|
||
|
||
let size = '0';
|
||
if (item.content) {
|
||
size = item.content.length.toString();
|
||
} else if (isDir) {
|
||
size = '4096';
|
||
}
|
||
size = size.padStart(8);
|
||
|
||
const date = new Date();
|
||
const monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
||
const month = monthNames[date.getMonth()];
|
||
const day = date.getDate().toString().padStart(2);
|
||
const time = date.toTimeString().substring(0, 5);
|
||
const dateStr = `${month} ${day} ${time}`;
|
||
|
||
let filename = n;
|
||
if (isDir) {
|
||
filename = `<span class='is-dir'>${n}/</span>`;
|
||
} else if (isExe) {
|
||
filename = `<span class='is-exe'>${n}*</span>`;
|
||
}
|
||
|
||
printLine(`${perms} ${links} ${owner} ${group} ${size} ${dateStr} ${filename}`);
|
||
});
|
||
} else {
|
||
const formatted = items.map(n => {
|
||
if (n === '.' || n === '..') {
|
||
return `<span class='is-dir'>${n}/</span>`;
|
||
}
|
||
const item = currentPath.children[n];
|
||
if (!item) return n;
|
||
if (item.type === 'dir') return `<span class='is-dir'>${n}/</span>`;
|
||
if (item.type === 'exe') return `<span class='is-exe'>${n}*</span>`;
|
||
return n;
|
||
});
|
||
printLine(formatted.join(' '));
|
||
}
|
||
break;
|
||
|
||
case 'cat':
|
||
const file = currentPath.children[args[1]];
|
||
if (file && file.type === 'file') {
|
||
printLine(file.content);
|
||
} else {
|
||
printLine(`cat: ${args[1] || ''}: No such file`, 'log-err');
|
||
}
|
||
break;
|
||
|
||
case 'cd':
|
||
if (!args[1]) {
|
||
currentPath = fileSystem.home.children.guest;
|
||
pathStr = "~";
|
||
} else if (args[1] === '..') {
|
||
if (pathStr === "/var/log") {
|
||
currentPath = fileSystem.var;
|
||
pathStr = "/var";
|
||
} else if (pathStr === "/var") {
|
||
currentPath = fileSystem.root;
|
||
pathStr = "/";
|
||
} else {
|
||
currentPath = fileSystem.home.children.guest;
|
||
pathStr = "~";
|
||
}
|
||
} else if (args[1] === '~' || args[1] === '/home/guest') {
|
||
currentPath = fileSystem.home.children.guest;
|
||
pathStr = "~";
|
||
} else if (args[1].startsWith('/var/log')) {
|
||
currentPath = fileSystem.var.children.log;
|
||
pathStr = "/var/log";
|
||
} else if (args[1].startsWith('/var')) {
|
||
currentPath = fileSystem.var;
|
||
pathStr = "/var";
|
||
} else if (args[1].startsWith('/etc')) {
|
||
currentPath = fileSystem.etc;
|
||
pathStr = "/etc";
|
||
} else if (args[1] === '/') {
|
||
currentPath = fileSystem.root;
|
||
pathStr = "/";
|
||
} else {
|
||
const subdir = currentPath.children[args[1]];
|
||
if (subdir && subdir.type === 'dir') {
|
||
currentPath = subdir;
|
||
pathStr = pathStr === "~" ? `~/${args[1]}` : `${pathStr}/${args[1]}`;
|
||
} else {
|
||
printLine(`cd: ${args[1]}: No such file or directory`, 'log-err');
|
||
}
|
||
}
|
||
break;
|
||
|
||
case 'pwd':
|
||
printLine(pathStr === "~" ? "/home/guest" : pathStr);
|
||
break;
|
||
|
||
case 'grep':
|
||
if (args.length < 3) {
|
||
printLine("Usage: grep [pattern] [file]");
|
||
} else {
|
||
const grepFile = currentPath.children[args[2]];
|
||
if (grepFile && grepFile.content) {
|
||
const lines = grepFile.content.split('\n');
|
||
lines.forEach(l => {
|
||
if (l.toLowerCase().includes(args[1].toLowerCase())) {
|
||
printLine(l);
|
||
}
|
||
});
|
||
} else {
|
||
printLine(`grep: ${args[2]}: No such file`);
|
||
}
|
||
}
|
||
break;
|
||
|
||
case 'find':
|
||
if (!args[1]) {
|
||
printLine("Usage: find [name]");
|
||
} else {
|
||
const results = [];
|
||
function searchDir(dir, path) {
|
||
Object.keys(dir.children || {}).forEach(name => {
|
||
if (name.includes(args[1])) {
|
||
results.push(`${path}/${name}`);
|
||
}
|
||
if (dir.children[name].type === 'dir') {
|
||
searchDir(dir.children[name], `${path}/${name}`);
|
||
}
|
||
});
|
||
}
|
||
searchDir(currentPath, pathStr === "~" ? "/home/guest" : pathStr);
|
||
if (results.length > 0) {
|
||
results.forEach(r => printLine(r));
|
||
} else {
|
||
printLine(`find: '${args[1]}': No such file`);
|
||
}
|
||
}
|
||
break;
|
||
|
||
case 'head':
|
||
if (!args[1]) {
|
||
printLine("Usage: head [file]");
|
||
} else {
|
||
const headFile = currentPath.children[args[1]];
|
||
if (headFile && headFile.content) {
|
||
const lines = headFile.content.split('\n').slice(0, 10);
|
||
lines.forEach(l => printLine(l));
|
||
} else {
|
||
printLine(`head: ${args[1]}: No such file`);
|
||
}
|
||
}
|
||
break;
|
||
|
||
case 'tail':
|
||
if (!args[1]) {
|
||
printLine("Usage: tail [file]");
|
||
} else {
|
||
const tailFile = currentPath.children[args[1]];
|
||
if (tailFile && tailFile.content) {
|
||
const lines = tailFile.content.split('\n').slice(-10);
|
||
lines.forEach(l => printLine(l));
|
||
} else {
|
||
printLine(`tail: ${args[1]}: No such file`);
|
||
}
|
||
}
|
||
break;
|
||
|
||
case 'wc':
|
||
if (!args[1]) {
|
||
printLine("Usage: wc [file]");
|
||
} else {
|
||
const wcFile = currentPath.children[args[1]];
|
||
if (wcFile && wcFile.content) {
|
||
const lines = wcFile.content.split('\n');
|
||
const words = wcFile.content.split(/\s+/).filter(w => w);
|
||
const chars = wcFile.content.length;
|
||
printLine(` ${lines.length} ${words.length} ${chars} ${args[1]}`);
|
||
} else {
|
||
printLine(`wc: ${args[1]}: No such file`);
|
||
}
|
||
}
|
||
break;
|
||
|
||
case 'whoami':
|
||
printLine("guest");
|
||
break;
|
||
|
||
case 'uname':
|
||
if (args.includes('-a')) {
|
||
printLine("Linux 404-void 4.0.4-void #1 SMP PREEMPT Fri Jan 09 2025 x86_64 GNU/Linux");
|
||
} else {
|
||
printLine("Linux");
|
||
}
|
||
break;
|
||
|
||
case 'date':
|
||
printLine(new Date().toString());
|
||
break;
|
||
|
||
case 'uptime':
|
||
const uptime = Math.floor((Date.now() - performance.timing.navigationStart) / 1000);
|
||
const hours = Math.floor(uptime / 3600);
|
||
const mins = Math.floor((uptime % 3600) / 60);
|
||
const secs = uptime % 60;
|
||
printLine(`up ${hours}:${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}, 1 user, load average: 0.00, 0.00, 0.00`);
|
||
break;
|
||
|
||
case 'hostname':
|
||
printLine("404-void-server");
|
||
break;
|
||
|
||
case 'ping':
|
||
const host = args[1] || "google.com";
|
||
printLine(`PING ${host} (127.0.0.1) 56(84) bytes of data.`);
|
||
for (let i = 0; i < 4; i++) {
|
||
await sleep(1000);
|
||
printLine(`64 bytes from ${host}: icmp_seq=${i + 1} ttl=118 time=${(Math.random() * 50 + 10).toFixed(1)} ms`);
|
||
}
|
||
printLine(`--- ${host} ping statistics ---`);
|
||
printLine("4 packets transmitted, 4 received, 0% packet loss");
|
||
break;
|
||
|
||
case 'ps':
|
||
printLine(" PID TTY TIME CMD");
|
||
printLine(" 1 ? 00:00:04 init");
|
||
printLine(" 404 ? 00:00:01 bash");
|
||
printLine(" 666 ? 00:00:00 reality");
|
||
break;
|
||
|
||
case 'top':
|
||
printLine("top - 00:00:00 up 0:00, 1 user, load average: 0.00, 0.00, 0.00");
|
||
printLine("Tasks: 3 total, 1 running, 2 sleeping, 0 stopped, 0 zombie");
|
||
printLine("%Cpu(s): 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st");
|
||
printLine("KiB Mem : 1048576 total, 999936 free, 12345 used, 36295 buff/cache");
|
||
printLine("KiB Swap: 0 total, 0 free, 0 used. 999936 avail Mem");
|
||
printLine("");
|
||
printLine(" PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND");
|
||
printLine(" 1 root 20 0 40404 4004 3000 S 0.0 0.1 0:04.04 init");
|
||
printLine(" 404 guest 20 0 999999 99999 5000 R 99.9 10.0 4:20.69 bash");
|
||
printLine(" 666 system -20 0 0 0 0 Z 0.0 0.0 0:00.00 reality");
|
||
break;
|
||
|
||
case 'kill':
|
||
if (!args[1]) {
|
||
printLine("Usage: kill [pid]");
|
||
} else {
|
||
printLine(`kill: cannot kill process ${args[1]}: Operation not permitted`, 'log-err');
|
||
}
|
||
break;
|
||
|
||
case 'history':
|
||
commandHistory.forEach((c, i) => printLine(` ${i + 1} ${c}`));
|
||
break;
|
||
|
||
case 'clear':
|
||
output.innerHTML = "";
|
||
break;
|
||
|
||
case 'exit':
|
||
window.location.href = '/';
|
||
break;
|
||
|
||
case 'hawkins':
|
||
case '011':
|
||
case 'eleven':
|
||
case 'upsidedown':
|
||
await triggerHawkins();
|
||
break;
|
||
|
||
case 'fsociety':
|
||
case 'elliot':
|
||
case 'bonsoir':
|
||
await triggerFsociety();
|
||
break;
|
||
|
||
case '42':
|
||
case 'answer':
|
||
await triggerDeepThought();
|
||
break;
|
||
|
||
case 'rm':
|
||
if (args[1] === '-rf' && args[2] === '/') {
|
||
await initiateMeltdown();
|
||
} else if (args[1]) {
|
||
printLine("rm: cannot remove: Read-only file system", 'log-err');
|
||
} else {
|
||
printLine("Usage: rm [file]");
|
||
}
|
||
break;
|
||
|
||
default:
|
||
printLine(`bash: ${cmd}: command not found`, 'log-err');
|
||
}
|
||
output.scrollTop = output.scrollHeight;
|
||
|
||
if (!systemFrozen && inputContainer.style.display === 'flex') {
|
||
setTimeout(() => input.focus(), 50);
|
||
}
|
||
}
|
||
|
||
async function triggerHawkins() {
|
||
if (hawkinsActive) {
|
||
printLine("Closing dimensional gate...", 'log-warn');
|
||
await sleep(500);
|
||
|
||
if (currentMusic) {
|
||
currentMusic.stop();
|
||
currentMusic = null;
|
||
}
|
||
|
||
document.body.classList.remove('hawkins');
|
||
hawkinsActive = false;
|
||
printLine("Returned to normal reality.", 'log-sys');
|
||
return;
|
||
}
|
||
|
||
hawkinsActive = true;
|
||
|
||
printLine("WARNING: Anomalous readings detected...", 'log-warn');
|
||
await sleep(600);
|
||
printLine("Dimensional instability increasing...", 'log-err');
|
||
await sleep(500);
|
||
|
||
document.body.style.filter = 'hue-rotate(180deg) contrast(1.5)';
|
||
await sleep(200);
|
||
document.body.style.filter = '';
|
||
await sleep(200);
|
||
document.body.style.filter = 'hue-rotate(180deg) contrast(1.5)';
|
||
await sleep(150);
|
||
|
||
printLine("CRITICAL: Breach imminent!", 'pulse-red');
|
||
await sleep(400);
|
||
printLine("Entering the Upside Down...", 'log-err');
|
||
await sleep(300);
|
||
|
||
if (currentMusic) {
|
||
currentMusic.stop();
|
||
currentMusic = null;
|
||
}
|
||
|
||
playSynth('scare');
|
||
currentMusic = playStrangerThingsTheme();
|
||
document.body.classList.add('hawkins');
|
||
|
||
const vecnaArt = `
|
||
████████████████████████████████
|
||
██ ██
|
||
██ ████ ████ ██
|
||
██ ██ ████ ██ ██
|
||
██ ██ ██ ██
|
||
██ ██ ██ ██ ██ ██
|
||
██ ██ ██ ██ ██ ██
|
||
██ ██ ██ ██
|
||
██ ██████████ ██
|
||
██ ██
|
||
██ ████████████████ ██
|
||
██ ██ ██ ██
|
||
██ ██ ██ ██
|
||
██ ██████████████ ██
|
||
██ ██
|
||
████████████████████████████████
|
||
`;
|
||
|
||
const overlay = document.getElementById('flash-overlay');
|
||
|
||
for (let i = 0; i < 3; i++) {
|
||
overlay.innerHTML = `<div class="ascii-art pulse-red" style="font-size:${10 + i * 2}px; transform: scale(${1.0 + i * 0.3});">${vecnaArt}</div>`;
|
||
overlay.style.display = 'flex';
|
||
overlay.style.background = `rgba(255, 0, 0, ${0.3 + i * 0.2})`;
|
||
await sleep(200);
|
||
overlay.style.display = 'none';
|
||
await sleep(100);
|
||
}
|
||
|
||
overlay.innerHTML = `<div class="ascii-art pulse-red" style="font-size:14px; transform: scale(1.5);">${vecnaArt}</div>`;
|
||
overlay.style.display = 'flex';
|
||
overlay.style.background = 'rgba(255, 0, 0, 0.7)';
|
||
await sleep(400);
|
||
overlay.style.display = 'none';
|
||
overlay.innerHTML = "";
|
||
|
||
const sporeInterval = setInterval(() => {
|
||
const spore = document.createElement('div');
|
||
spore.className = 'spore';
|
||
spore.style.left = Math.random() * 100 + '%';
|
||
spore.style.top = Math.random() * 100 + '%';
|
||
spore.style.opacity = '0.6';
|
||
document.body.appendChild(spore);
|
||
setTimeout(() => spore.remove(), 3000);
|
||
}, 300);
|
||
|
||
const glitchInterval = setInterval(() => {
|
||
if (!hawkinsActive) {
|
||
clearInterval(glitchInterval);
|
||
clearInterval(sporeInterval);
|
||
return;
|
||
}
|
||
document.body.style.filter = 'hue-rotate(180deg) contrast(1.3) brightness(0.9)';
|
||
setTimeout(() => {
|
||
document.body.style.filter = '';
|
||
}, 100 + Math.random() * 200);
|
||
}, 2000);
|
||
|
||
printLine("", 'log-dim');
|
||
printLine("████████████████████████████████████████", 'pulse-red');
|
||
printLine("█ YOU ARE NOW IN THE UPSIDE DOWN █", 'pulse-red');
|
||
printLine("████████████████████████████████████████", 'pulse-red');
|
||
printLine("", 'log-dim');
|
||
printLine("Reality is distorted. Time flows differently here.", 'log-warn');
|
||
printLine("Type 'hawkins' or '011' again to return.", 'log-dim');
|
||
|
||
setTimeout(() => {
|
||
if (hawkinsActive) {
|
||
clearInterval(glitchInterval);
|
||
clearInterval(sporeInterval);
|
||
printLine("", 'log-dim');
|
||
printLine("Dimensional gate closing automatically...", 'log-warn');
|
||
triggerHawkins();
|
||
}
|
||
}, 30000);
|
||
}
|
||
|
||
async function triggerFsociety() {
|
||
if (fsocietyActive) {
|
||
printLine("Disconnecting from fsociety network...", 'log-warn');
|
||
await sleep(500);
|
||
|
||
if (currentMusic) {
|
||
currentMusic.stop();
|
||
currentMusic = null;
|
||
}
|
||
|
||
document.body.classList.remove('fsociety-boot');
|
||
fsocietyActive = false;
|
||
systemFrozen = false;
|
||
printLine("Connection terminated.", 'log-sys');
|
||
return;
|
||
}
|
||
|
||
fsocietyActive = true;
|
||
systemFrozen = true;
|
||
inputContainer.style.display = 'none';
|
||
output.innerHTML = "";
|
||
document.body.classList.add('fsociety-boot');
|
||
|
||
if (currentMusic) {
|
||
currentMusic.stop();
|
||
currentMusic = null;
|
||
}
|
||
|
||
currentMusic = playMrRobotTheme();
|
||
|
||
printLine("$ ./fsociety.sh", 'log-k');
|
||
await sleep(250);
|
||
printLine("[*] Initializing breach protocol...", 'log-warn');
|
||
await sleep(180);
|
||
printLine("[*] Scanning target: E-Corp mainframe", 'log-warn');
|
||
await sleep(200);
|
||
printLine("[*] Exploiting CVE-2024-1337... 0x" + Array.from({length: 8}, () => Math.floor(Math.random() * 16).toString(16).toUpperCase()).join(''), 'log-dim');
|
||
await sleep(180);
|
||
printLine("[*] Bypassing firewall...", 'log-warn');
|
||
await sleep(180);
|
||
printLine("[*] Escalating privileges... root access granted", 'log-warn');
|
||
await sleep(200);
|
||
printLine("[*] Injecting payload... success", 'log-warn');
|
||
await sleep(180);
|
||
printLine("[*] Establishing backdoor...", 'log-warn');
|
||
await sleep(200);
|
||
printLine("", 'log-dim');
|
||
printLine(" ██ ██", 'fsociety-mask');
|
||
printLine(" ██ ██ ██ ██", 'fsociety-mask');
|
||
printLine(" ██ ████ ██", 'fsociety-mask');
|
||
printLine(" ██ ██", 'fsociety-mask');
|
||
printLine(" ██ ██ ██ ██", 'fsociety-mask');
|
||
printLine(" ██ ██ ██ ██", 'fsociety-mask');
|
||
printLine(" ██ ██████ ██", 'fsociety-mask');
|
||
printLine(" ██ ██", 'fsociety-mask');
|
||
printLine(" ██████████████", 'fsociety-mask');
|
||
await sleep(400);
|
||
printLine("", 'log-dim');
|
||
printLine("Hello friend.", 'log-k');
|
||
await sleep(350);
|
||
printLine("Control is an illusion.", 'log-k');
|
||
await sleep(350);
|
||
printLine("We are fsociety.", 'log-k');
|
||
await sleep(350);
|
||
printLine("", 'log-dim');
|
||
printLine(">>> Accessing E-Corp database... [████████████] 100%", 'log-warn');
|
||
await sleep(280);
|
||
printLine(">>> Encrypting files... [████████████] 100%", 'log-warn');
|
||
await sleep(280);
|
||
printLine(">>> Deleting debt records... [████████████] 100%", 'log-warn');
|
||
await sleep(280);
|
||
printLine("", 'log-dim');
|
||
printLine("Mission accomplished. The world is watching.", 'log-k');
|
||
await sleep(400);
|
||
|
||
printLine("", 'log-dim');
|
||
printLine("System compromised. Initiating emergency reboot...", 'log-err');
|
||
await sleep(1500);
|
||
|
||
if (currentMusic) {
|
||
currentMusic.stop();
|
||
currentMusic = null;
|
||
}
|
||
|
||
document.body.classList.remove('fsociety-boot');
|
||
fsocietyActive = false;
|
||
systemFrozen = false;
|
||
|
||
output.innerHTML = "";
|
||
await sleep(500);
|
||
|
||
printLine("Rebooting system...", 'log-warn');
|
||
await sleep(800);
|
||
printLine("Restoring from backup...", 'log-sys');
|
||
await sleep(1000);
|
||
printLine("System restored.", 'log-sys');
|
||
await sleep(500);
|
||
|
||
location.reload();
|
||
}
|
||
|
||
async function triggerDeepThought() {
|
||
printLine("Initializing Deep Thought...", 'log-sys');
|
||
await sleep(600);
|
||
printLine("", 'log-dim');
|
||
printLine("Deep Thought: Good morning.", 'log-k');
|
||
await sleep(800);
|
||
printLine("", 'log-dim');
|
||
printLine("Deep Thought: I am the second greatest computer in the Universe of Time and Space.", 'log-k');
|
||
await sleep(1000);
|
||
printLine("", 'log-dim');
|
||
printLine("Deep Thought: You want to know the Answer to the Ultimate Question?", 'log-k');
|
||
await sleep(800);
|
||
printLine("Deep Thought: The Answer to the Ultimate Question of Life, the Universe, and Everything?", 'log-k');
|
||
await sleep(1000);
|
||
printLine("", 'log-dim');
|
||
printLine("Deep Thought: ...", 'log-dim');
|
||
await sleep(500);
|
||
printLine("Deep Thought: Thinking...", 'log-dim');
|
||
await sleep(800);
|
||
|
||
if (currentMusic) {
|
||
currentMusic.stop();
|
||
currentMusic = null;
|
||
}
|
||
|
||
printLine("Deep Thought: This will take a moment...", 'log-dim');
|
||
await sleep(1200);
|
||
printLine("Deep Thought: (approximately 7,500,000 years)", 'log-dim');
|
||
await sleep(1000);
|
||
printLine("", 'log-dim');
|
||
printLine("Deep Thought: ...", 'log-dim');
|
||
await sleep(600);
|
||
printLine("Deep Thought: ...", 'log-dim');
|
||
await sleep(600);
|
||
printLine("Deep Thought: ...", 'log-dim');
|
||
await sleep(800);
|
||
printLine("", 'log-dim');
|
||
printLine("Deep Thought: I have the answer.", 'log-k');
|
||
await sleep(1000);
|
||
printLine("", 'log-dim');
|
||
printLine("The Answer to the Ultimate Question of Life, the Universe, and Everything is...", 'log-sys');
|
||
await sleep(1500);
|
||
printLine("", 'log-dim');
|
||
printLine("42", 'log-k');
|
||
await sleep(1000);
|
||
printLine("", 'log-dim');
|
||
printLine("Deep Thought: Though I'm not entirely sure what the question is.", 'log-dim');
|
||
await sleep(1000);
|
||
printLine("Deep Thought: But the answer is definitely 42.", 'log-k');
|
||
}
|
||
|
||
async function initiateMeltdown() {
|
||
systemFrozen = true;
|
||
inputContainer.style.display = 'none';
|
||
|
||
if (currentMusic) {
|
||
currentMusic.stop();
|
||
currentMusic = null;
|
||
}
|
||
|
||
printLine("CRITICAL: Attempting to delete root filesystem...", 'log-err');
|
||
await sleep(500);
|
||
printLine("WARNING: Memory corruption detected!", 'log-warn');
|
||
await sleep(400);
|
||
printLine("ERROR: RAM integrity compromised!", 'log-err');
|
||
await sleep(300);
|
||
|
||
playSynth('melt');
|
||
|
||
let corruptionCount = 0;
|
||
const corruptInterval = setInterval(() => {
|
||
const nodes = Array.from(output.childNodes).filter(n => n.nodeType === 1);
|
||
if (nodes.length > 0) {
|
||
const randomNode = nodes[Math.floor(Math.random() * nodes.length)];
|
||
if (randomNode.innerText && randomNode.innerText.length > 3) {
|
||
const chars = "¥§¶$@#%&XØ¥€©±×÷";
|
||
const glitchChar = chars[Math.floor(Math.random() * chars.length)];
|
||
randomNode.innerHTML = randomNode.innerHTML.replace(/[a-zA-Z0-9]/, `<span class="corrupted-text">${glitchChar}</span>`);
|
||
}
|
||
}
|
||
corruptionCount++;
|
||
|
||
if (corruptionCount === 15) {
|
||
printLine("MEMORY ERROR: 0xDEADBEEF at address 0xFFFFFFFF", 'memory-error');
|
||
} else if (corruptionCount === 30) {
|
||
printLine("KERNEL PANIC: Unable to handle kernel paging request", 'kernel-panic');
|
||
} else if (corruptionCount === 45) {
|
||
printLine("SYSTEM HALTED", 'kernel-panic');
|
||
clearInterval(corruptInterval);
|
||
|
||
document.body.classList.add('meltdown');
|
||
playSynth('melt');
|
||
|
||
setTimeout(() => {
|
||
document.body.classList.remove('meltdown');
|
||
document.body.style.background = '#000';
|
||
document.body.style.color = '#000';
|
||
output.style.display = 'none';
|
||
inputContainer.style.display = 'none';
|
||
|
||
setTimeout(() => {
|
||
output.innerHTML = '';
|
||
output.style.display = 'block';
|
||
output.style.color = '#33ff00';
|
||
document.body.style.color = '#33ff00';
|
||
document.body.style.background = '#020202';
|
||
|
||
printLine("", 'log-sys');
|
||
printLine("System backup restore initiated...", 'log-sys');
|
||
printLine("Recovering from kernel panic...", 'log-sys');
|
||
printLine("Restoring file system...", 'log-sys');
|
||
printLine("", 'log-sys');
|
||
|
||
setTimeout(() => {
|
||
location.reload();
|
||
}, 3000);
|
||
}, 2000);
|
||
}, 1000);
|
||
}
|
||
}, 80);
|
||
}
|
||
|
||
function printLine(text, type) {
|
||
const d = document.createElement('div');
|
||
d.innerHTML = text;
|
||
// Default color for normal text
|
||
d.style.color = 'var(--phosphor)';
|
||
if (type === 'log-warn') d.style.color = '#ffb000';
|
||
if (type === 'log-err' || type === 'alert') d.style.color = 'var(--alert)';
|
||
if (type === 'log-dim') {
|
||
d.style.opacity = '0.6';
|
||
d.style.color = 'var(--phosphor)';
|
||
}
|
||
if (type === 'log-sys') d.style.color = 'cyan';
|
||
if (type === 'log-k') d.style.color = '#fff';
|
||
if (type === 'pulse-red') d.classList.add('pulse-red');
|
||
output.appendChild(d);
|
||
}
|
||
|
||
function sleep(ms) {
|
||
return new Promise(resolve => setTimeout(resolve, ms));
|
||
}
|
||
</script>
|
||
</body>
|
||
</html>
|