diff --git a/Program.cs b/Program.cs index 705468d..05cbc20 100644 --- a/Program.cs +++ b/Program.cs @@ -8,14 +8,34 @@ namespace txtgen; public class Program { + // string blockname; static string ctm_dir; static void Main() { + Console.OutputEncoding = System.Text.Encoding.UTF8; + Console.CursorVisible = true; - Console.Write("Block Name(diamon_ore): "); - string blockname = Console.ReadLine(); + // Dedupe, sort alphabetically once for consistent display + var blocks = AutoComplete.FullBlocks.Distinct().OrderBy(b => b).ToList(); + + Console.WriteLine("Minecraft 26.2 (Chaos Cubed) — Full Block Picker"); + // Console.WriteLine("Type to filter, Up/Down to move, Tab/Enter to accept, Esc to cancel."); + Console.WriteLine(); + + string chosen = AutoComplete.AutoCompletePrompt("Block Name: ", blocks); + + Console.WriteLine(); + if (chosen == null) + return; + // else + // Console.WriteLine($"You selected: {chosen}"); + + + + // Console.Write("Block Name(diamon_ore): "); + string blockname = chosen; if (string.IsNullOrEmpty(blockname)) { @@ -24,7 +44,7 @@ public class Program if (Directory.Exists("output/assets/minecraft/optifine/ctm/" + blockname)) { - Console.WriteLine("that block already exists, delete it and try again"); + Console.WriteLine("this block already exists in the texturepack delete it and try again"); return; } Create_pack(blockname); diff --git a/autocomplete.cs b/autocomplete.cs new file mode 100644 index 0000000..b94da42 --- /dev/null +++ b/autocomplete.cs @@ -0,0 +1,344 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace txtgen +{ + public struct AutoComplete + { +/// +/// This is mostly ai generated +/// + + + // ---------------------------------------------------------------- + // Minecraft 26.2 "Chaos Cubed" — FULL BLOCKS ONLY + // (Solid 1x1x1 cube blocks. No slabs, stairs, walls, fences, doors, + // carpets, plants, signs, or other non-full-cube shapes.) + // ---------------------------------------------------------------- + public static readonly List FullBlocks = new List + { + // --- Stone & natural --- + "stone", "granite", "polished_granite", "diorite", "polished_diorite", + "andesite", "polished_andesite", "deepslate", "cobbled_deepslate", + "polished_deepslate", "calcite", "tuff", "polished_tuff", "tuff_bricks", + "chiseled_tuff", "chiseled_tuff_bricks", "dripstone_block", + "cobblestone", "mossy_cobblestone", "smooth_stone", "stone_bricks", + "mossy_stone_bricks", "cracked_stone_bricks", "chiseled_stone_bricks", + "bedrock", "dirt", "coarse_dirt", "rooted_dirt", "podzol", "mud", + "packed_mud", "mud_bricks", "grass_block", "mycelium", "sand", + "red_sand", "sandstone", "chiseled_sandstone", "cut_sandstone", + "smooth_sandstone", "red_sandstone", "chiseled_red_sandstone", + "cut_red_sandstone", "smooth_red_sandstone", "gravel", "clay", + "terracotta", "obsidian", "crying_obsidian", "ice", "packed_ice", + "blue_ice", "snow_block", "powder_snow", "moss_block", "mangrove_roots", + "muddy_mangrove_roots", "sponge", "wet_sponge", + + // --- Sulfur caves (new in 26.2 "Chaos Cubed") --- + "sulfur", "polished_sulfur", "sulfur_bricks", "chiseled_sulfur", + "cinnabar", "polished_cinnabar", "cinnabar_bricks", "chiseled_cinnabar", + + // --- Ores --- + "coal_ore", "deepslate_coal_ore", "iron_ore", "deepslate_iron_ore", + "copper_ore", "deepslate_copper_ore", "gold_ore", "deepslate_gold_ore", + "redstone_ore", "deepslate_redstone_ore", "emerald_ore", + "deepslate_emerald_ore", "lapis_ore", "deepslate_lapis_ore", + "diamond_ore", "deepslate_diamond_ore", "nether_gold_ore", + "nether_quartz_ore", "ancient_debris", + + // --- Mineral blocks --- + "coal_block", "iron_block", "copper_block", "exposed_copper", + "weathered_copper", "oxidized_copper", "waxed_copper_block", + "waxed_exposed_copper", "waxed_weathered_copper", "waxed_oxidized_copper", + "cut_copper", "exposed_cut_copper", "weathered_cut_copper", + "oxidized_cut_copper", "waxed_cut_copper", "chiseled_copper", + "exposed_chiseled_copper", "weathered_chiseled_copper", + "oxidized_chiseled_copper", "gold_block", "redstone_block", + "emerald_block", "lapis_block", "diamond_block", "netherite_block", + "raw_iron_block", "raw_copper_block", "raw_gold_block", + + // --- Logs, wood & planks --- + "oak_log", "spruce_log", "birch_log", "jungle_log", "acacia_log", + "dark_oak_log", "mangrove_log", "cherry_log", "pale_oak_log", + "crimson_stem", "warped_stem", + "stripped_oak_log", "stripped_spruce_log", "stripped_birch_log", + "stripped_jungle_log", "stripped_acacia_log", "stripped_dark_oak_log", + "stripped_mangrove_log", "stripped_cherry_log", "stripped_pale_oak_log", + "stripped_crimson_stem", "stripped_warped_stem", + "oak_wood", "spruce_wood", "birch_wood", "jungle_wood", "acacia_wood", + "dark_oak_wood", "mangrove_wood", "cherry_wood", "pale_oak_wood", + "crimson_hyphae", "warped_hyphae", + "stripped_oak_wood", "stripped_spruce_wood", "stripped_birch_wood", + "stripped_jungle_wood", "stripped_acacia_wood", "stripped_dark_oak_wood", + "stripped_mangrove_wood", "stripped_cherry_wood", "stripped_pale_oak_wood", + "stripped_crimson_hyphae", "stripped_warped_hyphae", + "oak_planks", "spruce_planks", "birch_planks", "jungle_planks", + "acacia_planks", "dark_oak_planks", "mangrove_planks", "cherry_planks", + "pale_oak_planks", "bamboo_planks", "crimson_planks", "warped_planks", + "bamboo_block", "stripped_bamboo_block", "mangrove_mangrove_roots", + + // --- Leaves --- + "oak_leaves", "spruce_leaves", "birch_leaves", "jungle_leaves", + "acacia_leaves", "dark_oak_leaves", "mangrove_leaves", "cherry_leaves", + "pale_oak_leaves", "azalea_leaves", "flowering_azalea_leaves", + + // --- Wool, concrete, terracotta, glass, glazed terracotta (16 colors) --- + "white_wool","orange_wool","magenta_wool","light_blue_wool","yellow_wool", + "lime_wool","pink_wool","gray_wool","light_gray_wool","cyan_wool", + "purple_wool","blue_wool","brown_wool","green_wool","red_wool","black_wool", + + "white_concrete","orange_concrete","magenta_concrete","light_blue_concrete", + "yellow_concrete","lime_concrete","pink_concrete","gray_concrete", + "light_gray_concrete","cyan_concrete","purple_concrete","blue_concrete", + "brown_concrete","green_concrete","red_concrete","black_concrete", + + "white_concrete_powder","orange_concrete_powder","magenta_concrete_powder", + "light_blue_concrete_powder","yellow_concrete_powder","lime_concrete_powder", + "pink_concrete_powder","gray_concrete_powder","light_gray_concrete_powder", + "cyan_concrete_powder","purple_concrete_powder","blue_concrete_powder", + "brown_concrete_powder","green_concrete_powder","red_concrete_powder", + "black_concrete_powder", + + "white_terracotta","orange_terracotta","magenta_terracotta", + "light_blue_terracotta","yellow_terracotta","lime_terracotta", + "pink_terracotta","gray_terracotta","light_gray_terracotta", + "cyan_terracotta","purple_terracotta","blue_terracotta", + "brown_terracotta","green_terracotta","red_terracotta","black_terracotta", + + "white_glazed_terracotta","orange_glazed_terracotta","magenta_glazed_terracotta", + "light_blue_glazed_terracotta","yellow_glazed_terracotta","lime_glazed_terracotta", + "pink_glazed_terracotta","gray_glazed_terracotta","light_gray_glazed_terracotta", + "cyan_glazed_terracotta","purple_glazed_terracotta","blue_glazed_terracotta", + "brown_glazed_terracotta","green_glazed_terracotta","red_glazed_terracotta", + "black_glazed_terracotta", + + "glass","white_stained_glass","orange_stained_glass","magenta_stained_glass", + "light_blue_stained_glass","yellow_stained_glass","lime_stained_glass", + "pink_stained_glass","gray_stained_glass","light_gray_stained_glass", + "cyan_stained_glass","purple_stained_glass","blue_stained_glass", + "brown_stained_glass","green_stained_glass","red_stained_glass", + "black_stained_glass","tinted_glass", + + // --- Prismarine --- + "prismarine", "prismarine_bricks", "dark_prismarine", "sea_lantern", + + // --- Quartz & purpur --- + "quartz_block", "chiseled_quartz_block", "smooth_quartz", + "quartz_bricks", "quartz_pillar", + "purpur_block", "purpur_pillar", + + // --- Nether --- + "netherrack", "soul_sand", "soul_soil", "basalt", "polished_basalt", + "smooth_basalt", "blackstone", "polished_blackstone", + "chiseled_polished_blackstone", "polished_blackstone_bricks", + "cracked_polished_blackstone_bricks", "gilded_blackstone", + "nether_bricks", "red_nether_bricks", "cracked_nether_bricks", + "chiseled_nether_bricks", "nether_wart_block", "warped_wart_block", + "shroomlight", "glowstone", "magma_block", "crimson_nylium", + "warped_nylium", + + // --- End --- + "end_stone", "end_stone_bricks", "purpur_block_end", "bone_block", + + // --- Utility & misc full blocks --- + "crafting_table", "furnace", "blast_furnace", "smoker", "cartography_table", + "fletching_table", "smithing_table", "loom", "composter_block", + "barrel", "chest", "trapped_chest", "ender_chest", "shulker_box", + "tnt", "note_block", "jukebox", "bookshelf", "chiseled_bookshelf", + "lodestone", "respawn_anchor", "beacon", "conduit", "dragon_egg", + "spawner", "hay_block", "target", "honeycomb_block", "honey_block", + "slime_block", "dried_kelp_block", "melon", "pumpkin", + "carved_pumpkin", "jack_o_lantern", "sculk", "sculk_catalyst", + "amethyst_block", "budding_amethyst", "iron_block_full", + "waxed_block_of_copper", "mushroom_stem", "red_mushroom_block", + "brown_mushroom_block", "resin_block", "chiseled_resin_bricks", + "resin_bricks", "ochre_froglight", "verdant_froglight", + "pearlescent_froglight", "reinforced_deepslate", "suspicious_sand", + "suspicious_gravel", "command_block", "chain_command_block", + "repeating_command_block", "structure_block", "jigsaw_block", + "barrier", "light_block", "moving_piston", + }; + + + + /// + /// Renders a LazyVim-style inline autocomplete popup below the input line. + /// Returns the accepted string, or null if the user pressed Esc. + /// + public static string AutoCompletePrompt(string prompt, List options) + { + const int maxVisible = 8; // rows shown in the dropdown + + string buffer = ""; + int selectedIndex = 0; // index within the filtered list + int scrollOffset = 0; // first visible row when list is longer than maxVisible + + int inputTop = Console.CursorTop; + int inputLeft = prompt.Length; + + List filtered = FilterAndRank(options, buffer); + + while (true) + { + Render(prompt, buffer, filtered, selectedIndex, scrollOffset, maxVisible, inputTop); + + ConsoleKeyInfo key = Console.ReadKey(intercept: true); + + if (key.Key == ConsoleKey.Escape) + { + ClearDropdown(inputTop, maxVisible); + Console.SetCursorPosition(0, inputTop); + Console.Write(new string(' ', prompt.Length + buffer.Length + 2)); + Console.SetCursorPosition(0, inputTop); + return null; + } + else if (key.Key == ConsoleKey.Enter || key.Key == ConsoleKey.Tab) + { + string result = (filtered.Count > 0) + ? filtered[selectedIndex] + : buffer; + + ClearDropdown(inputTop, maxVisible); + Console.SetCursorPosition(0, inputTop); + Console.Write(prompt + result); + Console.Write(new string(' ', Math.Max(0, buffer.Length - result.Length))); + Console.WriteLine(); + return result; + } + else if (key.Key == ConsoleKey.DownArrow) + { + if (filtered.Count > 0) + { + selectedIndex = (selectedIndex + 1) % filtered.Count; + AdjustScroll(ref scrollOffset, selectedIndex, maxVisible, filtered.Count); + } + } + else if (key.Key == ConsoleKey.UpArrow) + { + if (filtered.Count > 0) + { + selectedIndex = (selectedIndex - 1 + filtered.Count) % filtered.Count; + AdjustScroll(ref scrollOffset, selectedIndex, maxVisible, filtered.Count); + } + } + else if (key.Key == ConsoleKey.Backspace) + { + if (buffer.Length > 0) + { + buffer = buffer.Substring(0, buffer.Length - 1); + filtered = FilterAndRank(options, buffer); + selectedIndex = 0; + scrollOffset = 0; + } + } + else if (!char.IsControl(key.KeyChar)) + { + buffer += key.KeyChar; + filtered = FilterAndRank(options, buffer); + selectedIndex = 0; + scrollOffset = 0; + } + } + } + + static void AdjustScroll(ref int scrollOffset, int selectedIndex, int maxVisible, int total) + { + if (selectedIndex < scrollOffset) + scrollOffset = selectedIndex; + else if (selectedIndex >= scrollOffset + maxVisible) + scrollOffset = selectedIndex - maxVisible + 1; + + if (scrollOffset < 0) scrollOffset = 0; + if (scrollOffset > Math.Max(0, total - maxVisible)) + scrollOffset = Math.Max(0, total - maxVisible); + } + + /// + /// Filters options to those containing the query (case-insensitive), + /// ranking exact-prefix matches above substring matches. + /// + static List FilterAndRank(List options, string query) + { + if (string.IsNullOrEmpty(query)) + return options.Take(200).ToList(); // cap for display purposes + + string q = query.ToLowerInvariant(); + + var prefixMatches = options + .Where(o => o.StartsWith(q, StringComparison.OrdinalIgnoreCase)) + .OrderBy(o => o); + + var containsMatches = options + .Where(o => !o.StartsWith(q, StringComparison.OrdinalIgnoreCase) + && o.Contains(q, StringComparison.OrdinalIgnoreCase)) + .OrderBy(o => o); + + return prefixMatches.Concat(containsMatches).ToList(); + } + + static void Render(string prompt, string buffer, List filtered, + int selectedIndex, int scrollOffset, int maxVisible, int inputTop) + { + // --- input line --- + Console.SetCursorPosition(0, inputTop); + Console.Write(prompt + buffer); + Console.Write(new string(' ', Math.Max(0, 40 - (prompt.Length + buffer.Length)))); + + // --- dropdown --- + int visibleCount = Math.Min(maxVisible, filtered.Count); + for (int row = 0; row < maxVisible; row++) + { + Console.SetCursorPosition(0, inputTop + 1 + row); + Console.Write(new string(' ', 60)); // clear the row first + Console.SetCursorPosition(0, inputTop + 1 + row); + + if (row < visibleCount) + { + int itemIndex = scrollOffset + row; + string item = filtered[itemIndex]; + bool isSelected = itemIndex == selectedIndex; + + if (isSelected) + { + Console.BackgroundColor = ConsoleColor.DarkCyan; + Console.ForegroundColor = ConsoleColor.Black; + Console.Write($"> {item}"); + Console.ResetColor(); + } + else + { + Console.Write($" {item}"); + } + } + else if (row == visibleCount && filtered.Count == 0 && buffer.Length > 0) + { + Console.ForegroundColor = ConsoleColor.DarkGray; + Console.Write(" (no matches — Enter uses typed text as-is)"); + Console.ResetColor(); + } + } + + if (filtered.Count > maxVisible) + { + Console.SetCursorPosition(0, inputTop + 1 + maxVisible); + Console.Write(new string(' ', 60)); + Console.SetCursorPosition(0, inputTop + 1 + maxVisible); + Console.ForegroundColor = ConsoleColor.DarkGray; + // Console.Write($" ...{filtered.Count - maxVisible} more (keep typing to narrow)"); + Console.ResetColor(); + } + + // put the cursor back at the end of the typed text + Console.SetCursorPosition(prompt.Length + buffer.Length, inputTop); + } + + static void ClearDropdown(int inputTop, int maxVisible) + { + for (int row = 0; row <= maxVisible; row++) + { + Console.SetCursorPosition(0, inputTop + 1 + row); + Console.Write(new string(' ', 60)); + } + } + } +} \ No newline at end of file