using System; using System.IO; using System.Linq; using Server; using Server.Items; using Server.Commands; namespace Server.Commands { public static class SignExporter { // The complete list of sign graphics pulled directly from AddSign.cs private static readonly int[] _SignIDs = { 2965, 2966, 2979, 2980, 2981, 2982, 2983, 2984, 2985, 2986, 2987, 2988, 2989, 2990, 2991, 2992, 2993, 2994, 2995, 2996, 2997, 2998, 2999, 3000, 3001, 3002, 3003, 3004, 3005, 3006, 3007, 3008, 3009, 3010, 3011, 3012, 3013, 3014, 3015, 3016, 3017, 3018, 3019, 3020, 3021, 3022, 3023, 3024, 3025, 3026, 3027, 3028, 3029, 3030, 3031, 3032, 3033, 3034, 3035, 3036, 3037, 3038, 3039, 3040, 3041, 3042, 3043, 3044, 3045, 3046, 3047, 3048, 3049, 3050, 3051, 3052, 3053, 3054, 3055, 3056, 3057, 3058, 3059, 3060, 3061, 3062, 3063, 3064, 3065, 3066, 3067, 3068, 3069, 3070, 3071, 3072, 3073, 3074, 3075, 3076, 3077, 3078, 3079, 3080, 3081, 3082, 3083, 3084, 3085, 3086, 7976, 7977 }; public static void Configure() { CommandSystem.Register("SignExport", AccessLevel.Developer, SignExport_OnCommand); } [Usage("SignExport")] [Description("Scans the world for signs and exports them to Data/signs_export.cfg")] public static void SignExport_OnCommand(CommandEventArgs c) { Export(c.Mobile); } public static void Export(Mobile from) { string filePath = Path.Combine(Core.BaseDirectory, "Data/signs_export.cfg"); int count = 0; from.SendMessage("Scanning world for signs, please wait..."); using (StreamWriter op = new StreamWriter(filePath)) { foreach (Item item in World.Items.Values) { if (item.Map == null || item.Map == Map.Internal) continue; int mapIndex = GetMapIndex(item.Map); if (mapIndex == -1) continue; string text = ""; // Target 1: Programmed Sign objects (like those generated by SignGen) if (item is Sign sign) { if (sign is LocalizedSign locSign) text = "#" + locSign.Number; else text = sign.Name; } // Target 2: Generic Statics manually placed by builders using the GM Tool else if (item is Static staticItem && _SignIDs.Contains(staticItem.ItemID)) { text = staticItem.Name; } else { continue; } // Skip signs without custom names. A blank name will crash the importer later. if (string.IsNullOrWhiteSpace(text) || text.Equals("Static", StringComparison.OrdinalIgnoreCase)) continue; text = text.Replace("\n", " ").Replace("\r", ""); op.WriteLine($"{mapIndex} {item.ItemID} {item.X} {item.Y} {item.Z} {text}"); count++; } } from.SendMessage($"Sign export complete. {count} signs saved to Data/signs_export.cfg"); } private static int GetMapIndex(Map map) { if (map == Map.Felucca) return 1; if (map == Map.Trammel) return 2; if (map == Map.Ilshenar) return 3; if (map == Map.Malas) return 4; if (map == Map.Tokuno) return 5; return -1; } } }