# Table of Contents
- [Hello World Plugin | CounterStrikeSharp ](#hello-world-plugin-counterstrikesharp-)
- [Dependency Injection | CounterStrikeSharp ](#dependency-injection-counterstrikesharp-)
- [Automatically build/deploy your changes | CounterStrikeSharp ](#automatically-build-deploy-your-changes-counterstrikesharp-)
- [Getting Started | CounterStrikeSharp ](#getting-started-counterstrikesharp-)
- [Referencing Players | CounterStrikeSharp ](#referencing-players-counterstrikesharp-)
---
# Hello World Plugin | CounterStrikeSharp
##### Table of Contents
Hello World Plugin
==================
How to write your first plugin for CounterStrikeSharp
Creating a New Project[](https://docs.cssharp.dev/docs/guides/hello-world-plugin.html#creating-a-new-project)
--------------------------------------------------------------------------------------------------------------
First, ensure you have the relevant .NET 8.0 SDK for your platform installed on your machine. You can find the links to the latest downloads on the [official Microsoft download page](https://dotnet.microsoft.com/en-us/download/dotnet/8.0)
.
### Creating a Class Library[](https://docs.cssharp.dev/docs/guides/hello-world-plugin.html#creating-a-class-library)
All CounterStrikeSharp plugins are installed on the server as built .dll class library binary files, so we will get started by creating a new class library using the inbuilt dotnet sdk tools.
dotnet new classlib --name HelloWorldPlugin
Use your IDE (Visual Studio/Rider) to add a reference to the `CounterStrikeSharp.Api.dll` file that is installed onto the server. If you are using VSCode or a text editor, you can edit the .csproj file directly and add the following:
net8.0
enable
enable
+
+
+ [where you downloaded or installed]/addons/counterstrikesharp/api/CounterStrikeSharp.API.dll
+
+
##### Tip
Instead of manually adding a reference to `CounterStrikeSharp.Api.dll`, you can > install the NuGet package `CounterStrikeSharp.Api` using the following:
dotnet add package CounterStrikeSharp.API
### Creating a Plugin File[](https://docs.cssharp.dev/docs/guides/hello-world-plugin.html#creating-a-plugin-file)
Rename the default class file that came with your new project (by default it should be `Class1.cs`) to something more accurate, like `HelloWorldPlugin.cs`. Inside this file, we will insert the stub hello world plugin. Be sure to change the name and namespace so it matches your project name.
using CounterStrikeSharp.API.Core;
namespace HelloWorldPlugin;
public class HelloWorldPlugin : BasePlugin
{
public override string ModuleName => "Hello World Plugin";
public override string ModuleVersion => "0.0.1";
public override void Load(bool hotReload)
{
Console.WriteLine("Hello World!");
}
}
Now build your project using your ide or the `dotnet build` command. You should now have a built binary file in your `bin/Debug/net8.0` subdirectory in the project.
### Installing your Plugin[](https://docs.cssharp.dev/docs/guides/hello-world-plugin.html#installing-your-plugin)
Locate the `plugins` folder in your CS2 dedicated server (`/game/csgo/addons/counterstrikesharp/plugins`) and create a new folder with the exact same name as your output .dll file. In this example it would be `HelloWorldPlugin.dll`, so I will make a new folder called `HelloWorldPlugin`. Inside of this folder, copy and paste the: `HelloWorldPlugin.deps.json`, `HelloWorldPlugin.dll`, and `HelloWorldPlugin.pdb` files. Once completed, the folder should look as follows:
.
└── HelloWorldPlugin
├── HelloWorldPlugin.deps.json
├── HelloWorldPlugin.dll
└── HelloWorldPlugin.pdb
##### Caution
If you have installed external nuget packages for your plugin, you may need to include their respective `.dll`s. For example, if you utilize the `Stateless` C# library, include `stateless.dll` in your `HelloWorld` plugin directory.
##### Note
Note that some of these dependencies may change depending on the version of CounterStrikeSharp being used.
### Start the Server[](https://docs.cssharp.dev/docs/guides/hello-world-plugin.html#start-the-server)
Now start your CS2 dedicated server. Just before the `CounterStrikeSharp.API Loaded Successfully.` message you should see your `Hello World!` console write that we called from the load function, neat!
##### Note
By default, CounterStrikeSharp will automatically hot reload your plugin if you replace the .dll file in your plugin folder. When it does so, it will call the `Unload` and `Load` functions respectively, with the `hotReload` flag set to true.
It is worth noting that the framework will automatically deregister any event handlers or listeners for you automatically, so you can safely reregister these on load without checking this flag. However you may want to do some specific actions on a hot reload, which you can do in your `Load()` call by checking the flag!
[Edit this page](https://github.com/roflmuffin/CounterStrikeSharp/blob/main/docfx/docs/guides/hello-world-plugin.md/#L1)
Previous [Getting Started](https://docs.cssharp.dev/docs/guides/getting-started.html)
Next [Dependency Injection](https://docs.cssharp.dev/docs/guides/dependency-injection.html)
---
# Dependency Injection | CounterStrikeSharp
##### Table of Contents
Dependency Injection
====================
How to make use of dependency injection in CounterStrikeSharp
`CounterStrikeSharp` uses a standard [`IServiceCollection`](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-8.0)
to allow for dependency injection in plugins.
There are a handful of standard services that are predefined for you (`ILogger` for logging for instance), with more to come in the future. To add your own scoped & singleton services to the container, you can create a new class that implements the `IPluginServiceCollection` interface for your plugin.
public class TestPlugin : BasePlugin
{
// Plugin code...
}
public class TestPluginServiceCollection : IPluginServiceCollection
{
public void ConfigureServices(IServiceCollection serviceCollection)
{
serviceCollection.AddScoped();
serviceCollection.AddLogging(builder => ...);
}
}
CounterStrikeSharp will search your assembly for any implementations of `IPlugin` and then any implementations of `IPluginServiceCollection` where `T` is your plugin. It will then configure the service provider and then request a singleton instance of your plugin before proceeding to the load step.
In this way, any dependencies that are listed in your plugin class constructor will automatically get injected at instantation time (before load).
### Example[](https://docs.cssharp.dev/docs/guides/dependency-injection.html#example)
public class TestInjectedClass
{
private readonly ILogger _logger;
public TestInjectedClass(ILogger logger)
{
_logger = logger;
}
public void Hello()
{
_logger.LogInformation("Hello World from Test Injected Class");
}
}
public class TestPluginServiceCollection : IPluginServiceCollection
{
public void ConfigureServices(IServiceCollection serviceCollection)
{
serviceCollection.AddScoped();
}
}
public class SamplePlugin : BasePlugin
{
private readonly TestInjectedClass _testInjectedClass;
public SamplePlugin(TestInjectedClass testInjectedClass)
{
_testInjectedClass = testInjectedClass;
}
public override void Load(bool hotReload)
{
_testInjectedClass.Hello();
}
}
[Edit this page](https://github.com/roflmuffin/CounterStrikeSharp/blob/main/docfx/docs/guides/dependency-injection.md/#L1)
Previous [Hello World Plugin](https://docs.cssharp.dev/docs/guides/hello-world-plugin.html)
Next [Referencing Players](https://docs.cssharp.dev/docs/guides/referencing-players.html)
---
# Automatically build/deploy your changes | CounterStrikeSharp
##### Table of Contents
Automatically build and deploy your changes
===========================================
Adapted from the [original guide](https://github.com/uFloppyDisk/create-cssharp-plugin/blob/c8fca43f86a61a5e874624f2f3ed39c5271c9a55/templates/standard-plugin/docs/auto-live-hot-reloading.md)
.
During development of your plugin, you may find yourself repeating a workflow similar to the following:
1. Make a change to your plugin
2. Run your build task (ex. `dotnet build`)
3. Upload plugin DLLs to your server using an FTP client
4. Alt-tab to the game
5. Test your changes
6. Repeat
Iterating on your plugin this way is painfully slow and impacts your productivity. Below, you will find a guide and recommendations on how to setup your dev environment to watch for file changes and automatically update plugin files on your server as you work. By following this guide, your new workflow should look like this:
1. Make a change to your plugin
2. Alt-tab to the game
3. Test your changes
4. Repeat
##### Caution
Exercise caution when developing your plugin while using this workflow. Build time errors are mostly caught by .NET SDK before files are committed but incomplete implementation may lead to issues such as server crashes. Avoid using this workflow on a production server meant for players.
Setup[](https://docs.cssharp.dev/docs/guides/auto-build-and-deploy.html#setup)
-------------------------------------------------------------------------------
#### 1. Build plugin on file changes[](https://docs.cssharp.dev/docs/guides/auto-build-and-deploy.html#1-build-plugin-on-file-changes)
The `dotnet` CLI, included with the .NET SDK, offers a convenient command for automatically watching for source file changes. If you have access to the `dotnet` CLI, run the following command to start watching your source code.
dotnet watch build --project path/to/projectName.csproj
By default, `dotnet watch` executes the `dotnet run` command on file changes so specifying `build` as the first argument is required.
Your plugin will now build automatically on file change. By default, your builds should be placed in `bin//` in the same directory as your `.csproj`.
projectDirectory
├── projectName.csproj
├── bin
│ └── Debug
│ └── net8.0
│ └── PLUGIN BUILDS HERE
##### Tip
You can have your plugin build to a more convenient location by setting the `` build property in your `.csproj` file. Example: `./build/$(MSBuildProjectName)`
#### 2. Setup automatic uploads[](https://docs.cssharp.dev/docs/guides/auto-build-and-deploy.html#2-setup-automatic-uploads)
##### Using WinSCP (Windows only)
Once connected to your server:
1. Go to the `Commands` tab at the top of the WinSCP window and click `Keep Remote Directory up to Date`.
2. Select the plugin build directory containing your DLLs.
3. Select the plugin destination. (`csgo/addons/counterstrikesharp/plugins/`)
4. Click `Start`
##### Important
**For WSL users:** Applications running on Windows, such as WinSCP, cannot watch your Linux subsystem for file changes. Try using [this workaround](https://docs.cssharp.dev/docs/guides/auto-build-and-deploy.html#using-winscp-while-developing-in-wsl)
or consider moving development to Windows.
##### Using `lsyncd` (Linux)
> **TODO:** in-depth guide for setting up lsyncd
Learn more about `lsyncd`: [https://github.com/lsyncd/lsyncd](https://github.com/lsyncd/lsyncd)
* * *
#### Using WinSCP while developing in WSL[](https://docs.cssharp.dev/docs/guides/auto-build-and-deploy.html#using-winscp-while-developing-in-wsl)
Run the following watch command in place of the one mentioned in [Step 1](https://docs.cssharp.dev/docs/guides/auto-build-and-deploy.html#1-build-plugin-on-file-changes)
to build to a directory in your Windows filesystem
dotnet watch build --project path/to/.csproj --property:OutDir=/mnt//some/path/`
and have [WinSCP in Step 2](https://docs.cssharp.dev/docs/guides/auto-build-and-deploy.html#2-setup-automatic-uploads)
watch that path instead.
[Learn about Windows filesystem mounts in WSL](https://blogs.windows.com/windowsdeveloper/2016/07/22/fun-with-the-windows-subsystem-for-linux/#Working%20with%20Windows%20files:%7E:text=Working%20with%20Windows%20files)
[Edit this page](https://github.com/roflmuffin/CounterStrikeSharp/blob/main/docfx/docs/guides/auto-build-and-deploy.md/#L1)
Previous [Referencing Players](https://docs.cssharp.dev/docs/guides/referencing-players.html)
Next [Console Commands](https://docs.cssharp.dev/docs/features/console-commands.html)
---
# Getting Started | CounterStrikeSharp
##### Table of Contents
Getting Started
===============
In this guide you will learn how to install CounterStrikeSharp onto your vanilla Counter-Strike 2 server. `CounterStrikeSharp` uses `Metamod:Source` as its main way of communicating with the game server, so both frameworks will need to be installed.
If you're more of a visual person, here is a [Youtube video](https://www.youtube.com/watch?v=FlsKzStHJuY)
that covers everything.
Prerequisites[](https://docs.cssharp.dev/docs/guides/getting-started.html#prerequisites)
-----------------------------------------------------------------------------------------
* [Metamod: Source 2.X Dev Build](https://www.metamodsource.net/downloads.php/?branch=master)
* [CounterStrikeSharp With Runtime](https://github.com/roflmuffin/CounterStrikeSharp/releases)
Installing Metamod[](https://docs.cssharp.dev/docs/guides/getting-started.html#installing-metamod)
---------------------------------------------------------------------------------------------------
1. Extract Metamod and copy the `/addons/` directory to `/game/csgo/`.
2. Inside `/game/csgo/`, locate `gameinfo.gi`.
3. Create a new line underneath `Game_LowViolence csgo_lv` and add `Game csgo/addons/metamod`.
4. Restart your game server.
Your `gameinfo.gi` should look like [this](https://docs.cssharp.dev/images/gameinfogi-example.png)
. Type `meta list` in your server console to see if Metamod is loaded.
Installing CounterStrikeSharp[](https://docs.cssharp.dev/docs/guides/getting-started.html#installing-counterstrikesharp)
-------------------------------------------------------------------------------------------------------------------------
1. Extract CounterStrikeSharp and copy the `/addons/` directory to `/game/csgo/`.
2. Restart your game server.
Running the command `meta list` in the console should show 1 plugin loaded 🎉
meta list
Listing 1 plugin:
[01] CounterStrikeSharp (0.1.0) by Roflmuffin
##### Caution
For Windows servers, you must have [Visual Studio Redistributables](https://aka.ms/vs/17/release/vc_redist.x64.exe)
installed otherwise CounterStrikeSharp will not work.
Upgrading CounterStrikeSharp[](https://docs.cssharp.dev/docs/guides/getting-started.html#upgrading-counterstrikesharp)
-----------------------------------------------------------------------------------------------------------------------
To upgrade CounterStrikeSharp you simply need to download the latest release and copy it to your server, the same as the original installation.
CounterStrikeSharp is designed in a way where your configuration files will not be overwritten if you do this. As CounterStrikeSharp is already installed, you may download the non `with-runtime` build, but you will need to ensure your .NET runtime is up-to-date yourself.
Troubleshooting[](https://docs.cssharp.dev/docs/guides/getting-started.html#troubleshooting)
---------------------------------------------------------------------------------------------
* If this is your first time installing, you **MUST** download the `with-runtime` version. This includes a copy of the .NET runtime, which is required to run the plugin.
* Depending on your OS you might also either need to install `libicu` / `icu-libs` / `libicu-dev` using your package manager for .NET to run.
* If you get `Unknown Command` when typing `meta list` into your console, double-check the folders are copied over correctly and that your `gameinfo.gi` file is correctly modified.
Your folder structure should look like this:
/game/csgo/addons > tree -L 2
addons
├── counterstrikesharp
│ ├── api
│ ├── bin
│ ├── dotnet
│ ├── plugins
│ └── gamedata
│
├── metamod
│ ├── bin
│ ├── counterstrikesharp.vdf
│ ├── metaplugins.ini
│ └── README.txt
├── metamod.vdf
└── metamod_x64.vdf
[Edit this page](https://github.com/roflmuffin/CounterStrikeSharp/blob/main/docfx/docs/guides/getting-started.md/#L1)
Next [Hello World Plugin](https://docs.cssharp.dev/docs/guides/hello-world-plugin.html)
---
# Referencing Players | CounterStrikeSharp
##### Table of Contents
Referencing Players
===================
Difference between player slots, indexes, userids, controllers & pawns.
Controllers & Pawns[](https://docs.cssharp.dev/docs/guides/referencing-players.html#controllers--pawns)
--------------------------------------------------------------------------------------------------------
All players in CS2 are split between a player controller & a player pawn. The player controller represents the player on the server, and the player pawn represents the players physical character in the game world. This means to edit a players health for example, you would need to edit their `PlayerPawn`'s health; but to check for a player's SteamID, you would check the `PlayerController`.
Every player controller has access to a `PlayerPawn` property which is a `CHandle` to a players pawn. Likewise, a reverse lookup is possible as each `PlayerPawn` has a `Controller` property which provides access to a pawns controller.
CCSPlayerController player = ...;
CCSPlayerPawn playerPawn = player.PlayerPawn.Value; // as `PlayerPawn` is a `CHandle`, to fetch its underlying value we must get the `.Value` property
CCSPlayerController samePlayer = playerPawn.Controller.Value; // same as above.
Identifying Players[](https://docs.cssharp.dev/docs/guides/referencing-players.html#identifying-players)
---------------------------------------------------------------------------------------------------------
Players can be identified in a number of ways, by **slot**, by **index**, by **userid** and also by **pointer**. Player slot represents a "slot" in the server, and is basically an entity index minus one. So a player controller with an index of `10` is equivalent to player slot 9. Game events with `userid` as a field expose the pointer to the player controller directly from the engine, e.g.
RegisterEventHandler((@event, info) =>
{
CCSPlayerController player = @event.Userid;
}
### CPlayerSlot/Slot[](https://docs.cssharp.dev/docs/guides/referencing-players.html#cplayerslotslot)
Represents a "slot" in the server, and is basically an entity index minus one. So a player controller with an index of `10` is equivalent to player slot 9.
### User IDs[](https://docs.cssharp.dev/docs/guides/referencing-players.html#user-ids)
Userids are similar to a slot, and they are what show in the console when you type the `status` command. A Userid can be converted to a slot (and then ultimately an index by adding +1) by doing a bitshift `userid & 0xFF`.
### Entity Index[](https://docs.cssharp.dev/docs/guides/referencing-players.html#entity-index)
All entity instances have an entity index (similar to CSGO), which means both the player controller and the player pawn both have different indexes. The Player Controller has a reserved entity index (because of the slot system 0-MAXPLAYERS(64)), but a player pawn does not, so it is common to retrieve a player pawn with an index in the hundreds.
### Entity Pointers & Handles[](https://docs.cssharp.dev/docs/guides/referencing-players.html#entity-pointers--handles)
All "entity objects" you interact with in CounterStrikeSharp are actually wrappers around a **pointer** on the server, which can be accessed by retrieving the `.Handle` property. Which means to go from a CPlayerSlot, UserID or Index value, you must use the matching utility method to fetch the entity pointer. There are three utility methods to get an instance of a player using these identifiers:
var player = Utilities.GetPlayerFromUserid(userid);
var player = Utilities.GetPlayerFromIndex(index);
var player = Utilities.GetPlayerFromSlot(slot);
##### Note
Wherever possible, you should check the validity of any handle you are accessing before assuming it is safe to use.
RegisterEventHandler((@event, info) =>
{
if (!@event.Userid.IsValid) return 0; // Checks that the PlayerController is valid
if (!@event.Userid.PlayerPawn.IsValid) return 0; // Checks that the value of the CHandle is pointing to a valid PlayerPawn.
}
[Edit this page](https://github.com/roflmuffin/CounterStrikeSharp/blob/main/docfx/docs/guides/referencing-players.md/#L1)
Previous [Dependency Injection](https://docs.cssharp.dev/docs/guides/dependency-injection.html)
Next [Automatically build and deploy your changes](https://docs.cssharp.dev/docs/guides/auto-build-and-deploy.html)
---