From 6d52f9cc88a40c210cf12afcfdf57c3b62a3d636 Mon Sep 17 00:00:00 2001 From: krampus Date: Sat, 20 Jul 2024 18:36:11 +0000 Subject: [PATCH] Initial commit --- .gdlintrc | 49 ++++++++ .gitattributes | 4 + .githooks/pre-commit | 31 +++++ .gitignore | 21 ++++ DEVELOPMENT.md | 160 ++++++++++++++++++++++++ README.md | 7 ++ addons/format_on_save/LICENSE | 21 ++++ addons/format_on_save/format_on_save.gd | 70 +++++++++++ addons/format_on_save/plugin.cfg | 6 + addons/gdlint_plugin/LICENSE | 21 ++++ addons/gdlint_plugin/plugin.cfg | 6 + addons/gdlint_plugin/run_linter.gd | 33 +++++ project.godot | 40 ++++++ requirements.txt | 2 + 14 files changed, 471 insertions(+) create mode 100644 .gdlintrc create mode 100644 .gitattributes create mode 100755 .githooks/pre-commit create mode 100644 .gitignore create mode 100644 DEVELOPMENT.md create mode 100644 README.md create mode 100644 addons/format_on_save/LICENSE create mode 100644 addons/format_on_save/format_on_save.gd create mode 100644 addons/format_on_save/plugin.cfg create mode 100644 addons/gdlint_plugin/LICENSE create mode 100644 addons/gdlint_plugin/plugin.cfg create mode 100644 addons/gdlint_plugin/run_linter.gd create mode 100644 project.godot create mode 100644 requirements.txt diff --git a/.gdlintrc b/.gdlintrc new file mode 100644 index 0000000..eb8df5b --- /dev/null +++ b/.gdlintrc @@ -0,0 +1,49 @@ +class-definitions-order: +- tools +- classnames +- extends +- docstrings +- signals +- enums +- consts +- exports +- pubvars +- prvvars +- onreadypubvars +- onreadyprvvars +- staticvars +- others +class-load-variable-name: (([A-Z][a-z0-9]*)+|_?[a-z][a-z0-9]*(_[a-z0-9]+)*) +class-name: ([A-Z][a-z0-9]*)+ +class-variable-name: _?[a-z][a-z0-9]*(_[a-z0-9]+)* +comparison-with-itself: null +constant-name: _?[A-Z][A-Z0-9]*(_[A-Z0-9]+)* +disable: [] +duplicated-load: null +enum-element-name: '[A-Z][A-Z0-9]*(_[A-Z0-9]+)*' +enum-name: ([A-Z][a-z0-9]*)+ +excluded_directories: !!set + .git: null + addons: null +expression-not-assigned: null +function-argument-name: _?[a-z][a-z0-9]*(_[a-z0-9]+)* +function-arguments-number: 10 +function-name: (_on_([A-Z][a-z0-9]*)+(_[a-z0-9]+)*|_?[a-z][a-z0-9]*(_[a-z0-9]+)*) +function-preload-variable-name: ([A-Z][a-z0-9]*)+ +function-variable-name: '[a-z][a-z0-9]*(_[a-z0-9]+)*' +load-constant-name: (([A-Z][a-z0-9]*)+|_?[A-Z][A-Z0-9]*(_[A-Z0-9]+)*) +loop-variable-name: _?[a-z][a-z0-9]*(_[a-z0-9]+)* +max-file-lines: 1000 +max-line-length: 100 +max-public-methods: 20 +max-returns: 6 +mixed-tabs-and-spaces: null +no-elif-return: null +no-else-return: null +private-method-call: null +signal-name: '[a-z][a-z0-9]*(_[a-z0-9]+)*' +sub-class-name: _?([A-Z][a-z0-9]*)+ +tab-characters: 1 +trailing-whitespace: null +unnecessary-pass: null +unused-argument: null diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..8d7f999 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,4 @@ +# Normalize EOL for all files that Git considers text files. +* text=auto eol=lf +*.svg filter=lfs diff=lfs merge=lfs -text +*.png filter=lfs diff=lfs merge=lfs -text diff --git a/.githooks/pre-commit b/.githooks/pre-commit new file mode 100755 index 0000000..8ecbcd4 --- /dev/null +++ b/.githooks/pre-commit @@ -0,0 +1,31 @@ +#!/bin/sh + +GDFORMAT=gdformat +GDLINT=gdlint +VENV=.venv +PYTHON=python3 +PIP=$VENV/bin/pip + +if ! which $GDFORMAT &> /dev/null; then + if ! test -f $VENV/bin/$GDFORMAT; then + if ! which $PYTHON &> /dev/null; then + echo "Please install Python 3" + exit 1 + fi + + echo "gdscript-toolkit will be installed locally under $VENV." + echo "this only needs to be performed once." + echo "creating venv..." + $PYTHON -m venv $VENV + echo "installing gdscript-toolkit..." + $PIP install -r requirements.txt + fi + + GDFORMAT=$VENV/bin/$GDFORMAT + GDLINT=$VENV/bin/$GDLINT +fi + +set -x + +$GDFORMAT --check . +$GDLINT . diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2568c6c --- /dev/null +++ b/.gitignore @@ -0,0 +1,21 @@ +# Godot 4+ specific ignores +.godot/ + +# Godot-specific ignores +.import/ +export.cfg +export_presets.cfg + +# Imported translations (automatically generated from CSV files) +*.translation + +# Mono-specific ignores +.mono/ +data_*/ +mono_crash.*.json + +# Python venv +.venv + +# Project demos +/demos/ diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md new file mode 100644 index 0000000..6f1f39f --- /dev/null +++ b/DEVELOPMENT.md @@ -0,0 +1,160 @@ +# DEVELOPMENT.md + +This is a set of general guidelines for developers. + +## Dev Tools + +This project uses `gdlint` and `gdformat` from +[Scony/godot-gdscript-toolkit](https://github.com/Scony/godot-gdscript-toolkit) +for linting & formatting, respectively. + +These tools are integrated into our development workflow using Godot +plugins: +[ryan-haskell/gdformat-on-save](https://github.com/ryan-haskell/gdformat-on-save) +and +[krampus/gdlint-plugin](https://git.of.the.spectacle.lol/krampus/gdlint-plugin) +respectively. + +When a script is saved in the Godot editor, it is automatically +formatted and checked for linting errors which are shown as warnings. + +### Setup on Linux Environment + +`gdlint` and `gdformat` require Python >=3.8. On Ubuntu: + +```bash +$ sudo apt update +$ sudo apt install python3 python3-venv +``` + +Next, install `gdscript-toolkit` through `pip`: + +```bash +$ pip install --user -r requirements.txt +``` + +Then run `godot`. The plugins should be configured automatically. + +(If you prefer to install `gdscript-toolkit` in a venv, just make sure +the plugins can find their required binaries.) + +### Setup on Windows Environment + +Download and run the appropriate installer from the [Python website](https://www.python.org/downloads/windows/) + +During installation, select the "Add python.exe to PATH" checkbox when prompted. + +Open "Windows PowerShell" and run the following command to make sure pip is installed: +``` +pip --version +``` + +Assuming pip is installed you should see a message like: +``` +pip 24.0 from C:\Users\dummy\AppData\Local\Programs\Python\Python312\Lib\site-packages\pip (python 3.12) +``` + +If pip is installed, run the following command to install the toolkit for the linter and formatter: +``` +install gdtoolkit==4.2.2 +``` + +Then run the following command to finish the installation process: +``` +pip install setuptools==69.5.1 +``` + +Check that everything installed by running "gdlint -h" and you should see something like: + +``` +GDScript linter + +A tool for diagnosing typical GDScript code problems. +On success and the exitcode is 0. +On failure, python exception or list of problems is shown and exitcode is non-zero. +... +``` +Also run "gdformat -h" and you should see something like: + +``` +GDScript formatter + +Uncompromising GDScript code formatter. The only configurable thing is +max line length allowed and tabs/spaces indent. The rest will be taken +care of by gdformat in a one, consistent way. +... +``` + +### Git Hooks + +If you like, you can use the included githooks to automatically check formatting & linting before making a commit. + +You can enable our githooks like this: + +```bash +$ git config core.hooksPath .githooks +``` + +## Standards & Practices + +### Style + +Code should generally conform to the [GDScript style +guide](https://docs.godotengine.org/en/stable/tutorials/scripting/gdscript/gdscript_styleguide.html) +where possible. Use the provided [linter and formatter](#dev-tools) to +apply most style guidelines automatically. + +### Type Annotations + +Use explicit type annotations wherever possible. Don't fret about it +too much, this is GDScript and there are a lot of situations where you +gotta do some freaky duck typing, but try to do as much explicit type +annotation as you can. + +### Organization + +_NOTE update this section as we build out the project more_ + +- All non-code assets go under `assets` + - Graphical assets go under `assets/images` + - Sprites go under `assets/images/sprites` + - Audio assets go under `assets/audio` + - Music goes under `assets/audio/music` + - SFX assets go under `assets/audio/sfx` + - Video assets go under `assets/video` +- Scenes and GDScript source files go under `src` +- Godot plugins go under `addons` + +## Git Workflow + +We use a standard branching workflow. Here's the full process of getting something merged in: + +1. [Create an issue](../../../issues/new) for the feature you want to + implement or the bug you want to fix, and assign it to + yourself. Alternately, pick an existing issue you want to work on + from the [issue tracker](../../../issues). +2. In your local repo, create a new branch off of `main`. Your feature + branch's name should include the issue number and a brief + descriptive title, e.g. `37-immanentize-eschaton` or similar. +3. Build the feature or fix the bug or whatever it is you're + doing. Frequent, small commits are preferred, and it's a good idea + to merge new changes from `main` often. +4. Push your changes to the server and + [create a pull request](../../../compare/main...main) to merge your + feature branch into `main`. Your PR description should include the + changes you made. If you include the phrase _"closes #[issue + number]"_ in your PR description, the issue will automatically be + closed when your PR is merged, which is nice. +5. Request review from `intrusive/Owners`. If your patch touches + something you think a specific dev needs to see, tag them for + review explicitly. +6. Once your PR gets approval from either 1 member of + `intrusive/Owners` or from the specific developer who needs to see + it, merge it into `main` yourself. There should be a button on the + PR page to do this. If it says you can't merge automatically, you + probably need to merge new changes from `main` +7. If it wasn't done automatically, close the issue and delete the + feature branch. + +Try to stick to the above workflow as much as you can, but occasional +shortcuts for hotfixes etc aren't the end of the world. diff --git a/README.md b/README.md new file mode 100644 index 0000000..d941183 --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ +# Sunstation + +Stylish mech combat game (prototype) + +## Development + +see [[DEVELOPMENT.md]] diff --git a/addons/format_on_save/LICENSE b/addons/format_on_save/LICENSE new file mode 100644 index 0000000..250f450 --- /dev/null +++ b/addons/format_on_save/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Ryan Haskell-Glatz + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/addons/format_on_save/format_on_save.gd b/addons/format_on_save/format_on_save.gd new file mode 100644 index 0000000..e5ba809 --- /dev/null +++ b/addons/format_on_save/format_on_save.gd @@ -0,0 +1,70 @@ +@tool +class_name FormatOnSave extends EditorPlugin + +const SUCCESS: int = 0 +const AUTO_RELOAD_SETTING: String = "text_editor/behavior/files/auto_reload_scripts_on_external_change" +var original_auto_reload_setting: bool + + +# LIFECYCLE EVENTS +func _enter_tree(): + activate_auto_reload_setting() + resource_saved.connect(on_resource_saved) + + +func _exit_tree(): + resource_saved.disconnect(on_resource_saved) + restore_original_auto_reload_setting() + + +# CALLED WHEN A SCRIPT IS SAVED +func on_resource_saved(resource: Resource): + if resource is Script: + var script: Script = resource + var current_script = get_editor_interface().get_script_editor().get_current_script() + var text_edit: CodeEdit = ( + get_editor_interface().get_script_editor().get_current_editor().get_base_editor() + ) + + # Prevents other unsaved scripts from overwriting the active one + if current_script == script: + var filepath: String = ProjectSettings.globalize_path(resource.resource_path) + + # Run gdformat + var exit_code = OS.execute("gdformat", [filepath]) + + # Replace source_code with formatted source_code + if exit_code == SUCCESS: + var formatted_source = FileAccess.get_file_as_string(resource.resource_path) + FormatOnSave.reload_script(text_edit, formatted_source) + + +# Workaround until this PR is merged: +# https://github.com/godotengine/godot/pull/83267 +# Thanks, @KANAjetzt 💖 +static func reload_script(text_edit: TextEdit, source_code: String) -> void: + var column := text_edit.get_caret_column() + var row := text_edit.get_caret_line() + var scroll_position_h := text_edit.get_h_scroll_bar().value + var scroll_position_v := text_edit.get_v_scroll_bar().value + + text_edit.text = source_code + text_edit.set_caret_column(column) + text_edit.set_caret_line(row) + text_edit.scroll_horizontal = scroll_position_h + text_edit.scroll_vertical = scroll_position_v + + text_edit.tag_saved_version() + + +# For this workaround to work, we need to disable the "Reload/Resave" pop-up +func activate_auto_reload_setting(): + var settings := get_editor_interface().get_editor_settings() + original_auto_reload_setting = settings.get(AUTO_RELOAD_SETTING) + settings.set(AUTO_RELOAD_SETTING, true) + + +# If the plugin is disabled, let's attempt to restore the original editor setting +func restore_original_auto_reload_setting(): + var settings := get_editor_interface().get_editor_settings() + settings.set(AUTO_RELOAD_SETTING, original_auto_reload_setting) diff --git a/addons/format_on_save/plugin.cfg b/addons/format_on_save/plugin.cfg new file mode 100644 index 0000000..0fec65c --- /dev/null +++ b/addons/format_on_save/plugin.cfg @@ -0,0 +1,6 @@ +[plugin] +name="Format on Save" +description="Runs `gdformat` on save to automatically format your GD script as you code." +author="Ryan Haskell-Glatz" +version="1.2.0" +script="format_on_save.gd" diff --git a/addons/gdlint_plugin/LICENSE b/addons/gdlint_plugin/LICENSE new file mode 100644 index 0000000..57e8dda --- /dev/null +++ b/addons/gdlint_plugin/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Rob Kelly + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/addons/gdlint_plugin/plugin.cfg b/addons/gdlint_plugin/plugin.cfg new file mode 100644 index 0000000..af50175 --- /dev/null +++ b/addons/gdlint_plugin/plugin.cfg @@ -0,0 +1,6 @@ +[plugin] +name="gdLint Plugin" +description="Static code analysis with `gdlint`" +author="Rob Kelly" +version="1.0.0" +script="run_linter.gd" diff --git a/addons/gdlint_plugin/run_linter.gd b/addons/gdlint_plugin/run_linter.gd new file mode 100644 index 0000000..291a11e --- /dev/null +++ b/addons/gdlint_plugin/run_linter.gd @@ -0,0 +1,33 @@ +@tool +class_name GDLintPlugin extends EditorPlugin + +# If you've installed gdlint in a venv, you may want to overwrite this +const GDLINT: String = "gdlint" + + +func _enter_tree() -> void: + assert(not OS.execute(GDLINT, ["-h"]), "Could not find gdLint binary at {0}".format([GDLINT])) + resource_saved.connect(on_save) + + +func _exit_tree() -> void: + resource_saved.disconnect(on_save) + + +func on_save(resource: Resource) -> void: + # Run linting when a script resource is saved + if resource is Script: + var script: Script = resource + var filepath: String = ProjectSettings.globalize_path(resource.resource_path) + + var script_editor = EditorInterface.get_script_editor() + var code_editor: CodeEdit = ( + script_editor.get_current_editor().get_base_editor() + if script_editor.get_current_script() == script + else null + ) + + var gdlint_output: Array[String] = [] + var error: int = OS.execute(GDLINT, [filepath], gdlint_output, true) + if error: + push_warning("gdLint:\n" + gdlint_output[0]) diff --git a/project.godot b/project.godot new file mode 100644 index 0000000..322e0ef --- /dev/null +++ b/project.godot @@ -0,0 +1,40 @@ +; Engine configuration file. +; It's best edited using the editor UI and not directly, +; since the parameters that go here are not all obvious. +; +; Format: +; [section] ; section goes between [] +; param=value ; assign values to parameters + +config_version=5 + +[application] + +config/name="Sunstation" +config/features=PackedStringArray("4.2", "Forward Plus") +run/max_fps=60 +config/icon="res://icon.svg" + +[debug] + +gdscript/warnings/untyped_declaration=2 +gdscript/warnings/unsafe_property_access=2 +gdscript/warnings/unsafe_method_access=2 +gdscript/warnings/unsafe_cast=1 +gdscript/warnings/unsafe_call_argument=2 + +[display] + +window/stretch/mode="canvas_items" + +[dotnet] + +project/assembly_name="Sunstation" + +[editor] + +movie_writer/movie_file="demos/demo.avi" + +[editor_plugins] + +enabled=PackedStringArray("res://addons/format_on_save/plugin.cfg", "res://addons/gdlint_plugin/plugin.cfg") diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..7b113c9 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +gdtoolkit>=4.2.2,<4.3 +setuptools>=69.5.1,<69.6