// ============================================================ // CONFIG — alle einstellbaren Werte für den Minecraft Clone // ============================================================ // Hier kannst du Aussehen, Performance, Welt und Spieler- // verhalten anpassen. Strukturelle Engine-Konstanten // (Chunk-Größen, Block-IDs, Textur-Atlas) liegen in // constants.js und sollten NICHT geändert werden (sonst // drohen Mesh/Storage-Fehler). // // 👉 Live anpassen: Im Spiel **P** drücken (oder ⚙ oben // rechts). Grafik-Werte greifen sofort, Welt-/Performance- // Werte brauchen einen Neustart (Button im Panel). // Alle Änderungen werden in localStorage gespeichert und // überschreiben diese Defaults beim Laden. // // Nach jeder Direktänderung hier: HARD-REFRESH (Ctrl+Shift+R), // damit der Browser die Module nicht aus dem Cache lädt. // ============================================================ import * as THREE from 'three'; // Primitives sind `let`, damit gespeicherte Overrides (localStorage) // sie beim Laden überschreiben können. Objekte bleiben `const` und // werden per Object.assign gemutiert. export let WORLD_SEED = 1337; // gleicher Seed = gleiche Welt. Beliebige ganze Zahl. export let SEA_LEVEL = 26; // Höhe der Wasseroberfläche (muss < CHUNK_HEIGHT=64 bleiben) // Spawn-Position (X/Z in Blöcken; Y wird automatisch auf den Boden gesetzt). export const SPAWN = { x: 8, z: 8 }; export let RENDER_DISTANCE = 6; // Chunk-Radius um den Spieler (höher = weiter sichtbar, mehr Last) export let MAX_OPS_PER_FRAME = 2; // Chunk-Generierung/Meshing pro Frame (höher = lädt schneller, ruckelt eher) export let MAX_PIXEL_RATIO = 2; // Cap der Gerät-Pixelratio (2 = scharf; 1 = schneller auf HiDPI-Screens) export let ANTIALIAS = true; // MSAA direkt am Renderer (Kantenglättung ohne Composer) export let MSAA_SAMPLES = 4; // MSAA-Stufen im Post-Processing-Composer (WebGL2; 0 = aus) export let TONE_MAPPING = THREE.ACESFilmicToneMapping; // "Color Grading". Alternativen: THREE.Linear / Reinhard / Cineon export let TONE_MAPPING_EXPOSURE = 1.1; // globale Helligkeit (höher = heller). ACES dunkelt leicht ab. export let SKY_COLOR = 0xaaccff; // Hintergrund- und Nebelfarbe export let FOG_NEAR = 64; // Block-Distanz, ab der Nebel einsetzt (≈ (RENDER_DISTANCE-2)*16) export let FOG_FAR = 96; // Block-Distanz, ab der Nebel ganz undurchsichtig ist (≈ RENDER_DISTANCE*16) export let CAMERA_FOV = 72; // Sichtfeld in Grad (höher = weiterer Blickwinkel / Fisheye) export let CAMERA_NEAR = 0.1; export let CAMERA_FAR = 1000; export const HEMISPHERE = { sky: 0xbfdfff, ground: 0x5a6b3a, intensity: 1.05 }; // weiche Aufhellung von oben/unten export const SUN = { color: 0xfff4d6, intensity: 1.2 }; // gerichtetes Hauptlicht // Sonnenrichtung (wird intern normalisiert). Bestimmt, aus welcher Seite Licht/Schatten kommen. export const SUN_DIRECTION = [0.55, 0.72, 0.42]; export let SHADOWS_ENABLED = true; export let SHADOW_MAP_SIZE = 2048; // Schatten-Textur-Auflösung (höher = schärfer + mehr Last; 1024/2048 typisch) export let SHADOW_AREA = 44; // halbe Kantenlänge des Schatten-Frustums um den Spieler (Blöcke) export let SHADOW_BIAS = 0.0002; // gegen "Shadow Acne" (strichartige Selbstschatten) export let SHADOW_NORMAL_BIAS = 0.02; // gegen Acne auf Voxelflächen (in Normalenrichtung verschieben) export let BLOOM_ENABLED = true; export const BLOOM = { strength: 0.4, radius: 0.5, threshold: 0.55 }; // strength = Glanz-Stärke (höher = stärkeres Leuchten) // radius = Ausbreitung des Glanzes // threshold = nur Pixel HELLER als dieser Wert glühen (niedriger = mehr glüht) // AO-Stufe pro Vertex: Index 0 = stärkste Verdeckung (dunkelste Ecke), // 3 = keine Verdeckung. Niedrigere Werte = dunklere Ecken/Kanten. export const AO_LEVEL = [0.2, 0.4, 0.5, 1.8]; export const PLAYER = { HALF: 0.3, // halbe Spielerbreite (X/Z) — AABB-Kollisionskasten HEIGHT: 1.8, // Körperhöhe EYE: 1.62, // Augenposition über den Füßen GRAVITY: 26, // Fallbeschleunigung (Blöcke/s²) JUMP_VEL: 8.6, // Sprung-Startgeschwindigkeit WALK: 4.7, // Laufgeschwindigkeit (Blöcke/s) SPRINT: 7.2, // Sprintgeschwindigkeit (Shift) FLY_SPEED: 9.5, // Fluggeschwindigkeit (F-Modus) MAX_FALL: 50, // max. Fallgeschwindigkeit (Terminal-Speed) }; // Steuerungs-Werte (live änderbar). Zusammen im Objekt, damit das Panel // die Properties mutieren kann und Spieler/Raycast sie live sehen. export const CONTROLS = { MOUSE_SENSITIVITY: 0.0022, // Maus-Look-Empfindlichkeit (höher = schnellere Drehung) REACH: 6, // Reichweite für Abbauen/Bauen (Blöcke) }; // ──────────────────────────────────────────────────────────── // Defaults-Snapshot (für "Zurücksetzen" im Panel) // ──────────────────────────────────────────────────────────── // Wird VOR dem Anwenden gespeicherter Overrides erzeugt und // enthält die ursprünglichen Code-Defaults (als tiefe Kopie). const DEFAULTS = JSON.parse(JSON.stringify({ WORLD_SEED, SEA_LEVEL, SPAWN, RENDER_DISTANCE, MAX_OPS_PER_FRAME, MAX_PIXEL_RATIO, ANTIALIAS, MSAA_SAMPLES, TONE_MAPPING, TONE_MAPPING_EXPOSURE, SKY_COLOR, FOG_NEAR, FOG_FAR, CAMERA_FOV, CAMERA_NEAR, CAMERA_FAR, HEMISPHERE, SUN, SUN_DIRECTION, SHADOWS_ENABLED, SHADOW_MAP_SIZE, SHADOW_AREA, SHADOW_BIAS, SHADOW_NORMAL_BIAS, BLOOM_ENABLED, BLOOM, AO_LEVEL, PLAYER, CONTROLS, })); export { DEFAULTS }; // ──────────────────────────────────────────────────────────── // Persistenz (für das Live-Settings-Panel) // ──────────────────────────────────────────────────────────── const STORAGE_KEY = 'mc-clone-settings'; /** Gespeicherte Overrides aus localStorage (oder {}). */ export function loadSettings() { try { return JSON.parse(localStorage.getItem(STORAGE_KEY) || '{}'); } catch { return {}; } } /** Kompletten Settings-Stand schreiben. */ export function saveSettings(obj) { try { localStorage.setItem(STORAGE_KEY, JSON.stringify(obj)); } catch { /* localStorage gesperrt */ } } /** Gespeicherte Overrides löschen → nächster Load nutzt Code-Defaults. */ export function clearSettings() { try { localStorage.removeItem(STORAGE_KEY); } catch { /* ignore */ } } // Gespeicherte Overrides auf die Exporte anwenden — passiert beim Modul-Laden // (also VOR jedem Konsumenten, da ESM config.js zuerst vollständig auswertet). (() => { const s = loadSettings(); if (!s) return; if (s.WORLD_SEED != null) WORLD_SEED = s.WORLD_SEED; if (s.SEA_LEVEL != null) SEA_LEVEL = s.SEA_LEVEL; if (s.RENDER_DISTANCE != null) RENDER_DISTANCE = s.RENDER_DISTANCE; if (s.MAX_OPS_PER_FRAME != null) MAX_OPS_PER_FRAME = s.MAX_OPS_PER_FRAME; if (s.MAX_PIXEL_RATIO != null) MAX_PIXEL_RATIO = s.MAX_PIXEL_RATIO; if (typeof s.ANTIALIAS === 'boolean') ANTIALIAS = s.ANTIALIAS; if (s.MSAA_SAMPLES != null) MSAA_SAMPLES = s.MSAA_SAMPLES; if (s.TONE_MAPPING != null) TONE_MAPPING = s.TONE_MAPPING; if (s.TONE_MAPPING_EXPOSURE != null) TONE_MAPPING_EXPOSURE = s.TONE_MAPPING_EXPOSURE; if (s.SKY_COLOR != null) SKY_COLOR = s.SKY_COLOR; if (s.FOG_NEAR != null) FOG_NEAR = s.FOG_NEAR; if (s.FOG_FAR != null) FOG_FAR = s.FOG_FAR; if (s.CAMERA_FOV != null) CAMERA_FOV = s.CAMERA_FOV; if (s.CAMERA_NEAR != null) CAMERA_NEAR = s.CAMERA_NEAR; if (s.CAMERA_FAR != null) CAMERA_FAR = s.CAMERA_FAR; if (typeof s.SHADOWS_ENABLED === 'boolean') SHADOWS_ENABLED = s.SHADOWS_ENABLED; if (s.SHADOW_MAP_SIZE != null) SHADOW_MAP_SIZE = s.SHADOW_MAP_SIZE; if (s.SHADOW_AREA != null) SHADOW_AREA = s.SHADOW_AREA; if (s.SHADOW_BIAS != null) SHADOW_BIAS = s.SHADOW_BIAS; if (s.SHADOW_NORMAL_BIAS != null) SHADOW_NORMAL_BIAS = s.SHADOW_NORMAL_BIAS; if (typeof s.BLOOM_ENABLED === 'boolean') BLOOM_ENABLED = s.BLOOM_ENABLED; if (s.SPAWN) Object.assign(SPAWN, s.SPAWN); if (s.HEMISPHERE) Object.assign(HEMISPHERE, s.HEMISPHERE); if (s.SUN) Object.assign(SUN, s.SUN); if (s.SUN_DIRECTION) for (let i = 0; i < 3; i++) if (s.SUN_DIRECTION[i] != null) SUN_DIRECTION[i] = s.SUN_DIRECTION[i]; if (s.BLOOM) Object.assign(BLOOM, s.BLOOM); if (s.AO_LEVEL) for (let i = 0; i < 4; i++) if (s.AO_LEVEL[i] != null) AO_LEVEL[i] = s.AO_LEVEL[i]; if (s.PLAYER) Object.assign(PLAYER, s.PLAYER); if (s.CONTROLS) Object.assign(CONTROLS, s.CONTROLS); })();