8
8
<!-- Fixed asset loading - version 2 -->
9
9
10
10
<!-- Vite will process and bundle CSS automatically when imported in JS -->
11
- <!-- Vite entry point - must be in head for proper processing -->
12
- < script type ="module " src ="./src/main.js "> </ script >
13
-
14
11
< style >
15
12
body {
16
13
margin : 0 ;
457
454
transform : rotate (90deg );
458
455
}
459
456
</ style >
460
- </ head >
461
457
458
+ <!-- Performance monitoring and error handling -->
459
+ < script >
460
+ // Performance monitoring
461
+ window . performance . mark ( 'page-start' ) ;
462
+
463
+ // Global error handler to prevent unhandled exceptions from crashing the application
464
+ window . addEventListener ( 'error' , function ( event ) {
465
+ console . error ( 'Global error caught:' , {
466
+ error : event . error ,
467
+ message : event . message ,
468
+ filename : event . filename ,
469
+ lineno : event . lineno ,
470
+ colno : event . colno ,
471
+ stack : event . error ?. stack
472
+ } ) ;
473
+
474
+ // Show error to user for critical errors
475
+ const errorMessage = event . error ? ( event . error . stack || event . error . message ) : event . message ;
476
+ if ( errorMessage . includes ( 'WebGL' ) || errorMessage . includes ( 'THREE' ) || errorMessage . includes ( 'memory' ) ) {
477
+ showErrorOverlay ( errorMessage ) ;
478
+ }
479
+
480
+ event . preventDefault ( ) ;
481
+ return true ;
482
+ } ) ;
483
+
484
+ // Also catch unhandled promise rejections
485
+ window . addEventListener ( 'unhandledrejection' , function ( event ) {
486
+ console . error ( 'Unhandled promise rejection:' , {
487
+ reason : event . reason ,
488
+ stack : event . reason ?. stack
489
+ } ) ;
490
+ event . preventDefault ( ) ;
491
+ } ) ;
492
+
493
+ // Show error overlay
494
+ function showErrorOverlay ( message ) {
495
+ const errorOverlay = document . createElement ( 'div' ) ;
496
+ errorOverlay . style . cssText = `
497
+ position: fixed;
498
+ top: 10px;
499
+ left: 10px;
500
+ right: 10px;
501
+ background: rgba(255, 0, 0, 0.8);
502
+ color: white;
503
+ padding: 15px;
504
+ border-radius: 5px;
505
+ z-index: 100000;
506
+ font-family: sans-serif;
507
+ max-height: 200px;
508
+ overflow-y: auto;
509
+ ` ;
510
+ errorOverlay . innerHTML = `
511
+ <h3>An error occurred</h3>
512
+ <p>${ message } </p>
513
+ <button onclick="window.location.reload()" style="background: white; border: none; padding: 5px 10px; margin-top: 10px; cursor: pointer;">
514
+ Reload
515
+ </button>
516
+ <button onclick="this.parentNode.remove()" style="background: #333; color: white; border: none; padding: 5px 10px; margin-top: 10px; margin-left: 10px; cursor: pointer;">
517
+ Dismiss
518
+ </button>
519
+ ` ;
520
+ document . body . appendChild ( errorOverlay ) ;
521
+ }
522
+
523
+ // Simplified debug logger
524
+ window . debugLumon = {
525
+ log : function ( message ) {
526
+ console . log ( "%c[Lumon Debug] " + message , "color: #5CDED3" ) ;
527
+ } ,
528
+ error : function ( message ) {
529
+ console . error ( "%c[Lumon Debug] " + message , "color: #FF5555" ) ;
530
+ }
531
+ } ;
532
+ </ script >
533
+ </ head >
462
534
< body >
463
- <!-- Dev Terminal Overlay -->
464
- < div id ="dev-terminal-overlay ">
465
- < div id ="dev-terminal-header ">
466
- < span > Terminal - Severance Environment</ span >
467
- < div class ="terminal-controls ">
468
- < button class ="terminal-minimize "> -</ button >
469
- < button class ="terminal-maximize "> +</ button >
470
- < button class ="terminal-close " id ="dev-terminal-close "> ×</ button >
471
- </ div >
472
- </ div >
473
- < div id ="dev-terminal-body "> </ div >
474
- < div id ="dev-terminal-prompt "> </ div >
475
- </ div >
476
-
477
535
< div id ="app-container ">
478
536
< div id ="three-container "> </ div >
479
-
480
- <!-- HUD -->
481
- < div id ="game-hud " class ="hud ">
482
- < div id ="location-indicator "> Location: Unknown</ div >
483
-
484
- <!-- Subtitle container -->
485
- < div id ="subtitle-container ">
486
- < div id ="subtitle-text "> </ div >
487
- </ div >
488
537
489
- <!-- Interaction prompt -->
490
- < div id ="interaction-prompt ">
491
- Press E to interact
538
+ < div id ="subtitle-container "> </ div >
539
+ < div id ="ui-overlay ">
540
+ < div id ="location-indicator "> </ div >
541
+ < div id ="interaction-prompt " style ="display: none; "> </ div >
542
+ <!-- Dev Terminal Overlay (hidden by default) -->
543
+ < div id ="dev-terminal-overlay " style ="display:none; position:fixed; left:5vw; top:15vh; width:700px; height:400px; background:#000; color:#33ff33; border:2px solid #33ff33; border-radius:4px; z-index:10000; font-family:'Fira Mono', 'Courier New', monospace; box-shadow:0 0 10px rgba(51, 255, 51, 0.5); padding:0; overflow:hidden; ">
544
+ < div id ="dev-terminal-header ">
545
+ < div id ="dev-terminal-title "> TERMINAL</ div >
546
+ < div id ="dev-terminal-controls ">
547
+ < div class ="terminal-btn terminal-minimize "> </ div >
548
+ < div class ="terminal-btn terminal-maximize "> </ div >
549
+ < div class ="terminal-btn terminal-close " id ="dev-terminal-close "> </ div >
550
+ </ div >
551
+ </ div >
552
+ < div class ="terminal-scan-line "> </ div >
553
+ < div id ="dev-terminal-body "> </ div >
554
+ < div id ="dev-terminal-prompt "> </ div >
492
555
</ div >
493
-
494
- <!-- Controls info panel -->
556
+ </ div >
557
+
558
+ <!-- Game HUD -->
559
+ < div id ="game-hud " class ="hud ">
560
+ <!-- Improved controls info box -->
495
561
< div id ="controls-info ">
496
562
< div id ="controls-header "> CONTROLS</ div >
497
563
< div class ="control-items ">
523
589
</ div >
524
590
</ div >
525
591
</ div >
592
+
593
+ <!-- Vite will process this module script and bundle everything -->
594
+ < script type ="module " src ="./src/main.js "> </ script >
595
+
596
+ < script >
597
+ // Initialize UI components after DOM is loaded
598
+ document . addEventListener ( 'DOMContentLoaded' , ( ) => {
599
+ // Make sure controls are visible by default
600
+ const controlsInfo = document . getElementById ( 'controls-info' ) ;
601
+ if ( controlsInfo && controlsInfo . classList . contains ( 'hidden' ) ) {
602
+ controlsInfo . classList . remove ( 'hidden' ) ;
603
+ }
604
+
605
+ // Test terminal function (for development)
606
+ window . openTerminal = function ( ) {
607
+ if ( typeof window . showDevTerminalOverlay === 'function' ) {
608
+ window . showDevTerminalOverlay ( ) ;
609
+ }
610
+ } ;
611
+
612
+ // Keyboard shortcut for testing terminal (Alt + T)
613
+ document . addEventListener ( 'keydown' , function ( e ) {
614
+ if ( e . altKey && e . key === 't' ) {
615
+ window . openTerminal ( ) ;
616
+ }
617
+ } ) ;
618
+ } ) ;
619
+
620
+ // Add global mouse tracking for shaders
621
+ window . mouseX = window . innerWidth / 2 ;
622
+ window . mouseY = window . innerHeight / 2 ;
623
+
624
+ document . addEventListener ( 'mousemove' , ( event ) => {
625
+ window . mouseX = event . clientX ;
626
+ window . mouseY = event . clientY ;
627
+ } ) ;
628
+ </ script >
629
+
630
+ <!-- DEV TERMINAL OVERLAY LOGIC -->
631
+ < script >
632
+ ( function ( ) {
633
+ const overlay = document . getElementById ( 'dev-terminal-overlay' ) ;
634
+ const body = document . getElementById ( 'dev-terminal-body' ) ;
635
+ const promptDiv = document . getElementById ( 'dev-terminal-prompt' ) ;
636
+ const closeBtn = document . getElementById ( 'dev-terminal-close' ) ;
637
+ const minimizeBtn = document . querySelector ( '.terminal-minimize' ) ;
638
+ const maximizeBtn = document . querySelector ( '.terminal-maximize' ) ;
639
+
640
+ const PROMPT = 'parsa@portfolio:~$ ' ;
641
+ const WELCOME_MESSAGE = [
642
+ '█ AUTHORIZED ACCESS ONLY █' ,
643
+ '' ,
644
+ 'Type "help" for available commands.' ,
645
+ ''
646
+ ] . join ( '\n' ) ;
647
+
648
+ let input = '' ;
649
+ let isOpen = false ;
650
+ let cursorVisible = true ;
651
+ let cursorInterval = null ;
652
+ let commandHistory = [ ] ;
653
+ let historyIndex = - 1 ;
654
+
655
+ function renderPrompt ( ) {
656
+ promptDiv . innerHTML =
657
+ `<span style="color:#33ff33;">${ PROMPT } </span>` +
658
+ `<span id="dev-terminal-input">${ input . replace ( / / g, ' ' ) } </span>` +
659
+ `<span class="dev-terminal-cursor"> </span>` ;
660
+ }
661
+
662
+ function appendOutput ( text , className = '' ) {
663
+ if ( className ) {
664
+ body . innerHTML += `<div class="${ className } ">${ text } </div>` ;
665
+ } else {
666
+ body . innerHTML += `${ text } \n` ;
667
+ }
668
+ body . scrollTop = body . scrollHeight ;
669
+ }
670
+
671
+ function processCommand ( cmd ) {
672
+ if ( cmd . trim ( ) !== '' ) {
673
+ commandHistory . push ( cmd ) ;
674
+ historyIndex = commandHistory . length ;
675
+ }
676
+
677
+ appendOutput ( `${ PROMPT } ${ cmd } ` , 'terminal-command' ) ;
678
+
679
+ const trimmedCmd = cmd . trim ( ) . toLowerCase ( ) ;
680
+
681
+ switch ( trimmedCmd ) {
682
+ case 'help' :
683
+ appendOutput ( 'Available commands: help, clear, version, exit' , 'terminal-output' ) ;
684
+ break ;
685
+ case 'clear' :
686
+ body . innerHTML = '' ;
687
+ break ;
688
+ case 'version' :
689
+ appendOutput ( 'Severance Terminal v1.0' , 'terminal-output' ) ;
690
+ break ;
691
+ case 'exit' :
692
+ window . hideDevTerminalOverlay ( ) ;
693
+ return ;
694
+ default :
695
+ if ( trimmedCmd !== '' ) {
696
+ appendOutput ( `bash: ${ cmd } : command not found` , 'terminal-error' ) ;
697
+ }
698
+ }
699
+ }
700
+
701
+ function onKeyDown ( e ) {
702
+ if ( ! isOpen ) return ;
703
+
704
+ switch ( e . key ) {
705
+ case 'Escape' :
706
+ window . hideDevTerminalOverlay ( ) ;
707
+ e . preventDefault ( ) ;
708
+ return ;
709
+ case 'Backspace' :
710
+ input = input . slice ( 0 , - 1 ) ;
711
+ renderPrompt ( ) ;
712
+ e . preventDefault ( ) ;
713
+ return ;
714
+ case 'Enter' :
715
+ processCommand ( input ) ;
716
+ input = '' ;
717
+ renderPrompt ( ) ;
718
+ e . preventDefault ( ) ;
719
+ return ;
720
+ }
721
+
722
+ if ( e . key . length === 1 && ! e . ctrlKey && ! e . metaKey && ! e . altKey ) {
723
+ input += e . key ;
724
+ renderPrompt ( ) ;
725
+ e . preventDefault ( ) ;
726
+ }
727
+ }
728
+
729
+ window . showDevTerminalOverlay = function ( ) {
730
+ if ( isOpen ) return ;
731
+
732
+ overlay . style . display = 'block' ;
733
+ isOpen = true ;
734
+ input = '' ;
735
+
736
+ body . innerHTML = '' ;
737
+ appendOutput ( WELCOME_MESSAGE ) ;
738
+ renderPrompt ( ) ;
739
+
740
+ document . addEventListener ( 'keydown' , onKeyDown , true ) ;
741
+
742
+ if ( cursorInterval ) clearInterval ( cursorInterval ) ;
743
+ cursorInterval = setInterval ( ( ) => {
744
+ const cursor = promptDiv . querySelector ( '.dev-terminal-cursor' ) ;
745
+ if ( cursor ) cursor . style . opacity = cursorVisible ? '1' : '0' ;
746
+ cursorVisible = ! cursorVisible ;
747
+ } , 500 ) ;
748
+ } ;
749
+
750
+ window . hideDevTerminalOverlay = function ( ) {
751
+ if ( ! isOpen ) return ;
752
+
753
+ overlay . style . display = 'none' ;
754
+ isOpen = false ;
755
+
756
+ document . removeEventListener ( 'keydown' , onKeyDown , true ) ;
757
+
758
+ if ( cursorInterval ) clearInterval ( cursorInterval ) ;
759
+ } ;
760
+
761
+ if ( closeBtn ) closeBtn . onclick = window . hideDevTerminalOverlay ;
762
+ } ) ( ) ;
763
+ </ script >
526
764
</ body >
527
765
</ html >
0 commit comments