From 9d6b304a65032caa3decf6c391f6737e22c0d0b7 Mon Sep 17 00:00:00 2001 From: LoafyLemon Date: Fri, 17 May 2024 20:05:51 +0100 Subject: [PATCH] Custom Console Experiment --- .../creamy_pumpkin_pie/fonts/Hack-Bold.ttf | 3 + .../fonts/Hack-BoldItalic.ttf | 3 + .../creamy_pumpkin_pie/fonts/Hack-Italic.ttf | 3 + .../creamy_pumpkin_pie/fonts/Hack-Regular.ttf | 3 + game/scripts/utility/console.rpy | 573 ++++++++++++++++++ 5 files changed, 585 insertions(+) create mode 100644 game/gui/creamy_pumpkin_pie/fonts/Hack-Bold.ttf create mode 100644 game/gui/creamy_pumpkin_pie/fonts/Hack-BoldItalic.ttf create mode 100644 game/gui/creamy_pumpkin_pie/fonts/Hack-Italic.ttf create mode 100644 game/gui/creamy_pumpkin_pie/fonts/Hack-Regular.ttf create mode 100644 game/scripts/utility/console.rpy diff --git a/game/gui/creamy_pumpkin_pie/fonts/Hack-Bold.ttf b/game/gui/creamy_pumpkin_pie/fonts/Hack-Bold.ttf new file mode 100644 index 00000000..7ef2c656 --- /dev/null +++ b/game/gui/creamy_pumpkin_pie/fonts/Hack-Bold.ttf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5bbf531eff7f8a0c2559c9a0656718e2828a012a9b1f60b5f54006d59a4de8d4 +size 317628 diff --git a/game/gui/creamy_pumpkin_pie/fonts/Hack-BoldItalic.ttf b/game/gui/creamy_pumpkin_pie/fonts/Hack-BoldItalic.ttf new file mode 100644 index 00000000..30685999 --- /dev/null +++ b/game/gui/creamy_pumpkin_pie/fonts/Hack-BoldItalic.ttf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:64f74a079700b7dfe128551a1e28875d5ba980971e55f5e0f0596e37bdc6a6bc +size 322288 diff --git a/game/gui/creamy_pumpkin_pie/fonts/Hack-Italic.ttf b/game/gui/creamy_pumpkin_pie/fonts/Hack-Italic.ttf new file mode 100644 index 00000000..82f6011c --- /dev/null +++ b/game/gui/creamy_pumpkin_pie/fonts/Hack-Italic.ttf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:096fb67a2b85f3c866e9cb3e965b27c2c10b977315f4d3d7f095674be35091c1 +size 316156 diff --git a/game/gui/creamy_pumpkin_pie/fonts/Hack-Regular.ttf b/game/gui/creamy_pumpkin_pie/fonts/Hack-Regular.ttf new file mode 100644 index 00000000..45d33832 --- /dev/null +++ b/game/gui/creamy_pumpkin_pie/fonts/Hack-Regular.ttf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:15f55cc0c85a2988d2b4b3a8cdb5d77fdfbaf319e1bb5309d725db9818fb7125 +size 309408 diff --git a/game/scripts/utility/console.rpy b/game/scripts/utility/console.rpy new file mode 100644 index 00000000..a7243340 --- /dev/null +++ b/game/scripts/utility/console.rpy @@ -0,0 +1,573 @@ +init 2000 python in _console: + class DebugConsoleNew(object): + + def __init__(self): + + self.history = BoundedList(config.console_history_size, config.console_history_lines + config.console_history_size) + self.line_history = BoundedList(config.console_history_size) + self.line_index = 0 + + if persistent._console_history is not None: + for i in persistent._console_history: + he = ConsoleHistoryEntry(i[0], i[1], i[2]) + he.update_lines() + self.history.append(he) + + if persistent._console_line_history is not None: + self.line_history.extend(persistent._console_line_history) + + self.first_time = True + self.renpy_scripting = False + + self.reset() + + def backup(self): + + persistent._console_history = [ (i.command, i.result, i.is_error) for i in self.history ] + persistent._console_line_history = list(self.line_history) + + def start(self): + he = ConsoleHistoryEntry(None) + + if self.first_time: + message = __("Press to exit console. Type help for help.\n") + he.result = message + he.update_lines() + self.history.append(he) + self.first_time = False + + if self.can_renpy(): + self.renpy_scripting = True + else: + self.renpy_scripting = False + + def reset(self): + + # The list of lines that have been entered by the user, but not yet + # processed. + self.lines = [ "" ] + self.line_index = len(self.line_history) + + def recall_line(self, offset): + + self.line_index += offset + + if self.line_index < 0: + self.line_index = 0 + + if self.line_index > len(self.line_history): + self.line_index = len(self.line_history) + + if self.line_index == len(self.line_history): + self.lines = [ "" ] + else: + self.lines = list(self.line_history[self.line_index]) + + cs = renpy.get_screen("console") + + scope = cs.scope + consoleinput = scope["consoleinput"] + consoleinput.update_text(self.lines[-1], consoleinput.editable) + renpy.restart_interaction() + + def older(self): + self.recall_line(-1) + + def newer(self): + self.recall_line(1) + + def show_stdio(self): + + old_entry = None + + if persistent._console_short: + if len(stdio_lines) > 30: + stdio_lines[:] = stdio_lines[:10] + [ (False, " ... ") ] + stdio_lines[-20:] + + for error, l in stdio_lines: + if persistent._console_short: + if len(l) > 200: + l = l[:100] + "..." + l[-100:] + + if (old_entry is not None) and (error == old_entry.is_error): + old_entry.result += "\n" + l + else: + e = ConsoleHistoryEntry(None, l, error) + e.update_lines() + self.history.append(e) + old_entry = e + + if old_entry is not None: + old_entry.update_lines() + + stdio_lines[:] = _list() + + def can_renpy(self): + """ + Returns true if we can run Ren'Py code. + """ + + return renpy.game.context().rollback + + def format_exception(self): + etype, evalue, etb = sys.exc_info() + return traceback.format_exception_only(etype, evalue)[-1] + + def run(self, lines): + + line_count = len(lines) + code = "\n".join(lines) + + he = ConsoleHistoryEntry(code) + self.history.append(he) + + try: + + # If we have 1 line, try to parse it as a command. + if line_count == 1: + block = [ ( "", 1, code, [ ]) ] + l = renpy.parser.Lexer(block) + l.advance() + + # Command can be None, but that's okay, since the lookup will fail. + command = l.word() + + command_fn = config.console_commands.get(command, None) + + if command_fn is not None: + he.result = command_fn(l) + he.update_lines() + return + + error = None + + # Try to run it as Ren'Py. + if self.can_renpy(): + + # TODO: Can we run Ren'Py code? + name = renpy.load_string(code + "\nreturn") + + if name is not None: + renpy.game.context().exception_handler = ScriptErrorHandler() + renpy.call(name) + else: + error = "\n\n".join(renpy.get_parse_errors()) + + # Try to eval it. + try: + renpy.python.py_compile(code, 'eval') + except Exception: + pass + else: + result = renpy.python.py_eval(code) + if persistent._console_short and not getattr(result, "_console_always_long", False): + he.result = aRepr.repr(result) + else: + he.result = repr(result) + + he.update_lines() + return + + # Try to exec it. + try: + renpy.python.py_compile(code, "exec") + except Exception: + if error is None: + error = self.format_exception() + else: + renpy.python.py_exec(code) + return + + if error is not None: + he.result = error + he.update_lines() + he.is_error = True + + except renpy.game.CONTROL_EXCEPTIONS: + raise + + except Exception: + import traceback + traceback.print_exc() + + he.result = self.format_exception().rstrip() + he.update_lines() + he.is_error = True + + console = DebugConsoleNew() + + @command(_("exit: exit the console")) + def exit(l): + renpy.hide_screen("console") + + @command() + def quit(l): + renpy.hide_screen("console") + + @command() + def stack(l): + console.run(["renpy.exports.get_return_stack()"]) + + @command(_("call