Structure Refactor

This commit is contained in:
torsten 2026-02-20 16:02:57 +01:00
parent df727c4c88
commit 98199a1543
44 changed files with 143 additions and 197 deletions

View file

@ -3,17 +3,7 @@ class_name SaveLoad
const SAVE_PATH = "user://player_data.json"
static func save_character(data: CharacterData):
var save_dict = {
"id": data.id,
"name": data.name,
"level": data.level,
"area": data.area,
"position": { # Vector3 als Dictionary speichern
"x": data.position.x,
"y": data.position.y,
"z": data.position.z
}
}
var save_dict = data.to_dict()
var file = FileAccess.open(SAVE_PATH, FileAccess.WRITE)
if file:
@ -35,11 +25,7 @@ static func load_character() -> CharacterData:
return null
var char_data = CharacterData.new()
char_data.id = data["id"]
char_data.name = data["name"]
char_data.level = data["level"]
char_data.area = data["area"]
char_data.position = Vector3(data["position"]["x"],data["position"]["y"],data["position"]["z"])
char_data.from_dict(data)
print("Loaded player data from ", SAVE_PATH)
return char_data
else:

View file

@ -1,16 +1,13 @@
extends Node
signal ui_join_requested(ip: String, username: String, password: String)
signal ui_host_requested()
signal player_area_join_requested(area_key: String)
signal ui_create_character_screen()
signal ui_character_created(character: CharacterData)
signal ui_character_select()
signal ui_area_join_requested(area_key: String)
signal player_area_join_requested(area_key: String)
signal network_show_characters(characters:Array)
signal ui_create_character_screen()
signal ui_character_created(character: CharacterData)
signal ui_character_select()
signal network_new_character_received(character: CharacterData)

View file

@ -8,8 +8,8 @@ var local_camera: Camera3D = null
# Mapping der Areas
var area_paths = {
"keuwin_grasland": "res://maps/outdoor/grass/keuwin_grasland.tscn",
"ahnenhalle": "res://maps/planes/fugue/halle_der_ahnen.tscn"
"keuwin_grasland": "res://05_worlds/area/outdoor/grass/keuwin_grasland.tscn",
"ahnenhalle": "res://05_worlds/area/planes/fugue/halle_der_ahnen.tscn"
}
# Server-seitiges Tracking: peer_id -> SubViewportContainer
@ -18,6 +18,7 @@ var player_worlds = {}
func _ready():
GameEvents.ui_host_requested.connect(host_game)
GameEvents.ui_join_requested.connect(join_game)
GameEvents.ui_character_created.connect(request_character_store)
if DisplayServer.get_name() == "headless" or OS.get_cmdline_args().has("--server"):
host_game()
@ -158,7 +159,7 @@ func cl_load_area(area_key):
func setup_client_camera(node):
local_camera = Camera3D.new()
local_camera.name = "Camera3D"
local_camera.set_script(load("res://systems/player/camera_logic.gd"))
local_camera.set_script(load("res://01_core/components/camera_logic.gd"))
local_camera.current = true
node.add_child(local_camera)
# Ein AudioListener gehört auf dem Client auch an die Kamera
@ -224,8 +225,25 @@ func srv_handle_area_change_request(area_key: String):
else:
print("Old viewport:", old_viewport)
print("Player for erasing not found:", id)
# 2. Bestehende Funktion für den Wechsel aufrufen
change_player_area(id, area_key)
func request_character_store(new_character: CharacterData):
var character_dict = new_character.to_dict()
srv_store_new_character.rpc_id(1,character_dict)
@rpc("any_peer", "call_remote", "reliable")
func srv_store_new_character(character_dict: Dictionary):
var new_character = CharacterData.new()
new_character.from_dict(character_dict)
# TODO: In Zukunft erhalten neue Charaktere einen area_key und position gesetzt
var client_id = multiplayer.get_remote_sender_id()
cl_receive_new_character.rpc_id(client_id, new_character.to_dict())
@rpc("authority", "call_remote", "reliable")
func cl_receive_new_character(char_dict: Dictionary):
var new_character = CharacterData.new()
new_character.from_dict(char_dict)
GameEvents.network_new_character_received.emit(new_character)

