diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index e22c60eb2..351cdd3be 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -4,55 +4,65 @@ on: push: branches: - master - pull_request: - branches: - - master -defaults: - run: - working-directory: ./EXILED +# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages +permissions: + actions: read + pages: write + id-token: write env: - EXILED_REFERENCES_URL: https://misaka-zerotwo.github.io/SL-References/Master.zip + EXILED_REFERENCES_URL: https://Exiled-Official.github.io/SL-References/Dev.zip EXILED_REFERENCES_PATH: ${{ github.workspace }}/EXILED/References + +# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. +# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. +# Important due to https://t.ly/5DZAy +concurrency: + group: "pages" + cancel-in-progress: false jobs: - build_and_publish_docs: - runs-on: windows-latest - + publish-docs: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + + runs-on: ubuntu-latest + steps: - - name: Checkout - uses: actions/checkout@v2.3.4 - - - name: Setup .NET Core SDK - uses: actions/setup-dotnet@v1.7.2 - - - name: Setup Nuget - uses: iRebbok/setup-nuget@master - - - name: Get references - shell: pwsh - run: | - Invoke-WebRequest -Uri ${{ EXILED_REFERENCES_URL }} -OutFile ${{ github.workspace }}/EXILED/References.zip - Expand-Archive -Path References.zip -DestinationPath ${{ env.EXILED_REFERENCES_PATH }} - - - name: Download DocFX - uses: crazy-max/ghaction-chocolatey@v1 - with: - args: install docfx --pre - - - name: Run DocFX - env: - EXILED_REFERENCES: ${{ env.EXILED_REFERENCES_PATH }} - run: docfx docfx.json; docfx docfx.json - - - name: Deploy to GitHub Pages - if: github.event_name == 'push' && success() #Only publishes on push to master to avoid docs mishaps - uses: crazy-max/ghaction-github-pages@v2 - with: - target_branch: gh-pages - build_dir: _site - keep_history: true - jekyll: false - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Checkout + uses: actions/checkout@v3 + + - name: Dotnet Setup + uses: actions/setup-dotnet@v3 + with: + dotnet-version: 8.x + + - run: dotnet tool update -g docfx + + - name: Setup .NET Core SDK + uses: actions/setup-dotnet@v1.7.2 + + - name: Setup Nuget + uses: iRebbok/setup-nuget@master + + - name: Get references + shell: pwsh + run: | + Invoke-WebRequest -Uri $env:EXILED_REFERENCES_URL -OutFile $env:GITHUB_WORKSPACE/EXILED/References.zip + Expand-Archive -Path $env:GITHUB_WORKSPACE/EXILED/References.zip -DestinationPath $env:EXILED_REFERENCES_PATH + + - run: docfx EXILED/docs/docfx.json + env: + EXILED_REFERENCES: ${{ env.EXILED_REFERENCES_PATH }} + + - name: Upload artifact + uses: actions/upload-pages-artifact@v3 + with: + # Upload entire repository + path: 'EXILED/docs/_site' + + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 diff --git a/EXILED/Exiled.CustomItems/API/Features/CustomArmor.cs b/EXILED/Exiled.CustomItems/API/Features/CustomArmor.cs index b41051f12..b50954d64 100644 --- a/EXILED/Exiled.CustomItems/API/Features/CustomArmor.cs +++ b/EXILED/Exiled.CustomItems/API/Features/CustomArmor.cs @@ -30,7 +30,7 @@ public override ItemType Type get => base.Type; set { - if (!value.IsArmor() && (value != ItemType.None)) + if (value != ItemType.None && !value.IsArmor()) throw new ArgumentOutOfRangeException("Type", value, "Invalid armor type."); base.Type = value; diff --git a/EXILED/Exiled.Loader/LoaderPlugin.cs b/EXILED/Exiled.Loader/LoaderPlugin.cs index 23dc888e2..ea9977fb4 100644 --- a/EXILED/Exiled.Loader/LoaderPlugin.cs +++ b/EXILED/Exiled.Loader/LoaderPlugin.cs @@ -38,6 +38,12 @@ public class LoaderPlugin [PluginPriority(byte.MinValue)] public void Enable() { + if (Config == null) + { + Log.Error("Detected null config, EXILED will not be loaded."); + return; + } + if (!Config.IsEnabled) { Log.Info("EXILED is disabled on this server via config."); diff --git a/EXILED/docs/articles/contributing/index.md b/EXILED/docs/articles/contributing/index.md new file mode 100644 index 000000000..021e1baa6 --- /dev/null +++ b/EXILED/docs/articles/contributing/index.md @@ -0,0 +1,38 @@ +--- +title: Contributing to EXILED +--- +# Contributing to EXILED + +This is a simple tutorial guiding you to contribute to our framework. + +### Forking EXILED +First, create a fork of our [GitHub repository](https://github.com/Exiled-Official/EXILED). + +Then, clone it to your computer like so: `git clone https://github.com/your-username/EXILED.git` + +Open a terminal in your forked EXILED folder and run ```git checkout dev```. This will switch you to the dev branch, which all pull requests should be submitted to. + +### Setting `EXILED_REFERENCES` + +If you haven't already, install the `SCP: Secret Laboratory Dedicated Server` through Steam or extract [this zip file](https://Exiled-Official.github.io/SL-References/Dev.zip) to an easily accessible folder. + +#### Windows users +Open the Environment Variables menu by searching for `Environment Variables` in the Start Menu. + +Create a new environment variable titled `EXILED_REFERENCES`. + +The value should point to `your_steamapps_directory/common/SCP Secret Laboratory Dedicated Server/SCPSL_Data/Managed`, or to the folder where you extracted the zip file mentioned earlier. + +#### Linux users +Add `export EXILED_REFERENCES="PATH"` to your `~/.bashrc` or similar file. + +PATH should point to `your_steamapps_directory/common/SCP Secret Laboratory Dedicated Server/SCPSL_Data/Managed`, or to the folder where you extracted the zip file mentioned earlier. + +--- + +You should now be able to open the EXILED directory in your favorite IDE. + + +Once you are done, test your changes thoroughly, and then submit a pull request to the main EXILED repository. Make sure you are targeting the `dev` branch, not `master`! + +Happy coding! \ No newline at end of file diff --git a/EXILED/docs/articles/index.md b/EXILED/docs/articles/index.md new file mode 100644 index 000000000..48ce7e0e1 --- /dev/null +++ b/EXILED/docs/articles/index.md @@ -0,0 +1,49 @@ +--- +title: Introduction +--- + +# Exiled Introduction + +## About EXILED + +**EXILED** is a low level plugin framework for SCP: Secret Laboratory. + +It offers an event system for developers to hook in order to manipulate or change game code, or implement their own functions. + +All **EXILED** events are coded with [Harmony](https://harmony.pardeike.net/) using IL transpilers, meaning they require no direct editing of server Assemblies to function, which allows for two unique benefits. + +- The entirety of the frameworks code can be freely published and shared. Allowing developers to better understand how it works, as well as contributing to the framework itself. +- Since all of the code related to the framework is done outside of the server assembly, things like small game updates will have little, if any, effect on the framework. + +--- + +# Frequently Asked Questions + +## What is EXILED? +EXILED - short for "EXtended In-runtime Library for External Development" is a plugin framework for SCP: Secret Laboratory compatible with MP2. It is not a direct replacement for SMOD, but it's purpose is to implement an event-based framework using Harmony patches, that plugin developers can utilize to develop plugins for SCP:SL servers. + +## How do I install EXILED? +See the [Installation](https://jesus-qc.github.io/EXILED/articles/installation/index.html) page for installation information. + +## How do I install plugins? +All plugins contain a DLL file (found in its latest release) that is used to load the plugin. Place the plugin in the appropriate plugin folder. +- Windows: `%AppData%\EXILED\Configs(ServerPortHere)-configs.yml` +- Linux: `~/.config/EXILED/Configs(ServerPortHere)-configs.yml` + +## Where is plugin configuration stored? +Plugin configuration is stored in a separate folder than the base-game config files. +- Windows: `%AppData%\EXILED\Plugins` +- Linux: `~/.config/EXILED/Plugins` + +## Is there a plugin for upgrading items in hand, inside SCP-914? +No, this is unnecessary because this is a base-game feature! Simply set the `914_mode` config_gameplay config to `DroppedAndHeld`. + +## What is Harmony? +Harmony is a library that examines the code of a program as it is being run, allowing developers to tap into those functions, and run their own code, either adding onto, or completely replacing, the code the program would normally run. + + +The reason EXILED uses harmony is to allow easier updating of the framework in conjunction with game updates. Under ideal circumstances, a new game update will not break EXILED itself, and the only thing needed to make EXILED work again, is a very simple copy/paste of a few lines of code into the new Assembly-CSharp file. + + +By keeping all of our code outside of the Assembly, other developers can have full, unhindered access to the entirety of EXILED's source code, making collaboration easier.
+Additionally, it means that our code will be mostly unaffected by game updates. Unless the game drastically changes code in a very specific function EXILED uses for an event patch, a game update may not even require EXILED itself to also be updated. diff --git a/EXILED/docs/articles/installation/automatic/linux.md b/EXILED/docs/articles/installation/automatic/linux.md new file mode 100644 index 000000000..2bd2e6934 --- /dev/null +++ b/EXILED/docs/articles/installation/automatic/linux.md @@ -0,0 +1,43 @@ +--- +title: Automatic Linux Installation +--- + +# Automatic Linux Installation + +Download `Exiled.Installer-Linux` from [here](https://github.com/Exiled-Official/EXILED/releases). + +Move it into your **server directory** and run it using `./Exiled.Installer-Linux` +- Make sure the server directory is the one where LocalAdmin executable is found. + +#### Usage +``` +Usage: + Exiled.Installer [options] [[--] ...]] + +Options: + -p, --path (REQUIRED) Path to the folder with the SL server [default: YourWorkingFolder] + --appdata (REQUIRED) Forces the folder to be the AppData folder (useful for containers when pterodactyl runs as root) [default: YourAppDataPath] + --pre-releases Includes pre-releases [default: False] + --target-version Target version for installation + --github--token Uses a token for auth in case the rate limit is exceeded (no permissions required) + --exit Automatically exits the application anyway + --get-versions Gets all possible versions for installation + --version Show version information + -?, -h, --help Show help and usage information + +Additional Arguments: + Arguments passed to the application that is being run. +``` + +----- + +#### Examples + +- ##### Installation in a specific folder, specific version and specific appdata folder +```powershell title="Basic installation in the folder you are in" +.\Exiled.Installer-Linux --pre-releases +``` + +```powershell title="Installation in a specific folder, specific version and specific appdata folder" +.\Exiled.Installer-Linux -p /home/user/scpsl/server --appdata /home/user/scpsl --target-version 2.0.8 +``` \ No newline at end of file diff --git a/EXILED/docs/articles/installation/automatic/windows.md b/EXILED/docs/articles/installation/automatic/windows.md new file mode 100644 index 000000000..d28ba2449 --- /dev/null +++ b/EXILED/docs/articles/installation/automatic/windows.md @@ -0,0 +1,43 @@ +--- +title: Automatic Windows Installation +--- + +# Automatic Windows Installation + +Download `Exiled.Installer-Win.exe` from [here](https://github.com/Exiled-Official/EXILED/releases). + +Move it into your **server directory** and double click the .exe. +- Make sure the server directory is the one where LocalAdmin.exe is found. + +#### Usage +``` +Usage: + Exiled.Installer [options] [[--] ...]] + +Options: + -p, --path (REQUIRED) Path to the folder with the SL server [default: YourWorkingFolder] + --appdata (REQUIRED) Forces the folder to be the AppData folder (useful for containers when pterodactyl runs as root) [default: YourAppDataPath] + --pre-releases Includes pre-releases [default: False] + --target-version Target version for installation + --github--token Uses a token for auth in case the rate limit is exceeded (no permissions required) + --exit Automatically exits the application anyway + --get-versions Gets all possible versions for installation + --version Show version information + -?, -h, --help Show help and usage information + +Additional Arguments: + Arguments passed to the application that is being run. +``` + +----- + +#### Examples +Using powershell. + +```powershell title="Basic installation in the folder you are in" +.\Exiled.Installer-Win --pre-releases +``` + +```powershell title="Installation in a specific folder, specific version and specific appdata folder" +.\Exiled.Installer-Win -p D:\Games\SCPSL\Server --appdata C --target-version 2.0.8 +``` \ No newline at end of file diff --git a/EXILED/docs/articles/installation/index.md b/EXILED/docs/articles/installation/index.md new file mode 100644 index 000000000..dba236d2c --- /dev/null +++ b/EXILED/docs/articles/installation/index.md @@ -0,0 +1,15 @@ +--- +title: Installing EXILED +--- + +# Installing EXILED + +## Automatic Installation + +Exiled has a tool that allows you to install **automatically** the framework for you. + +## Guides + +- [Window Automatic Installation](/EXILED/articles/installation/automatic/windows.html). +- [Linux Automatic Installation](/EXILED/articles/installation/automatic/linux.html). +- [Manual Installation](EXILED/articles/installation/manual.html). \ No newline at end of file diff --git a/EXILED/docs/articles/installation/manual.md b/EXILED/docs/articles/installation/manual.md new file mode 100644 index 000000000..650f02fbc --- /dev/null +++ b/EXILED/docs/articles/installation/manual.md @@ -0,0 +1,24 @@ +--- +title: Manual Installation +--- + +# Manual Installation + +You can download exiled manually following this steps: + +### Pick a release + +You can select a release inside [our official GitHub repo](https://github.com/Exiled-Official/EXILED/releases/). + +### Download the release + +Download the `Exiled.tar.gz` file and extract it with your favourite tool, we recommend [7Zip](https://www.7-zip.org/) or [WinRar](https://www.win-rar.com/download.html?&L=6). + +### Installation + +1. Move the file **``Assembly-CSharp.dll``** to: **`(Your Server Folder)/SCPSL_Data/Managed`** and replace the file. +2. Move the **``EXILED``** folder to **`%appdata%`** + +#### Note: +- Windows: This **`%appdata%`** folder is the one located inside **`AppData/Roaming`**, not just `AppData`. +- Linux: This **`%appdata%`** folder is the one called **`~/.config`**. \ No newline at end of file diff --git a/EXILED/docs/articles/plugins/events.md b/EXILED/docs/articles/plugins/events.md new file mode 100644 index 000000000..8bd83cc15 --- /dev/null +++ b/EXILED/docs/articles/plugins/events.md @@ -0,0 +1,61 @@ +--- +title: Events +--- + +This tutorial assumes that you are familiar with C# and with setting up a plugin in the EXILED framework. See the tutorial if you are unfamiliar with setting up a plugin using EXILED. + +# Events: What are they? +**Events** play a key role in the EXILED framework and all of the plugins utilizing it. Almost every plugin created using the EXILED framework uses events in one way or another. So, what are they? An event is a simple way of being informed when *something* happens. Events range from the round ending, to a player throwing an item or opening a door, to even SCP-096 being enraged! Events allow you to attach code that executes when something occurs before, during, or at the conclusion of a round. + +For example, say that you have the following method. + +```cs +public void OnDead() +{ + // Show hint to player. +} +``` + +With EXILED, it is possible to achieve the desired result: Showing a hint to a player who dies. + +## Event structure +The EXILED framework consists of two different types of events: Events that can be disallowed, and those that cannot. Events that can be disallowed can prevent certain events from happening; as an example, preventing a player from dying when they normally should. The ability to prevent certain events from happening is what gives EXILED its beauty. + +All events are part of a static class called a **handler**. All handlers can be found in the `Exiled.Events` namespace. Every handler is related to a specific feature in the game (eg. `Exiled.Events.Scp096` contains SCP-096 related events). + +Almost all events have a corresponding **event argument** class. The event argument provides the data of an event, as well as the ability to prevent it from occurring. All event arguments can be found in the `Exiled.Events.EventArgs` namespace, and all event arguments inherit from `System.EventArgs`. + +### Example: Enraging event +The following is the structure of the `Exiled.Events.EventArgs.EnragingEventArgs`. +```cs +public class EnragingEventArgs : System.EventArgs +{ + // Note: Constructor omitted. + public Scp096 Scp096 { get; } // The SCP-096 instance. + public Player Player { get; } // The player controlling SCP-096. + public bool IsAllowed { get; set; } // Whether or not SCP-096 can be enraged. +} +``` +Notice the `IsAllowed` property of the event. This property, which defaults to `true`, can be set to `false` to prevent SCP-096 from being enraged. For most events that can be disallowed, `IsAllowed` is set to `true` by default, and plugins can set it to `false` to prevent the event from occurring. However, in some cases, `IsAllowed` defaults to false and plugins can set it to `true` to *allow* the event to occur. An example of this behavior is the `InteractingDoor` event. `IsAllowed` will default to `false` in this event if a player cannot open a door, however plugins may set it to `true` to allow the player to open it regardless. + +## Connecting events +Events can be connected and disconnected by using the `+=` and `-=` operators. These can be used in the plugin's `OnEnabled` and `OnDisabled` methods, respectively. +```cs +// Base plugin class +// This example assumes a method called "OnEnraging" exists in this class. For best practice, you should create a new class to handle events. +using Exiled.Events; +public override void OnEnabled() +{ + Scp096.Enraging += OnEnraging; // Scp096 is the event handler, while Enraging is the name of the event. The += operator connects this event to the provided method. +} +public override void OnDisabled() +{ + Scp096.Enraging -= OnEnraging; // The -= operator disconnects this event from the provided method. +} +// Some other class +using Exiled.Events.EventArgs; +public void OnEnraging(EnragingEventArgs ev) // ev is the arguments for the event. Every event has a different argument class with different parameters, so make sure to check its documentation. +{ + Log.Info(ev.Player.Nickname + " has just been enraged!"); +} +``` \ No newline at end of file diff --git a/EXILED/docs/articles/plugins/mec.md b/EXILED/docs/articles/plugins/mec.md new file mode 100644 index 000000000..af80eb0c7 --- /dev/null +++ b/EXILED/docs/articles/plugins/mec.md @@ -0,0 +1,49 @@ +--- +title: MEC (More Effective Coroutines) +--- + +This tutorial assumes that you are familiar with C# and with setting up a plugin in the EXILED framework. See the Plugin Structure tutorial if you are unfamiliar with setting up a plugin using **EXILED**. + +# MEC (More Effective Coroutines) +If you are unfamiliar with MEC, this will be a very brief and simple primer to get you started. **MEC Coroutines** are basically timed methods, that support waiting periods of time before continuing execution, without interrupting/sleeping the main game thread. MEC coroutines are safe to use with Unity, unlike traditional threading, which *will* crash the server. + +MEC is useful for plugins which require a pre-defined timeout between execution. As an example, an automatic nuke plugin would want to pause for a certain amount of seconds before activating the warhead. A supply drop plugin would want to wait in certain intervals before executing a supply drop. Both of these are possible with MEC. + +## Setup +Unlike other API provided by SCP:SL, MEC requires a reference to the `Assembly-CSharp-firstpass` DLL file. After referencing this file, a `using MEC;` statement allows MEC to be used. + +## Coroutine +MEC offers [tons of features](http://trinary.tech/category/mec/free/) for controlling threads. For this tutorial, we are going to look at two of them: coroutines, and delayed calls. A coroutine is a method that is executed by MEC and supports delays. These methods must return type `IEnumerator` and must be called by `Timing.RunCoroutine(Method())`. An example can be seen below, using an infinite loop with a 5 second delay. + +```cs +using MEC; +using Exiled.API.Features; +public void SomeMethod() +{ + Timing.RunCoroutine(MyCoroutine()); +} +public IEnumerator MyCoroutine() +{ + for (;;) //repeat the loop infinitely + { + Log.Info("Hey, I'm a infinite loop!"); //Call Log.Info to print a line to the game console/server logs. + yield return Timing.WaitForSeconds(5f); //Tells the coroutine to wait 5 seconds before continuing. Since this is at the end of the loop, it effectively stalls the loop from repeating for 5 seconds. + } +} +``` +This example prints, "Hey, I'm an infinite loop!" every 5 seconds infinitely. Coroutines can have multiple `yield return` statements. + +## Delayed Calls +A simpler method of running an action after a delay is using `Timing.CallDelayed(float, Action)`, which executes code after a given number of seconds passes. This method does not require a coroutine to be created, hence why it's useful. An example can be seen below, logging a message 5 seconds after the method is called. +```cs +using MEC; +using Exiled.API.Features; +public void SomeMethod() +{ + Timing.CallDelayed(5f, () => // Execute the provided method 5 seconds late. + { + Log.Info("This log was printed 5 seconds late!"); + }) +} +``` +It is ***strongly*** recommended that you do some googling, or ask around **[in the EXILED Discord server](https://discord.gg/PyUkWTg)** if you are unfamiliar with MEC and would like to learn more, get advice, or need help. Questions, no matter how 'stupid' they are, will always be answered as helpfully and clearly as possible for plugin developers to excel. Better code is better for everyone. diff --git a/EXILED/docs/articles/plugins/structure.md b/EXILED/docs/articles/plugins/structure.md new file mode 100644 index 000000000..7a0d5997d --- /dev/null +++ b/EXILED/docs/articles/plugins/structure.md @@ -0,0 +1,172 @@ +--- +title: Plugin Structure +--- + +This tutorial assumes that you are familiar with C#. + +### Plugin Structure +In order to be loaded onto the framework, *every* plugin must follow a certain structure and inherit from certain members. If this is not achieved, the plugin will not execute. This tutorial will explain the proper setup for a plugin on the EXILED framework. + +## Plugin Core +Every plugin must have a .cs file that consists of the plugin class itself. This file (and the class itself) are typically simply named "Plugin"; however, any name is appropriate for the main plugin class. This example will use "Plugin" as the name of the class. + +After the main file is created, the Plugin class must be declared as a plugin, so that the EXILED framework loads it. This can be done by inheriting the `Plugin` class, provided in the `Exiled.API.Features` namespace. + +The following example shows how to properly inherit the class. However, notice the `Config` class inside of the angled brackets. This class must be created and must inherit from `IConfig`, which is part of the `Exiled.API.Interfaces` namespace. Upon the creation of the Config class, the interface will require you to add an `IsEnabled` property. +```cs +namespace MyPluginNamespace +{ + using Exiled.API.Features; + public class Plugin : Plugin + { + // This plugin will now be recognized by the EXILED framework! + } + // It is strongly encouraged to create a separate file for your Config class. + using Exiled.API.Interfaces; + public class Config : IConfig + { + public bool IsEnabled { get; set; } + } +} +``` +By creating the `Config` class and including it in the angled brackets, the rest of the plugin's code, as well as the EXILED framework, will recognize that the class resembles configuration for server owners. For more information about setting up configuration, see the Configuration section below. + +## OnEnabled and OnDisabled +The plugin is now successfully loaded onto the framework. However, it doesn't actually do anything; no functionality has been assigned. The `Plugin` class provides two overridable methods in order to give the plugin functionality: `OnEnabled` and `OnDisabled`. These two methods do exactly as they sound: Execute when the plugin is enabled/loaded, and when it is disabled. + +The following example shows how to utilize these methods to send a message to the console. +```cs +namespace MyPluginNamespace +{ + using Exiled.API.Features; + public class Plugin : Plugin + { + public override void OnEnabled() + { + Log.Info("My plugin has been enabled!"); + } + public override void OnDisabled() + { + Log.Info("My plugin has been disabled!"); + } + } + // Config.cs file + using Exiled.API.Interfaces; + public class Config : IConfig + { + public bool IsEnabled { get; set; } + } +} +``` +All of the code for the plugin *must* be enabled in the OnEnabled method, and *must* be disabled on the OnDisabled method. It is important that these two methods execute as expected, because server hosts can enable and disable plugins as much as they'd like, and the plugin *must* be able to respond to these changes appropriately. + +## Plugin Data +In order for a plugin to be submitted for public use, the plugin must override three properties: `Name`, `Author`, and `Version`. The first two are strings, whereas the last one is a `Version` class (`using System;` is required). + +The following example shows how to properly override this data. +```cs +namespace MyPluginNamespace +{ + using System; + using Exiled.API.Features; + public class Plugin : Plugin + { + public override string Name => "My Awesome Plugin"; + public override string Author => "MyName"; + public override Version Version => new Version(1, 0, 0); + } + // ... +} +``` + +## Configuration +This section is related to creating and reading the value of configuration. + +### Creating Configs +A lot of plugins provide configuration to allow the server hosts to change various features of the plugin. Luckily, creating configuration is very simple. + +To start, take a look at your Config.cs file. +```cs +namespace MyPluginNamespace +{ + using Exiled.API.Interfaces; + public class Config : IConfig + { + public bool IsEnabled { get; set; } + } +} +``` +There is currently one config, called `IsEnabled`. As stated above, this config is required and cannot be removed. However, more config can be added. The YAML serialization allows almost any type to be added and still work, including bools, ints, arrays of anything, enums, and even whole classes! + +In the following example, a config file with three configs is created. +```cs +namespace MyPluginNamespace +{ + using Exiled.API.Interfaces; + public class Config : IConfig + { + public bool IsEnabled { get; set; } + public bool MyBoolConfig { get; set; } + public string MyStringConfig { get; set; } + public int MyIntConfig { get; set; } = 5; // Set to 5 by default. + } +} +``` +To server hosts, the functionality of these configs might be confusing at first. So, the `System.ComponentModel.DescriptionAttribute` can be used to provide a description for each config! +```cs +namespace MyPluginNamespace +{ + using System.ComponentModel; + using Exiled.API.Interfaces; + public class Config : IConfig + { + [Description("Whether or not the plugin is enabled.")] + public bool IsEnabled { get; set; } + [Description("Config that must be true or false!")] + public bool MyBoolConfig { get; set; } + [Description("Config that must be a string!")] + public string MyStringConfig { get; set; } + [Description("Config that must be a number! Defaults to 5.")] + public int MyIntConfig { get; set; } = 5; + } +} +``` + +### Reading Configs +> [!NOTE] +> You do not need to read the value of the `IsEnabled` config; EXILED will automatically prevent your plugin from executing if its `IsEnabled` config is set to false. + + +Reading configuration is more simple than creating it. The base `Plugin` class provides a property, called `Config`, which can be used to access these values. + +In the following example, our config from the previous class is displayed when the plugin starts. +```cs +namespace MyPluginNamespace +{ + using Exiled.API.Features; + public class Plugin : Plugin + { + public override void OnEnabled() + { + Log.Info("Boolean config: " + Config.MyBoolConfig); + Log.Info("String config: " + Config.MyStringConfig); + Log.Info("Int config: " + Config.MyIntConfig); + } + } + // Config.cs file + using System.ComponentModel; + using Exiled.API.Interfaces; + public class Config : IConfig + { + [Description("Whether or not the plugin is enabled.")] + public bool IsEnabled { get; set; } + [Description("Config that must be true or false!")] + public bool MyBoolConfig { get; set; } + [Description("Config that must be a string!")] + public string MyStringConfig { get; set; } + [Description("Config that must be a number! Defaults to 5.")] + public int MyIntConfig { get; set; } = 5; + } +} +``` + diff --git a/EXILED/docs/articles/toc.yml b/EXILED/docs/articles/toc.yml new file mode 100644 index 000000000..5b863000c --- /dev/null +++ b/EXILED/docs/articles/toc.yml @@ -0,0 +1,21 @@ +- name: Introduction + href: index.md +- name: Installation + href: installation/index.md + items: + - name: Automatic (Linux) + href: installation/automatic/linux.md + - name: Automatic (Windows) + href: installation/automatic/windows.md + - name: Manual + href: installation/manual.md +- name: Plugin Development + items: + - name: Plugin Structure + href: plugins/structure.md + - name: More Effective Coroutines + href: plugins/mec.md + - name: Events + href: plugins/events.md +- name: Contributing + href: contributing/index.md diff --git a/EXILED/docs/assets/exiled.png b/EXILED/docs/assets/exiled.png new file mode 100644 index 000000000..b80bc81af Binary files /dev/null and b/EXILED/docs/assets/exiled.png differ diff --git a/EXILED/docs/assets/favicon.ico b/EXILED/docs/assets/favicon.ico new file mode 100644 index 000000000..4f9fa586f Binary files /dev/null and b/EXILED/docs/assets/favicon.ico differ diff --git a/EXILED/docs/docfx.json b/EXILED/docs/docfx.json new file mode 100644 index 000000000..a84191683 --- /dev/null +++ b/EXILED/docs/docfx.json @@ -0,0 +1,60 @@ +{ + "metadata": [ + { + "src": [ + { + "files": [ + "**/*.csproj" + ], + "exclude": [ + "**/bin/**", + "**/obj/**" + ], + "src": "../" + } + ], + "dest": "api", + "filter": "filterConfig.yml", + "namespaceLayout": "nested", + } + ], + "build": { + "globalMetadata": { + "_appTitle": "EXILED", + "_appLogoPath": "assets/exiled.png", + "_appFaviconPath": "assets/favicon.ico", + "_enableSearch": true, + "_lang": "en", + "_gitContribute": { + "repo": "https://github.com/Exiled-Official/EXILED", + "branch": "dev" + } + }, + "template": ["default", "modern"], + "content": [ + { + "files": [ + "api/**.yml", + "api/index.md", + "toc.yml", + "*.md" + ] + }, + { + "files": [ + "articles/toc.yml", + "articles/**.md" + ] + } + ], + "resource": [ + { + "files": [ + "assets/**" + ] + } + ], + "dest": "_site", + "docfx": "SGVsbG8sIHRoaXMgd2FzIG1hZGUgYnkgamVzdXNxYywgaG9wZSB5b3UgYXJlIG5vdCBjb3B5aW5nIHRoaXMgYmVjYXVzZSBpdCB3b3VsZCBiZSBoaWxhcmlvdXMg8J+YrfCfmK3wn5it8J+YrQ==" + } +} diff --git a/EXILED/docs/filterConfig.yml b/EXILED/docs/filterConfig.yml new file mode 100644 index 000000000..1fa0a3ca9 --- /dev/null +++ b/EXILED/docs/filterConfig.yml @@ -0,0 +1,10 @@ +apiRules: + - exclude: + uidRegex: Exiled.Updater + type: Namespace + - exclude: + uidRegex: Exiled.Example + type: Namespace + - exclude: + uidRegex: Exiled.CreditTags + type: Namespace diff --git a/EXILED/docs/index.md b/EXILED/docs/index.md new file mode 100644 index 000000000..58917327b --- /dev/null +++ b/EXILED/docs/index.md @@ -0,0 +1,16 @@ +--- +title: Home +--- +# Exiled +Join our [Discord](https://discord.gg/PyUkWTg) for support. + +EXILED is a plugin framework for SCP: Secret Laboratory servers. It offers an event system for developers to hook into in order to manipulate or change game code or implement their own functions. + +## Support +We consistently deliver updates and releases to address bugs and introduce new features or contributions swiftly. + +## Community +We encourage developers to contribute actively rather than solely relying on Exiled, thereby boosting project activity. + +## Features +We offer diverse features, providing users with flexibility. These features are optional, catering to various needs. diff --git a/EXILED/docs/toc.yml b/EXILED/docs/toc.yml new file mode 100644 index 000000000..bbebe92c1 --- /dev/null +++ b/EXILED/docs/toc.yml @@ -0,0 +1,6 @@ +- name: Articles + href: articles/ +- name: API Documentation + href: api/Exiled.html +- name: Repository + href: https://github.com/Exiled-Official/EXILED