b0c83af092
Complete replacement of the tactical-shooter project with the netfox-cs-sample (MIT) — a CS 1.6 inspired multiplayer FPS built with Godot 4 and netfox. ## What's new - Full CS-style gameplay: teams (T/CT), rounds, economy, buy menu - 6 weapons: Knife, Glock, USP, AK-47, M4A1, AWP - Bomb plant/defuse with 2 bombsites - Flashbang & smoke grenades - Proper netfox rollback netcode at 64 tick - Network popup UI for host/join - HUD, crosshair, round timer, scoreboard - All netfox singletons registered as autoloads (works in exported builds) ## Architecture - Listen-server (host from client, no dedicated server binary) - Multiplayer-fps game lives at examples/multiplayer-fps/ - Netfox addons registered as autoloads for exported build compat - Godot 4.7 with Forward+ renderer ## Removed - Old headless-server architecture (client_main, server_main, player.gd, etc.) - Custom netfox bootstrap with ENet fallback - Old ChaffGames FPS template (2,420 lines, 844 KB) - SimulationServer GDExtension stub - Godot-jolt physics (netfox sample uses default Godot physics) - Duplicate weapon_data.gd, anti_cheat.gd, round_manager.gd, etc. - Server browser API Python venv (87 MB) - test_range map and modular assets ## Preserved - Git history - Server config at config/default_server_config.cfg - Windows export preset - Build directory (gitignored) Co-authored-by: naxIO <naxIO@users.noreply.github.com>
136 lines
4.7 KiB
GDScript
136 lines
4.7 KiB
GDScript
@tool
|
|
extends Node
|
|
class_name AssetTools
|
|
## Asset generation tools for MCP.
|
|
## Handles: generate_2d_asset, search_comfyui_nodes,
|
|
## inspect_runninghub_workflow, customize_and_run_workflow
|
|
|
|
var _editor_plugin: EditorPlugin = null
|
|
|
|
func set_editor_plugin(plugin: EditorPlugin) -> void:
|
|
_editor_plugin = plugin
|
|
|
|
func _refresh_filesystem() -> void:
|
|
if _editor_plugin:
|
|
_editor_plugin.get_editor_interface().get_resource_filesystem().scan()
|
|
|
|
# =============================================================================
|
|
# generate_2d_asset - Generate PNG from SVG code
|
|
# =============================================================================
|
|
func generate_2d_asset(args: Dictionary) -> Dictionary:
|
|
var svg_code: String = str(args.get(&"svg_code", ""))
|
|
var filename: String = str(args.get(&"filename", ""))
|
|
var save_path: String = str(args.get(&"save_path", "res://assets/generated/"))
|
|
|
|
if svg_code.strip_edges().is_empty():
|
|
return {&"ok": false, &"error": "Missing 'svg_code'"}
|
|
if filename.strip_edges().is_empty():
|
|
return {&"ok": false, &"error": "Missing 'filename'"}
|
|
|
|
# Ensure .png extension
|
|
if not filename.ends_with(".png"):
|
|
filename += ".png"
|
|
|
|
# Ensure save path
|
|
if not save_path.begins_with("res://"):
|
|
save_path = "res://" + save_path
|
|
if not save_path.ends_with("/"):
|
|
save_path += "/"
|
|
|
|
# Create directory if needed
|
|
if not DirAccess.dir_exists_absolute(save_path):
|
|
DirAccess.make_dir_recursive_absolute(save_path)
|
|
|
|
# Parse SVG dimensions from the svg_code
|
|
var width := 64
|
|
var height := 64
|
|
|
|
# Simple regex-free parsing for width/height
|
|
var w_start := svg_code.find("width=\"")
|
|
if w_start != -1:
|
|
var w_val := svg_code.substr(w_start + 7)
|
|
var w_end := w_val.find("\"")
|
|
if w_end != -1:
|
|
width = int(w_val.substr(0, w_end))
|
|
|
|
var h_start := svg_code.find("height=\"")
|
|
if h_start != -1:
|
|
var h_val := svg_code.substr(h_start + 8)
|
|
var h_end := h_val.find("\"")
|
|
if h_end != -1:
|
|
height = int(h_val.substr(0, h_end))
|
|
|
|
# Create Image from SVG
|
|
var image := Image.new()
|
|
|
|
# Save SVG to temp file, then load as image
|
|
var temp_svg_path := "user://temp_asset.svg"
|
|
var svg_file := FileAccess.open(temp_svg_path, FileAccess.WRITE)
|
|
if not svg_file:
|
|
return {&"ok": false, &"error": "Failed to create temp SVG file"}
|
|
svg_file.store_string(svg_code)
|
|
svg_file.close()
|
|
|
|
# Load SVG as image
|
|
var err := image.load(temp_svg_path)
|
|
if err != OK:
|
|
# Fallback: try loading SVG data directly
|
|
image = Image.create(width, height, false, Image.FORMAT_RGBA8)
|
|
image.fill(Color(1, 0, 1, 1)) # Magenta fallback = something went wrong
|
|
print("[MCP] Warning: Could not render SVG, created fallback image")
|
|
|
|
# Clean up temp file
|
|
DirAccess.remove_absolute(temp_svg_path)
|
|
|
|
# Save as PNG
|
|
var full_path := save_path + filename
|
|
var global_path := ProjectSettings.globalize_path(full_path)
|
|
err = image.save_png(global_path)
|
|
if err != OK:
|
|
return {&"ok": false, &"error": "Failed to save PNG: " + str(err)}
|
|
|
|
_refresh_filesystem()
|
|
|
|
return {
|
|
&"ok": true,
|
|
&"resource_path": full_path,
|
|
&"dimensions": {&"width": width, &"height": height},
|
|
&"message": "Generated %s (%dx%d)" % [full_path, width, height],
|
|
}
|
|
|
|
# =============================================================================
|
|
# search_comfyui_nodes - Stub (requires external database)
|
|
# =============================================================================
|
|
func search_comfyui_nodes(args: Dictionary) -> Dictionary:
|
|
# This tool requires the ComfyUI node database which was bundled with the old plugin
|
|
# For now, return a message indicating it needs setup
|
|
return {
|
|
&"ok": true,
|
|
&"results": [],
|
|
&"count": 0,
|
|
&"message": "ComfyUI node search requires the node database. This feature will be available in a future update.",
|
|
}
|
|
|
|
# =============================================================================
|
|
# inspect_runninghub_workflow - Stub (requires API key)
|
|
# =============================================================================
|
|
func inspect_runninghub_workflow(args: Dictionary) -> Dictionary:
|
|
var workflow_id: String = str(args.get(&"workflow_id", ""))
|
|
if workflow_id.strip_edges().is_empty():
|
|
return {&"ok": false, &"error": "Missing 'workflow_id'"}
|
|
|
|
return {
|
|
&"ok": true,
|
|
&"workflow_id": workflow_id,
|
|
&"message": "RunningHub workflow inspection requires API configuration. This feature will be available in a future update.",
|
|
}
|
|
|
|
# =============================================================================
|
|
# customize_and_run_workflow - Stub (requires API key)
|
|
# =============================================================================
|
|
func customize_and_run_workflow(args: Dictionary) -> Dictionary:
|
|
return {
|
|
&"ok": true,
|
|
&"message": "RunningHub workflow execution requires API configuration. This feature will be available in a future update.",
|
|
}
|