Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v6.3.0 #528

Merged
merged 13 commits into from
Jan 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions .github/actions/godot-install/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Inspired by https://github.com/bitbrain/beehave/blob/godot-4.x/.github/actions/godot-install/action.yml

name: install-godot-binary
description: "Installs the Godot Runtime"

inputs:
godot-version:
description: "The Godot engine version"
type: string
required: true
godot-status-version:
description: "The Godot engine status version"
type: string
required: true
godot-bin-name:
type: string
required: true
godot-cache-path:
type: string
required: true


runs:
using: composite
steps:

- name: "Set Cache Name"
shell: bash
run: |
echo "CACHE_NAME=${{ runner.OS }}-Godot_v${{ inputs.godot-version }}-${{ inputs.godot-status-version }}" >> "$GITHUB_ENV"

- name: "Godot Cache Restore"
uses: actions/cache/restore@v3
id: godot-restore-cache
with:
path: ${{ inputs.godot-cache-path }}
key: ${{ env.CACHE_NAME }}

- name: "Download and Install Godot ${{ inputs.godot-version }}"
if: steps.godot-restore-cache.outputs.cache-hit != 'true'
continue-on-error: false
shell: bash
run: |
mkdir -p ${{ inputs.godot-cache-path }}
chmod 770 ${{ inputs.godot-cache-path }}
DIR="$HOME/.config/godot"
if [ ! -d "$DIR" ]; then
mkdir -p "$DIR"
chmod 770 "$DIR"
fi

DOWNLOAD_URL=https://github.com/godotengine/godot/releases/download/${{ inputs.godot-version }}-${{ inputs.godot-status-version }}
GODOT_BIN=Godot_v${{ inputs.godot-version }}-${{ inputs.godot-status-version }}_${{ inputs.godot-bin-name }}

GODOT_PACKAGE=$GODOT_BIN.zip
wget $DOWNLOAD_URL/$GODOT_PACKAGE -P ${{ inputs.godot-cache-path }}
unzip ${{ inputs.godot-cache-path }}/$GODOT_PACKAGE -d ${{ inputs.godot-cache-path }}

mv ${{ inputs.godot-cache-path }}/$GODOT_BIN ${{ inputs.godot-cache-path }}/godot

chmod u+x ${{ inputs.godot-cache-path }}/godot
echo "${{ inputs.godot-cache-path }}/godot"

- name: "Godot Cache Save"
if: steps.godot-restore-cache.outputs.cache-hit != 'true'
uses: actions/cache/save@v3
with:
path: ${{ inputs.godot-cache-path }}
key: ${{ steps.godot-restore-cache.outputs.cache-primary-key }}
80 changes: 80 additions & 0 deletions .github/actions/test/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# Inspired by https://github.com/utopia-rise/fmod-gdextension/blob/godot-3.x/demo/run_tests.sh

name: test
description: "Runs the tests via GUT CLI"

inputs:
gut-download-path:
required: true
default: ~/gut_download
gut-addons-path:
required: true
default: ${{ github.workspace }}/test/addons/gut
godot-test-project:
required: true
default: ${{ github.workspace }}/test

runs:
using: composite

steps:

- name: "Set Cache Name"
shell: bash
run: |
echo "CACHE_NAME_GUT=GUT_v7.4.1" >> "$GITHUB_ENV"

- name: "GUT Cache Restore"
uses: actions/cache/restore@v3
id: gut-restore-cache
with:
path: ${{ inputs.gut-download-path }}
key: ${{ runner.os }}-${{ env.CACHE_NAME_GUT }}

- name: "Download GUT"
if: steps.gut-restore-cache.outputs.cache-hit != 'true'
continue-on-error: false
shell: bash
run: |
mkdir -p ${{ inputs.gut-download-path }}
chmod 770 ${{ inputs.gut-download-path }}

wget https://github.com/bitwes/Gut/archive/refs/tags/v7.4.1.zip -P ${{ inputs.gut-download-path }}
unzip ${{ inputs.gut-download-path }}/v7.4.1.zip -d ${{ inputs.gut-download-path }}/unzip

- name: "GUT Cache Save"
if: steps.gut-restore-cache.outputs.cache-hit != 'true'
uses: actions/cache/save@v3
with:
path: ${{ inputs.gut-download-path }}
key: ${{ steps.gut-restore-cache.outputs.cache-primary-key }}

- name: "Create addons Directory"
if: ${{ !cancelled() }}
shell: bash
run: mkdir -p ${{ github.workspace }}/test/addons

- name: "⚔ Link GUT"
if: ${{ !cancelled() }}
shell: bash
run: ln -s ${{ inputs.gut-download-path }}/unzip/Gut-7.4.1/addons/gut ${{ github.workspace }}/test/addons/gut

- name: "⚔ Link Mod Loader"
if: ${{ !cancelled() }}
shell: bash
run: ln -s ${{ github.workspace }}/addons/mod_loader ${{ github.workspace }}/test/addons/mod_loader

