diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 0ec66d33..f2b0876f 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -3,7 +3,7 @@ "isRoot": true, "tools": { "gmodnet.versiontool": { - "version": "2.0.0", + "version": "2.1.0", "commands": [ "gmodnet-vt" ] @@ -13,6 +13,12 @@ "commands": [ "dotnet-script" ] + }, + "docfx": { + "version": "2.60.2", + "commands": [ + "docfx" + ] } } } \ No newline at end of file diff --git a/.github/workflows/azure-static-web-apps-nightly-docs.yml b/.github/workflows/azure-static-web-apps-nightly-docs.yml index b2a5396e..f4dcb842 100644 --- a/.github/workflows/azure-static-web-apps-nightly-docs.yml +++ b/.github/workflows/azure-static-web-apps-nightly-docs.yml @@ -8,14 +8,11 @@ on: types: [opened, synchronize, reopened, closed, labeled, unlabeled] jobs: - build_docs: + build_and_deploy_docs: if: (github.event_name == 'push' || (github.event_name == 'pull_request_target' && github.event.action != 'closed' && github.event.action != 'unlabeled' && contains(github.event.pull_request.labels.*.name, 'pr-generate-docs-preview'))) && github.repository_owner == 'GmodNET' - runs-on: windows-latest - name: Build Docs + runs-on: ubuntu-latest + name: Build and Deploy Nightly Docs steps: - - name: Install DocFX - run: choco install docfx --version=2.58.9 -y - - name: Checkout branch if: github.event_name == 'push' uses: actions/checkout@v2.3.4 @@ -28,14 +25,21 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Install .NET SDK - uses: actions/setup-dotnet@v1.8.1 + - name: Setup .NET SDK + uses: actions/setup-dotnet@v3.0.3 + with: + global-json-file: "./global.json" + - name: Restore dotnet tools + run: dotnet tool restore + + # We force DocFX to use latest runtime (and latest SDK) by setting DOTNET_ROLL_FORWARD='LatestMajor' env var - name: Build docs with DocFX shell: pwsh run: | $env:GITHUB_ACTIONS='false' - docfx .\docfx_project\docfx.json + $env:DOTNET_ROLL_FORWARD='LatestMajor' + dotnet docfx ./docfx_project/docfx.json - name: Upload docs as artifact uses: actions/upload-artifact@v2.2.4 @@ -43,17 +47,6 @@ jobs: name: site path: docfx_project/_site/ - deploy_docs: - needs: build_docs - runs-on: ubuntu-latest - name: Deploy Docs - steps: - - name: Dowload docs build - uses: actions/download-artifact@v2.0.10 - with: - name: site - path: site - - name: Deploy docs uses: Azure/static-web-apps-deploy@v1 with: @@ -62,7 +55,7 @@ jobs: action: "upload" ###### Repository/Build Configurations - These values can be configured to match your app requirements. ###### # For more information regarding Static Web App workflow configurations, please visit: https://aka.ms/swaworkflowconfig - app_location: "./site" # App source code path + app_location: "./docfx_project/_site/" # App source code path api_location: "" # Api source code path - optional output_location: "" # Built app content directory - optional skip_app_build: true diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 31ab98af..d206fe6f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,7 +2,8 @@ name: CI on: pull_request: - push: {} + push: + branches: release: types: [published] @@ -127,7 +128,7 @@ jobs: windows-build: - runs-on: windows-latest + runs-on: windows-2019 steps: - name: Checkout @@ -234,7 +235,7 @@ jobs: mac-build: - runs-on: macos-latest + runs-on: macos-10.15 steps: @@ -294,7 +295,7 @@ jobs: trigger_autorebase: - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 needs: [linux-build, windows-build, mac-build] @@ -385,9 +386,11 @@ jobs: file_glob: true - name: Restore dotnet version tool + if: ${{ github.event_name == 'push' }} run: dotnet tool restore - name: Generate token for GmodNET/runtime-nightly repo + if: ${{ github.event_name == 'push' }} id: generate_token_for_github_nightly uses: tibdex/github-app-token@v1.3.0 with: @@ -396,26 +399,32 @@ jobs: repository: GmodNET/runtime-nightly - name: Get current version + if: ${{ github.event_name == 'push' }} id: get_version run: echo "::set-output name=version::$(dotnet gmodnet-vt getVersion version.json --skip-build-data)" - name: Get current head + if: ${{ github.event_name == 'push' }} id: get_git_head run: echo "::set-output name=head_name::'$(dotnet gmodnet-vt getBranchName version.json)'" - name: Add new git remote for nightly builds + if: ${{ github.event_name == 'push' }} run: | git fetch --unshallow origin git config --local --unset-all http.https://github.com/.extraheader git remote add nightly https://x-access-token:${{ steps.generate_token_for_github_nightly.outputs.token }}@github.com/GmodNET/runtime-nightly.git - name: Apply git tag + if: ${{ github.event_name == 'push' }} run: git tag ${{ steps.get_version.outputs.version }} - name: Push tag to nightly builds repo + if: ${{ github.event_name == 'push' }} run: git push nightly ${{ steps.get_version.outputs.version }} --force - name: Upload build artifacts to nightly repo releases + if: ${{ github.event_name == 'push' }} uses: svenstaro/upload-release-action@2.2.1 with: repo_token: ${{ steps.generate_token_for_github_nightly.outputs.token }} @@ -426,6 +435,7 @@ jobs: file_glob: true - name: Send Discord message + if: ${{ github.event_name == 'push' }} working-directory: csx env: DOTNET_ROLL_FORWARD: Major diff --git a/.github/workflows/deploy-production-docs-to-zure.yml b/.github/workflows/deploy-production-docs-to-zure.yml index f3a460dc..a772ca00 100644 --- a/.github/workflows/deploy-production-docs-to-zure.yml +++ b/.github/workflows/deploy-production-docs-to-zure.yml @@ -4,24 +4,28 @@ on: workflow_dispatch: jobs: - build_docs: - runs-on: windows-latest - name: Build Docs + build_and_deploy_docs: + runs-on: ubuntu-latest + name: Build and deploy docs steps: - - name: Install DocFX - run: choco install docfx --version=2.58.9 -y - - name: Checkout uses: actions/checkout@v2.3.4 - - name: Install .NET SDK - uses: actions/setup-dotnet@v1.8.1 + - name: Setup .NET SDK + uses: actions/setup-dotnet@v3.0.3 + with: + global-json-file: "./global.json" + - name: Restore dotnet tools + run: dotnet tool restore + + # We force DocFX to use latest runtime (and latest SDK) by setting DOTNET_ROLL_FORWARD='LatestMajor' env var - name: Build docs with DocFX shell: pwsh run: | $env:GITHUB_ACTIONS='false' - docfx .\docfx_project\docfx.json + $env:DOTNET_ROLL_FORWARD='LatestMajor' + dotnet docfx ./docfx_project/docfx.json - name: Upload docs as artifact uses: actions/upload-artifact@v2.2.4 @@ -29,17 +33,6 @@ jobs: name: site path: docfx_project/_site/ - deploy_docs: - needs: build_docs - runs-on: ubuntu-latest - name: Deploy Docs - steps: - - name: Dowload docs build - uses: actions/download-artifact@v2.0.10 - with: - name: site - path: site - - name: Deploy docs uses: Azure/static-web-apps-deploy@v1 with: @@ -48,7 +41,7 @@ jobs: action: "upload" ###### Repository/Build Configurations - These values can be configured to match your app requirements. ###### # For more information regarding Static Web App workflow configurations, please visit: https://aka.ms/swaworkflowconfig - app_location: "./site" # App source code path + app_location: "./docfx_project/_site/" # App source code path api_location: "" # Api source code path - optional output_location: "" # Built app content directory - optional skip_app_build: true diff --git a/LICENSE b/LICENSE index da8e467d..f67892df 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2018 - 2020 Gleb Krasilich +Copyright (c) 2018 - 2023 Gleb Krasilich and GmodNET contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 49cb83b1..1e149ecb 100644 --- a/README.md +++ b/README.md @@ -2,28 +2,23 @@ [![CI](https://github.com/GlebChili/GmodDotNet/workflows/CI/badge.svg?branch=master)](https://github.com/GlebChili/GmodDotNet/actions?query=workflow%3ACI) # Gmod.NET -[![Current Runtime](https://img.shields.io/badge/Current%20Runtime-0.6.0-2db94e)](https://github.com/GlebChili/GmodDotNet/wiki/GmodNET-Runtime-and-GmodNET.API-version-correspondence#gmodnet-and-gmodnetapi) [![Current API](https://img.shields.io/badge/Current%20API-0.6.0-2db94e)](https://github.com/GlebChili/GmodDotNet/wiki/GmodNET-Runtime-and-GmodNET.API-version-correspondence#gmodnet-and-gmodnetapi) -Cross-platform .NET Module/Plugin platform for Garry's Mod powered by [__.NET Core__](https://dotnet.microsoft.com/). +Cross-platform .NET Module/Plugin platform for Garry's Mod powered by [__.NET__](https://dotnet.microsoft.com/). ## About Gmod.NET is Garry's Mod Module/Plugin loader for C# and other .NET languages which runs across all platforms (Windows, -Linux, Mac Os). Gmod.NET allows you to develop cross-platform Garry's Mod extensions without +Linux, macOS). Gmod.NET allows you to develop cross-platform Garry's Mod extensions without need to close or reload your game or server. -## Similar projects - -Check out [gmod_csModuleLoader](https://github.com/dedady157/gmod_csModuleLoader) by [Bailey Drahoss](https://github.com/dedady157). - -## Current features - -GmodNET provides functionality to write Garry's Mod modules in C# or any other CIL-compiled language as [__.NET Core 3.1__](https://dotnet.microsoft.com/) class libraries. For more information on modules and API check out [project's wiki](https://github.com/GlebChili/GmodDotNet/wiki). Only `x86_64` version of Garry's Mod is currently supported. +Gmod.NET allows you to write Garry's Mod modules in C# or any other CIL-compiled language as [__.NET__](https://dotnet.microsoft.com/) class libraries. +For more information on modules and API check out [our documentation](https://docs.gmodnet.xyz/). +Only `x86_64` version of Garry's Mod is currently supported. ## Need help? -Check out our [wiki](https://github.com/GlebChili/GmodDotNet/wiki) or join our [discord server](https://discord.gg/9bP8nMT). +Check out [our docs](https://docs.gmodnet.xyz/) and join our [discord server](https://discord.gg/9bP8nMT). ## Building and contributing @@ -37,7 +32,7 @@ To build GmodDotNet you need to have following software installed and registered 3. Latest version of dotnet SDK -4. (On Windows) Latest version of Visual Studio 2019 with C++ package +4. (On Windows) Latest version of Visual Studio 2019 with C++ workload 5. (On macOS) Latest version of Xcode @@ -49,7 +44,7 @@ Build steps: 2. In the root of the cloned repository run `dotnet build runtime.csproj -c Debug` or `dotnet build runtime.csproj -c Release` instruction in your command prompt. -__NOTE__: `runtime.csproj` is not a real C# project file but a kind of build script. To work with the managed part of GmodDotNet open `gm_dotnet_managed/gm_dotnet_managed.sln` solution file in your IDE instead. +__NOTE__: `runtime.csproj` is not a real C# project file but a kind of build script. To work with the managed part of Gmod.NET open `gm_dotnet_managed/gm_dotnet_managed.sln` solution file in your IDE instead. `runtime.csproj` build script will produce following folders in the root of repository: @@ -59,22 +54,9 @@ __NOTE__: `runtime.csproj` is not a real C# project file but a kind of build scr 3. `nupkgs` folder contains `GmodNET.API` NuGet package. -You may also want to copy the content of `lua` folder to the corresponding destinations in `garrysmod/lua`. - -### Folder structure - -Gmod.NET is subdivided into three subprojects. - -Garry's Mod binary native module and helper libraries are -contained in `gm_dotnet_native` folder and organized as CMake project. - -Managed part is contained in `gm_dotnet_managed` folder and organized with .NET soultion file `gm_dotnet_managed.sln`. - -Bootstrap Lua scripts are contained in `lua` folder. - ### Nightly builds -You can find latest nightly builds GmodDotNet runtime at http://nightly.gmodnet.xyz/. To use nightly NuGet packages connect to [our nightly NuGet feed](https://dev.azure.com/GmodNET/gmodnet-artifacts/_packaging?_a=feed&feed=gmodnet-packages). +You can find latest nightly builds of Gmod.NET runtime at http://nightly.gmodnet.xyz/. To use our nightly NuGet packages connect to [our nightly NuGet feed](https://dev.azure.com/GmodNET/gmodnet-artifacts/_packaging?_a=feed&feed=gmodnet-packages). ## Installation and usage @@ -84,17 +66,13 @@ You can find latest nightly builds GmodDotNet runtime at http://nightly.gmodnet. 3. Create a `Modules` folder inside `garrysmod/lua/bin/`. -4. Download and copy `gm_dotnet_server.lua` to `garrysmod/lua/autorun/server` folder. - -5. Download and copy `gm_dotnet_client.lua` to `garrysmod/lua/autorun/client` folder. +4. Place your .NET module, ...deps.json file, and all dependencies in `Modules/%exact_name_of_the_module_without_dll%/` folder. -6. Place your .NET module, ...deps.json file, and all dependencies in `Modules/%exact_name_of_the_module_without_dll/` folder. +5. Load Gmod.NET runtime in game by executing Lua function `require("dotnet")`. -7. If you signed your module with [GmodNetModuleSigner](https://github.com/GlebChili/GmodNetModuleSigner), copy `[name_of_your_module].modulekey` and `[name_of_your_module].modulesign` to the same folder as above (`Modules/%exact_name_of_the_module_without_dll/`). +6. Load your module by running Lua function `dotnet.load("%exact_name_of_the_module_without_dll%")`. -8. If you want your module to be serverside (clientside) only then add file `TYPE` to `Modules/%exact_name_of_the_module_without_dll/` with content `server` (`client`). - -9. Use `gmod_net_load_all` (`gmod_net_load_all_cl` for client-side) console command to load all managed modules and `gmod_net_unload_all` (`gmod_net_unload_all_cl`) to unload them. Modules can be hot-reloaded, so one doesn't need to quit game to see changes. +For more info check out [our quick start guide](https://docs.gmodnet.xyz/articles/tutorials/hello-world/index.html). ## License @@ -102,14 +80,4 @@ Whole project is licensed under MIT License. ## Dependencies and code usage -Gmod.NET is making use of or borrows code from the following projects: - -1. [CoreCLR](https://github.com/dotnet/coreclr), [CoreFX](https://github.com/dotnet/corefx), and [core-setup](https://github.com/dotnet/core-setup) by [.NET Foundation](https://github.com/dotnet) (MIT License) - -2. [pure_lua_SHA](https://github.com/Egor-Skriptunoff/pure_lua_SHA) by [Egor Skriptunoff](https://github.com/Egor-Skriptunoff) (MIT License) - -3. [NSec](https://nsec.rocks/) by [Klaus Hartke](https://github.com/ektrah) (MIT License) - -4. [Libsodium](http://libsodium.org) by [Frank Denis](https://github.com/jedisct1) (ISC License) - -See other copyright notices in the NOTICE file. +See the NOTICE file. diff --git a/docfx_project/articles/overview/core_concepts/core_concepts.md b/docfx_project/articles/overview/core_concepts/core_concepts.md index a1bc3a4c..e0cfbf87 100644 --- a/docfx_project/articles/overview/core_concepts/core_concepts.md +++ b/docfx_project/articles/overview/core_concepts/core_concepts.md @@ -5,7 +5,7 @@ title: "Core Concepts" # Core Concepts -Gmod.NET modules are essentially .NET (currently version 6.0) class libraries which reference [GmodNET.API nuget package](https://www.nuget.org/packages/GmodNET.API/) as their dependency. +Gmod.NET modules are essentially .NET (currently version 7.0) class libraries which reference [GmodNET.API nuget package](https://www.nuget.org/packages/GmodNET.API/) as their dependency. Each module should contain one or more implementation of [GmodNET.API.IModule](xref:GmodNET.API.IModule) interface. Gmod.NET runtime will instantiate each class derived from `IModule` by calling its parameterless constructor. diff --git a/docfx_project/articles/tutorials/hello-world-detailed/index.md b/docfx_project/articles/tutorials/hello-world-detailed/index.md index 517f2b84..0aff854f 100644 --- a/docfx_project/articles/tutorials/hello-world-detailed/index.md +++ b/docfx_project/articles/tutorials/hello-world-detailed/index.md @@ -4,7 +4,7 @@ title: "A comprehensive introduction to Visual Studio, C# and the 'Hello World' --- > [!WARNING] -> This article was written for an earlier version of Gmod.NET. In order to use the latest version of Gmod.NET you need to have **.NET 6** instead of **.NET 5** and **Visual Studio 2022** instead of **Visual Studio 2019**. +> This article was written for an earlier version of Gmod.NET. In order to use the latest version of Gmod.NET you need to have **.NET 7** instead of **.NET 5** and **Visual Studio 2022** instead of **Visual Studio 2019**. # A comprehensive introduction to Visual Studio, C# and the Hello World code At the end of this tutorial you will have created and installed your own module that simply states: 'Hello World!' in the console. We will write a bit of C# (pronounce C-Sharp) code and learn about the basics of C# with regards to Gmod.NET module making. diff --git a/docfx_project/articles/tutorials/hello-world/index.md b/docfx_project/articles/tutorials/hello-world/index.md index 76b7cc95..61295c7c 100644 --- a/docfx_project/articles/tutorials/hello-world/index.md +++ b/docfx_project/articles/tutorials/hello-world/index.md @@ -3,6 +3,9 @@ uid: tutorial_hello_world title: "A quick start with 'Hello World'" --- +> [!WARNING] +> This article was written for an earlier version of Gmod.NET. In order to use the latest version of Gmod.NET you need to have **.NET 7** instead of **.NET 6**. + # A quick start with 'Hello World' At the end of this tutorial you will have created and installed your own module that simply states: 'Hello World!' in the console. We will write our module using a bit of C# (pronounce C-Sharp) code. @@ -16,7 +19,7 @@ At the end of this tutorial you will have created and installed your own module * .NET SDK * NuGet Package manager * C# and Visual Basic - * .NET 6.0 Runtime + * .NET 7.0 Runtime * Windows 10 or newer. * An internet connection * A copy of [Garry's Mod installed through Steam](https://store.steampowered.com/app/4000/garrys_mod) diff --git a/global.json b/global.json index 04702084..9b920806 100644 --- a/global.json +++ b/global.json @@ -1,5 +1,5 @@ { "sdk": { - "version": "6.0.100" + "version": "7.0.102" } } diff --git a/gm_dotnet_managed/GmodNET.API/GmodNET.API.csproj b/gm_dotnet_managed/GmodNET.API/GmodNET.API.csproj index c0646440..eac47395 100644 --- a/gm_dotnet_managed/GmodNET.API/GmodNET.API.csproj +++ b/gm_dotnet_managed/GmodNET.API/GmodNET.API.csproj @@ -2,16 +2,18 @@ net6.0 + enable + Nullable MIT - GmodNET API - GmodNET API library contains all necessary interfaces to write a GmodNET module. + GmodNET.API + GmodNET.API library contains all necessary interfaces to write a Gmod.NET module. https://github.com/GmodNET/GmodDotNet Git garrysmod; GmodNET https://github.com/GmodNET/GmodDotNet gmodnetlogo.png GmodNET - Copyright (c) 2018 - 2021 Gleb Krasilich, GmodNET + Copyright (c) 2018 - 2023 Gleb Krasilich, GmodNET true true Portable @@ -26,10 +28,10 @@ - + all - + diff --git a/gm_dotnet_managed/GmodNET.API/ILua.cs b/gm_dotnet_managed/GmodNET.API/ILua.cs index 4a6a1b15..b34afe40 100644 --- a/gm_dotnet_managed/GmodNET.API/ILua.cs +++ b/gm_dotnet_managed/GmodNET.API/ILua.cs @@ -61,8 +61,8 @@ public interface ILua /// } /// /// - /// - public void GetField(int iStackPos, in string key); + /// + public void GetField(int iStackPos, string key); /// /// Does a table key-value assignment t[k] = v, @@ -102,8 +102,8 @@ public interface ILua /// } /// /// - /// - public void SetField(int iStackPos, in string key); + /// + public void SetField(int iStackPos, string key); /// /// Creates a new table and pushes it to the top of the stack. @@ -375,7 +375,7 @@ public interface ILua /// See lua_pushstring function in the Lua manual: https://www.lua.org/manual/5.1/manual.html /// /// A string to push. - public void PushString(in string str); + public void PushString(string str); /// /// Pushes a given double-precision number to the Lua stack. @@ -593,7 +593,7 @@ public interface ILua /// Creates a new Lua type, pushes its metatable onto the stack, and returns new type’s id. /// /// - /// allows you to extend Lua and Garry’s Mod type system with custom types. + /// allows you to extend Lua and Garry’s Mod type system with custom types. /// Returned type id can be used with . /// /// See section "Metatables" in the Lua manual for more information about types and metatables: https://www.lua.org/manual/5.1/manual.html @@ -601,7 +601,7 @@ public interface ILua /// A name for the new type. /// A type id for newly created type. /// - public int CreateMetaTable(in string name); + public int CreateMetaTable(string name); /// /// Pushes a metatable of the given type onto the stack. @@ -668,7 +668,7 @@ public interface ILua /// and k is an object on top of the stack. /// /// - /// Unlike , allows to get a value from the table when the key in the key-value pair is not a string. + /// Unlike , allows to get a value from the table when the key in the key-value pair is not a string. /// /// Pops a key object from the stack. /// @@ -676,7 +676,7 @@ public interface ILua /// /// A stack position of the table to get a value from. /// - /// The following example shows how can be used to get a value from the table instead of . + /// The following example shows how can be used to get a value from the table instead of . /// /// public static int GetTableExample(ILua lua) /// { @@ -691,7 +691,7 @@ public interface ILua /// } /// /// - /// + /// public void GetTable(int iStackPos); /// @@ -701,7 +701,7 @@ public interface ILua /// and k is a key at stack index -2. /// /// - /// Unlike , allows to add a key-value pair to a table with the key not being a string. + /// Unlike , allows to add a key-value pair to a table with the key not being a string. /// /// Pops both the key and the value from the stack. /// @@ -709,7 +709,7 @@ public interface ILua /// /// A stack position of the table to add a key-value pair to. /// - /// The following example shows how can be used instead of . + /// The following example shows how can be used instead of . /// /// public static int SetTableExample(ILua lua) /// { @@ -723,7 +723,7 @@ public interface ILua /// } /// /// - /// + /// public void SetTable(int iStackPos); /// @@ -882,7 +882,7 @@ public class GmodLuaException : Exception /// /// A Lua exception code. Must be one of the values defined by Lua specification. /// A Lua exception message. - public GmodLuaException(int lua_error_code, string lua_error_message) : base(lua_error_message) + public GmodLuaException(int lua_error_code, string? lua_error_message) : base(lua_error_message) { this.error_code = lua_error_code; } diff --git a/gm_dotnet_managed/GmodNET.API/ModuleAssemblyLoadContext.cs b/gm_dotnet_managed/GmodNET.API/ModuleAssemblyLoadContext.cs index 17099846..6d4f083a 100644 --- a/gm_dotnet_managed/GmodNET.API/ModuleAssemblyLoadContext.cs +++ b/gm_dotnet_managed/GmodNET.API/ModuleAssemblyLoadContext.cs @@ -21,7 +21,7 @@ public abstract class ModuleAssemblyLoadContext : AssemblyLoadContext /// /// Get current custom native library resolver delegate. /// - public abstract Func CustomNativeLibraryResolver {get; } + public abstract Func? CustomNativeLibraryResolver { get; } /// /// Initializes a new instance of the class with a value that indicates whether unloading is enabled. diff --git a/gm_dotnet_managed/GmodNET/GameConsoleWriter.cs b/gm_dotnet_managed/GmodNET/GameConsoleWriter.cs index 6eb016e2..47a06a21 100644 --- a/gm_dotnet_managed/GmodNET/GameConsoleWriter.cs +++ b/gm_dotnet_managed/GmodNET/GameConsoleWriter.cs @@ -110,11 +110,11 @@ public GameConsoleWriter(ILua lua) private delegate void MsgFunc(string str); - private static MsgFunc Msg; + private static MsgFunc? Msg; - public override void Write(string value) + public override void Write(string? value) { - if (!String.IsNullOrEmpty(value)) + if (!String.IsNullOrEmpty(value) && Msg is not null) { Msg(value); } @@ -123,7 +123,7 @@ public override void Write(char value) { Write(value.ToString()); } - public override void Write(char[] value) + public override void Write(char[]? value) { Write(new string(value)); } @@ -135,7 +135,7 @@ public override void Write(ReadOnlySpan buffer) { Write(new string(buffer)); } - public override void Write(StringBuilder value) + public override void Write(StringBuilder? value) { if (value != null) { @@ -143,7 +143,7 @@ public override void Write(StringBuilder value) } } // \n begins here - public override void WriteLine(string value) + public override void WriteLine(string? value) { if (!String.IsNullOrEmpty(value)) { @@ -158,7 +158,7 @@ public override void WriteLine(char value) { Write(value.ToString() + NewLine); } - public override void WriteLine(char[] buffer) + public override void WriteLine(char[]? buffer) { Write(new string(buffer) + NewLine); } @@ -170,7 +170,7 @@ public override void WriteLine(ReadOnlySpan buffer) { Write(new string(buffer) + NewLine); } - public override void WriteLine(StringBuilder value) + public override void WriteLine(StringBuilder? value) { if (value != null) { @@ -213,7 +213,7 @@ public override void WriteLine(decimal value) { Write(value.ToString() + NewLine); } - public override void WriteLine(object value) + public override void WriteLine(object? value) { if (value == null) { diff --git a/gm_dotnet_managed/GmodNET/GloabalContext.cs b/gm_dotnet_managed/GmodNET/GloabalContext.cs index 4f01f2cb..b7256910 100644 --- a/gm_dotnet_managed/GmodNET/GloabalContext.cs +++ b/gm_dotnet_managed/GmodNET/GloabalContext.cs @@ -103,9 +103,12 @@ int LoadModule(ILua lua) foreach (Type t in module_types) { - IModule current_module = (IModule)Activator.CreateInstance(t); - modules.Add(current_module); - gc_handles.Add(GCHandle.Alloc(current_module)); + IModule? current_module = Activator.CreateInstance(t) as IModule; + if (current_module is not null) + { + modules.Add(current_module); + gc_handles.Add(GCHandle.Alloc(current_module)); + } } if (modules.Count == 0) @@ -150,7 +153,7 @@ WeakReference UnloadHelper(string module_name) { foreach (GCHandle h in module_contexts[module_name].Item2) { - ((IModule)h.Target).Unload(lua); + (h.Target as IModule)?.Unload(lua); h.Free(); } diff --git a/gm_dotnet_managed/GmodNET/GmodNET.csproj b/gm_dotnet_managed/GmodNET/GmodNET.csproj index e5ef28e3..66333857 100644 --- a/gm_dotnet_managed/GmodNET/GmodNET.csproj +++ b/gm_dotnet_managed/GmodNET/GmodNET.csproj @@ -2,7 +2,9 @@ Exe - net6.0 + net7.0 + enable + Nullable GmodNET.BuidReq GmodNET managed module loader. MIT @@ -10,7 +12,7 @@ Git GmodNET $(Description) - Copyright (c) 2018 - 2021 Gleb Krasilich, GmodNET + Copyright (c) 2018 - 2023 Gleb Krasilich, GmodNET true true Portable @@ -23,10 +25,10 @@ - + all - + diff --git a/gm_dotnet_managed/GmodNET/GmodNetModuleAssemblyLoadContext.cs b/gm_dotnet_managed/GmodNET/GmodNetModuleAssemblyLoadContext.cs index a929658d..d76d4d3e 100644 --- a/gm_dotnet_managed/GmodNET/GmodNetModuleAssemblyLoadContext.cs +++ b/gm_dotnet_managed/GmodNET/GmodNetModuleAssemblyLoadContext.cs @@ -14,7 +14,7 @@ internal class GmodNetModuleAssemblyLoadContext : ModuleAssemblyLoadContext { private AssemblyDependencyResolver resolver; private string module_name; - private Func customNativeLibraryResolver; + private Func? customNativeLibraryResolver; private List native_libray_handles; public override string ModuleName @@ -25,13 +25,7 @@ public override string ModuleName } } - public override Func CustomNativeLibraryResolver - { - get - { - return customNativeLibraryResolver; - } - } + public override Func? CustomNativeLibraryResolver => customNativeLibraryResolver; public override void SetCustomNativeLibraryResolver(Func resolver) { @@ -65,14 +59,14 @@ internal GmodNetModuleAssemblyLoadContext(string module_name) : base(module_name }; } - protected override System.Reflection.Assembly Load(System.Reflection.AssemblyName assemblyName) + protected override System.Reflection.Assembly? Load(System.Reflection.AssemblyName assemblyName) { if(assemblyName.Name == "GmodNET.API") { return null; } - string path = resolver.ResolveAssemblyToPath(assemblyName); + string? path = resolver.ResolveAssemblyToPath(assemblyName); if (string.IsNullOrEmpty(path)) { return null; @@ -98,7 +92,7 @@ protected override IntPtr LoadUnmanagedDll (string unmanagedDllName) } else { - string unmanaged_dep_path = resolver.ResolveUnmanagedDllToPath(unmanagedDllName); + string? unmanaged_dep_path = resolver.ResolveUnmanagedDllToPath(unmanagedDllName); if(String.IsNullOrEmpty(unmanaged_dep_path)) { diff --git a/gm_dotnet_managed/GmodNET/Lua.cs b/gm_dotnet_managed/GmodNET/Lua.cs index 13d7ea68..e6242bf6 100644 --- a/gm_dotnet_managed/GmodNET/Lua.cs +++ b/gm_dotnet_managed/GmodNET/Lua.cs @@ -20,11 +20,21 @@ internal Lua(IntPtr ptr) public int Top() { + if (top is null) + { + throw new LuaInteropDelegateIsNullException(nameof(top)); + } + return top(ptr); } public void Push(int iStackPos) { + if (push is null) + { + throw new LuaInteropDelegateIsNullException(nameof(push)); + } + if (iStackPos == 0) { throw new ArgumentOutOfRangeException("iStackPos", "iStackPos can't be zero!"); @@ -34,6 +44,11 @@ public void Push(int iStackPos) public void Pop(int IAmt = 1) { + if (pop is null) + { + throw new LuaInteropDelegateIsNullException(nameof(pop)); + } + if (IAmt < 0) { throw new ArgumentOutOfRangeException("iAmt", "Can't pop negative number of items from the stack"); @@ -46,8 +61,13 @@ public void Pop(int IAmt = 1) pop(ptr, IAmt); } - public void GetField(int iStackPos, in string key) + public void GetField(int iStackPos, string key) { + if (get_field is null) + { + throw new LuaInteropDelegateIsNullException(nameof(get_field)); + } + if (iStackPos == 0) { throw new ArgumentOutOfRangeException("iStackPos", "iStackPos can't be zero!"); @@ -62,8 +82,13 @@ public void GetField(int iStackPos, in string key) } } - public void SetField(int iStackPos, in string key) + public void SetField(int iStackPos, string key) { + if (set_field is null) + { + throw new LuaInteropDelegateIsNullException(nameof(set_field)); + } + if (iStackPos == 0) { throw new ArgumentOutOfRangeException("iStackPos", "iStackPos can't be zero!"); @@ -80,11 +105,21 @@ public void SetField(int iStackPos, in string key) public void CreateTable() { + if (create_table is null) + { + throw new LuaInteropDelegateIsNullException(nameof(create_table)); + } + create_table(ptr); } public void SetMetaTable(int iStackPos) { + if (set_metatable is null) + { + throw new LuaInteropDelegateIsNullException(nameof(set_metatable)); + } + if (iStackPos == 0) { throw new ArgumentOutOfRangeException("iStackPos", "iStackPos can't be zero!"); @@ -94,6 +129,11 @@ public void SetMetaTable(int iStackPos) public bool GetMetaTable(int iStackPos) { + if (get_metatable is null) + { + throw new LuaInteropDelegateIsNullException(nameof(get_metatable)); + } + if (iStackPos == 0) { throw new ArgumentOutOfRangeException("iStackPos", "iStackPos can't be zero!"); @@ -113,16 +153,31 @@ public bool GetMetaTable(int iStackPos) [Obsolete("Unsafe. Use Lua.PCall instead.", false)] public void Call(int iArgs, int iResults) { + if (call is null) + { + throw new LuaInteropDelegateIsNullException(nameof(call)); + } + call(ptr, iArgs, iResults); } public int PCall(int IArgs, int IResults, int ErrorFunc) { + if (pcall is null) + { + throw new LuaInteropDelegateIsNullException(nameof(pcall)); + } + return pcall(ptr, IArgs, IResults, ErrorFunc); } public bool Equal(int iA, int iB) { + if (equal is null) + { + throw new LuaInteropDelegateIsNullException(nameof(equal)); + } + if(iA == 0 || iB == 0) { throw new ArgumentException("Neither iA or iB can't be 0"); @@ -141,6 +196,11 @@ public bool Equal(int iA, int iB) public bool RawEqual(int iA, int iB) { + if (raw_equal is null) + { + throw new LuaInteropDelegateIsNullException(nameof(raw_equal)); + } + if(iA == 0 || iB == 0) { throw new ArgumentException("Neither iA or iB can't be 0"); @@ -159,6 +219,11 @@ public bool RawEqual(int iA, int iB) public void Insert(int iStackPos) { + if (insert is null) + { + throw new LuaInteropDelegateIsNullException(nameof(insert)); + } + if (iStackPos == 0) { throw new ArgumentOutOfRangeException("iStackPos", "iStackPos can't be zero!"); @@ -168,6 +233,11 @@ public void Insert(int iStackPos) public void Remove(int iStackPos) { + if (remove is null) + { + throw new LuaInteropDelegateIsNullException(nameof(remove)); + } + if (iStackPos == 0) { throw new ArgumentOutOfRangeException("iStackPos", "iStackPos can't be zero!"); @@ -177,6 +247,11 @@ public void Remove(int iStackPos) public int Next(int iStackPos) { + if (next is null) + { + throw new LuaInteropDelegateIsNullException(nameof(next)); + } + if (iStackPos == 0) { throw new ArgumentOutOfRangeException("iStackPos", "iStackPos can't be zero!"); @@ -187,6 +262,11 @@ public int Next(int iStackPos) [Obsolete("BUG: LuaJIT exception mechanism is incompatible with CoreCLR.", true)] public void ThrowError(in string error_message) { + if (throw_error is null) + { + throw new LuaInteropDelegateIsNullException(nameof(throw_error)); + } + byte[] buff = Encoding.UTF8.GetBytes(error_message + "\0"); unsafe { @@ -200,6 +280,11 @@ public void ThrowError(in string error_message) [Obsolete("BUG: LuaJIT exception mechanism is incompatible with CoreCLR.", true)] public void CheckType(int iStackPos, int IType) { + if (check_type is null) + { + throw new LuaInteropDelegateIsNullException(nameof(check_type)); + } + if (iStackPos == 0) { throw new ArgumentOutOfRangeException("iStackPos", "iStackPos can't be zero!"); @@ -210,6 +295,11 @@ public void CheckType(int iStackPos, int IType) [Obsolete("BUG: LuaJIT exception mechanism is incompatible with CoreCLR.", true)] public void ArgError(int iArgNum, in string error_message) { + if (arg_error is null) + { + throw new LuaInteropDelegateIsNullException(nameof(arg_error)); + } + byte[] buff = Encoding.UTF8.GetBytes(error_message); unsafe { @@ -222,6 +312,11 @@ public void ArgError(int iArgNum, in string error_message) public string GetString(int iStackPos) { + if (get_string is null) + { + throw new LuaInteropDelegateIsNullException(nameof(get_string)); + } + if (iStackPos == 0) { throw new ArgumentOutOfRangeException("iStackPos", "iStackPos can't be zero!"); @@ -241,6 +336,11 @@ public string GetString(int iStackPos) public double GetNumber(int iStackPos) { + if (get_number is null) + { + throw new LuaInteropDelegateIsNullException(nameof(get_number)); + } + if (iStackPos == 0) { throw new ArgumentOutOfRangeException("iStackPos", "iStackPos can't be zero!"); @@ -250,6 +350,11 @@ public double GetNumber(int iStackPos) public bool GetBool(int iStackPos) { + if (get_bool is null) + { + throw new LuaInteropDelegateIsNullException(nameof(get_bool)); + } + if (iStackPos == 0) { throw new ArgumentOutOfRangeException("iStackPos", "iStackPos can't be zero!"); @@ -268,6 +373,11 @@ public bool GetBool(int iStackPos) public IntPtr GetCFunction(int iStackPos) { + if (get_c_function is null) + { + throw new LuaInteropDelegateIsNullException(nameof(get_c_function)); + } + if (iStackPos == 0) { throw new ArgumentOutOfRangeException("iStackPos", "iStackPos can't be zero!"); @@ -277,11 +387,21 @@ public IntPtr GetCFunction(int iStackPos) public void PushNil() { + if (push_nil is null) + { + throw new LuaInteropDelegateIsNullException(nameof(push_nil)); + } + push_nil(ptr); } - public void PushString(in string str) + public void PushString(string str) { + if (push_string is null) + { + throw new LuaInteropDelegateIsNullException(nameof(push_string)); + } + byte[] buff = Encoding.UTF8.GetBytes(str); unsafe @@ -295,11 +415,21 @@ public void PushString(in string str) public void PushNumber(double val) { + if (push_number is null) + { + throw new LuaInteropDelegateIsNullException(nameof(push_number)); + } + push_number(ptr, val); } public void PushBool(bool val) { + if (push_bool is null) + { + throw new LuaInteropDelegateIsNullException(nameof(push_bool)); + } + int tmp; if(val) @@ -316,6 +446,11 @@ public void PushBool(bool val) public unsafe void PushCFunction(IntPtr native_func_ptr) { + if (push_c_function is null) + { + throw new LuaInteropDelegateIsNullException(nameof(push_c_function)); + } + if(native_func_ptr == IntPtr.Zero) { throw new ArgumentNullException("native_func_ptr", "Parameter can't be nullptr."); @@ -326,6 +461,11 @@ public unsafe void PushCFunction(IntPtr native_func_ptr) public unsafe void PushCFunction(delegate* unmanaged[Cdecl] function_pointer) { + if (push_c_function is null) + { + throw new LuaInteropDelegateIsNullException(nameof(push_c_function)); + } + IntPtr int_ptr = (IntPtr)function_pointer; if (int_ptr == IntPtr.Zero) @@ -338,31 +478,61 @@ public unsafe void PushCFunction(delegate* unmanaged[Cdecl] functio public void PushCClosure(IntPtr native_func_ptr, int iVars) { + if (push_c_closure is null) + { + throw new LuaInteropDelegateIsNullException(nameof(push_c_closure)); + } + push_c_closure(ptr, native_func_ptr, iVars); } public int ReferenceCreate() { + if (reference_create is null) + { + throw new LuaInteropDelegateIsNullException(nameof(reference_create)); + } + return reference_create(ptr); } public void ReferenceFree(int reference) { + if (reference_free is null) + { + throw new LuaInteropDelegateIsNullException(nameof(reference_free)); + } + reference_free(ptr, reference); } public void ReferencePush(int reference) { + if (reference_push is null) + { + throw new LuaInteropDelegateIsNullException(nameof(reference_push)); + } + reference_push(ptr, reference); } public void PushSpecial(SPECIAL_TABLES table) { + if (push_special is null) + { + throw new LuaInteropDelegateIsNullException(nameof(push_special)); + } + push_special(ptr, (int)table); } public bool IsType(int iStackPos, int iType) { + if (is_type is null) + { + throw new LuaInteropDelegateIsNullException(nameof(is_type)); + } + if (iStackPos == 0) { throw new ArgumentOutOfRangeException("iStackPos", "iStackPos can't be zero!"); @@ -386,6 +556,11 @@ public bool IsType(int iStackPos, TYPES type) public int GetType(int iStackPos) { + if (get_type is null) + { + throw new LuaInteropDelegateIsNullException(nameof(get_type)); + } + if (iStackPos == 0) { throw new ArgumentOutOfRangeException("iStackPos", "iStackPos can't be zero!"); @@ -395,6 +570,11 @@ public int GetType(int iStackPos) public string GetTypeName(int iType) { + if (get_type_name is null) + { + throw new LuaInteropDelegateIsNullException(nameof(get_type_name)); + } + int len = 0; unsafe @@ -414,6 +594,11 @@ public string GetTypeName(TYPES type) public int ObjLen(int iStackPos) { + if (obj_len is null) + { + throw new LuaInteropDelegateIsNullException(nameof(obj_len)); + } + if (iStackPos == 0) { throw new ArgumentOutOfRangeException("iStackPos", "iStackPos can't be zero!"); @@ -423,6 +608,11 @@ public int ObjLen(int iStackPos) public Vector3 GetAngle(int iStackPos) { + if (get_angle is null) + { + throw new LuaInteropDelegateIsNullException(nameof(get_angle)); + } + if (iStackPos == 0) { throw new ArgumentOutOfRangeException("iStackPos", "iStackPos can't be zero!"); @@ -441,6 +631,11 @@ public Vector3 GetAngle(int iStackPos) public Vector3 GetVector(int iStackPos) { + if (get_vector is null) + { + throw new LuaInteropDelegateIsNullException(nameof(get_vector)); + } + if (iStackPos == 0) { throw new ArgumentOutOfRangeException("iStackPos", "iStackPos can't be zero!"); @@ -459,21 +654,41 @@ public Vector3 GetVector(int iStackPos) public void PushAngle(Vector3 ang) { + if (push_angle is null) + { + throw new LuaInteropDelegateIsNullException(nameof(push_angle)); + } + push_angle(ptr, ang.X, ang.Y, ang.Z); } public void PushVector(Vector3 vec) { + if (push_vector is null) + { + throw new LuaInteropDelegateIsNullException(nameof(push_vector)); + } + push_vector(ptr, vec.X, vec.Y, vec.Z); } public void SetState(IntPtr lua_state) { + if (set_state is null) + { + throw new LuaInteropDelegateIsNullException(nameof(set_state)); + } + set_state(ptr, lua_state); } - public int CreateMetaTable(in string name) + public int CreateMetaTable(string name) { + if (create_metatable is null) + { + throw new LuaInteropDelegateIsNullException(nameof(create_metatable)); + } + byte[] buff = Encoding.UTF8.GetBytes(name); unsafe @@ -487,6 +702,11 @@ public int CreateMetaTable(in string name) public bool PushMetaTable(int iType) { + if (push_metatable is null) + { + throw new LuaInteropDelegateIsNullException(nameof(push_metatable)); + } + int tmp = push_metatable(ptr, iType); if(tmp == 0) @@ -506,11 +726,21 @@ public bool PushMetaTable(TYPES type) public void PushUserType(IntPtr data_pointer, int iType) { + if (push_user_type is null) + { + throw new LuaInteropDelegateIsNullException(nameof(push_user_type)); + } + push_user_type(ptr, data_pointer, iType); } public void SetUserType(int iStackPos, IntPtr data_pointer) { + if (set_user_type is null) + { + throw new LuaInteropDelegateIsNullException(nameof(set_user_type)); + } + if (iStackPos == 0) { throw new ArgumentOutOfRangeException("iStackPos", "iStackPos can't be zero!"); @@ -519,7 +749,12 @@ public void SetUserType(int iStackPos, IntPtr data_pointer) } public IntPtr GetUserType(int iStackPos, int iType) - { + { + if (get_user_type is null) + { + throw new LuaInteropDelegateIsNullException(nameof(get_user_type)); + } + if (iStackPos == 0) { throw new ArgumentOutOfRangeException("iStackPos", "iStackPos can't be zero!"); @@ -529,6 +764,11 @@ public IntPtr GetUserType(int iStackPos, int iType) public void GetTable(int iStackPos) { + if (get_table is null) + { + throw new LuaInteropDelegateIsNullException(nameof(get_table)); + } + if (iStackPos == 0) { throw new ArgumentOutOfRangeException("iStackPos", "iStackPos can't be zero!"); @@ -538,6 +778,11 @@ public void GetTable(int iStackPos) public void SetTable(int iStackPos) { + if (set_table is null) + { + throw new LuaInteropDelegateIsNullException(nameof(set_table)); + } + if (iStackPos == 0) { throw new ArgumentOutOfRangeException("iStackPos", "iStackPos can't be zero!"); @@ -547,6 +792,11 @@ public void SetTable(int iStackPos) public void RawGet(int iStackPos) { + if (raw_get is null) + { + throw new LuaInteropDelegateIsNullException(nameof(raw_get)); + } + if (iStackPos == 0) { throw new ArgumentOutOfRangeException("iStackPos", "iStackPos can't be zero!"); @@ -556,6 +806,11 @@ public void RawGet(int iStackPos) public void RawSet(int iStackPos) { + if (raw_set is null) + { + throw new LuaInteropDelegateIsNullException(nameof(raw_set)); + } + if (iStackPos == 0) { throw new ArgumentOutOfRangeException("iStackPos", "iStackPos can't be zero!"); @@ -565,12 +820,22 @@ public void RawSet(int iStackPos) public void PushUserData(IntPtr data) { + if (push_user_data is null) + { + throw new LuaInteropDelegateIsNullException(nameof(push_user_data)); + } + push_user_data(ptr, data); } [Obsolete("BUG: LuaJIT exception mechanism is incompatible with CoreCLR.", true)] public string CheckString(int iStackPos) { + if (check_string is null) + { + throw new LuaInteropDelegateIsNullException(nameof(check_string)); + } + int str_len = 0; unsafe { @@ -591,6 +856,11 @@ public string CheckString(int iStackPos) [Obsolete("BUG: LuaJIT exception mechanism is incompatible with CoreCLR.", true)] public double CheckNumber(int iStackPos) { + if (check_number is null) + { + throw new LuaInteropDelegateIsNullException(nameof(check_number)); + } + return check_number(ptr, iStackPos); } diff --git a/gm_dotnet_managed/GmodNET/LuaInterop.cs b/gm_dotnet_managed/GmodNET/LuaInterop.cs index b381ab1c..e527034a 100644 --- a/gm_dotnet_managed/GmodNET/LuaInterop.cs +++ b/gm_dotnet_managed/GmodNET/LuaInterop.cs @@ -9,121 +9,134 @@ namespace GmodNET [SuppressUnmanagedCodeSecurity] internal static class LuaInterop { - static internal Func top; + static internal Func? top; - static internal Action push; + static internal Action? push; - static internal Action pop; + static internal Action? pop; - static internal Action get_field; + static internal Action? get_field; - static internal Action set_field; + static internal Action? set_field; - static internal Action create_table; + static internal Action? create_table; - static internal Action set_metatable; + static internal Action? set_metatable; - static internal Func get_metatable; + static internal Func? get_metatable; - static internal Action call; + static internal Action? call; - static internal Func pcall; + static internal Func? pcall; - static internal Func equal; + static internal Func? equal; - static internal Func raw_equal; + static internal Func? raw_equal; - static internal Action insert; + static internal Action? insert; - static internal Action remove; + static internal Action? remove; - static internal Func next; + static internal Func? next; - static internal Action throw_error; + static internal Action? throw_error; - static internal Action check_type; + static internal Action? check_type; - static internal Action arg_error; + static internal Action? arg_error; - static internal Func get_string; + static internal Func? get_string; - static internal Func get_number; + static internal Func? get_number; - static internal Func get_bool; + static internal Func? get_bool; - static internal Func get_c_function; + static internal Func? get_c_function; - static internal Action push_nil; + static internal Action? push_nil; - static internal Action push_string; + static internal Action? push_string; - static internal Action push_number; + static internal Action? push_number; - static internal Action push_bool; + static internal Action? push_bool; - static internal Action push_c_function; + static internal Action? push_c_function; - static internal Action push_c_closure; + static internal Action? push_c_closure; - static internal Func reference_create; + static internal Func? reference_create; - static internal Action reference_free; + static internal Action? reference_free; - static internal Action reference_push; + static internal Action? reference_push; - static internal Action push_special; + static internal Action? push_special; - static internal Func is_type; + static internal Func? is_type; - static internal Func get_type; + static internal Func? get_type; - static internal Func get_type_name; + static internal Func? get_type_name; - static internal Func obj_len; + static internal Func? obj_len; - static internal Action get_angle; + static internal Action? get_angle; - static internal Action get_vector; + static internal Action? get_vector; - static internal Action push_angle; + static internal Action? push_angle; - static internal Action push_vector; + static internal Action? push_vector; - static internal Action set_state; + static internal Action? set_state; - static internal Func create_metatable; + static internal Func? create_metatable; - static internal Func push_metatable; + static internal Func? push_metatable; - static internal Action push_user_type; + static internal Action? push_user_type; - static internal Action set_user_type; + static internal Action? set_user_type; - static internal Func get_user_type; + static internal Func? get_user_type; - static internal Func get_iluabase_from_the_lua_state; + static internal Func? get_iluabase_from_the_lua_state; - static internal Action get_table; + static internal Action? get_table; - static internal Action set_table; + static internal Action? set_table; - static internal Action raw_get; + static internal Action? raw_get; - static internal Action raw_set; + static internal Action? raw_set; - static internal Action push_user_data; + static internal Action? push_user_data; - static internal Func check_string; + static internal Func? check_string; - static internal Func check_number; + static internal Func? check_number; - static internal Action push_c_function_safe; + static internal Action? push_c_function_safe; internal static ILua ExtructLua(IntPtr lua_state) - { + { + if (get_iluabase_from_the_lua_state is null) + { + throw new LuaInteropDelegateIsNullException(nameof(get_iluabase_from_the_lua_state)); + } + IntPtr tmp_ptr = LuaInterop.get_iluabase_from_the_lua_state(lua_state); return new Lua(tmp_ptr); } } + + internal class LuaInteropDelegateIsNullException : Exception + { + public LuaInteropDelegateIsNullException(string nameOfDelegate) : base($"Delegate {nameOfDelegate} is null. Critical Gmod.NET runtime error occurred") + { + + } + } } diff --git a/gm_dotnet_managed/GmodNET/ManagedFunctionMetaMethods.cs b/gm_dotnet_managed/GmodNET/ManagedFunctionMetaMethods.cs index 2120590c..009d93f9 100644 --- a/gm_dotnet_managed/GmodNET/ManagedFunctionMetaMethods.cs +++ b/gm_dotnet_managed/GmodNET/ManagedFunctionMetaMethods.cs @@ -28,7 +28,12 @@ internal static int ManagedDelegateExecutor(IntPtr lua_state) IntPtr managed_delegate_handle = lua.GetUserType(GmodInterop.GetUpvalueIndex(1, false), managed_delegate_type_id); - Func managed_delegate = (Func)GCHandle.FromIntPtr(managed_delegate_handle).Target; + Func? managed_delegate = GCHandle.FromIntPtr(managed_delegate_handle).Target as Func; + + if (managed_delegate is null) + { + throw new Exception("Unable to get managed delegate from GCHandle"); + } return Math.Max(0, managed_delegate(lua)); } diff --git a/gm_dotnet_managed/GmodNET/RuntimeServices.cs b/gm_dotnet_managed/GmodNET/RuntimeServices.cs index 87be015a..ef97f442 100644 --- a/gm_dotnet_managed/GmodNET/RuntimeServices.cs +++ b/gm_dotnet_managed/GmodNET/RuntimeServices.cs @@ -12,7 +12,7 @@ internal static class RuntimeServices { internal static T CreateNativeCaller(IntPtr native_pointer) where T : Delegate { - MethodInfo invoke_info = typeof(T).GetMethod("Invoke"); + MethodInfo invoke_info = typeof(T).GetMethod("Invoke")!; // T is constrained to Delegates only, so Invoke method is always present. var return_type = invoke_info.ReturnType; var parameters_types = invoke_info.GetParameters().Select(param => param.ParameterType).Prepend(typeof(object)).ToArray(); diff --git a/gm_dotnet_managed/GmodNET/Startup.cs b/gm_dotnet_managed/GmodNET/Startup.cs index a971cf2a..03996b2f 100644 --- a/gm_dotnet_managed/GmodNET/Startup.cs +++ b/gm_dotnet_managed/GmodNET/Startup.cs @@ -27,9 +27,20 @@ internal static unsafe IntPtr Main(IntPtr lua_base, IntPtr native_version_string { try { - string full_assembly_version = FileVersionInfo.GetVersionInfo(typeof(Startup).Assembly.Location).ProductVersion; - string friendly_version = full_assembly_version.Split("+")[0]; - string version_codename = full_assembly_version.Split("+")[1].Split(".")[1]; + string full_assembly_version = FileVersionInfo.GetVersionInfo(typeof(Startup).Assembly.Location).ProductVersion ?? string.Empty; + + string friendly_version; + string version_codename; + + try + { + friendly_version = full_assembly_version.Split("+")[0]; + version_codename = full_assembly_version.Split("+")[1].Split(".")[1]; + } + catch + { + throw new Exception("Unable to parse version number according to specification"); + } string native_version = Encoding.UTF8.GetString((byte*)native_version_string.ToPointer(), version_string_length); diff --git a/gm_dotnet_managed/Tests/Tests.csproj b/gm_dotnet_managed/Tests/Tests.csproj index f20f5dcf..74f94255 100644 --- a/gm_dotnet_managed/Tests/Tests.csproj +++ b/gm_dotnet_managed/Tests/Tests.csproj @@ -1,7 +1,7 @@  - net6.0 + net7.0 @@ -27,7 +27,7 @@ - + all diff --git a/gm_dotnet_native/external_includes/netcore/hostfxr.h b/gm_dotnet_native/external_includes/netcore/hostfxr.h index 49afae3d..591a8ebb 100644 --- a/gm_dotnet_native/external_includes/netcore/hostfxr.h +++ b/gm_dotnet_native/external_includes/netcore/hostfxr.h @@ -64,7 +64,7 @@ typedef void(HOSTFXR_CALLTYPE *hostfxr_error_writer_fn)(const char_t *message); // By default no callback is registered in which case the errors are written to stderr. // // Each call to the error writer is sort of like writing a single line (the EOL character is omitted). -// Multiple calls to the error writer may occure for one failure. +// Multiple calls to the error writer may occur for one failure. // // If the hostfxr invokes functions in hostpolicy as part of its operation, the error writer // will be propagated to hostpolicy for the duration of the call. This means that errors from @@ -314,10 +314,10 @@ struct hostfxr_dotnet_environment_info const char_t* hostfxr_commit_hash; size_t sdk_count; - const hostfxr_dotnet_environment_sdk_info* sdks; + const struct hostfxr_dotnet_environment_sdk_info* sdks; size_t framework_count; - const hostfxr_dotnet_environment_framework_info* frameworks; + const struct hostfxr_dotnet_environment_framework_info* frameworks; }; #endif //__HOSTFXR_H__ diff --git a/runtime.csproj b/runtime.csproj index d4931796..f645661b 100644 --- a/runtime.csproj +++ b/runtime.csproj @@ -2,20 +2,20 @@ - net6.0 + net7.0 - 6.0.0 + 7.0.2 - https://download.visualstudio.microsoft.com/download/pr/3cc56ba5-399e-455a-9e36-3d384e1af246/92cc0b1f002350c18262a06f5a99bbc1/aspnetcore-runtime-6.0.0-win-x64.zip + https://download.visualstudio.microsoft.com/download/pr/79dbfb6e-78b4-4e2c-a3a9-040666d6b407/ad24076fc19fdfa6c7acdd6bad8a1fc5/aspnetcore-runtime-7.0.2-win-x64.zip - https://download.visualstudio.microsoft.com/download/pr/a8dd1c9d-1a47-4135-8ad8-7091ff6bbe1e/6af53c3eee71038248937daf4599f06a/aspnetcore-runtime-6.0.0-linux-x64.tar.gz + https://download.visualstudio.microsoft.com/download/pr/1d8c4b4c-aec9-451b-9bd3-bf7cdbd28477/def6c1a7a9cfd4590698d4f338da2803/aspnetcore-runtime-7.0.2-linux-x64.tar.gz - https://download.visualstudio.microsoft.com/download/pr/27e5cf62-0d07-44cd-a057-425887434b9e/5f87e0c4d9be2151a2d0c9efc4530751/aspnetcore-runtime-6.0.0-osx-x64.tar.gz + https://download.visualstudio.microsoft.com/download/pr/035d61f7-0418-4834-8364-eec4d3c3d112/b1fd356e10f14ee2c930e023654186f3/aspnetcore-runtime-7.0.2-osx-x64.tar.gz diff --git a/version.json b/version.json index 3a4ad186..fca5373e 100644 --- a/version.json +++ b/version.json @@ -1,4 +1,4 @@ { - "Version": "0.7.0-rc.1", - "Codename": "UstIlimsk" + "Version": "1.0.0", + "Codename": "Trubchevsk" }