View file

@ -4,12 +4,12 @@ importer="scene"
importer_version=1
type="PackedScene"
uid="uid://do451iws7munv"
path="res://.godot/imported/dude.glb-2cdcb6b05658711e71be066b772220a0.scn"
path="res://.godot/imported/dude.glb-ff042c8f74305db1da7e47c7a83b2cea.scn"
[deps]
source_file="res://assets/characters/humanoid/dude.glb"
dest_files=["res://.godot/imported/dude.glb-2cdcb6b05658711e71be066b772220a0.scn"]
source_file="res://02_library/meshes/humanoid/dude.glb"
dest_files=["res://.godot/imported/dude.glb-ff042c8f74305db1da7e47c7a83b2cea.scn"]
[params]

View file

@ -1,6 +1,6 @@
[gd_scene format=3 uid="uid://dgjgtr82ye25d"]
[ext_resource type="ArrayMesh" uid="uid://bi22s15yeh6mw" path="res://assets/characters/humanoid/dude.tres" id="1_jchph"]
[ext_resource type="ArrayMesh" uid="uid://bi22s15yeh6mw" path="res://02_library/meshes/humanoid/dude.tres" id="1_jchph"]
[node name="Dude" type="MeshInstance3D" unique_id=1185543431]
mesh = ExtResource("1_jchph")

View file

Before

Width:  |  Height:  |  Size: 1.5 MiB

After

Width:  |  Height:  |  Size: 1.5 MiB

Before After
Before After

View file

@ -3,15 +3,15 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://d1cyxxj8ypfu"
path="res://.godot/imported/logo_projekt_weltenauge.png-faafe98462d8081c55aa7ba6fc11610a.ctex"
path="res://.godot/imported/logo_projekt_weltenauge.png-050b0b56f8f1da7cb817f7c3bf842b44.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/icons/program/logo_projekt_weltenauge.png"
dest_files=["res://.godot/imported/logo_projekt_weltenauge.png-faafe98462d8081c55aa7ba6fc11610a.ctex"]
source_file="res://02_library/ui_assets/icons/program/logo_projekt_weltenauge.png"
dest_files=["res://.godot/imported/logo_projekt_weltenauge.png-050b0b56f8f1da7cb817f7c3bf842b44.ctex"]
[params]

View file

@ -1,7 +1,7 @@
[gd_scene format=3 uid="uid://bjurf8vfd1fg8"]
[ext_resource type="PackedScene" uid="uid://dgjgtr82ye25d" path="res://assets/characters/humanoid/dude.tscn" id="1_2anqx"]
[ext_resource type="Script" uid="uid://bhym64rc7xtin" path="res://systems/player/player_controller.gd" id="1_ktl23"]
[ext_resource type="Script" uid="uid://bhym64rc7xtin" path="res://04_entities/player/player_controller.gd" id="1_pnayr"]
[ext_resource type="PackedScene" uid="uid://dgjgtr82ye25d" path="res://02_library/meshes/humanoid/dude.tscn" id="2_11qf6"]
[sub_resource type="CylinderShape3D" id="CylinderShape3D_ktl23"]
@ -10,7 +10,7 @@
[sub_resource type="SceneReplicationConfig" id="SceneReplicationConfig_fqfg4"]
[node name="CharacterBody3D" type="CharacterBody3D" unique_id=682006733 groups=["players"]]
script = ExtResource("1_ktl23")
script = ExtResource("1_pnayr")
interpolation_speed = 5.0
[node name="CollisionShape3D" type="CollisionShape3D" parent="." unique_id=159496934]
@ -20,7 +20,7 @@ shape = SubResource("CylinderShape3D_ktl23")
[node name="Visuals" type="Node3D" parent="." unique_id=1840405751]
transform = Transform3D(-0.99988204, 0, 0.015358234, 0, 1, 0, -0.015358234, 0, -0.99988204, 0, 0, 0)
[node name="Dude" parent="Visuals" unique_id=1185543431 instance=ExtResource("1_2anqx")]
[node name="Dude" parent="Visuals" unique_id=1185543431 instance=ExtResource("2_11qf6")]
[node name="AnimationPlayer" type="AnimationPlayer" parent="." unique_id=1343500738]
root_node = NodePath("../..")