- name: "⚔ Link JSON_Schema_Validator"
if: ${{ !cancelled() }}
shell: bash
run: ln -s ${{ github.workspace }}/addons/JSON_Schema_Validator ${{ github.workspace }}/test/addons/JSON_Schema_Validator

- name: "Run Tests"
if: ${{ runner.OS == 'Linux'}} && ${{ !cancelled() }}
env:
TEST_PROJECT: ${{ inputs.godot-test-project }}
shell: bash
run: |
cd "${TEST_PROJECT}"
chmod +x run_tests.sh
./run_tests.sh "$HOME/godot-linux/godot"
37 changes: 29 additions & 8 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,30 @@
on: [pull_request]
# Inspired by https://github.com/bitbrain/beehave/blob/godot-4.x/.github/workflows/beehave-ci.yml

name: Mod Loader CI

on:
push:
paths-ignore:
- '**.jpg'
- '**.png'
- '**.svg'
- '**.md'
- '**plugin.cfg'
pull_request:
paths-ignore:
- '**.jpg'
- '**.png'
- '**.svg'
- '**.md'
- '**plugin.cfg'

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
check_dependencies:
runs-on: ubuntu-latest
name: PR Dependency Check
steps:
- uses: gregsdennis/dependencies-action@main
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
tests:
name: "Running GUT tests on Godot 3.5.3"
uses: ./.github/workflows/tests.yml
with:
godot-version: '3.5.3'
58 changes: 58 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Inspired by https://github.com/bitbrain/beehave/blob/godot-4.x/.github/workflows/unit-tests.yml

name: tests
run-name: ${{ github.head_ref || github.ref_name }}-tests

on:
workflow_call:
inputs:
os:
required: false
type: string
default: 'ubuntu-22.04'
godot-version:
required: true
type: string
default: '3.5.3'

workflow_dispatch:
inputs:
os:
required: false
type: string
default: 'ubuntu-22.04'
godot-version:
required: true
type: string

concurrency:
group: tests-${{ github.head_ref || github.ref_name }}-${{ inputs.godot-version }}
cancel-in-progress: true

jobs:
test:
name: "Tests"
runs-on: ${{ inputs.os }}
timeout-minutes: 15

steps:
- name: "📦 Checkout Mod Loader Repository"
uses: actions/checkout@v4
with:
lfs: true
submodules: 'recursive'

- name: "🤖 Install Godot ${{ inputs.godot-version }}"
uses: ./.github/actions/godot-install
with:
godot-version: ${{ inputs.godot-version }}
godot-status-version: 'stable'
godot-bin-name: 'linux_headless.64'
godot-cache-path: '~/godot-linux'

