├── .gitignore ├── LICENSE ├── README.md └── addons └── csharpConsole ├── AddCommandAttribute.cs ├── AddCommandDescriptionAttribute.cs ├── CommandConsole.cs ├── Console_Plugin.cs └── plugin.cfg /.gitignore: -------------------------------------------------------------------------------- 1 | # Godot 4+ specific ignores 2 | .godot/ 3 | 4 | # Godot-specific ignores 5 | .import/ 6 | export.cfg 7 | export_presets.cfg 8 | 9 | # Imported translations (automatically generated from CSV files) 10 | *.translation 11 | 12 | # Mono-specific ignores 13 | .mono/ 14 | data_*/ 15 | mono_crash.*.json 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 MolikoDeveloper 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. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | > [!WARNING] 2 | > this project is out of date. 3 | 4 | im currencly working but you can take this project as a base. 5 | 6 | # Csharp-Console-Godot 7 | original project: 8 | [Godot Console](https://github.com/jitspoe/godot-console) 9 | 10 | example: 11 | ```c# 12 | using Godot; 13 | public partial class Example : Node 14 | { 15 | public override void _Ready() 16 | { 17 | CommandConsole.AddCommand("print", Print); 18 | CommandConsole.AddCommandDescription("print", "Prints the given text in the console."); 19 | CommandConsole.AddParameterDescription(CommandName: "print", param:"text", description:"The text to print."); 20 | 21 | CommandConsole.AddCommand("heloworld", HelloWorld); 22 | CommandConsole.AddCommandDescription("heloworld", "Prints 'Hola Mundo!' in the console."); 23 | } 24 | 25 | void Print(string text) 26 | { 27 | GD.Print(text); 28 | } 29 | 30 | void HelloWorld() 31 | { 32 | GD.PrintErr("Hola Mundo!"); 33 | } 34 | 35 | //also you can add the Attribute 36 | [AddCommand("testing"), AddCommandDescription("[color=red]Prints on GD Console[/color]")] 37 | public void testing(string text) 38 | { 39 | GD.Print(text); 40 | } 41 | } 42 | 43 | ``` 44 | 45 | in game run with: 46 | > `test` "testing the example" => set `testing the example` as param value 47 | 48 | > `test` testing the example => set `testing` `the` `example` as params values 49 | 50 | > `test` "testing the" example => set `testing the` `example` as params 51 | 52 | ![image](https://github.com/MolikoDeveloper/Csharp-Console-Godot/assets/58595683/d17ee243-80b2-47dc-9acf-477ce4562e2c) 53 | 54 | command_list command: 55 | 56 | ![image](https://github.com/MolikoDeveloper/Csharp-Console-Godot/assets/58595683/5810666b-d237-406f-96fd-f655bd0f2feb) 57 | 58 | 59 | 60 | print example: 61 | 62 | ![image](https://github.com/MolikoDeveloper/Csharp-Console-Godot/assets/58595683/4ebf6452-bbb5-4651-a0b0-a48eeb8148ae) 63 | 64 | 65 | all with a maximum of 16 params. 66 | -------------------------------------------------------------------------------- /addons/csharpConsole/AddCommandAttribute.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Diagnostics; 5 | using System.IO; 6 | using System.Linq; 7 | using System.Reflection; 8 | 9 | [AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)] 10 | public class AddCommandAttribute: Attribute 11 | { 12 | public string CommandName { get; private set; } 13 | 14 | public AddCommandAttribute(string commandName) 15 | { 16 | CommandName = commandName; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /addons/csharpConsole/AddCommandDescriptionAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Godot; 3 | 4 | [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)] 5 | public class AddCommandDescriptionAttribute : Attribute 6 | { 7 | public string Description { get; private set; } 8 | 9 | public AddCommandDescriptionAttribute(string description) 10 | { 11 | this.Description = description; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /addons/csharpConsole/CommandConsole.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Reflection; 6 | using System.Text.RegularExpressions; 7 | 8 | public partial class CommandConsole : Node 9 | { 10 | public event Action console_opened; 11 | public event Action console_closed; 12 | public event Action console_unknown_command; 13 | 14 | static CommandConsole instance; 15 | 16 | class Command 17 | { 18 | public bool base_command = false; 19 | public Callable function; 20 | public int param_count; 21 | public Dictionary Params = new Dictionary(); 22 | public string Description = "Description Not Definned"; 23 | 24 | public Command(Callable in_function, int in_param_count) 25 | { 26 | this.function = in_function; 27 | this.param_count = in_param_count; 28 | } 29 | } 30 | 31 | Control control; 32 | RichTextLabel rich_label; 33 | RichTextLabel syntaxLabel; 34 | LineEdit line_edit; 35 | 36 | Dictionary Commands = new Dictionary(); 37 | List console_history = new List(); 38 | int console_history_index = 0; 39 | 40 | 41 | List Suggestions = new List(); 42 | int CurrentSuggestion = 0; 43 | bool Suggesting = false; 44 | 45 | // Called when the node enters the scene tree for the first time. 46 | public override void _Ready() 47 | { 48 | #region Create 49 | 50 | instance = this; 51 | this.control = new Control(); 52 | this.rich_label = new RichTextLabel(); 53 | this.syntaxLabel = new RichTextLabel(); 54 | this.line_edit = new LineEdit(); 55 | 56 | 57 | StyleBoxFlat style = new StyleBoxFlat(); 58 | StyleBoxFlat style2 = new StyleBoxFlat(); 59 | style.BgColor = new Color(0, 0, 1, 0.5f); 60 | style2.BgColor = new Color(0, 0, 0, 0.5f); 61 | 62 | CanvasLayer canvas = new CanvasLayer(); 63 | canvas.Layer = 3; 64 | AddChild(canvas); 65 | control.AnchorBottom = 1; 66 | control.AnchorRight = 1; 67 | canvas.AddChild(control); 68 | 69 | rich_label.ScrollFollowing = true; 70 | rich_label.AnchorRight = 1.0f; 71 | rich_label.AnchorBottom = 0.5f; 72 | rich_label.AddThemeStyleboxOverride("normal", style); 73 | control.AddChild(rich_label); 74 | 75 | rich_label.Text = "Development Console. \n"; 76 | line_edit.PlaceholderText = "Enter \"help\" for instructions"; 77 | line_edit.AnchorTop = 0.54f; 78 | line_edit.AnchorRight = 1; 79 | line_edit.AnchorBottom = 0.59f; 80 | 81 | syntaxLabel.AnchorTop = 0.5f; 82 | syntaxLabel.AnchorRight = 1.0f; 83 | syntaxLabel.AnchorBottom = 0.54f; 84 | 85 | syntaxLabel.AddThemeStyleboxOverride("normal",style2); 86 | control.AddChild(syntaxLabel); 87 | 88 | 89 | control.AddChild(line_edit); 90 | line_edit.TextSubmitted += OnTextSubmited; 91 | line_edit.TextChanged += OnTextChanged; 92 | control.Visible = false; 93 | this.ProcessMode = ProcessModeEnum.Always; 94 | #endregion 95 | 96 | #region add commands 97 | AddCommand("quit", Quit); 98 | Commands["quit"].base_command = true; 99 | AddCommandDescription("quit", "Quits the game."); 100 | AddCommand("exit", Quit); 101 | Commands["exit"].base_command = true; 102 | AddCommandDescription("exit", "Quits the game."); 103 | AddCommand("help", Help); 104 | Commands["help"].base_command = true; 105 | AddCommandDescription("help", "Shows a list of all the currently registered commands."); 106 | AddCommand("clear", clear); 107 | Commands["clear"].base_command = true; 108 | AddCommandDescription("clear", "Clears the current registry view."); 109 | AddCommand("delete_history", DeleteHistory); 110 | Commands["delete_history"].base_command = true; 111 | AddCommandDescription("delete_history", "Deletes the commands history."); 112 | 113 | AddCommand("command_list", ShowExternalCommands); 114 | Commands["command_list"].base_command = true; 115 | AddCommandDescription("command_list", "Shows a list of all the currently registered commands."); 116 | 117 | GetCommandsWithAttribute(); 118 | #endregion 119 | } 120 | #region base Command Console 121 | private void OnTextChanged(string newText) 122 | { 123 | ShowDescription(newText); 124 | ResetAutoComplete(); 125 | 126 | } 127 | 128 | void OnTextSubmited(string text) 129 | { 130 | ScrollToBottom(); 131 | ResetAutoComplete(); 132 | line_edit.Clear(); 133 | syntaxLabel.Clear(); 134 | AddInputHistory(text); 135 | PrintLine(text); 136 | 137 | //string[] splitText = text.Split(' '); 138 | string[] splitText = SplitConsideringQuotes(text); 139 | 140 | if (splitText.Length > 0 ) 141 | { 142 | string commandString = splitText[0].ToLower(); 143 | 144 | if (Commands.ContainsKey(commandString)) 145 | { 146 | Command commandEntry = Commands[commandString]; 147 | 148 | switch (commandEntry.param_count) 149 | { 150 | case 0: 151 | commandEntry.function.Call(); 152 | break; 153 | case > 0: 154 | List InGameparams_ = new List(); 155 | 156 | for (int i = 1; i < splitText.Length; i++) 157 | { 158 | InGameparams_.Add(splitText[i]); 159 | } 160 | 161 | //verify the ammount of params 162 | if(InGameparams_.Count < commandEntry.Params.Count) 163 | { 164 | PrintLine("Not enough parameters."); 165 | break; 166 | } 167 | if(InGameparams_.Count > commandEntry.Params.Count) 168 | { 169 | PrintLine("too much parameters."); 170 | break; 171 | } 172 | 173 | commandEntry.function.Call(InGameparams_.ToArray()); 174 | break; 175 | } 176 | } 177 | else 178 | { 179 | console_unknown_command?.Invoke(); 180 | PrintLine("Command not found."); 181 | 182 | } 183 | } 184 | } 185 | 186 | string[] SplitConsideringQuotes(string input) 187 | { 188 | var matches = Regex.Matches(input, @"""[^""]+""|\S+"); 189 | var parts = new string[matches.Count]; 190 | 191 | for (int i = 0; i < matches.Count; i++) 192 | { 193 | parts[i] = matches[i].Value.Trim('"'); 194 | } 195 | 196 | return parts; 197 | } 198 | 199 | public override void _Input(InputEvent @event) 200 | { 201 | if (@event is InputEventKey eventKey) 202 | { 203 | // ~ key 204 | if (eventKey.Keycode == Key.Quoteleft) 205 | { 206 | if (eventKey.Pressed) 207 | { 208 | ToggleConsole(); 209 | } 210 | GetTree().Root.SetInputAsHandled(); 211 | } 212 | //toggle console size 213 | else if (eventKey.Keycode == Key.Quoteleft && eventKey.IsCommandOrControlPressed()) 214 | { 215 | if (eventKey.Pressed) 216 | { 217 | if (control.Visible) 218 | ToggleSize(); 219 | else 220 | { 221 | ToggleConsole(); 222 | ToggleSize(); 223 | } 224 | GetTree().Root.SetInputAsHandled(); 225 | } 226 | } 227 | //disable control on ESC 228 | else if (eventKey.Keycode == Key.Escape && control.Visible) 229 | { 230 | if (eventKey.Pressed) 231 | ToggleConsole(); 232 | GetTree().Root.SetInputAsHandled(); 233 | } 234 | 235 | if (control.Visible && eventKey.Pressed) 236 | { 237 | if (eventKey.GetKeycodeWithModifiers() == Key.Up) 238 | { 239 | GetTree().Root.SetInputAsHandled(); 240 | if (console_history_index > 0) 241 | { 242 | console_history_index--; 243 | if (console_history_index >= 0) 244 | { 245 | line_edit.Text = console_history[console_history_index]; 246 | line_edit.CaretColumn = line_edit.Text.Length; 247 | ResetAutoComplete(); 248 | } 249 | } 250 | } 251 | 252 | if (eventKey.GetKeycodeWithModifiers() == Key.Down) 253 | { 254 | GetTree().Root.SetInputAsHandled(); 255 | if(console_history_index < console_history.Count) 256 | { 257 | console_history_index++; 258 | if(console_history_index < console_history.Count) 259 | { 260 | line_edit.Text = console_history[console_history_index]; 261 | line_edit.CaretColumn = line_edit.Text.Length; 262 | ResetAutoComplete(); 263 | } 264 | else 265 | { 266 | line_edit.Clear(); 267 | ResetAutoComplete(); 268 | } 269 | } 270 | } 271 | 272 | if (eventKey.Keycode == Key.Pageup) 273 | { 274 | VScrollBar scroll = rich_label.GetVScrollBar(); 275 | scroll.Value -= scroll.Page - scroll.Page * 0.1; 276 | GetTree().Root.SetInputAsHandled(); 277 | } 278 | if (eventKey.Keycode == Key.Pagedown) 279 | { 280 | VScrollBar scroll = rich_label.GetVScrollBar(); 281 | scroll.Value += scroll.Page - scroll.Page * 0.1; 282 | GetTree().Root.SetInputAsHandled(); 283 | } 284 | if (eventKey.Keycode == Key.Tab) 285 | { 286 | AutoComplete(); 287 | GetTree().Root.SetInputAsHandled(); 288 | } 289 | } 290 | } 291 | } 292 | 293 | void ToggleConsole() 294 | { 295 | control.Visible = !control.Visible; 296 | if (control.Visible) 297 | { 298 | //GetTree().Paused = true; 299 | line_edit.GrabFocus(); 300 | console_opened?.Invoke(); 301 | } 302 | else 303 | { 304 | control.AnchorBottom = 1f; 305 | //GetTree().Paused = false; 306 | ScrollToBottom(); 307 | ResetAutoComplete(); 308 | console_closed?.Invoke(); 309 | } 310 | } 311 | void ToggleSize() 312 | { 313 | if (control.AnchorBottom == 1.0f) 314 | { 315 | control.AnchorBottom = 1.9f; 316 | } 317 | else 318 | { 319 | control.AnchorBottom = 1.0f; 320 | } 321 | } 322 | void AutoComplete() 323 | { 324 | if (Suggesting) 325 | { 326 | for (int i = 0; i < Suggestions.Count; i++) 327 | { 328 | if (CurrentSuggestion == i) 329 | { 330 | line_edit.Text = Suggestions[i]; 331 | line_edit.CaretColumn = line_edit.Text.Length; 332 | if (CurrentSuggestion == Suggestions.Count -1) 333 | { 334 | CurrentSuggestion = 0; 335 | } 336 | else 337 | { 338 | CurrentSuggestion++; 339 | } 340 | return; 341 | } 342 | } 343 | } 344 | else 345 | { 346 | Suggesting = true; 347 | List commands = new List(); 348 | foreach (var command in Commands) 349 | { 350 | commands.Add(command.Key); 351 | } 352 | commands.Sort(); 353 | commands.Reverse(); 354 | 355 | int PrevIndex = 0; 356 | foreach (var command in commands) 357 | { 358 | if (command.Contains(line_edit.Text)) 359 | { 360 | int index = command.Find(line_edit.Text); 361 | if (index <= PrevIndex) 362 | { 363 | Suggestions.Insert(0, command); 364 | } 365 | else 366 | { 367 | Suggestions.Add(command); 368 | } 369 | PrevIndex = index; 370 | } 371 | } 372 | AutoComplete(); 373 | 374 | } 375 | } 376 | 377 | void ScrollToBottom() 378 | { 379 | ScrollBar scroll = rich_label.GetVScrollBar(); 380 | scroll.Value = scroll.MaxValue - scroll.Page; 381 | } 382 | void ResetAutoComplete() 383 | { 384 | this.Suggestions.Clear(); 385 | CurrentSuggestion = 0; 386 | Suggesting = false; 387 | } 388 | 389 | void ShowDescription(string input) 390 | { 391 | syntaxLabel.Clear(); 392 | var matches = Regex.Matches(input, @"""[^""]+""|\S+"); 393 | string _function = ""; 394 | string _params = ""; 395 | 396 | foreach (var match in matches) 397 | { 398 | foreach (var command in Commands.Keys) 399 | { 400 | if(command == match.ToString()) 401 | { 402 | _function = command; 403 | 404 | foreach(string _param in Commands[command].Params.Keys) 405 | { 406 | _params += " [color=yellow]" + _param + "[/color]"; 407 | 408 | } 409 | } 410 | } 411 | } 412 | 413 | syntaxLabel.AppendText(_function); 414 | syntaxLabel.AppendText(_params); 415 | } 416 | 417 | void PrintLine(string text) 418 | { 419 | if (rich_label == null) 420 | { 421 | CallDeferred("PrintLine", text); 422 | } 423 | else 424 | { 425 | rich_label.AddText(text + "\n"); 426 | } 427 | } 428 | 429 | void AddInputHistory(string text) 430 | { 431 | if (console_history.Count == 0 || text != console_history.Last()) 432 | { 433 | console_history.Add(text); 434 | } 435 | console_history_index = console_history.Count; 436 | } 437 | 438 | void RemoveCommand(string CommandName) 439 | { 440 | Commands.Remove(CommandName); 441 | } 442 | 443 | public void Quit() 444 | { 445 | GetTree().Quit(); 446 | } 447 | 448 | void clear() 449 | { 450 | rich_label.Clear(); 451 | } 452 | 453 | void DeleteHistory() 454 | { 455 | console_history.Clear(); 456 | console_history_index = 0; 457 | DirAccess.RemoveAbsolute(GetPath()+"/Commands.log"); 458 | } 459 | void Help() 460 | { 461 | rich_label.AddText("Commands:\n"); 462 | foreach (var command in Commands.OrderBy(d => d.Key)) 463 | { 464 | if(command.Value.base_command) 465 | rich_label.AppendText(string.Format("\t[color=light_green]{0}[/color]: {1}\n", command.Key, command.Value.Description)); 466 | } 467 | rich_label.AppendText("" + 468 | "\r\n\t\t[color=light_blue]Up[/color] and [color=light_blue]Down[/color] arrow keys to navigate commands history" + 469 | "\r\n\t\t[color=light_blue]PageUp[/color] and [color=light_blue]PageDown[/color] to navigate registry history" + 470 | "\r\n\t\t[color=light_blue]Ctr+Tilde[/color] to change console size between half screen and full creen" + 471 | "\r\n\t\t[color=light_blue]Tilde[/color] or [color=light_blue]Esc[/color] to close the console" + 472 | "\r\n\t\t[color=light_blue]Tab[/color] for basic autocomplete\n"); 473 | } 474 | 475 | void ShowExternalCommands() 476 | { 477 | foreach (var command in Commands.OrderBy(d => d.Key)) 478 | { 479 | if (!command.Value.base_command) 480 | rich_label.AppendText(string.Format("\t[color=light_green]{0}[/color]: {1}\n", command.Key, command.Value.Description)); 481 | } 482 | } 483 | 484 | #endregion 485 | 486 | /// 487 | /// add a command to the console ingame, active console with ~ button. 488 | /// 489 | /// CommandConsole.AddCommand("testing", test); 490 | /// 491 | /// any opinion is accepted. 492 | /// 493 | /// name of the function called in game console 494 | /// reference to the method 495 | public static void AddCommand(string CommandName, Delegate function) 496 | { 497 | try 498 | { 499 | 500 | instance.Commands.Add(CommandName, new Command(new Callable((GodotObject)function.Target, function.Method.Name), function.Method.GetParameters().Length)); 501 | 502 | foreach (var param in function.Method.GetParameters()) 503 | { 504 | instance.Commands[CommandName].Params.Add(param.Name, null); 505 | } 506 | } 507 | catch (Exception e) 508 | { 509 | GD.PrintErr(e); 510 | } 511 | } 512 | 513 | /// 514 | /// work in progress 515 | /// 516 | /// 517 | /// 518 | /// 519 | public static void AddParameterDescription(string CommandName, string param, string description) 520 | { 521 | try 522 | { 523 | instance.Commands[CommandName].Params[param] = description; 524 | } 525 | catch (Exception e) 526 | { 527 | GD.PrintErr(e); 528 | } 529 | } 530 | 531 | /// 532 | /// shows a description of the command in the console with commandlist 533 | /// 534 | /// 535 | /// 536 | public static void AddCommandDescription(string CommandName, string description) 537 | { 538 | try 539 | { 540 | instance.Commands[CommandName].Description = description; 541 | } 542 | catch (Exception e) 543 | { 544 | GD.PrintErr(e); 545 | } 546 | } 547 | 548 | void GetCommandsWithAttribute() 549 | { 550 | var Methods = 551 | Assembly.GetExecutingAssembly() 552 | .GetTypes(). 553 | SelectMany(x => x.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) 554 | ; 555 | 556 | 557 | foreach (var Method in Methods) 558 | { 559 | var commandAttributes = Method.GetCustomAttributes(typeof(AddCommandAttribute), false); 560 | AddCommandDescriptionAttribute commandDescriptionAttribute = (AddCommandDescriptionAttribute)Method.GetCustomAttribute(typeof(AddCommandDescriptionAttribute), false); 561 | 562 | foreach (AddCommandAttribute att in commandAttributes) 563 | { 564 | try 565 | { 566 | Delegate delegateInstance = null; 567 | 568 | if (Method.IsStatic) 569 | { 570 | 571 | return; 572 | /* 573 | delegateInstance = Delegate.CreateDelegate( 574 | System.Linq.Expressions.Expression.GetActionType( 575 | Method.GetParameters().Select(p => p.ParameterType).ToArray()), 576 | null, 577 | Method);*/ 578 | } 579 | 580 | else 581 | { 582 | var targetType = Method.DeclaringType; 583 | var targetInstance = Activator.CreateInstance(targetType); // This assumes the type has a parameterless constructor 584 | delegateInstance = Delegate.CreateDelegate( 585 | System.Linq.Expressions.Expression.GetActionType( 586 | Method.GetParameters().Select(p => p.ParameterType).ToArray()), 587 | targetInstance, 588 | Method); 589 | } 590 | 591 | AddCommand(att.CommandName, delegateInstance); 592 | 593 | if (commandDescriptionAttribute != null) 594 | { 595 | AddCommandDescription(att.CommandName, commandDescriptionAttribute.Description); 596 | } 597 | } 598 | catch (Exception ex) 599 | { 600 | GD.PrintErr(ex.ToString()); 601 | } 602 | } 603 | } 604 | } 605 | } 606 | -------------------------------------------------------------------------------- /addons/csharpConsole/Console_Plugin.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | 3 | [Tool] 4 | public partial class Console_Plugin : EditorPlugin 5 | { 6 | public override void _EnterTree() 7 | { 8 | base._EnterTree(); 9 | AddAutoloadSingleton("CommandConsole", "res://addons/csharpConsole/CommandConsole.cs"); 10 | } 11 | 12 | public override void _ExitTree() 13 | { 14 | base._ExitTree(); 15 | RemoveAutoloadSingleton("CommandConsole"); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /addons/csharpConsole/plugin.cfg: -------------------------------------------------------------------------------- 1 | [plugin] 2 | 3 | name="C# Console" 4 | description="Developer console. 5 | Press ~ to activate it in game and execute commands. 6 | 7 | Based on jitspoe console" 8 | author="Moliko" 9 | version="1.0.3" 10 | script="Console_Plugin.cs" 11 | --------------------------------------------------------------------------------