godot-mcp-tool 0.0.0-stage → 0.1.0

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.
Files changed (532) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +57 -2
  3. package/addon/godot_mcp_tool/addon_info.gd +10 -0
  4. package/addon/godot_mcp_tool/addon_info.gd.uid +1 -0
  5. package/addon/godot_mcp_tool/animation/animation_reference.gd +50 -0
  6. package/addon/godot_mcp_tool/animation/animation_reference.gd.uid +1 -0
  7. package/addon/godot_mcp_tool/animation/animation_report.gd +48 -0
  8. package/addon/godot_mcp_tool/animation/animation_report.gd.uid +1 -0
  9. package/addon/godot_mcp_tool/animation/animation_track_planner.gd +188 -0
  10. package/addon/godot_mcp_tool/animation/animation_track_planner.gd.uid +1 -0
  11. package/addon/godot_mcp_tool/animation/animation_vocabulary.gd +50 -0
  12. package/addon/godot_mcp_tool/animation/animation_vocabulary.gd.uid +1 -0
  13. package/addon/godot_mcp_tool/animation/state_machine_plan.gd +157 -0
  14. package/addon/godot_mcp_tool/animation/state_machine_plan.gd.uid +1 -0
  15. package/addon/godot_mcp_tool/animation/state_machine_report.gd +74 -0
  16. package/addon/godot_mcp_tool/animation/state_machine_report.gd.uid +1 -0
  17. package/addon/godot_mcp_tool/assets/import_options.gd +75 -0
  18. package/addon/godot_mcp_tool/assets/import_options.gd.uid +1 -0
  19. package/addon/godot_mcp_tool/assets/import_settings.gd +92 -0
  20. package/addon/godot_mcp_tool/assets/import_settings.gd.uid +1 -0
  21. package/addon/godot_mcp_tool/assets/imported_scene_report.gd +69 -0
  22. package/addon/godot_mcp_tool/assets/imported_scene_report.gd.uid +1 -0
  23. package/addon/godot_mcp_tool/bridge/authenticator.gd +39 -0
  24. package/addon/godot_mcp_tool/bridge/authenticator.gd.uid +1 -0
  25. package/addon/godot_mcp_tool/bridge/bridge_connection.gd +84 -0
  26. package/addon/godot_mcp_tool/bridge/bridge_connection.gd.uid +1 -0
  27. package/addon/godot_mcp_tool/bridge/bridge_probe.gd +29 -0
  28. package/addon/godot_mcp_tool/bridge/bridge_probe.gd.uid +1 -0
  29. package/addon/godot_mcp_tool/bridge/bridge_server.gd +53 -0
  30. package/addon/godot_mcp_tool/bridge/bridge_server.gd.uid +1 -0
  31. package/addon/godot_mcp_tool/bridge/bridge_session.gd +126 -0
  32. package/addon/godot_mcp_tool/bridge/bridge_session.gd.uid +1 -0
  33. package/addon/godot_mcp_tool/bridge/discovery_file.gd +67 -0
  34. package/addon/godot_mcp_tool/bridge/discovery_file.gd.uid +1 -0
  35. package/addon/godot_mcp_tool/bridge/json_rpc.gd +37 -0
  36. package/addon/godot_mcp_tool/bridge/json_rpc.gd.uid +1 -0
  37. package/addon/godot_mcp_tool/bridge/ndjson_buffer.gd +31 -0
  38. package/addon/godot_mcp_tool/bridge/ndjson_buffer.gd.uid +1 -0
  39. package/addon/godot_mcp_tool/bridge/token_generator.gd +7 -0
  40. package/addon/godot_mcp_tool/bridge/token_generator.gd.uid +1 -0
  41. package/addon/godot_mcp_tool/capture/bounds.gd +58 -0
  42. package/addon/godot_mcp_tool/capture/bounds.gd.uid +1 -0
  43. package/addon/godot_mcp_tool/capture/bounds_report.gd +50 -0
  44. package/addon/godot_mcp_tool/capture/bounds_report.gd.uid +1 -0
  45. package/addon/godot_mcp_tool/capture/camera_views.gd +28 -0
  46. package/addon/godot_mcp_tool/capture/camera_views.gd.uid +1 -0
  47. package/addon/godot_mcp_tool/capture/capture_params.gd +29 -0
  48. package/addon/godot_mcp_tool/capture/capture_params.gd.uid +1 -0
  49. package/addon/godot_mcp_tool/capture/capture_store.gd +45 -0
  50. package/addon/godot_mcp_tool/capture/capture_store.gd.uid +1 -0
  51. package/addon/godot_mcp_tool/capture/image_fitter.gd +44 -0
  52. package/addon/godot_mcp_tool/capture/image_fitter.gd.uid +1 -0
  53. package/addon/godot_mcp_tool/capture/preview_lighting.gd +22 -0
  54. package/addon/godot_mcp_tool/capture/preview_lighting.gd.uid +1 -0
  55. package/addon/godot_mcp_tool/capture/screenshot_file.gd +22 -0
  56. package/addon/godot_mcp_tool/capture/screenshot_file.gd.uid +1 -0
  57. package/addon/godot_mcp_tool/capture/view_renderer.gd +67 -0
  58. package/addon/godot_mcp_tool/capture/view_renderer.gd.uid +1 -0
  59. package/addon/godot_mcp_tool/capture/view_requests.gd +125 -0
  60. package/addon/godot_mcp_tool/capture/view_requests.gd.uid +1 -0
  61. package/addon/godot_mcp_tool/codec/converters/array_converter.gd +70 -0
  62. package/addon/godot_mcp_tool/codec/converters/array_converter.gd.uid +1 -0
  63. package/addon/godot_mcp_tool/codec/converters/color_converter.gd +40 -0
  64. package/addon/godot_mcp_tool/codec/converters/color_converter.gd.uid +1 -0
  65. package/addon/godot_mcp_tool/codec/converters/converter.gd +82 -0
  66. package/addon/godot_mcp_tool/codec/converters/converter.gd.uid +1 -0
  67. package/addon/godot_mcp_tool/codec/converters/dictionary_converter.gd +19 -0
  68. package/addon/godot_mcp_tool/codec/converters/dictionary_converter.gd.uid +1 -0
  69. package/addon/godot_mcp_tool/codec/converters/enum_converter.gd +54 -0
  70. package/addon/godot_mcp_tool/codec/converters/enum_converter.gd.uid +1 -0
  71. package/addon/godot_mcp_tool/codec/converters/flags_converter.gd +60 -0
  72. package/addon/godot_mcp_tool/codec/converters/flags_converter.gd.uid +1 -0
  73. package/addon/godot_mcp_tool/codec/converters/godot_syntax_converter.gd +23 -0
  74. package/addon/godot_mcp_tool/codec/converters/godot_syntax_converter.gd.uid +1 -0
  75. package/addon/godot_mcp_tool/codec/converters/node_reference_converter.gd +25 -0
  76. package/addon/godot_mcp_tool/codec/converters/node_reference_converter.gd.uid +1 -0
  77. package/addon/godot_mcp_tool/codec/converters/primitive_converter.gd +25 -0
  78. package/addon/godot_mcp_tool/codec/converters/primitive_converter.gd.uid +1 -0
  79. package/addon/godot_mcp_tool/codec/converters/resource_converter.gd +82 -0
  80. package/addon/godot_mcp_tool/codec/converters/resource_converter.gd.uid +1 -0
  81. package/addon/godot_mcp_tool/codec/converters/untyped_converter.gd +11 -0
  82. package/addon/godot_mcp_tool/codec/converters/untyped_converter.gd.uid +1 -0
  83. package/addon/godot_mcp_tool/codec/converters/vector_converter.gd +68 -0
  84. package/addon/godot_mcp_tool/codec/converters/vector_converter.gd.uid +1 -0
  85. package/addon/godot_mcp_tool/codec/decode_outcome.gd +11 -0
  86. package/addon/godot_mcp_tool/codec/decode_outcome.gd.uid +1 -0
  87. package/addon/godot_mcp_tool/codec/enum_options.gd +24 -0
  88. package/addon/godot_mcp_tool/codec/enum_options.gd.uid +1 -0
  89. package/addon/godot_mcp_tool/codec/value_comparison.gd +66 -0
  90. package/addon/godot_mcp_tool/codec/value_comparison.gd.uid +1 -0
  91. package/addon/godot_mcp_tool/codec/value_decoder.gd +7 -0
  92. package/addon/godot_mcp_tool/codec/value_decoder.gd.uid +1 -0
  93. package/addon/godot_mcp_tool/codec/variant_codec.gd +94 -0
  94. package/addon/godot_mcp_tool/codec/variant_codec.gd.uid +1 -0
  95. package/addon/godot_mcp_tool/commands/animation/animation_delete_command.gd +47 -0
  96. package/addon/godot_mcp_tool/commands/animation/animation_delete_command.gd.uid +1 -0
  97. package/addon/godot_mcp_tool/commands/animation/animation_get_command.gd +51 -0
  98. package/addon/godot_mcp_tool/commands/animation/animation_get_command.gd.uid +1 -0
  99. package/addon/godot_mcp_tool/commands/animation/animation_set_command.gd +104 -0
  100. package/addon/godot_mcp_tool/commands/animation/animation_set_command.gd.uid +1 -0
  101. package/addon/godot_mcp_tool/commands/animation/animation_tree_get_command.gd +39 -0
  102. package/addon/godot_mcp_tool/commands/animation/animation_tree_get_command.gd.uid +1 -0
  103. package/addon/godot_mcp_tool/commands/animation/animation_tree_set_command.gd +92 -0
  104. package/addon/godot_mcp_tool/commands/animation/animation_tree_set_command.gd.uid +1 -0
  105. package/addon/godot_mcp_tool/commands/asset/asset_import_settings_get_command.gd +53 -0
  106. package/addon/godot_mcp_tool/commands/asset/asset_import_settings_get_command.gd.uid +1 -0
  107. package/addon/godot_mcp_tool/commands/asset/asset_import_settings_set_command.gd +112 -0
  108. package/addon/godot_mcp_tool/commands/asset/asset_import_settings_set_command.gd.uid +1 -0
  109. package/addon/godot_mcp_tool/commands/command.gd +8 -0
  110. package/addon/godot_mcp_tool/commands/command.gd.uid +1 -0
  111. package/addon/godot_mcp_tool/commands/command_catalog.gd +135 -0
  112. package/addon/godot_mcp_tool/commands/command_catalog.gd.uid +1 -0
  113. package/addon/godot_mcp_tool/commands/command_error.gd +11 -0
  114. package/addon/godot_mcp_tool/commands/command_error.gd.uid +1 -0
  115. package/addon/godot_mcp_tool/commands/command_router.gd +19 -0
  116. package/addon/godot_mcp_tool/commands/command_router.gd.uid +1 -0
  117. package/addon/godot_mcp_tool/commands/editor/editor_breakpoints_command.gd +13 -0
  118. package/addon/godot_mcp_tool/commands/editor/editor_breakpoints_command.gd.uid +1 -0
  119. package/addon/godot_mcp_tool/commands/editor/editor_rescan_command.gd +30 -0
  120. package/addon/godot_mcp_tool/commands/editor/editor_rescan_command.gd.uid +1 -0
  121. package/addon/godot_mcp_tool/commands/editor/editor_run_script_command.gd +55 -0
  122. package/addon/godot_mcp_tool/commands/editor/editor_run_script_command.gd.uid +1 -0
  123. package/addon/godot_mcp_tool/commands/editor/editor_screenshot_command.gd +75 -0
  124. package/addon/godot_mcp_tool/commands/editor/editor_screenshot_command.gd.uid +1 -0
  125. package/addon/godot_mcp_tool/commands/editor/editor_select_command.gd +69 -0
  126. package/addon/godot_mcp_tool/commands/editor/editor_select_command.gd.uid +1 -0
  127. package/addon/godot_mcp_tool/commands/editor/editor_unsaved_files_command.gd +26 -0
  128. package/addon/godot_mcp_tool/commands/editor/editor_unsaved_files_command.gd.uid +1 -0
  129. package/addon/godot_mcp_tool/commands/file/filesystem_delete_command.gd +112 -0
  130. package/addon/godot_mcp_tool/commands/file/filesystem_delete_command.gd.uid +1 -0
  131. package/addon/godot_mcp_tool/commands/file/filesystem_move_command.gd +174 -0
  132. package/addon/godot_mcp_tool/commands/file/filesystem_move_command.gd.uid +1 -0
  133. package/addon/godot_mcp_tool/commands/file/resource_find_usages_command.gd +24 -0
  134. package/addon/godot_mcp_tool/commands/file/resource_find_usages_command.gd.uid +1 -0
  135. package/addon/godot_mcp_tool/commands/game/game_get_output_command.gd +31 -0
  136. package/addon/godot_mcp_tool/commands/game/game_get_output_command.gd.uid +1 -0
  137. package/addon/godot_mcp_tool/commands/game/game_request_command.gd +32 -0
  138. package/addon/godot_mcp_tool/commands/game/game_request_command.gd.uid +1 -0
  139. package/addon/godot_mcp_tool/commands/game/game_run_command.gd +117 -0
  140. package/addon/godot_mcp_tool/commands/game/game_run_command.gd.uid +1 -0
  141. package/addon/godot_mcp_tool/commands/game/game_stop_command.gd +22 -0
  142. package/addon/godot_mcp_tool/commands/game/game_stop_command.gd.uid +1 -0
  143. package/addon/godot_mcp_tool/commands/input/input_map_get_command.gd +25 -0
  144. package/addon/godot_mcp_tool/commands/input/input_map_get_command.gd.uid +1 -0
  145. package/addon/godot_mcp_tool/commands/input/input_map_set_command.gd +89 -0
  146. package/addon/godot_mcp_tool/commands/input/input_map_set_command.gd.uid +1 -0
  147. package/addon/godot_mcp_tool/commands/navigation/navigation_bake_command.gd +90 -0
  148. package/addon/godot_mcp_tool/commands/navigation/navigation_bake_command.gd.uid +1 -0
  149. package/addon/godot_mcp_tool/commands/node/node_add_command.gd +7 -0
  150. package/addon/godot_mcp_tool/commands/node/node_add_command.gd.uid +1 -0
  151. package/addon/godot_mcp_tool/commands/node/node_call_method_command.gd +102 -0
  152. package/addon/godot_mcp_tool/commands/node/node_call_method_command.gd.uid +1 -0
  153. package/addon/godot_mcp_tool/commands/node/node_delete_command.gd +7 -0
  154. package/addon/godot_mcp_tool/commands/node/node_delete_command.gd.uid +1 -0
  155. package/addon/godot_mcp_tool/commands/node/node_duplicate_command.gd +7 -0
  156. package/addon/godot_mcp_tool/commands/node/node_duplicate_command.gd.uid +1 -0
  157. package/addon/godot_mcp_tool/commands/node/node_find_command.gd +55 -0
  158. package/addon/godot_mcp_tool/commands/node/node_find_command.gd.uid +1 -0
  159. package/addon/godot_mcp_tool/commands/node/node_get_bounds_command.gd +49 -0
  160. package/addon/godot_mcp_tool/commands/node/node_get_bounds_command.gd.uid +1 -0
  161. package/addon/godot_mcp_tool/commands/node/node_get_properties_command.gd +40 -0
  162. package/addon/godot_mcp_tool/commands/node/node_get_properties_command.gd.uid +1 -0
  163. package/addon/godot_mcp_tool/commands/node/node_reparent_command.gd +7 -0
  164. package/addon/godot_mcp_tool/commands/node/node_reparent_command.gd.uid +1 -0
  165. package/addon/godot_mcp_tool/commands/node/node_set_groups_command.gd +7 -0
  166. package/addon/godot_mcp_tool/commands/node/node_set_groups_command.gd.uid +1 -0
  167. package/addon/godot_mcp_tool/commands/node/node_set_properties_command.gd +7 -0
  168. package/addon/godot_mcp_tool/commands/node/node_set_properties_command.gd.uid +1 -0
  169. package/addon/godot_mcp_tool/commands/params.gd +65 -0
  170. package/addon/godot_mcp_tool/commands/params.gd.uid +1 -0
  171. package/addon/godot_mcp_tool/commands/ping_command.gd +5 -0
  172. package/addon/godot_mcp_tool/commands/ping_command.gd.uid +1 -0
  173. package/addon/godot_mcp_tool/commands/project/autoload_add_command.gd +55 -0
  174. package/addon/godot_mcp_tool/commands/project/autoload_add_command.gd.uid +1 -0
  175. package/addon/godot_mcp_tool/commands/project/autoload_remove_command.gd +32 -0
  176. package/addon/godot_mcp_tool/commands/project/autoload_remove_command.gd.uid +1 -0
  177. package/addon/godot_mcp_tool/commands/project/project_info_command.gd +43 -0
  178. package/addon/godot_mcp_tool/commands/project/project_info_command.gd.uid +1 -0
  179. package/addon/godot_mcp_tool/commands/project/project_settings_get_command.gd +55 -0
  180. package/addon/godot_mcp_tool/commands/project/project_settings_get_command.gd.uid +1 -0
  181. package/addon/godot_mcp_tool/commands/project/project_settings_set_command.gd +49 -0
  182. package/addon/godot_mcp_tool/commands/project/project_settings_set_command.gd.uid +1 -0
  183. package/addon/godot_mcp_tool/commands/resource/resource_create_command.gd +41 -0
  184. package/addon/godot_mcp_tool/commands/resource/resource_create_command.gd.uid +1 -0
  185. package/addon/godot_mcp_tool/commands/resource/resource_get_command.gd +31 -0
  186. package/addon/godot_mcp_tool/commands/resource/resource_get_command.gd.uid +1 -0
  187. package/addon/godot_mcp_tool/commands/resource/resource_set_properties_command.gd +42 -0
  188. package/addon/godot_mcp_tool/commands/resource/resource_set_properties_command.gd.uid +1 -0
  189. package/addon/godot_mcp_tool/commands/scene/scene_batch_edit_command.gd +91 -0
  190. package/addon/godot_mcp_tool/commands/scene/scene_batch_edit_command.gd.uid +1 -0
  191. package/addon/godot_mcp_tool/commands/scene/scene_close_command.gd +70 -0
  192. package/addon/godot_mcp_tool/commands/scene/scene_close_command.gd.uid +1 -0
  193. package/addon/godot_mcp_tool/commands/scene/scene_create_command.gd +77 -0
  194. package/addon/godot_mcp_tool/commands/scene/scene_create_command.gd.uid +1 -0
  195. package/addon/godot_mcp_tool/commands/scene/scene_get_tree_command.gd +39 -0
  196. package/addon/godot_mcp_tool/commands/scene/scene_get_tree_command.gd.uid +1 -0
  197. package/addon/godot_mcp_tool/commands/scene/scene_open_command.gd +33 -0
  198. package/addon/godot_mcp_tool/commands/scene/scene_open_command.gd.uid +1 -0
  199. package/addon/godot_mcp_tool/commands/scene/scene_save_command.gd +42 -0
  200. package/addon/godot_mcp_tool/commands/scene/scene_save_command.gd.uid +1 -0
  201. package/addon/godot_mcp_tool/commands/scene_edit_command.gd +33 -0
  202. package/addon/godot_mcp_tool/commands/scene_edit_command.gd.uid +1 -0
  203. package/addon/godot_mcp_tool/commands/signal/signal_connect_command.gd +7 -0
  204. package/addon/godot_mcp_tool/commands/signal/signal_connect_command.gd.uid +1 -0
  205. package/addon/godot_mcp_tool/commands/signal/signal_disconnect_command.gd +7 -0
  206. package/addon/godot_mcp_tool/commands/signal/signal_disconnect_command.gd.uid +1 -0
  207. package/addon/godot_mcp_tool/commands/signal/signal_list_command.gd +58 -0
  208. package/addon/godot_mcp_tool/commands/signal/signal_list_command.gd.uid +1 -0
  209. package/addon/godot_mcp_tool/commands/unsafe_command.gd +21 -0
  210. package/addon/godot_mcp_tool/commands/unsafe_command.gd.uid +1 -0
  211. package/addon/godot_mcp_tool/editor/autoload_registry.gd +9 -0
  212. package/addon/godot_mcp_tool/editor/autoload_registry.gd.uid +1 -0
  213. package/addon/godot_mcp_tool/editor/bottom_panel.gd +26 -0
  214. package/addon/godot_mcp_tool/editor/bottom_panel.gd.uid +1 -0
  215. package/addon/godot_mcp_tool/editor/command_journal.gd +32 -0
  216. package/addon/godot_mcp_tool/editor/command_journal.gd.uid +1 -0
  217. package/addon/godot_mcp_tool/editor/editor_autoload_registry.gd +21 -0
  218. package/addon/godot_mcp_tool/editor/editor_autoload_registry.gd.uid +1 -0
  219. package/addon/godot_mcp_tool/editor/editor_file_system_access.gd +32 -0
  220. package/addon/godot_mcp_tool/editor/editor_file_system_access.gd.uid +1 -0
  221. package/addon/godot_mcp_tool/editor/editor_script_editor_access.gd +46 -0
  222. package/addon/godot_mcp_tool/editor/editor_script_editor_access.gd.uid +1 -0
  223. package/addon/godot_mcp_tool/editor/editor_services.gd +225 -0
  224. package/addon/godot_mcp_tool/editor/editor_services.gd.uid +1 -0
  225. package/addon/godot_mcp_tool/editor/editor_viewport_access.gd +33 -0
  226. package/addon/godot_mcp_tool/editor/editor_viewport_access.gd.uid +1 -0
  227. package/addon/godot_mcp_tool/editor/file_system_access.gd +21 -0
  228. package/addon/godot_mcp_tool/editor/file_system_access.gd.uid +1 -0
  229. package/addon/godot_mcp_tool/editor/file_trash.gd +5 -0
  230. package/addon/godot_mcp_tool/editor/file_trash.gd.uid +1 -0
  231. package/addon/godot_mcp_tool/editor/first_scan_gate.gd +25 -0
  232. package/addon/godot_mcp_tool/editor/first_scan_gate.gd.uid +1 -0
  233. package/addon/godot_mcp_tool/editor/godot_version_text.gd +15 -0
  234. package/addon/godot_mcp_tool/editor/godot_version_text.gd.uid +1 -0
  235. package/addon/godot_mcp_tool/editor/mcp_dock.gd +114 -0
  236. package/addon/godot_mcp_tool/editor/mcp_dock.gd.uid +1 -0
  237. package/addon/godot_mcp_tool/editor/responsiveness_controller.gd +36 -0
  238. package/addon/godot_mcp_tool/editor/responsiveness_controller.gd.uid +1 -0
  239. package/addon/godot_mcp_tool/editor/responsiveness_policy.gd +10 -0
  240. package/addon/godot_mcp_tool/editor/responsiveness_policy.gd.uid +1 -0
  241. package/addon/godot_mcp_tool/editor/script_editor_access.gd +21 -0
  242. package/addon/godot_mcp_tool/editor/script_editor_access.gd.uid +1 -0
  243. package/addon/godot_mcp_tool/editor/script_error_capture.gd +19 -0
  244. package/addon/godot_mcp_tool/editor/script_error_capture.gd.uid +1 -0
  245. package/addon/godot_mcp_tool/editor/script_sync.gd +40 -0
  246. package/addon/godot_mcp_tool/editor/script_sync.gd.uid +1 -0
  247. package/addon/godot_mcp_tool/editor/supported_engine.gd +15 -0
  248. package/addon/godot_mcp_tool/editor/supported_engine.gd.uid +1 -0
  249. package/addon/godot_mcp_tool/editor/unsafe_tools_switch.gd +40 -0
  250. package/addon/godot_mcp_tool/editor/unsafe_tools_switch.gd.uid +1 -0
  251. package/addon/godot_mcp_tool/files/file_usages.gd +84 -0
  252. package/addon/godot_mcp_tool/files/file_usages.gd.uid +1 -0
  253. package/addon/godot_mcp_tool/files/project_file_index.gd +28 -0
  254. package/addon/godot_mcp_tool/files/project_file_index.gd.uid +1 -0
  255. package/addon/godot_mcp_tool/files/project_paths.gd +43 -0
  256. package/addon/godot_mcp_tool/files/project_paths.gd.uid +1 -0
  257. package/addon/godot_mcp_tool/files/reference_rewriter.gd +29 -0
  258. package/addon/godot_mcp_tool/files/reference_rewriter.gd.uid +1 -0
  259. package/addon/godot_mcp_tool/input/input_actions.gd +53 -0
  260. package/addon/godot_mcp_tool/input/input_actions.gd.uid +1 -0
  261. package/addon/godot_mcp_tool/input/input_event_codec.gd +178 -0
  262. package/addon/godot_mcp_tool/input/input_event_codec.gd.uid +1 -0
  263. package/addon/godot_mcp_tool/navigation/navigation_bake_report.gd +79 -0
  264. package/addon/godot_mcp_tool/navigation/navigation_bake_report.gd.uid +1 -0
  265. package/addon/godot_mcp_tool/plugin.cfg +7 -0
  266. package/addon/godot_mcp_tool/plugin.gd +43 -0
  267. package/addon/godot_mcp_tool/plugin.gd.uid +1 -0
  268. package/addon/godot_mcp_tool/project/autoload_list.gd +34 -0
  269. package/addon/godot_mcp_tool/project/autoload_list.gd.uid +1 -0
  270. package/addon/godot_mcp_tool/project/autoload_names.gd +38 -0
  271. package/addon/godot_mcp_tool/project/autoload_names.gd.uid +1 -0
  272. package/addon/godot_mcp_tool/project/global_class_summary.gd +26 -0
  273. package/addon/godot_mcp_tool/project/global_class_summary.gd.uid +1 -0
  274. package/addon/godot_mcp_tool/project/project_query.gd +66 -0
  275. package/addon/godot_mcp_tool/project/project_query.gd.uid +1 -0
  276. package/addon/godot_mcp_tool/project/script_indentation.gd +39 -0
  277. package/addon/godot_mcp_tool/project/script_indentation.gd.uid +1 -0
  278. package/addon/godot_mcp_tool/resources/resource_factory.gd +59 -0
  279. package/addon/godot_mcp_tool/resources/resource_factory.gd.uid +1 -0
  280. package/addon/godot_mcp_tool/resources/resource_files.gd +70 -0
  281. package/addon/godot_mcp_tool/resources/resource_files.gd.uid +1 -0
  282. package/addon/godot_mcp_tool/runtime/debugger_sink.gd +15 -0
  283. package/addon/godot_mcp_tool/runtime/debugger_sink.gd.uid +1 -0
  284. package/addon/godot_mcp_tool/runtime/editor_game_launcher.gd +31 -0
  285. package/addon/godot_mcp_tool/runtime/editor_game_launcher.gd.uid +1 -0
  286. package/addon/godot_mcp_tool/runtime/game_channel.gd +61 -0
  287. package/addon/godot_mcp_tool/runtime/game_channel.gd.uid +1 -0
  288. package/addon/godot_mcp_tool/runtime/game_commands/game_bounds_command.gd +31 -0
  289. package/addon/godot_mcp_tool/runtime/game_commands/game_bounds_command.gd.uid +1 -0
  290. package/addon/godot_mcp_tool/runtime/game_commands/game_command_catalog.gd +40 -0
  291. package/addon/godot_mcp_tool/runtime/game_commands/game_command_catalog.gd.uid +1 -0
  292. package/addon/godot_mcp_tool/runtime/game_commands/game_eval_command.gd +40 -0
  293. package/addon/godot_mcp_tool/runtime/game_commands/game_eval_command.gd.uid +1 -0
  294. package/addon/godot_mcp_tool/runtime/game_commands/game_input_command.gd +308 -0
  295. package/addon/godot_mcp_tool/runtime/game_commands/game_input_command.gd.uid +1 -0
  296. package/addon/godot_mcp_tool/runtime/game_commands/game_pause_command.gd +23 -0
  297. package/addon/godot_mcp_tool/runtime/game_commands/game_pause_command.gd.uid +1 -0
  298. package/addon/godot_mcp_tool/runtime/game_commands/game_performance_command.gd +75 -0
  299. package/addon/godot_mcp_tool/runtime/game_commands/game_performance_command.gd.uid +1 -0
  300. package/addon/godot_mcp_tool/runtime/game_commands/game_properties_get_command.gd +78 -0
  301. package/addon/godot_mcp_tool/runtime/game_commands/game_properties_get_command.gd.uid +1 -0
  302. package/addon/godot_mcp_tool/runtime/game_commands/game_properties_set_command.gd +35 -0
  303. package/addon/godot_mcp_tool/runtime/game_commands/game_properties_set_command.gd.uid +1 -0
  304. package/addon/godot_mcp_tool/runtime/game_commands/game_scene.gd +54 -0
  305. package/addon/godot_mcp_tool/runtime/game_commands/game_scene.gd.uid +1 -0
  306. package/addon/godot_mcp_tool/runtime/game_commands/game_screenshot_command.gd +66 -0
  307. package/addon/godot_mcp_tool/runtime/game_commands/game_screenshot_command.gd.uid +1 -0
  308. package/addon/godot_mcp_tool/runtime/game_commands/game_step_command.gd +28 -0
  309. package/addon/godot_mcp_tool/runtime/game_commands/game_step_command.gd.uid +1 -0
  310. package/addon/godot_mcp_tool/runtime/game_commands/game_tree_command.gd +29 -0
  311. package/addon/godot_mcp_tool/runtime/game_commands/game_tree_command.gd.uid +1 -0
  312. package/addon/godot_mcp_tool/runtime/game_commands/game_wait_command.gd +103 -0
  313. package/addon/godot_mcp_tool/runtime/game_commands/game_wait_command.gd.uid +1 -0
  314. package/addon/godot_mcp_tool/runtime/game_launcher.gd +29 -0
  315. package/addon/godot_mcp_tool/runtime/game_launcher.gd.uid +1 -0
  316. package/addon/godot_mcp_tool/runtime/game_request_responder.gd +28 -0
  317. package/addon/godot_mcp_tool/runtime/game_request_responder.gd.uid +1 -0
  318. package/addon/godot_mcp_tool/runtime/game_state.gd +53 -0
  319. package/addon/godot_mcp_tool/runtime/game_state.gd.uid +1 -0
  320. package/addon/godot_mcp_tool/runtime/game_time.gd +69 -0
  321. package/addon/godot_mcp_tool/runtime/game_time.gd.uid +1 -0
  322. package/addon/godot_mcp_tool/runtime/log_entry_builder.gd +58 -0
  323. package/addon/godot_mcp_tool/runtime/log_entry_builder.gd.uid +1 -0
  324. package/addon/godot_mcp_tool/runtime/log_file_writer.gd +38 -0
  325. package/addon/godot_mcp_tool/runtime/log_file_writer.gd.uid +1 -0
  326. package/addon/godot_mcp_tool/runtime/log_store.gd +77 -0
  327. package/addon/godot_mcp_tool/runtime/log_store.gd.uid +1 -0
  328. package/addon/godot_mcp_tool/runtime/run_arguments.gd +21 -0
  329. package/addon/godot_mcp_tool/runtime/run_arguments.gd.uid +1 -0
  330. package/addon/godot_mcp_tool/runtime/run_request.gd +7 -0
  331. package/addon/godot_mcp_tool/runtime/run_request.gd.uid +1 -0
  332. package/addon/godot_mcp_tool/runtime/runtime_activation.gd +13 -0
  333. package/addon/godot_mcp_tool/runtime/runtime_activation.gd.uid +1 -0
  334. package/addon/godot_mcp_tool/runtime/runtime_agent.gd +108 -0
  335. package/addon/godot_mcp_tool/runtime/runtime_agent.gd.uid +1 -0
  336. package/addon/godot_mcp_tool/runtime/runtime_context.gd +18 -0
  337. package/addon/godot_mcp_tool/runtime/runtime_context.gd.uid +1 -0
  338. package/addon/godot_mcp_tool/runtime/runtime_debugger.gd +65 -0
  339. package/addon/godot_mcp_tool/runtime/runtime_debugger.gd.uid +1 -0
  340. package/addon/godot_mcp_tool/runtime/runtime_logger.gd +57 -0
  341. package/addon/godot_mcp_tool/runtime/runtime_logger.gd.uid +1 -0
  342. package/addon/godot_mcp_tool/runtime/runtime_protocol.gd +8 -0
  343. package/addon/godot_mcp_tool/runtime/runtime_protocol.gd.uid +1 -0
  344. package/addon/godot_mcp_tool/runtime/server_connection.gd +70 -0
  345. package/addon/godot_mcp_tool/runtime/server_connection.gd.uid +1 -0
  346. package/addon/godot_mcp_tool/scene/change_set.gd +79 -0
  347. package/addon/godot_mcp_tool/scene/change_set.gd.uid +1 -0
  348. package/addon/godot_mcp_tool/scene/editing_context.gd +26 -0
  349. package/addon/godot_mcp_tool/scene/editing_context.gd.uid +1 -0
  350. package/addon/godot_mcp_tool/scene/editor_scene_access.gd +64 -0
  351. package/addon/godot_mcp_tool/scene/editor_scene_access.gd.uid +1 -0
  352. package/addon/godot_mcp_tool/scene/editor_undo_history.gd +39 -0
  353. package/addon/godot_mcp_tool/scene/editor_undo_history.gd.uid +1 -0
  354. package/addon/godot_mcp_tool/scene/edits/group_change.gd +71 -0
  355. package/addon/godot_mcp_tool/scene/edits/group_change.gd.uid +1 -0
  356. package/addon/godot_mcp_tool/scene/edits/node_addition.gd +47 -0
  357. package/addon/godot_mcp_tool/scene/edits/node_addition.gd.uid +1 -0
  358. package/addon/godot_mcp_tool/scene/edits/node_deletion.gd +51 -0
  359. package/addon/godot_mcp_tool/scene/edits/node_deletion.gd.uid +1 -0
  360. package/addon/godot_mcp_tool/scene/edits/node_duplication.gd +63 -0
  361. package/addon/godot_mcp_tool/scene/edits/node_duplication.gd.uid +1 -0
  362. package/addon/godot_mcp_tool/scene/edits/node_move.gd +109 -0
  363. package/addon/godot_mcp_tool/scene/edits/node_move.gd.uid +1 -0
  364. package/addon/godot_mcp_tool/scene/edits/property_change.gd +37 -0
  365. package/addon/godot_mcp_tool/scene/edits/property_change.gd.uid +1 -0
  366. package/addon/godot_mcp_tool/scene/edits/scene_edit.gd +47 -0
  367. package/addon/godot_mcp_tool/scene/edits/scene_edit.gd.uid +1 -0
  368. package/addon/godot_mcp_tool/scene/edits/signal_connection.gd +74 -0
  369. package/addon/godot_mcp_tool/scene/edits/signal_connection.gd.uid +1 -0
  370. package/addon/godot_mcp_tool/scene/edits/signal_disconnection.gd +61 -0
  371. package/addon/godot_mcp_tool/scene/edits/signal_disconnection.gd.uid +1 -0
  372. package/addon/godot_mcp_tool/scene/node_factory.gd +73 -0
  373. package/addon/godot_mcp_tool/scene/node_factory.gd.uid +1 -0
  374. package/addon/godot_mcp_tool/scene/node_locator.gd +45 -0
  375. package/addon/godot_mcp_tool/scene/node_locator.gd.uid +1 -0
  376. package/addon/godot_mcp_tool/scene/node_matcher.gd +52 -0
  377. package/addon/godot_mcp_tool/scene/node_matcher.gd.uid +1 -0
  378. package/addon/godot_mcp_tool/scene/node_path_updates.gd +70 -0
  379. package/addon/godot_mcp_tool/scene/node_path_updates.gd.uid +1 -0
  380. package/addon/godot_mcp_tool/scene/plain_undo_history.gd +51 -0
  381. package/addon/godot_mcp_tool/scene/plain_undo_history.gd.uid +1 -0
  382. package/addon/godot_mcp_tool/scene/property_editor.gd +211 -0
  383. package/addon/godot_mcp_tool/scene/property_editor.gd.uid +1 -0
  384. package/addon/godot_mcp_tool/scene/scene_access.gd +45 -0
  385. package/addon/godot_mcp_tool/scene/scene_access.gd.uid +1 -0
  386. package/addon/godot_mcp_tool/scene/scene_resolver.gd +95 -0
  387. package/addon/godot_mcp_tool/scene/scene_resolver.gd.uid +1 -0
  388. package/addon/godot_mcp_tool/scene/scene_snapshot.gd +16 -0
  389. package/addon/godot_mcp_tool/scene/scene_snapshot.gd.uid +1 -0
  390. package/addon/godot_mcp_tool/scene/scene_tree_describer.gd +69 -0
  391. package/addon/godot_mcp_tool/scene/scene_tree_describer.gd.uid +1 -0
  392. package/addon/godot_mcp_tool/scene/signal_catalog.gd +112 -0
  393. package/addon/godot_mcp_tool/scene/signal_catalog.gd.uid +1 -0
  394. package/addon/godot_mcp_tool/scene/spatial_transforms.gd +12 -0
  395. package/addon/godot_mcp_tool/scene/spatial_transforms.gd.uid +1 -0
  396. package/addon/godot_mcp_tool/scene/undo_history.gd +44 -0
  397. package/addon/godot_mcp_tool/scene/undo_history.gd.uid +1 -0
  398. package/addon/godot_mcp_tool/util/global_classes.gd +24 -0
  399. package/addon/godot_mcp_tool/util/global_classes.gd.uid +1 -0
  400. package/addon/godot_mcp_tool/util/indefinite_article.gd +8 -0
  401. package/addon/godot_mcp_tool/util/indefinite_article.gd.uid +1 -0
  402. package/addon/godot_mcp_tool/util/number_text.gd +5 -0
  403. package/addon/godot_mcp_tool/util/number_text.gd.uid +1 -0
  404. package/addon/godot_mcp_tool/util/resource_paths.gd +8 -0
  405. package/addon/godot_mcp_tool/util/resource_paths.gd.uid +1 -0
  406. package/addon/godot_mcp_tool/util/similar_names.gd +48 -0
  407. package/addon/godot_mcp_tool/util/similar_names.gd.uid +1 -0
  408. package/addon/godot_mcp_tool/util/waiting.gd +10 -0
  409. package/addon/godot_mcp_tool/util/waiting.gd.uid +1 -0
  410. package/dist/addon/AddonInstaller.js +99 -0
  411. package/dist/addon/InstalledAddon.js +38 -0
  412. package/dist/addon/PluginActivation.js +56 -0
  413. package/dist/bridge/BridgeClient.js +174 -0
  414. package/dist/bridge/BridgeErrors.js +19 -0
  415. package/dist/bridge/DiscoveryFileReader.js +95 -0
  416. package/dist/bridge/EditorConnection.js +131 -0
  417. package/dist/bridge/NdjsonDecoder.js +29 -0
  418. package/dist/cli/CommandLine.js +51 -0
  419. package/dist/cli/CommandReport.js +7 -0
  420. package/dist/cli/Doctor.js +102 -0
  421. package/dist/cli/runCommand.js +115 -0
  422. package/dist/createApplication.js +150 -0
  423. package/dist/createGodotContext.js +41 -0
  424. package/dist/debug/DebugAdapterClient.js +158 -0
  425. package/dist/debug/GameDebugger.js +225 -0
  426. package/dist/docs/BbcodeMarkdown.js +140 -0
  427. package/dist/docs/ClassDoc.js +21 -0
  428. package/dist/docs/DocsLibrary.js +148 -0
  429. package/dist/docs/DocsSource.js +167 -0
  430. package/dist/docs/EngineApiDocs.js +127 -0
  431. package/dist/docs/ProjectClassDocs.js +88 -0
  432. package/dist/editor/EditorGateway.js +4 -0
  433. package/dist/editor/EditorLauncher.js +73 -0
  434. package/dist/editor/EditorOrHeadlessGateway.js +21 -0
  435. package/dist/export/ExportDestination.js +108 -0
  436. package/dist/export/ExportError.js +4 -0
  437. package/dist/export/ExportOutput.js +51 -0
  438. package/dist/export/ExportPresets.js +16 -0
  439. package/dist/export/ProjectExporter.js +169 -0
  440. package/dist/godot/GodotBinaryLocator.js +66 -0
  441. package/dist/godot/GodotCli.js +24 -0
  442. package/dist/godot/GodotVersion.js +35 -0
  443. package/dist/godot/supportedGodotVersion.js +7 -0
  444. package/dist/hooks/EditedScriptCheck.js +42 -0
  445. package/dist/hooks/hookResponse.js +15 -0
  446. package/dist/index.js +28 -0
  447. package/dist/lsp/LanguageServerClient.js +234 -0
  448. package/dist/packageFiles.js +3 -0
  449. package/dist/process/DetachedLauncher.js +36 -0
  450. package/dist/process/ProcessLauncher.js +66 -0
  451. package/dist/process/ProcessRunner.js +24 -0
  452. package/dist/project/ConfigText.js +72 -0
  453. package/dist/project/HeadlessProjectQuery.js +60 -0
  454. package/dist/project/ProjectFile.js +29 -0
  455. package/dist/project/ProjectFiles.js +36 -0
  456. package/dist/project/ProjectLocator.js +65 -0
  457. package/dist/project/ScriptLines.js +20 -0
  458. package/dist/prompts/FixLastRunPrompt.js +46 -0
  459. package/dist/prompts/McpPrompt.js +2 -0
  460. package/dist/prompts/PlaytestPrompt.js +28 -0
  461. package/dist/protocol/ContentLengthMessages.js +34 -0
  462. package/dist/resources/McpResource.js +2 -0
  463. package/dist/resources/ToolViewResource.js +17 -0
  464. package/dist/resources/godotResources.js +33 -0
  465. package/dist/runtime/ErrorSummary.js +121 -0
  466. package/dist/runtime/GameGatewayRouter.js +52 -0
  467. package/dist/runtime/GameOutputCursor.js +10 -0
  468. package/dist/runtime/LocalGameChannel.js +158 -0
  469. package/dist/runtime/LocalGameGateway.js +279 -0
  470. package/dist/runtime/LogBook.js +48 -0
  471. package/dist/runtime/RecordFile.js +56 -0
  472. package/dist/scripts/CheckOnlyOutput.js +21 -0
  473. package/dist/scripts/ScriptErrorOutput.js +17 -0
  474. package/dist/scripts/ScriptFiles.js +40 -0
  475. package/dist/scripts/ScriptLoadErrors.js +23 -0
  476. package/dist/scripts/ScriptProblem.js +2 -0
  477. package/dist/scripts/ScriptValidator.js +71 -0
  478. package/dist/scripts/createScriptValidator.js +27 -0
  479. package/dist/serveOverStdio.js +23 -0
  480. package/dist/server/ToolPolicy.js +37 -0
  481. package/dist/server/createMcpServer.js +55 -0
  482. package/dist/server/serverInstructions.js +23 -0
  483. package/dist/serverInfo.js +4 -0
  484. package/dist/testing/JUnitReport.js +53 -0
  485. package/dist/testing/TestFrameworks.js +53 -0
  486. package/dist/testing/TestRunner.js +178 -0
  487. package/dist/tools/EditorLaunchTool.js +48 -0
  488. package/dist/tools/ErrorReportingTool.js +31 -0
  489. package/dist/tools/ExportProjectTool.js +79 -0
  490. package/dist/tools/GodotStatusTool.js +57 -0
  491. package/dist/tools/TestRunTool.js +130 -0
  492. package/dist/tools/Tool.js +2 -0
  493. package/dist/tools/animationTools.js +163 -0
  494. package/dist/tools/animationTreeTools.js +160 -0
  495. package/dist/tools/annotations.js +10 -0
  496. package/dist/tools/assetTools.js +120 -0
  497. package/dist/tools/autoloadTools.js +52 -0
  498. package/dist/tools/batchTools.js +91 -0
  499. package/dist/tools/bridge/BridgeTool.js +49 -0
  500. package/dist/tools/captureTools.js +124 -0
  501. package/dist/tools/debugTools.js +225 -0
  502. package/dist/tools/docsTools.js +108 -0
  503. package/dist/tools/editorTools.js +61 -0
  504. package/dist/tools/fileTools.js +82 -0
  505. package/dist/tools/formatting/classReference.js +229 -0
  506. package/dist/tools/formatting/counting.js +4 -0
  507. package/dist/tools/formatting/fileUsageReports.js +29 -0
  508. package/dist/tools/formatting/logEntries.js +26 -0
  509. package/dist/tools/formatting/propertyReports.js +75 -0
  510. package/dist/tools/formatting/sceneTree.js +70 -0
  511. package/dist/tools/formatting/scriptReports.js +49 -0
  512. package/dist/tools/gameControlTools.js +134 -0
  513. package/dist/tools/gameInspectionTools.js +145 -0
  514. package/dist/tools/gameTools.js +203 -0
  515. package/dist/tools/inputTools.js +276 -0
  516. package/dist/tools/navigationTools.js +64 -0
  517. package/dist/tools/nodeStructureTools.js +85 -0
  518. package/dist/tools/nodeTools.js +263 -0
  519. package/dist/tools/parameters.js +23 -0
  520. package/dist/tools/projectTools.js +184 -0
  521. package/dist/tools/resourceTools.js +99 -0
  522. package/dist/tools/results.js +7 -0
  523. package/dist/tools/sceneTools.js +134 -0
  524. package/dist/tools/scriptTools.js +47 -0
  525. package/dist/tools/signalTools.js +121 -0
  526. package/dist/tools/unsafeTools.js +156 -0
  527. package/dist/util/CacheDirectory.js +20 -0
  528. package/dist/util/SimilarNames.js +60 -0
  529. package/dist/util/XmlDocument.js +56 -0
  530. package/dist/util/errors.js +7 -0
  531. package/dist/util/ports.js +5 -0
  532. package/package.json +59 -4
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 facelessdiplomat
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,58 @@
1
- # Temporary Holding Version
1
+ # godot-mcp-tool
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ The MCP server and command-line tool of [Godot MCP Tool](https://github.com/facelessdiplomat/godot-mcp-tool). With
4
+ it, Claude Code makes Godot 4 games through the Godot editor: it builds scenes that Ctrl+Z can undo, writes and checks
5
+ GDScript, runs the game, plays input into it and reads its errors with stack traces.
6
+
7
+ You need Godot 4.7 or newer, Node.js 22 or newer and Claude Code.
8
+
9
+ ## Quick start
10
+
11
+ 1. Install the editor addon into your Godot project. In the project folder, with the editor closed, run:
12
+
13
+ ```bash
14
+ npx godot-mcp-tool install-addon
15
+ ```
16
+
17
+ 2. Connect Claude Code. The Claude Code plugin is the best way: it also checks every GDScript file Claude writes.
18
+
19
+ ```bash
20
+ claude plugin marketplace add facelessdiplomat/godot-mcp-tool
21
+ claude plugin install godot@godot-mcp-tool
22
+ ```
23
+
24
+ Without the plugin, add the server to the project:
25
+
26
+ ```bash
27
+ claude mcp add --scope project godot -- npx -y godot-mcp-tool
28
+ ```
29
+
30
+ 3. Open the project in Godot, start `claude` in the project folder and ask: "Check the Godot connection."
31
+
32
+ ## Commands
33
+
34
+ ```text
35
+ godot-mcp-tool Run the MCP server; Claude Code starts it
36
+ godot-mcp-tool install-addon [folder] Copy the addon into the Godot project and enable its plugin
37
+ godot-mcp-tool update-addon [folder] Replace the addon of the project with the version of this package
38
+ godot-mcp-tool doctor [folder] Check Node.js, Godot, the addon, the plugin and the connection to the editor
39
+ godot-mcp-tool check-edited-script Check the .gd file of a Claude Code hook input; the plugin's hook runs it
40
+ ```
41
+
42
+ The folder is the Godot project: by default `GODOT_PROJECT_PATH`, or the current folder or the nearest folder above
43
+ it that has a `project.godot`.
44
+
45
+ ## Documentation
46
+
47
+ - [Setup guide](https://github.com/facelessdiplomat/godot-mcp-tool/blob/master/docs/setup.md): installing, connecting,
48
+ settings and troubleshooting.
49
+ - [Usage guide](https://github.com/facelessdiplomat/godot-mcp-tool/blob/master/docs/usage.md): example requests,
50
+ safety and limitations.
51
+ - [Tool reference](https://github.com/facelessdiplomat/godot-mcp-tool/blob/master/docs/tools.md): every tool with its
52
+ parameters.
53
+ - [Security](https://github.com/facelessdiplomat/godot-mcp-tool/blob/master/SECURITY.md): how to report a problem and
54
+ how the tool protects your project.
55
+
56
+ ## License
57
+
58
+ [MIT](https://github.com/facelessdiplomat/godot-mcp-tool/blob/master/LICENSE)
@@ -0,0 +1,10 @@
1
+ extends RefCounted
2
+
3
+ const ADDON_VERSION := "0.1.0"
4
+ const BRIDGE_PROTOCOL_VERSION := 1
5
+ const DISCOVERY_RELATIVE_PATH := ".godot/godot_mcp_tool/bridge.json"
6
+ const CAPTURES_RELATIVE_PATH := ".godot/godot_mcp_tool/captures"
7
+ const LOOPBACK_ADDRESS := "127.0.0.1"
8
+ const RUNTIME_AUTOLOAD_NAME := "GodotMcpRuntime"
9
+ const SETTINGS_SECTION := "godot_mcp_tool"
10
+ const UNSAFE_TOOLS_KEY := "allow_unsafe_tools"
@@ -0,0 +1 @@
1
+ uid://cmkw424ct17bi
@@ -0,0 +1,50 @@
1
+ extends RefCounted
2
+
3
+ const CommandError := preload("../commands/command_error.gd")
4
+ const IndefiniteArticle := preload("../util/indefinite_article.gd")
5
+ const JsonRpc := preload("../bridge/json_rpc.gd")
6
+ const NodeFactory := preload("../scene/node_factory.gd")
7
+ const NodeLocator := preload("../scene/node_locator.gd")
8
+
9
+ const FORBIDDEN_NAME_CHARACTERS := ["/", ":", ",", "["]
10
+ const LIBRARY_SEPARATOR := "/"
11
+
12
+ var library_name := ""
13
+ var animation_name := ""
14
+
15
+
16
+ static func find_player(scene_root: Node, player_path: String) -> Variant:
17
+ var node := NodeLocator.find(scene_root, player_path)
18
+ if node == null:
19
+ return CommandError.new(JsonRpc.NOT_FOUND, "Node \"%s\" not found" % player_path, NodeLocator.not_found_hint(scene_root, player_path))
20
+ if not node is AnimationPlayer:
21
+ return CommandError.new(
22
+ JsonRpc.INVALID_PARAMS,
23
+ "%s is %s, not an AnimationPlayer" % [player_path, IndefiniteArticle.before(NodeFactory.display_class(node))],
24
+ "Add an AnimationPlayer with node_add; its tracks animate the nodes under its parent.",
25
+ )
26
+ return node
27
+
28
+
29
+ static func parse(full_name: String) -> Variant:
30
+ var reference := new()
31
+ var name := full_name.strip_edges()
32
+ if name.contains(LIBRARY_SEPARATOR):
33
+ reference.library_name = name.get_slice(LIBRARY_SEPARATOR, 0)
34
+ name = name.substr(reference.library_name.length() + 1)
35
+ reference.animation_name = name
36
+ if name.is_empty() or FORBIDDEN_NAME_CHARACTERS.any(func(character: String) -> bool: return name.contains(character)) or _has_forbidden_character(reference.library_name):
37
+ return CommandError.new(
38
+ JsonRpc.INVALID_PARAMS,
39
+ "\"%s\" is not a valid animation name" % full_name,
40
+ "Animation names cannot be empty or contain / : , [; write \"library/name\" for an animation of another library than the default one.",
41
+ )
42
+ return reference
43
+
44
+
45
+ static func _has_forbidden_character(library_name: String) -> bool:
46
+ return FORBIDDEN_NAME_CHARACTERS.any(func(character: String) -> bool: return library_name.contains(character))
47
+
48
+
49
+ func full_name() -> String:
50
+ return animation_name if library_name.is_empty() else "%s%s%s" % [library_name, LIBRARY_SEPARATOR, animation_name]
@@ -0,0 +1 @@
1
+ uid://deaayqfs2ns82
@@ -0,0 +1,48 @@
1
+ extends RefCounted
2
+
3
+ const AnimationVocabulary := preload("animation_vocabulary.gd")
4
+ const VariantCodec := preload("../codec/variant_codec.gd")
5
+
6
+ const MAXIMUM_KEYS_SHOWN := 20
7
+ const DECIMAL_SCALE := 1000.0
8
+
9
+
10
+ static func list(player: AnimationPlayer) -> Array:
11
+ var animations: Array = []
12
+ for name in player.get_animation_list():
13
+ var animation := player.get_animation(name)
14
+ animations.append({"name": str(name), "length": _rounded(animation.length), "loop": loop_name(animation), "tracks": animation.get_track_count()})
15
+ return animations
16
+
17
+
18
+ static func detail(animation: Animation, name: String, codec: VariantCodec) -> Dictionary:
19
+ var tracks: Array = []
20
+ for index in animation.get_track_count():
21
+ tracks.append(_track(animation, index, codec))
22
+ return {"name": name, "length": _rounded(animation.length), "loop": loop_name(animation), "tracks": tracks}
23
+
24
+
25
+ static func loop_name(animation: Animation) -> String:
26
+ return AnimationVocabulary.name_of(AnimationVocabulary.LOOP_MODES, animation.loop_mode)
27
+
28
+
29
+ static func _track(animation: Animation, index: int, codec: VariantCodec) -> Dictionary:
30
+ var type := animation.track_get_type(index)
31
+ var track := {
32
+ "path": str(animation.track_get_path(index)),
33
+ "type": AnimationVocabulary.name_of(AnimationVocabulary.TRACK_TYPES, type),
34
+ "interpolation": AnimationVocabulary.name_of(AnimationVocabulary.INTERPOLATIONS, animation.track_get_interpolation_type(index)),
35
+ }
36
+ if type == Animation.TYPE_VALUE:
37
+ track["update"] = AnimationVocabulary.name_of(AnimationVocabulary.UPDATE_MODES, animation.value_track_get_update_mode(index))
38
+ var key_count := animation.track_get_key_count(index)
39
+ var keys: Array = []
40
+ for key_index in mini(key_count, MAXIMUM_KEYS_SHOWN):
41
+ keys.append({"time": _rounded(animation.track_get_key_time(index, key_index)), "value": codec.encode(animation.track_get_key_value(index, key_index))})
42
+ track["key_count"] = key_count
43
+ track["keys"] = keys
44
+ return track
45
+
46
+
47
+ static func _rounded(value: float) -> float:
48
+ return roundf(value * DECIMAL_SCALE) / DECIMAL_SCALE
@@ -0,0 +1 @@
1
+ uid://dmelrjna2x0rf
@@ -0,0 +1,188 @@
1
+ extends RefCounted
2
+
3
+ const AnimationVocabulary := preload("animation_vocabulary.gd")
4
+ const NodeLocator := preload("../scene/node_locator.gd")
5
+ const SimilarNames := preload("../util/similar_names.gd")
6
+ const VariantCodec := preload("../codec/variant_codec.gd")
7
+
8
+ const STEPPED_TYPES := [TYPE_BOOL, TYPE_STRING, TYPE_STRING_NAME, TYPE_NODE_PATH, TYPE_OBJECT]
9
+ const DEFAULT_LENGTH := 1.0
10
+ const DECIMAL_SCALE := 1000.0
11
+ const RESET_LENGTH := 0.001
12
+
13
+ var _codec: VariantCodec
14
+ var _root: Node
15
+
16
+
17
+ func _init(codec: VariantCodec, root: Node) -> void:
18
+ _codec = codec
19
+ _root = root
20
+
21
+
22
+ func plan(track_descriptions: Array, requested_length: Variant) -> Dictionary:
23
+ var planned: Array = []
24
+ var rejected: Array = []
25
+ var used_paths: Array = []
26
+ for index in track_descriptions.size():
27
+ var description: Variant = track_descriptions[index]
28
+ var path := str(description.get("path", "")) if description is Dictionary else ""
29
+ var track: Variant = _plan_track(description)
30
+ if track is String:
31
+ rejected.append({"index": index, "path": path, "reason": track})
32
+ continue
33
+ if path in used_paths:
34
+ rejected.append({"index": index, "path": path, "reason": "this track is given twice; give each property one track with all its keys"})
35
+ continue
36
+ used_paths.append(path)
37
+ track["index"] = index
38
+ planned.append(track)
39
+ var length: float = requested_length if requested_length != null else _last_key_time(planned)
40
+ var within_length: Array = []
41
+ for track in planned:
42
+ var late_key := _first_key_after(track, length)
43
+ if late_key >= 0.0:
44
+ var reason := "the key at %s s is after the end of the animation at %s s; make the animation longer with length" % [_seconds(late_key), _seconds(length)]
45
+ rejected.append({"index": track["index"], "path": track["path"], "reason": reason})
46
+ continue
47
+ within_length.append(track)
48
+ rejected.sort_custom(func(left: Dictionary, right: Dictionary) -> bool: return left["index"] < right["index"])
49
+ var rejections := rejected.map(func(rejection: Dictionary) -> Dictionary: return {"path": rejection["path"], "reason": rejection["reason"]})
50
+ return {"tracks": within_length, "rejected": rejections, "length": length}
51
+
52
+
53
+ func build(planned_tracks: Array, length: float, loop_mode: int) -> Animation:
54
+ var animation := Animation.new()
55
+ animation.length = length
56
+ animation.loop_mode = loop_mode
57
+ for track in planned_tracks:
58
+ var index := animation.add_track(Animation.TYPE_VALUE)
59
+ animation.track_set_path(index, NodePath(track["path"]))
60
+ animation.track_set_interpolation_type(index, track["interpolation"])
61
+ animation.value_track_set_update_mode(index, track["update"])
62
+ for key in track["keys"]:
63
+ animation.track_insert_key(index, key["time"], key["value"])
64
+ return animation
65
+
66
+
67
+ func build_reset(previous: Animation, planned_tracks: Array) -> Animation:
68
+ var reset := previous.duplicate() as Animation if previous != null else Animation.new()
69
+ if previous == null:
70
+ reset.length = RESET_LENGTH
71
+ for track in planned_tracks:
72
+ var index := reset.add_track(Animation.TYPE_VALUE)
73
+ reset.track_set_path(index, NodePath(track["path"]))
74
+ reset.track_set_interpolation_type(index, track["interpolation"])
75
+ reset.value_track_set_update_mode(index, track["update"])
76
+ reset.track_insert_key(index, 0.0, current_value(track))
77
+ return reset
78
+
79
+
80
+ func current_value(track: Dictionary) -> Variant:
81
+ var path := str(track["path"])
82
+ var node_part := path.get_slice(":", 0)
83
+ return _root.get_node(NodePath(node_part)).get_indexed(NodePath(":" + path.substr(node_part.length() + 1)))
84
+
85
+
86
+ func describe(track: Dictionary) -> Dictionary:
87
+ var keys: Array = track["keys"]
88
+ return {
89
+ "path": track["path"],
90
+ "keys": keys.size(),
91
+ "interpolation": AnimationVocabulary.name_of(AnimationVocabulary.INTERPOLATIONS, track["interpolation"]),
92
+ "update": AnimationVocabulary.name_of(AnimationVocabulary.UPDATE_MODES, track["update"]),
93
+ "from": _codec.encode(keys.front()["value"]),
94
+ "to": _codec.encode(keys.back()["value"]),
95
+ }
96
+
97
+
98
+ func _plan_track(description: Variant) -> Variant:
99
+ if not description is Dictionary:
100
+ return "a track is an object such as {\"path\": \"Door:position\", \"keys\": [{\"time\": 0, \"value\": [0, 0, 0]}]}"
101
+ var path := str(description.get("path", ""))
102
+ var node_part := path.get_slice(":", 0)
103
+ var property_path := path.substr(node_part.length() + 1) if path.contains(":") else ""
104
+ if node_part.is_empty() or property_path.is_empty():
105
+ return "track paths are Node:property relative to the parent of the AnimationPlayer, such as \"Door:position\" or \".:visible\""
106
+ var target := _root.get_node_or_null(NodePath(node_part))
107
+ if target == null:
108
+ return "there is no node %s under %s. %s" % [node_part, _root.name, NodeLocator.not_found_hint(_root, node_part)]
109
+ var property: Variant = _property_of(target, property_path)
110
+ if property is String:
111
+ return property
112
+ var interpolation: Variant = _named_value(description, "interpolation", AnimationVocabulary.INTERPOLATIONS, "linear")
113
+ if interpolation is String:
114
+ return interpolation
115
+ var default_update := "discrete" if _is_stepped(property) else "continuous"
116
+ var update: Variant = _named_value(description, "update", AnimationVocabulary.UPDATE_MODES, default_update)
117
+ if update is String:
118
+ return update
119
+ var keys: Variant = _decode_keys(description.get("keys", []), property, target, property_path)
120
+ if keys is String:
121
+ return keys
122
+ return {"path": path, "interpolation": interpolation, "update": update, "keys": keys}
123
+
124
+
125
+ func _property_of(target: Node, property_path: String) -> Variant:
126
+ var property_name := property_path.get_slice(":", 0)
127
+ var properties := {}
128
+ for property in target.get_property_list():
129
+ properties[str(property["name"])] = property
130
+ if not properties.has(property_name):
131
+ var similar := SimilarNames.hint(property_name, properties.keys())
132
+ return "%s has no property \"%s\"%s" % [target.name, property_name, "" if similar.is_empty() else ". " + similar]
133
+ if property_path == property_name:
134
+ return properties[property_name]
135
+ var current: Variant = target.get_indexed(NodePath(":" + property_path))
136
+ if current == null:
137
+ return "%s has no part \"%s\"" % [target.name, property_path]
138
+ return {"name": property_path, "type": typeof(current), "hint": PROPERTY_HINT_NONE, "hint_string": "", "usage": PROPERTY_USAGE_DEFAULT}
139
+
140
+
141
+ func _decode_keys(key_descriptions: Variant, property: Dictionary, target: Node, property_path: String) -> Variant:
142
+ if not key_descriptions is Array or (key_descriptions as Array).is_empty():
143
+ return "a track needs keys, such as [{\"time\": 0, \"value\": [0, 0, 0]}, {\"time\": 1, \"value\": [0, 3, 0]}]"
144
+ var keys: Array = []
145
+ for key_description in key_descriptions:
146
+ if not key_description is Dictionary or not (key_description.get("time") is int or key_description.get("time") is float) or float(key_description["time"]) < 0.0:
147
+ return "each key is {\"time\": seconds from 0, \"value\": ...}"
148
+ if not key_description.has("value"):
149
+ return "the key at %s s has no value" % _seconds(key_description["time"])
150
+ var outcome := _codec.decode(key_description["value"], property, target)
151
+ if not outcome.is_success:
152
+ return "%s at %s s: %s" % [property_path, _seconds(key_description["time"]), outcome.error]
153
+ keys.append({"time": float(key_description["time"]), "value": outcome.value})
154
+ keys.sort_custom(func(left: Dictionary, right: Dictionary) -> bool: return left["time"] < right["time"])
155
+ return keys
156
+
157
+
158
+ static func _named_value(description: Dictionary, key: String, names: Dictionary, default_name: String) -> Variant:
159
+ var name: Variant = description.get(key, default_name)
160
+ var value: Variant = AnimationVocabulary.value_of(names, name)
161
+ if value == null:
162
+ return "unknown %s \"%s\"; use one of: %s" % [key, name, AnimationVocabulary.listed(names)]
163
+ return value
164
+
165
+
166
+ static func _is_stepped(property: Dictionary) -> bool:
167
+ if property["type"] in STEPPED_TYPES:
168
+ return true
169
+ return property["type"] == TYPE_INT and property.get("hint") == PROPERTY_HINT_ENUM
170
+
171
+
172
+ static func _last_key_time(tracks: Array) -> float:
173
+ var last := 0.0
174
+ for track in tracks:
175
+ last = maxf(last, (track["keys"] as Array).back()["time"])
176
+ return last if last > 0.0 else DEFAULT_LENGTH
177
+
178
+
179
+ static func _first_key_after(track: Dictionary, length: float) -> float:
180
+ for key in track["keys"]:
181
+ if key["time"] > length + 0.0001:
182
+ return key["time"]
183
+ return -1.0
184
+
185
+
186
+ static func _seconds(value: Variant) -> String:
187
+ var rounded := roundf(float(value) * DECIMAL_SCALE) / DECIMAL_SCALE
188
+ return str(roundi(rounded)) if is_equal_approx(rounded, roundf(rounded)) else str(rounded)
@@ -0,0 +1 @@
1
+ uid://x5xohexuoo0t
@@ -0,0 +1,50 @@
1
+ extends RefCounted
2
+
3
+ const INTERPOLATIONS := {
4
+ "nearest": Animation.INTERPOLATION_NEAREST,
5
+ "linear": Animation.INTERPOLATION_LINEAR,
6
+ "cubic": Animation.INTERPOLATION_CUBIC,
7
+ "linear_angle": Animation.INTERPOLATION_LINEAR_ANGLE,
8
+ "cubic_angle": Animation.INTERPOLATION_CUBIC_ANGLE,
9
+ }
10
+
11
+ const UPDATE_MODES := {
12
+ "continuous": Animation.UPDATE_CONTINUOUS,
13
+ "discrete": Animation.UPDATE_DISCRETE,
14
+ "capture": Animation.UPDATE_CAPTURE,
15
+ }
16
+
17
+ const LOOP_MODES := {
18
+ "none": Animation.LOOP_NONE,
19
+ "linear": Animation.LOOP_LINEAR,
20
+ "pingpong": Animation.LOOP_PINGPONG,
21
+ }
22
+
23
+ const TRACK_TYPES := {
24
+ "value": Animation.TYPE_VALUE,
25
+ "position_3d": Animation.TYPE_POSITION_3D,
26
+ "rotation_3d": Animation.TYPE_ROTATION_3D,
27
+ "scale_3d": Animation.TYPE_SCALE_3D,
28
+ "blend_shape": Animation.TYPE_BLEND_SHAPE,
29
+ "method": Animation.TYPE_METHOD,
30
+ "bezier": Animation.TYPE_BEZIER,
31
+ "audio": Animation.TYPE_AUDIO,
32
+ "animation": Animation.TYPE_ANIMATION,
33
+ }
34
+
35
+
36
+ static func name_of(names: Dictionary, value: int) -> String:
37
+ for name in names:
38
+ if names[name] == value:
39
+ return name
40
+ return str(value)
41
+
42
+
43
+ static func value_of(names: Dictionary, name: Variant) -> Variant:
44
+ if not name is String:
45
+ return null
46
+ return names.get((name as String).to_lower(), null)
47
+
48
+
49
+ static func listed(names: Dictionary) -> String:
50
+ return ", ".join(PackedStringArray(names.keys()))
@@ -0,0 +1 @@
1
+ uid://c0ybwpwuqs80q
@@ -0,0 +1,157 @@
1
+ extends RefCounted
2
+
3
+ const SimilarNames := preload("../util/similar_names.gd")
4
+
5
+ const START := "Start"
6
+ const END := "End"
7
+ const SWITCH_MODES := {
8
+ "immediate": AnimationNodeStateMachineTransition.SWITCH_MODE_IMMEDIATE,
9
+ "sync": AnimationNodeStateMachineTransition.SWITCH_MODE_SYNC,
10
+ "at_end": AnimationNodeStateMachineTransition.SWITCH_MODE_AT_END,
11
+ }
12
+ const ADVANCE_MODES := {
13
+ "disabled": AnimationNodeStateMachineTransition.ADVANCE_MODE_DISABLED,
14
+ "enabled": AnimationNodeStateMachineTransition.ADVANCE_MODE_ENABLED,
15
+ "auto": AnimationNodeStateMachineTransition.ADVANCE_MODE_AUTO,
16
+ }
17
+ const MAXIMUM_PRIORITY := 32
18
+ const STATES_PER_ROW := 4
19
+ const FIRST_STATE_POSITION := Vector2(200, 250)
20
+ const STATE_SPACING := Vector2(200, 150)
21
+
22
+ var states: Array = []
23
+ var transitions: Array = []
24
+ var rejected: Array = []
25
+ var warnings: Array = []
26
+ var _player: AnimationPlayer
27
+ var _condition_pattern := RegEx.create_from_string("^[A-Za-z_][A-Za-z0-9_]*$")
28
+
29
+
30
+ func _init(player: AnimationPlayer) -> void:
31
+ _player = player
32
+
33
+
34
+ func plan(state_descriptions: Array, transition_descriptions: Array) -> void:
35
+ for description in state_descriptions:
36
+ _plan_state(description)
37
+ for description in transition_descriptions:
38
+ _plan_transition(description)
39
+ if not states.is_empty() and not transitions.any(func(transition: Dictionary) -> bool: return transition["from"] == START):
40
+ warnings.append("no transition leaves Start, so the tree plays nothing until a script calls travel() or start() on parameters/playback; add one such as {\"from\": \"Start\", \"to\": \"%s\"}" % states[0]["name"])
41
+
42
+
43
+ func build() -> AnimationNodeStateMachine:
44
+ var machine := AnimationNodeStateMachine.new()
45
+ for index in states.size():
46
+ var node := AnimationNodeAnimation.new()
47
+ node.animation = states[index]["animation"]
48
+ var grid_cell := Vector2(index % STATES_PER_ROW, index / STATES_PER_ROW)
49
+ machine.add_node(states[index]["name"], node, FIRST_STATE_POSITION + grid_cell * STATE_SPACING)
50
+ for planned in transitions:
51
+ var transition := AnimationNodeStateMachineTransition.new()
52
+ transition.advance_mode = ADVANCE_MODES[planned["advance"]]
53
+ transition.switch_mode = SWITCH_MODES[planned["switch"]]
54
+ transition.xfade_time = planned["xfade"]
55
+ transition.advance_condition = planned.get("condition", "")
56
+ transition.advance_expression = planned.get("expression", "")
57
+ transition.priority = planned.get("priority", 1)
58
+ machine.add_transition(planned["from"], planned["to"], transition)
59
+ return machine
60
+
61
+
62
+ func _plan_state(description: Variant) -> void:
63
+ if not description is Dictionary or not description.get("name") is String or not description.get("animation") is String:
64
+ rejected.append({"item": str(description), "reason": "a state is {\"name\": \"walk\", \"animation\": \"walk\"}"})
65
+ return
66
+ var name: String = description["name"]
67
+ var animation: String = description["animation"]
68
+ var reason := ""
69
+ if name.is_empty() or name.contains("/"):
70
+ reason = "state names cannot be empty or contain /"
71
+ elif name == START or name == END:
72
+ reason = "%s and %s are the built-in entry and exit of every state machine; give the state another name" % [START, END]
73
+ elif states.any(func(state: Dictionary) -> bool: return state["name"] == name):
74
+ reason = "this state is given twice"
75
+ elif not _player.has_animation(animation):
76
+ var known := Array(_player.get_animation_list()).map(func(animation_name: StringName) -> String: return str(animation_name))
77
+ var similar := SimilarNames.hint(animation, known)
78
+ reason = "%s has no animation \"%s\"%s" % [_player.name, animation, "" if similar.is_empty() else ". " + similar]
79
+ if not reason.is_empty():
80
+ rejected.append({"item": name, "reason": reason})
81
+ return
82
+ states.append({"name": name, "animation": animation})
83
+
84
+
85
+ func _plan_transition(description: Variant) -> void:
86
+ if not description is Dictionary or not description.get("from") is String or not description.get("to") is String:
87
+ rejected.append({"item": str(description), "reason": "a transition is {\"from\": \"idle\", \"to\": \"walk\"}"})
88
+ return
89
+ var from: String = description["from"]
90
+ var to: String = description["to"]
91
+ var label := "%s -> %s" % [from, to]
92
+ var planned: Variant = _transition(description, from, to)
93
+ if planned is String:
94
+ rejected.append({"item": label, "reason": planned})
95
+ return
96
+ transitions.append(planned)
97
+
98
+
99
+ func _transition(description: Dictionary, from: String, to: String) -> Variant:
100
+ if from == END:
101
+ return "no transition can leave %s" % END
102
+ if to == START:
103
+ return "no transition can enter %s" % START
104
+ if from == to:
105
+ return "a state cannot have a transition to itself"
106
+ for state_name in [from, to]:
107
+ if not _is_known_state(state_name):
108
+ return "there is no state %s. %s" % [state_name, SimilarNames.hint(state_name, _state_names())]
109
+ if transitions.any(func(transition: Dictionary) -> bool: return transition["from"] == from and transition["to"] == to):
110
+ return "this transition is given twice"
111
+ var planned := {"from": from, "to": to}
112
+ var condition: Variant = description.get("condition")
113
+ if condition != null:
114
+ if not condition is String or not _condition_pattern.search(condition):
115
+ return "the condition \"%s\" is not a valid name; use letters, digits and _, such as moving" % condition
116
+ planned["condition"] = condition
117
+ var expression: Variant = description.get("expression")
118
+ if expression != null:
119
+ var parsed := Expression.new()
120
+ if not expression is String or parsed.parse(expression) != OK:
121
+ return "the expression \"%s\" does not parse: %s" % [expression, parsed.get_error_text()]
122
+ planned["expression"] = expression
123
+ var default_advance := "auto" if from == START or planned.has("condition") or planned.has("expression") else "enabled"
124
+ var advance: Variant = description.get("advance", default_advance)
125
+ if not advance in ADVANCE_MODES:
126
+ return "unknown advance \"%s\"; use one of: %s" % [advance, ", ".join(PackedStringArray(ADVANCE_MODES.keys()))]
127
+ var switch: Variant = description.get("switch", "immediate")
128
+ if not switch in SWITCH_MODES:
129
+ return "unknown switch \"%s\"; use one of: %s" % [switch, ", ".join(PackedStringArray(SWITCH_MODES.keys()))]
130
+ var xfade: Variant = description.get("xfade", 0.0)
131
+ if not (xfade is int or xfade is float) or float(xfade) < 0.0:
132
+ return "xfade is the cross-fade time in seconds, 0 or more"
133
+ planned["advance"] = advance
134
+ planned["switch"] = switch
135
+ planned["xfade"] = float(xfade)
136
+ var priority: Variant = description.get("priority")
137
+ if priority != null:
138
+ if not (priority is int or priority is float) or int(priority) < 0 or int(priority) > MAXIMUM_PRIORITY:
139
+ return "priority is a whole number from 0 to %d; lower numbers win" % MAXIMUM_PRIORITY
140
+ planned["priority"] = int(priority)
141
+ return _ordered(planned)
142
+
143
+
144
+ func _is_known_state(state_name: String) -> bool:
145
+ return state_name == START or state_name == END or states.any(func(state: Dictionary) -> bool: return state["name"] == state_name)
146
+
147
+
148
+ func _state_names() -> Array:
149
+ return [START, END] + states.map(func(state: Dictionary) -> String: return state["name"])
150
+
151
+
152
+ static func _ordered(planned: Dictionary) -> Dictionary:
153
+ var ordered := {"from": planned["from"], "to": planned["to"], "advance": planned["advance"], "switch": planned["switch"], "xfade": planned["xfade"]}
154
+ for optional in ["condition", "expression", "priority"]:
155
+ if planned.has(optional):
156
+ ordered[optional] = planned[optional]
157
+ return ordered
@@ -0,0 +1 @@
1
+ uid://bgf2wtiyqaon4