View file

@ -5,6 +5,7 @@ extends Control
func _on_host_button_pressed() -> void:
print("host pressed")
GameEvents.ui_host_requested.emit()
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_MINIMIZED)
hide()
func _on_join_button_pressed():

View file

@ -1,6 +1,6 @@
[gd_scene format=3 uid="uid://lb6btb6426mi"]
[ext_resource type="Script" uid="uid://c6yngwnpqsnpi" path="res://ui/account/login.gd" id="1_x74xt"]
[ext_resource type="Script" uid="uid://c6yngwnpqsnpi" path="res://04_entities/ui/windows/account/login.gd" id="1_x74xt"]
[node name="Login" type="Control" unique_id=1694671237]
layout_mode = 3

View file

@ -12,7 +12,8 @@ func show_creation_screen():
func _on_create_button_pressed() -> void:
var new_character = CharacterData.new()
new_character.name = name_line_edit.text
GameEvents.ui_character_created.emit(new_character)
print("Create Button pressed")
GameEvents.ui_character_created.emit(new_character)
hide()

View file

@ -1,6 +1,6 @@
[gd_scene format=3 uid="uid://cdwkmx452hc4k"]
[ext_resource type="Script" uid="uid://dx24rxnsd0eoj" path="res://ui/character_create/character_create.gd" id="1_mdh5q"]
[ext_resource type="Script" uid="uid://dx24rxnsd0eoj" path="res://04_entities/ui/windows/character_create/character_create.gd" id="1_mdh5q"]
[node name="CharacterCreate" type="Control" unique_id=2056198803]
layout_mode = 3

View file

@ -6,9 +6,9 @@ var characters: Array[CharacterData] = []
func _ready():
GameEvents.network_show_characters.connect(show_list)
GameEvents.ui_character_created.connect(character_created)
func character_created(character):
GameEvents.network_new_character_received.connect(receive_new_character)
func receive_new_character(character: CharacterData):
characters.append(character)
character_item_list.add_item(character.name)
show()

View file

@ -1,6 +1,6 @@
[gd_scene format=3 uid="uid://ca2bhph2k3xpy"]
[ext_resource type="Script" uid="uid://b5htxbkq23mo6" path="res://ui/character_select/character_select.gd" id="1_o7qwi"]
[ext_resource type="Script" uid="uid://b5htxbkq23mo6" path="res://04_entities/ui/windows/character_select/character_select.gd" id="1_o7qwi"]
[node name="CharacterSelect" type="Control" unique_id=2056198803]
layout_mode = 3

View file