- name: "🧪 Run Tests"
if: ${{ !cancelled() }}
timeout-minutes: 4
uses: ./.github/actions/test
with:
godot-test-project: ${{ github.workspace }}/test
14 changes: 10 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,14 @@ You can find detailed documentation, for game and mod developers, on the [Wiki](
4. Use the [API Methods](https://wiki.godotmodding.com/#/api/mod_loader_api)
*A list of all available API Methods.*

## Godot Version
The current version of the Mod Loader is developed for Godot 3. The Godot 4 version is in progress on the [4.x branch](https://github.com/GodotModding/godot-mod-loader/tree/4.x) and can be used as long as no `class_name`s are in the project. Projects with `class_name`s are currently affected by an [engine bug](https://github.com/godotengine/godot/issues/83542). We are hopeful that this issue will be resolved in the near future. For more details and updates on the Godot 4 version, please follow this [issue](https://github.com/GodotModding/godot-mod-loader/issues/315) or join us on [our Discord](https://discord.godotmodding.com).
## Godot Version
The Mod Loader currently supports Godot 3.5 and later, as well as Godot 4.1 and later. Feel free to [open an issue](https://github.com/GodotModding/godot-mod-loader/issues/new) if you need support for a different version.

## Development
The latest work-in-progress build can be found on the [development branch](https://github.com/GodotModding/godot-mod-loader/tree/development).
## Development
The latest work-in-progress build for Godot 3 is available on the [development branch](https://github.com/GodotModding/godot-mod-loader/tree/development). For Godot 4, visit the [4.x branch](https://github.com/GodotModding/godot-mod-loader/tree/4.x).

## Releases
You can find the latest release versions and detailed installation instructions on the [Releases Page](https://github.com/GodotModding/godot-mod-loader/releases).

## Compatibility
The Mod Loader supports the following platforms:
Expand All @@ -39,6 +42,9 @@ The Mod Loader supports the following platforms:
- Android
- iOS

## Keep in touche
For more details and updates join us on [our Discord](https://discord.godotmodding.com).

## Games Made Moddable by This Project
- [Brotato](https://store.steampowered.com/app/1942280/Brotato/) by
[Blobfish Games](https://store.steampowered.com/developer/blobfishgames)
Expand Down
22 changes: 17 additions & 5 deletions addons/mod_loader/api/log.gd
Original file line number Diff line number Diff line change
Expand Up @@ -385,15 +385,27 @@ static func _log(message: String, mod_name: String, log_type: String = "info", o
_write_to_log_file(log_entry.get_entry())


static func _is_mod_name_ignored(mod_name: String) -> bool:
static func _is_mod_name_ignored(mod_log_name: String) -> bool:
if not ModLoaderStore:
return false

var ignored_mod_names := ModLoaderStore.ml_options.ignored_mod_names_in_log as Array
var ignored_mod_log_names := ModLoaderStore.ml_options.ignored_mod_names_in_log as Array

if not ignored_mod_names.size() == 0:
if mod_name in ignored_mod_names:
return true
# No ignored mod names
if ignored_mod_log_names.size() == 0:
return false

# Directly match a full mod log name. ex: "ModLoader:Deprecated"
if mod_log_name in ignored_mod_log_names:
return true

# Match a mod log name with a wildcard. ex: "ModLoader:*"
for ignored_mod_name in ignored_mod_log_names:
if ignored_mod_name.ends_with("*"):
if mod_log_name.begins_with(ignored_mod_name.trim_suffix("*")):
return true

# No match
return false


Expand Down
10 changes: 7 additions & 3 deletions addons/mod_loader/api/mod.gd
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const LOG_NAME := "ModLoader:Mod"
# Returns: void
static func install_script_extension(child_script_path: String) -> void:

var mod_id: String = ModLoaderUtils.get_string_in_between(child_script_path, "res://mods-unpacked/", "/")
var mod_id: String = _ModLoaderPath.get_mod_dir(child_script_path)
var mod_data: ModData = get_mod_data(mod_id)
if not ModLoaderStore.saved_extension_paths.has(mod_data.manifest.get_mod_id()):
ModLoaderStore.saved_extension_paths[mod_data.manifest.get_mod_id()] = []
Expand Down Expand Up @@ -71,8 +71,12 @@ static func add_translation(resource_path: String) -> void:
return

var translation_object: Translation = load(resource_path)
TranslationServer.add_translation(translation_object)
ModLoaderLog.info("Added Translation from Resource -> %s" % resource_path, LOG_NAME)
if translation_object:
TranslationServer.add_translation(translation_object)
ModLoaderLog.info("Added Translation from Resource -> %s" % resource_path, LOG_NAME)
else:
ModLoaderLog.fatal("Failed to load translation at path: %s" % [resource_path], LOG_NAME)



# Appends a new node to a modified scene.
Expand Down
46 changes: 46 additions & 0 deletions addons/mod_loader/api/profile.gd
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,45 @@ static func create_profile(profile_name: String) -> bool:
return is_save_success


# Renames an existing user profile.
#
# Parameters:
# - old_profile_name (String): The current name for the user profile (must be unique).
# - new_profile_name (String): The new name for the user profile (must be unique).
#
# Returns: bool
static func rename_profile(old_profile_name: String, new_profile_name: String) -> bool:
# Verify that the old profile name is already in use
if not ModLoaderStore.user_profiles.has(old_profile_name):
ModLoaderLog.error("User profile with the name of \"%s\" does not exist." % old_profile_name, LOG_NAME)
return false

# Verify that the new profile_name is not already in use
if ModLoaderStore.user_profiles.has(new_profile_name):
ModLoaderLog.error("User profile with the name of \"%s\" already exists." % new_profile_name, LOG_NAME)
return false

# Rename user profile
var profile_renamed := ModLoaderStore.user_profiles[old_profile_name].duplicate() as ModUserProfile
profile_renamed.name = new_profile_name

# Remove old profile entry, replace it with new name entry in the ModLoaderStore
ModLoaderStore.user_profiles.erase(old_profile_name)
ModLoaderStore.user_profiles[new_profile_name] = profile_renamed

# Set it as the current profile if it was the current profile
if ModLoaderStore.current_user_profile.name == old_profile_name:
set_profile(profile_renamed)

# Store the new profile in the json file
var is_save_success := _save()

if is_save_success:
ModLoaderLog.debug("Renamed user profile from \"%s\" to \"%s\"" % [old_profile_name, new_profile_name], LOG_NAME)

return is_save_success


# Sets the current user profile to the given user profile.
#
# Parameters:
Expand Down Expand Up @@ -187,6 +226,13 @@ static func get_all_as_array() -> Array:
return user_profiles


# Returns true if the Mod User Profiles are initialized.
# On the first execution of the game, user profiles might not yet be created.
# Use this method to check if everything is ready to interact with the ModLoaderUserProfile API.
static func is_initialized() -> bool:
return _ModLoaderFile.file_exists(FILE_PATH_USER_PROFILES)


# Internal profile functions
# =============================================================================

Expand Down
Loading