gopeak 2.3.7 → 2.3.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,126 +1,126 @@
1
- @tool
2
- extends EditorPlugin
3
-
4
- ## Auto Reload Plugin for Godot MCP
5
- ## Automatically reloads scenes and scripts when modified externally
6
- ##
7
- ## Features:
8
- ## - Auto-detects external file changes (scenes, scripts, resources)
9
- ## - Reloads without confirmation popup
10
- ## - Lightweight 1-second polling (negligible performance impact)
11
- ## - Perfect for MCP integration workflow
12
-
13
- var check_interval: float = 1.0 # Check every 1 second
14
- var timer: Timer
15
- var watched_files: Dictionary = {} # {path: last_modified_time}
16
- var editor_interface: EditorInterface
17
-
18
- # File extensions to watch
19
- var watched_extensions: Array[String] = [".tscn", ".scn", ".gd", ".tres", ".res"]
20
-
21
- func _enter_tree() -> void:
22
- editor_interface = get_editor_interface()
23
-
24
- # Create timer for periodic file checking
25
- timer = Timer.new()
26
- timer.wait_time = check_interval
27
- timer.timeout.connect(_check_for_changes)
28
- add_child(timer)
29
- timer.start()
30
-
31
- # Initial scan of open scenes
32
- _update_watched_files()
33
-
34
- print("[Godot MCP - AutoReload] Plugin activated - watching for external changes")
35
-
36
- func _exit_tree() -> void:
37
- if timer:
38
- timer.stop()
39
- timer.queue_free()
40
- print("[Godot MCP - AutoReload] Plugin deactivated")
41
-
42
- func _update_watched_files() -> void:
43
- # Get currently edited scene
44
- var edited_scene = editor_interface.get_edited_scene_root()
45
- if edited_scene and edited_scene.scene_file_path:
46
- var path = edited_scene.scene_file_path
47
- if not watched_files.has(path):
48
- watched_files[path] = _get_modified_time(path)
49
-
50
- # Also watch attached scripts
51
- _watch_node_scripts(edited_scene)
52
-
53
- func _watch_node_scripts(node: Node) -> void:
54
- # Watch the script attached to this node
55
- var script = node.get_script()
56
- if script and script.resource_path:
57
- var path = script.resource_path
58
- if not watched_files.has(path):
59
- watched_files[path] = _get_modified_time(path)
60
-
61
- # Recursively watch children
62
- for child in node.get_children():
63
- _watch_node_scripts(child)
64
-
65
- func _get_modified_time(path: String) -> int:
66
- var global_path = ProjectSettings.globalize_path(path)
67
- if FileAccess.file_exists(global_path):
68
- return FileAccess.get_modified_time(global_path)
69
- return 0
70
-
71
- func _check_for_changes() -> void:
72
- _update_watched_files()
73
-
74
- var files_to_reload: Array = []
75
- var scripts_to_reload: Array = []
76
-
77
- for path in watched_files.keys():
78
- var current_time = _get_modified_time(path)
79
- var last_time = watched_files[path]
80
-
81
- if current_time > last_time:
82
- if path.ends_with(".gd"):
83
- scripts_to_reload.append(path)
84
- else:
85
- files_to_reload.append(path)
86
- watched_files[path] = current_time
87
-
88
- # Reload changed scripts first
89
- for path in scripts_to_reload:
90
- _reload_script(path)
91
-
92
- # Then reload changed scenes
93
- for path in files_to_reload:
94
- _reload_scene(path)
95
-
96
- func _reload_script(path: String) -> void:
97
- print("[Godot MCP - AutoReload] Script changed: ", path)
98
-
99
- # Reload the script resource
100
- var script = load(path)
101
- if script:
102
- ResourceLoader.load(path, "", ResourceLoader.CACHE_MODE_REPLACE)
103
- print("[Godot MCP - AutoReload] Script reloaded: ", path)
104
-
105
- func _reload_scene(path: String) -> void:
106
- print("[Godot MCP - AutoReload] Scene changed: ", path)
107
-
108
- # Check if this is the currently edited scene
109
- var edited_scene = editor_interface.get_edited_scene_root()
110
- if edited_scene and edited_scene.scene_file_path == path:
111
- # Reload the current scene
112
- editor_interface.reload_scene_from_path(path)
113
- print("[Godot MCP - AutoReload] Scene reloaded: ", path)
114
-
115
- # Public API for configuration
116
- func set_check_interval(interval: float) -> void:
117
- check_interval = interval
118
- if timer:
119
- timer.wait_time = interval
120
-
121
- func add_watched_extension(ext: String) -> void:
122
- if not watched_extensions.has(ext):
123
- watched_extensions.append(ext)
124
-
125
- func clear_watched_files() -> void:
126
- watched_files.clear()
1
+ @tool
2
+ extends EditorPlugin
3
+
4
+ ## Auto Reload Plugin for Godot MCP
5
+ ## Automatically reloads scenes and scripts when modified externally
6
+ ##
7
+ ## Features:
8
+ ## - Auto-detects external file changes (scenes, scripts, resources)
9
+ ## - Reloads without confirmation popup
10
+ ## - Lightweight 1-second polling (negligible performance impact)
11
+ ## - Perfect for MCP integration workflow
12
+
13
+ var check_interval: float = 1.0 # Check every 1 second
14
+ var timer: Timer
15
+ var watched_files: Dictionary = {} # {path: last_modified_time}
16
+ var editor_interface: EditorInterface
17
+
18
+ # File extensions to watch
19
+ var watched_extensions: Array[String] = [".tscn", ".scn", ".gd", ".tres", ".res"]
20
+
21
+ func _enter_tree() -> void:
22
+ editor_interface = get_editor_interface()
23
+
24
+ # Create timer for periodic file checking
25
+ timer = Timer.new()
26
+ timer.wait_time = check_interval
27
+ timer.timeout.connect(_check_for_changes)
28
+ add_child(timer)
29
+ timer.start()
30
+
31
+ # Initial scan of open scenes
32
+ _update_watched_files()
33
+
34
+ print("[Godot MCP - AutoReload] Plugin activated - watching for external changes")
35
+
36
+ func _exit_tree() -> void:
37
+ if timer:
38
+ timer.stop()
39
+ timer.queue_free()
40
+ print("[Godot MCP - AutoReload] Plugin deactivated")
41
+
42
+ func _update_watched_files() -> void:
43
+ # Get currently edited scene
44
+ var edited_scene = editor_interface.get_edited_scene_root()
45
+ if edited_scene and edited_scene.scene_file_path:
46
+ var path = edited_scene.scene_file_path
47
+ if not watched_files.has(path):
48
+ watched_files[path] = _get_modified_time(path)
49
+
50
+ # Also watch attached scripts
51
+ _watch_node_scripts(edited_scene)
52
+
53
+ func _watch_node_scripts(node: Node) -> void:
54
+ # Watch the script attached to this node
55
+ var script = node.get_script()
56
+ if script and script.resource_path:
57
+ var path = script.resource_path
58
+ if not watched_files.has(path):
59
+ watched_files[path] = _get_modified_time(path)
60
+
61
+ # Recursively watch children
62
+ for child in node.get_children():
63
+ _watch_node_scripts(child)
64
+
65
+ func _get_modified_time(path: String) -> int:
66
+ var global_path = ProjectSettings.globalize_path(path)
67
+ if FileAccess.file_exists(global_path):
68
+ return FileAccess.get_modified_time(global_path)
69
+ return 0
70
+
71
+ func _check_for_changes() -> void:
72
+ _update_watched_files()
73
+
74
+ var files_to_reload: Array = []
75
+ var scripts_to_reload: Array = []
76
+
77
+ for path in watched_files.keys():
78
+ var current_time = _get_modified_time(path)
79
+ var last_time = watched_files[path]
80
+
81
+ if current_time > last_time:
82
+ if path.ends_with(".gd"):
83
+ scripts_to_reload.append(path)
84
+ else:
85
+ files_to_reload.append(path)
86
+ watched_files[path] = current_time
87
+
88
+ # Reload changed scripts first
89
+ for path in scripts_to_reload:
90
+ _reload_script(path)
91
+
92
+ # Then reload changed scenes
93
+ for path in files_to_reload:
94
+ _reload_scene(path)
95
+
96
+ func _reload_script(path: String) -> void:
97
+ print("[Godot MCP - AutoReload] Script changed: ", path)
98
+
99
+ # Reload the script resource
100
+ var script = load(path)
101
+ if script:
102
+ ResourceLoader.load(path, "", ResourceLoader.CACHE_MODE_REPLACE)
103
+ print("[Godot MCP - AutoReload] Script reloaded: ", path)
104
+
105
+ func _reload_scene(path: String) -> void:
106
+ print("[Godot MCP - AutoReload] Scene changed: ", path)
107
+
108
+ # Check if this is the currently edited scene
109
+ var edited_scene = editor_interface.get_edited_scene_root()
110
+ if edited_scene and edited_scene.scene_file_path == path:
111
+ # Reload the current scene
112
+ editor_interface.reload_scene_from_path(path)
113
+ print("[Godot MCP - AutoReload] Scene reloaded: ", path)
114
+
115
+ # Public API for configuration
116
+ func set_check_interval(interval: float) -> void:
117
+ check_interval = interval
118
+ if timer:
119
+ timer.wait_time = interval
120
+
121
+ func add_watched_extension(ext: String) -> void:
122
+ if not watched_extensions.has(ext):
123
+ watched_extensions.append(ext)
124
+
125
+ func clear_watched_files() -> void:
126
+ watched_files.clear()
@@ -1,7 +1,7 @@
1
- [plugin]
2
-
3
- name="Godot MCP Auto Reload"
4
- description="Automatically reload scenes and scripts when modified externally. Essential for MCP (Model Context Protocol) integration workflow."
5
- author="HaD0Yun"
6
- version="1.0.0"
7
- script="auto_reload.gd"
1
+ [plugin]
2
+
3
+ name="Godot MCP Auto Reload"
4
+ description="Automatically reload scenes and scripts when modified externally. Essential for MCP (Model Context Protocol) integration workflow."
5
+ author="HaD0Yun"
6
+ version="1.0.0"
7
+ script="auto_reload.gd"
@@ -1,178 +1,178 @@
1
- @tool
2
- extends Node
3
- class_name MCPEditorClient
4
-
5
- signal connected
6
- signal disconnected
7
- signal tool_requested(request_id: String, tool_name: String, args: Dictionary)
8
-
9
- const DEFAULT_URL := "ws://127.0.0.1:6505/godot"
10
- const RECONNECT_DELAY := 3.0
11
- const MAX_RECONNECT_DELAY := 30.0
12
-
13
- var socket: WebSocketPeer = WebSocketPeer.new()
14
- var server_url: String = DEFAULT_URL
15
- var _is_connected := false
16
- var _reconnect_timer: Timer
17
- var _current_reconnect_delay := RECONNECT_DELAY
18
- var _should_reconnect := true
19
- var _project_path: String
20
- var _initialized := false
21
-
22
-
23
- func _ready() -> void:
24
- _project_path = ProjectSettings.globalize_path("res://")
25
-
26
- _reconnect_timer = Timer.new()
27
- _reconnect_timer.one_shot = true
28
- _reconnect_timer.timeout.connect(_on_reconnect_timer)
29
- add_child(_reconnect_timer)
30
-
31
- set_process(true)
32
- _initialized = true
33
-
34
-
35
- func _process(_delta: float) -> void:
36
- if not _initialized:
37
- return
38
-
39
- if socket.get_ready_state() == WebSocketPeer.STATE_CLOSED:
40
- if _is_connected:
41
- _handle_disconnect()
42
- return
43
-
44
- socket.poll()
45
-
46
- match socket.get_ready_state():
47
- WebSocketPeer.STATE_OPEN:
48
- if not _is_connected:
49
- _handle_connect()
50
-
51
- while socket.get_available_packet_count() > 0:
52
- var packet := socket.get_packet()
53
- _handle_message(packet.get_string_from_utf8())
54
-
55
- WebSocketPeer.STATE_CLOSING:
56
- pass
57
-
58
- WebSocketPeer.STATE_CLOSED:
59
- if _is_connected:
60
- _handle_disconnect()
61
-
62
-
63
- func connect_to_server(url: String = "") -> void:
64
- server_url = _resolve_server_url(url)
65
- _should_reconnect = true
66
- _current_reconnect_delay = RECONNECT_DELAY
67
- _attempt_connection()
68
-
69
-
70
- func _resolve_server_url(explicit_url: String) -> String:
71
- if explicit_url != "":
72
- return explicit_url
73
-
74
- var env_keys := ["GODOT_BRIDGE_PORT", "MCP_BRIDGE_PORT", "GOPEAK_BRIDGE_PORT"]
75
- for key in env_keys:
76
- var raw := OS.get_environment(key)
77
- if raw == "":
78
- continue
79
- if raw.is_valid_int():
80
- var port := int(raw)
81
- if port >= 1 and port <= 65535:
82
- return "ws://127.0.0.1:%d/godot" % port
83
-
84
- return DEFAULT_URL
85
-
86
-
87
- func disconnect_from_server() -> void:
88
- _should_reconnect = false
89
- if _reconnect_timer:
90
- _reconnect_timer.stop()
91
- if socket.get_ready_state() == WebSocketPeer.STATE_OPEN:
92
- socket.close()
93
- _is_connected = false
94
-
95
-
96
- func _attempt_connection() -> void:
97
- if socket.get_ready_state() != WebSocketPeer.STATE_CLOSED:
98
- socket.close()
99
-
100
- var err := socket.connect_to_url(server_url)
101
- if err != OK:
102
- push_error("[MCP Editor] Failed to connect: %s" % err)
103
- _schedule_reconnect()
104
-
105
-
106
- func _handle_connect() -> void:
107
- _is_connected = true
108
- _current_reconnect_delay = RECONNECT_DELAY
109
-
110
- _send_message({
111
- "type": "godot_ready",
112
- "project_path": _project_path
113
- })
114
-
115
- connected.emit()
116
-
117
-
118
- func _handle_disconnect() -> void:
119
- _is_connected = false
120
- disconnected.emit()
121
-
122
- if _should_reconnect:
123
- _schedule_reconnect()
124
-
125
-
126
- func _schedule_reconnect() -> void:
127
- if _reconnect_timer == null:
128
- return
129
- _reconnect_timer.start(_current_reconnect_delay)
130
- _current_reconnect_delay = min(_current_reconnect_delay * 2.0, MAX_RECONNECT_DELAY)
131
-
132
-
133
- func _on_reconnect_timer() -> void:
134
- _attempt_connection()
135
-
136
-
137
- func _handle_message(json_string: String) -> void:
138
- var message = JSON.parse_string(json_string)
139
- if message == null:
140
- push_error("[MCP Editor] Failed to parse message: %s" % json_string)
141
- return
142
-
143
- match message.get("type", ""):
144
- "ping":
145
- _send_message({"type": "pong"})
146
-
147
- "tool_invoke":
148
- var request_id: String = message.get("id", "")
149
- var tool_name: String = message.get("tool", "")
150
- var args: Dictionary = message.get("args", {})
151
- tool_requested.emit(request_id, tool_name, args)
152
-
153
- _:
154
- pass
155
-
156
-
157
- func send_tool_result(request_id: String, success: bool, result = null, error: String = "") -> void:
158
- var response := {
159
- "type": "tool_result",
160
- "id": request_id,
161
- "success": success
162
- }
163
-
164
- if success:
165
- response["result"] = result
166
- else:
167
- response["error"] = error
168
-
169
- _send_message(response)
170
-
171
-
172
- func _send_message(message: Dictionary) -> void:
173
- if socket.get_ready_state() == WebSocketPeer.STATE_OPEN:
174
- socket.send_text(JSON.stringify(message))
175
-
176
-
177
- func is_connected_to_server() -> bool:
178
- return _is_connected
1
+ @tool
2
+ extends Node
3
+ class_name MCPEditorClient
4
+
5
+ signal connected
6
+ signal disconnected
7
+ signal tool_requested(request_id: String, tool_name: String, args: Dictionary)
8
+
9
+ const DEFAULT_URL := "ws://127.0.0.1:6505/godot"
10
+ const RECONNECT_DELAY := 3.0
11
+ const MAX_RECONNECT_DELAY := 30.0
12
+
13
+ var socket: WebSocketPeer = WebSocketPeer.new()
14
+ var server_url: String = DEFAULT_URL
15
+ var _is_connected := false
16
+ var _reconnect_timer: Timer
17
+ var _current_reconnect_delay := RECONNECT_DELAY
18
+ var _should_reconnect := true
19
+ var _project_path: String
20
+ var _initialized := false
21
+
22
+
23
+ func _ready() -> void:
24
+ _project_path = ProjectSettings.globalize_path("res://")
25
+
26
+ _reconnect_timer = Timer.new()
27
+ _reconnect_timer.one_shot = true
28
+ _reconnect_timer.timeout.connect(_on_reconnect_timer)
29
+ add_child(_reconnect_timer)
30
+
31
+ set_process(true)
32
+ _initialized = true
33
+
34
+
35
+ func _process(_delta: float) -> void:
36
+ if not _initialized:
37
+ return
38
+
39
+ if socket.get_ready_state() == WebSocketPeer.STATE_CLOSED:
40
+ if _is_connected:
41
+ _handle_disconnect()
42
+ return
43
+
44
+ socket.poll()
45
+
46
+ match socket.get_ready_state():
47
+ WebSocketPeer.STATE_OPEN:
48
+ if not _is_connected:
49
+ _handle_connect()
50
+
51
+ while socket.get_available_packet_count() > 0:
52
+ var packet := socket.get_packet()
53
+ _handle_message(packet.get_string_from_utf8())
54
+
55
+ WebSocketPeer.STATE_CLOSING:
56
+ pass
57
+
58
+ WebSocketPeer.STATE_CLOSED:
59
+ if _is_connected:
60
+ _handle_disconnect()
61
+
62
+
63
+ func connect_to_server(url: String = "") -> void:
64
+ server_url = _resolve_server_url(url)
65
+ _should_reconnect = true
66
+ _current_reconnect_delay = RECONNECT_DELAY
67
+ _attempt_connection()
68
+
69
+
70
+ func _resolve_server_url(explicit_url: String) -> String:
71
+ if explicit_url != "":
72
+ return explicit_url
73
+
74
+ var env_keys := ["GODOT_BRIDGE_PORT", "MCP_BRIDGE_PORT", "GOPEAK_BRIDGE_PORT"]
75
+ for key in env_keys:
76
+ var raw := OS.get_environment(key)
77
+ if raw == "":
78
+ continue
79
+ if raw.is_valid_int():
80
+ var port := int(raw)
81
+ if port >= 1 and port <= 65535:
82
+ return "ws://127.0.0.1:%d/godot" % port
83
+
84
+ return DEFAULT_URL
85
+
86
+
87
+ func disconnect_from_server() -> void:
88
+ _should_reconnect = false
89
+ if _reconnect_timer:
90
+ _reconnect_timer.stop()
91
+ if socket.get_ready_state() == WebSocketPeer.STATE_OPEN:
92
+ socket.close()
93
+ _is_connected = false
94
+
95
+
96
+ func _attempt_connection() -> void:
97
+ if socket.get_ready_state() != WebSocketPeer.STATE_CLOSED:
98
+ socket.close()
99
+
100
+ var err := socket.connect_to_url(server_url)
101
+ if err != OK:
102
+ push_error("[MCP Editor] Failed to connect: %s" % err)
103
+ _schedule_reconnect()
104
+
105
+
106
+ func _handle_connect() -> void:
107
+ _is_connected = true
108
+ _current_reconnect_delay = RECONNECT_DELAY
109
+
110
+ _send_message({
111
+ "type": "godot_ready",
112
+ "project_path": _project_path
113
+ })
114
+
115
+ connected.emit()
116
+
117
+
118
+ func _handle_disconnect() -> void:
119
+ _is_connected = false
120
+ disconnected.emit()
121
+
122
+ if _should_reconnect:
123
+ _schedule_reconnect()
124
+
125
+
126
+ func _schedule_reconnect() -> void:
127
+ if _reconnect_timer == null:
128
+ return
129
+ _reconnect_timer.start(_current_reconnect_delay)
130
+ _current_reconnect_delay = min(_current_reconnect_delay * 2.0, MAX_RECONNECT_DELAY)
131
+
132
+
133
+ func _on_reconnect_timer() -> void:
134
+ _attempt_connection()
135
+
136
+
137
+ func _handle_message(json_string: String) -> void:
138
+ var message = JSON.parse_string(json_string)
139
+ if message == null:
140
+ push_error("[MCP Editor] Failed to parse message: %s" % json_string)
141
+ return
142
+
143
+ match message.get("type", ""):
144
+ "ping":
145
+ _send_message({"type": "pong"})
146
+
147
+ "tool_invoke":
148
+ var request_id: String = message.get("id", "")
149
+ var tool_name: String = message.get("tool", "")
150
+ var args: Dictionary = message.get("args", {})
151
+ tool_requested.emit(request_id, tool_name, args)
152
+
153
+ _:
154
+ pass
155
+
156
+
157
+ func send_tool_result(request_id: String, success: bool, result = null, error: String = "") -> void:
158
+ var response := {
159
+ "type": "tool_result",
160
+ "id": request_id,
161
+ "success": success
162
+ }
163
+
164
+ if success:
165
+ response["result"] = result
166
+ else:
167
+ response["error"] = error
168
+
169
+ _send_message(response)
170
+
171
+
172
+ func _send_message(message: Dictionary) -> void:
173
+ if socket.get_ready_state() == WebSocketPeer.STATE_OPEN:
174
+ socket.send_text(JSON.stringify(message))
175
+
176
+
177
+ func is_connected_to_server() -> bool:
178
+ return _is_connected
@@ -1,6 +1,6 @@
1
- [plugin]
2
- name="Godot MCP Editor"
3
- description="MCP Editor Plugin - Scene manipulation via Godot API"
4
- author="HaD0Yun"
5
- version="1.0.0"
6
- script="plugin.gd"
1
+ [plugin]
2
+ name="Godot MCP Editor"
3
+ description="MCP Editor Plugin - Scene manipulation via Godot API"
4
+ author="HaD0Yun"
5
+ version="1.0.0"
6
+ script="plugin.gd"