@ -1,6 +1,6 @@
[gd_scene format=3 uid="uid://h5qt2pcidh8x"]
[ext_resource type="PackedScene" uid="uid://coq1j1cdrvqyn" path="res://systems/interaction/portal/portal.tscn" id="1_1yg6u"]
[ext_resource type="PackedScene" uid="uid://coq1j1cdrvqyn" path="res://05_worlds/prefabs/portal/portal.tscn" id="1_1yg6u"]
[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_d3jw7"]

View file

@ -1,6 +1,6 @@
[gd_scene format=3 uid="uid://bef0tj7n6g8uo"]
[ext_resource type="PackedScene" uid="uid://coq1j1cdrvqyn" path="res://systems/interaction/portal/portal.tscn" id="1_4r2hu"]
[ext_resource type="PackedScene" uid="uid://coq1j1cdrvqyn" path="res://05_worlds/prefabs/portal/portal.tscn" id="1_4r2hu"]
[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_d3jw7"]
sky_top_color = Color(0.055328622, 0.3637527, 0.67898166, 1)

View file

@ -1,6 +1,6 @@
[gd_scene format=3 uid="uid://coq1j1cdrvqyn"]
[ext_resource type="Script" uid="uid://c23uu6akws8nj" path="res://systems/interaction/portal/portal.gd" id="1_8dnr8"]
[ext_resource type="Script" uid="uid://c23uu6akws8nj" path="res://05_worlds/prefabs/portal/portal.gd" id="1_8dnr8"]
[sub_resource type="BoxShape3D" id="BoxShape3D_h1tlh"]
size = Vector3(3.2, 1, 1)

View file

@ -24,17 +24,48 @@
Alle Skripte und die dazugehörige Logik sollen thematisch in Unterordnern unter `res://systems/` abgelegt werden:
- `/core/`: Haupt-Game-Loop, State-Machine (Laden, Menü, Spiel).
- `/network/`: Peer-Verbindung, Headless-Logik, Synchronisation, RPCs.
- `/player/`: Input-Handling, Kamera-Steuerung, lokale Charakter-Steuerung.
- `/ai/`: NPC-Verhaltenslogik (z.B. Behavior Trees).
- `/combat/`: Kampfsystem, Trefferberechnung, Würfelwürfe.
- `/dialogue/`: Gesprächs-System.
- `/inventory/`: Item-Management, Ausrüstung, Truhen.
- `/interaction/`: Interaktionslogik für Türen, Hebel, Portale.
- `/navigation/`: A-Stern (AStar) Pfadfindungs-Logik.
- `/data/`: Speicher-Logik, Daten-Wrapper (z.B. für JSON, SQLite).
- `/ui/`: (Existierender Ordner) UI-Szenen und Skripte.
/project_root
│
├── 01_core/                     # Die Logik (Script-only, Architektur)
│   ├── systems/                 # Globale Manager (Autoloads): network.gd, game_state.gd, signal_bus.gd
│   ├── components/              # Logik-Nodes: health_component.gd, interactor.gd, inventory_controller.gd
│   └── base_classes/            # Definitionen & Klassen: item_data.gd, spell_base.gd, entity_base.gd
│
├── 02_library/                  # Das Rohmaterial (Assets & Bausteine)
│   ├── meshes/                  # 3D-Importe (.glb, .obj) nach Kategorien: nature/, architecture/
│ ├── mesh_libraries/ # Deine fertigen GridMap-Kataloge (.tres)
│   ├── materials/               # Globale Materialien (.tres): wood.tres, stone.tres, metal.tres
│   ├── textures/                # Roh-Bilder für Materialien & Shader
│   ├── ui_assets/               # Visuelles Interface: icons/, fonts/, themes/
│   ├── shaders/                 # Shader-Dateien (.gdshader)
│   ├── vfx/                     # Partikelsysteme und visuelle Effekte
│   └── audio/                   # Sound-Dateien: sfx/, music/, ambient/
│
├── 03_database/                 # Die Spieldaten (Content-Definitionen)
│   ├── items/                   # Hunderte .tres Dateien (iron_sword.tres, health_potion.tres)
│   ├── spells/                  # Zaubersprüche als Resources (.tres)
│   ├── loot_tables/             # Definitionen für Drops und Wahrscheinlichkeiten
│   ├── dialogues/               # Dialog-Skripte oder JSON-Dateien
│   ├── localization/            # Übersetzungsdateien (.csv, .po)
│ └── spawn_tables/ # Definitionen: Welche Monster-Gruppe spawnt in welcher Area?
│
├── 04_entities/                 # Die Spielobjekte (Zusammengesetzte Szenen)
│   ├── player/                  # Spieler-Szene (player.tscn + player.gd)
│   ├── npcs/                    # Monster, Händler, KI-Gegner
│   ├── props/                   # Interaktive Welt-Objekte: chest.tscn, door.tscn
│   ├── pickups/                 # Das world_item.tscn (Visualisierung von Database-Items)
│   ├── ui/                      # UI-Szenen: hud/, windows/, menus/, shared/
│ └── markers/ # Unsichtbare Helfer: spawn_point.tscn, area_trigger.tscn
│
├── 05_worlds/                   # Die Level (Das "NWN Modul")
│   ├── areas/                   # Die eigentlichen Karten/Level (.tscn)
│   ├── prefabs/                 # Wiederverwendbare Szenen-Gruppen (Häuser, Lagerfeuer-Sets)
│   └── environments/            # Licht- & Welt-Einstellungen (.tres)
│
└── 06_tests/                    # Die Sandkästen (Isolierte Prototypen)
    ├── test_ui.tscn             # Nur UI-Fenster testen
    ├── test_combat.tscn         # Kampf-Mechanik ohne Level testen
    └── test_inventory.tscn      # Item-Logik prüfen
## 4. Wichtige Dateien & Szenen

View file

@ -1,9 +1,9 @@
[gd_scene format=3 uid="uid://cpxxy0664jyjm"]
[ext_resource type="Script" uid="uid://162cjpb4lac4" path="res://game_root.gd" id="1_xj5yv"]
[ext_resource type="PackedScene" uid="uid://ca2bhph2k3xpy" path="res://ui/character_select/character_select.tscn" id="3_bxsma"]
[ext_resource type="PackedScene" uid="uid://lb6btb6426mi" path="res://ui/account/login.tscn" id="3_lkrbl"]
[ext_resource type="PackedScene" uid="uid://cdwkmx452hc4k" path="res://ui/character_create/character_create.tscn" id="4_lkrbl"]
[ext_resource type="PackedScene" uid="uid://ca2bhph2k3xpy" path="res://04_entities/ui/windows/character_select/character_select.tscn" id="3_bxsma"]
[ext_resource type="PackedScene" uid="uid://lb6btb6426mi" path="res://04_entities/ui/windows/account/login.tscn" id="3_lkrbl"]
[ext_resource type="PackedScene" uid="uid://cdwkmx452hc4k" path="res://04_entities/ui/windows/character_create/character_create.tscn" id="4_lkrbl"]
[node name="Game_root" type="Node2D" unique_id=1336425327]
script = ExtResource("1_xj5yv")

View file

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128"><rect width="124" height="124" x="2" y="2" fill="#363d52" stroke="#212532" stroke-width="4" rx="14"/><g fill="#fff" transform="translate(12.322 12.322)scale(.101)"><path d="M105 673v33q407 354 814 0v-33z"/><path fill="#478cbf" d="m105 673 152 14q12 1 15 14l4 67 132 10 8-61q2-11 15-15h162q13 4 15 15l8 61 132-10 4-67q3-13 15-14l152-14V427q30-39 56-81-35-59-83-108-43 20-82 47-40-37-88-64 7-51 8-102-59-28-123-42-26 43-46 89-49-7-98 0-20-46-46-89-64 14-123 42 1 51 8 102-48 27-88 64-39-27-82-47-48 49-83 108 26 42 56 81zm0 33v39c0 276 813 276 814 0v-39l-134 12-5 69q-2 10-14 13l-162 11q-12 0-16-11l-10-65H446l-10 65q-4 11-16 11l-162-11q-12-3-14-13l-5-69z"/><path d="M483 600c0 34 58 34 58 0v-86c0-34-58-34-58 0z"/><circle cx="725" cy="526" r="90"/><circle cx="299" cy="526" r="90"/></g><g fill="#414042" transform="translate(12.322 12.322)scale(.101)"><circle cx="307" cy="532" r="60"/><circle cx="717" cy="532" r="60"/></g></svg>

Before

Width:  |  Height:  |  Size: 995 B

View file

@ -1,43 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://d4fyt5amswlam"
path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://icon.svg"
dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

View file

@ -1,6 +1,6 @@
[gd_scene format=3 uid="uid://2fal1f0f8fdh"]
[gd_scene format=3 uid="uid://dvmffuxafo75u"]
[ext_resource type="ArrayMesh" uid="uid://bi22s15yeh6mw" path="res://assets/characters/humanoid/dude.tres" id="1_ig7tw"]
[ext_resource type="ArrayMesh" uid="uid://bi22s15yeh6mw" path="res://02_library/meshes/humanoid/dude.tres" id="1_ig7tw"]
[node name="Node3D" type="Node3D" unique_id=1431241737]

View file

@ -15,7 +15,7 @@ run/main_scene="uid://cpxxy0664jyjm"
config/features=PackedStringArray("4.6", "Forward Plus")
run/low_processor_mode=true
boot_splash/image="uid://d1cyxxj8ypfu"
config/icon="res://icon.svg"
config/icon="uid://d1cyxxj8ypfu"
boot_splash/minimum_display_time=1000
[autoload]

View file

@ -1,85 +0,0 @@
# test_player_movement.gd
extends Node
#@onready var multiplayer = MultiplayerPeerExtension.new()
var player: CharacterBody3D
var initial_position: Vector3
func _ready():
# 1. Szene laden
var test_scene = load("res://maps/outdoor/grass/keuwin_grasland.tscn").instantiate()
add_child(test_scene)
# 2. MultiplayerSpawner finden und Player erstellen
var spawner = test_scene.get_node("AreaSpawner")
if not spawner:
printerr("Kein Spawner gefunden!")
queue_free() # Test beenden
# Test-Spieler erstellen
var player_scene = load("res://systems/player/player.tscn")
player = player_scene.instantiate()
player.name = "TestPlayer"
spawner.get_parent().add_child(player)
# Initialen Zustand speichern
initial_position = player.global_position
print("Initial position: ", initial_position)
# 3. Test starten (verzögert, damit alles geladen ist)
call_deferred("start_test")
func start_test():
print("Starte Bewegungstest...")
# Simulieren eines Klicks
var target_position = Vector3(5, 0, 5) # Irgendein Punkt in der Nähe
print("Simuliere Klick auf: ", target_position)
# Hier MÜSSEN wir den RPC direkt aufrufen. InputEvent geht nicht.
player.server_request_move.rpc_id(1, target_position) # 1 = Server
# Auf Bewegung warten (etwas unsauber, aber für den Moment ok)
await get_tree().create_timer(1.0).timeout # Warte 1 Sekunde
# Ergebnis überprüfen
var new_position = player.global_position
print("Neue Position: ", new_position)
# Toleranz, da die Bewegung nicht exakt sein muss
var tolerance = 0.5
if new_position.distance_to(initial_position) > tolerance:
print("Test erfolgreich! Avatar hat sich bewegt.")
else:
printerr("Test fehlgeschlagen! Avatar hat sich nicht bewegt.")
# Test beenden (optional)
queue_free()
"""Erläuterungen:
1.) Szene laden: Lädt eine Test-Szene (keuwin_grasland.tscn). Das heisst, diese muss eine Spawner Instanz mit dem Namen AreaSpawner enthalten.
2.) Avatar erzeugen: Sucht den Spawner und erzeugt einen Avatar (keinen Multiplayer, nur lokal für den Test).
3.) Test starten (deferred): Startet den Test in start_test(), um sicherzustellen, dass alles geladen ist.
4.) Simulierter Klick: Sendet den request_move-RPC direkt an den Avatar.
5.) Warten: Wartet 1 Sekunde (eine sehr einfache, blockierende Methode).
6.) Ergebnis prüfen: Vergleicht die neue Position mit der alten.
Wie man diesen Test benutzt:
1.) Erstelle eine neue Szene (z.B. test_scene.tscn).
2.) Füge einen Node vom Typ Node als Root hinzu.
3.) Speichere das obige Skript (test_player_movement.gd) im Ordner /systems/player/.
3.) Füge ein Script Node hinzu und weise ihm das Skript test_player_movement.gd zu.
4.) Starte die Szene test_scene.tscn.
5.) Das Skript sollte automatisch ablaufen, die Ergebnisse in der Konsole ausgeben und sich dann selbst beenden.
Wichtige Einschränkungen:
Kein echter Multiplayer: Dies ist ein reiner Einzelspieler-Test. Er prüft nur, ob sich der lokale Avatar bewegt.
Blockierendes Warten: Die Verwendung von create_timer(1.0).timeout.await blockiert den Haupt-Thread. Für einen echten Test wäre das schlecht, aber für unseren einfachen Zweck ist es akzeptabel.
Geringe Präzision: Der Toleranzwert von 0.5 bedeutet, dass kleine Bewegungen möglicherweise nicht erkannt werden.
Keine Fehlerbehandlung: Wenn irgendetwas schiefgeht (kein Spawner, keine Szene, falscher Node-Name), bricht der Test einfach ab.
Auch mit diesen Einschränkungen ist dieser Test extrem wertvoll. Er gibt uns eine schnelle und einfache Möglichkeit, um sicherzustellen, dass die grundlegende Click-to-Move-Mechanik weiterhin funktioniert, wenn wir Änderungen am Code vornehmen."""

View file

@ -1 +0,0 @@
uid://c8p3yn461hle1

42
weltenauge_struktur.txt Normal file
View file

@ -0,0 +1,42 @@
/project_root
│
├── 01_core/                     # Die Logik (Script-only, Architektur)
│   ├── systems/                 # Globale Manager (Autoloads): network.gd, game_state.gd, signal_bus.gd
│   ├── components/              # Logik-Nodes: health_component.gd, interactor.gd, inventory_controller.gd
│   └── base_classes/            # Definitionen & Klassen: item_data.gd, spell_base.gd, entity_base.gd
│
├── 02_library/                  # Das Rohmaterial (Assets & Bausteine)
│   ├── meshes/                  # 3D-Importe (.glb, .obj) nach Kategorien: nature/, architecture/
│ ├── mesh_libraries/ # Deine fertigen GridMap-Kataloge (.tres)
│   ├── materials/               # Globale Materialien (.tres): wood.tres, stone.tres, metal.tres
│   ├── textures/                # Roh-Bilder für Materialien & Shader
│   ├── ui_assets/               # Visuelles Interface: icons/, fonts/, themes/
│   ├── shaders/                 # Shader-Dateien (.gdshader)
│   ├── vfx/                     # Partikelsysteme und visuelle Effekte
│   └── audio/                   # Sound-Dateien: sfx/, music/, ambient/
│
├── 03_database/                 # Die Spieldaten (Content-Definitionen)
│   ├── items/                   # Hunderte .tres Dateien (iron_sword.tres, health_potion.tres)
│   ├── spells/                  # Zaubersprüche als Resources (.tres)
│   ├── loot_tables/             # Definitionen für Drops und Wahrscheinlichkeiten
│   ├── dialogues/               # Dialog-Skripte oder JSON-Dateien
│   ├── localization/            # Übersetzungsdateien (.csv, .po)
│ └── spawn_tables/ # Definitionen: Welche Monster-Gruppe spawnt in welcher Area?
│
├── 04_entities/                 # Die Spielobjekte (Zusammengesetzte Szenen)
│   ├── player/                  # Spieler-Szene (player.tscn + player.gd)
│   ├── npcs/                    # Monster, Händler, KI-Gegner
│   ├── props/                   # Interaktive Welt-Objekte: chest.tscn, door.tscn
│   ├── pickups/                 # Das world_item.tscn (Visualisierung von Database-Items)
│   ├── ui/                      # UI-Szenen: hud/, windows/, menus/, shared/
│ └── markers/ # Unsichtbare Helfer: spawn_point.tscn, area_trigger.tscn
│
├── 05_worlds/                   # Die Level (Das "NWN Modul")
│   ├── areas/                   # Die eigentlichen Karten/Level (.tscn)
│   ├── prefabs/                 # Wiederverwendbare Szenen-Gruppen (Häuser, Lagerfeuer-Sets)
│   └── environments/            # Licht- & Welt-Einstellungen (.tres)
│
└── 06_tests/                    # Die Sandkästen (Isolierte Prototypen)
    ├── test_ui.tscn             # Nur UI-Fenster testen
    ├── test_combat.tscn         # Kampf-Mechanik ohne Level testen
    └── test_inventory.tscn      # Item-Logik prüfen