Skip to content

Commit 0895e1d

Browse files
committed
Initial Commit
0 parents  commit 0895e1d

8 files changed

Lines changed: 1008 additions & 0 deletions

.gitignore

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# User-specific build configuration — never commit
2+
local.build.props
3+
4+
# Build outputs
5+
bin/
6+
obj/
7+
8+
# IDE
9+
.vs/
10+
.idea/
11+
*.user
12+
*.suo
13+
*.userosscache
14+
*.DotSettings.user
15+
16+
# Local scripts and release zips
17+
pack.sh
18+
*.zip
19+
20+
# OS
21+
.DS_Store
22+
Thumbs.db
23+
24+
# NuGet
25+
*.nupkg
26+
*.snupkg
27+
packages/
28+
project.lock.json

README.md

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
# S1DS-PlayerList
2+
3+
A player list overlay for Schedule I clients connected to a dedicated server, built on the S1DS mod API.
4+
5+
![Player list overlay](docs/screenshot.png)
6+
7+
## Features
8+
9+
- Hold the configured key (default **F8**) to show the player list; release to dismiss it
10+
- Displays player name, role badge (Operator / Admin / Player), and ping
11+
- Roles are colour-coded: cyan for Operator, gold for Admin, grey for Player
12+
- Ping is colour-coded: green < 70 ms, yellow 70–150 ms, red > 150 ms
13+
- Panel is anchored to the **top-right** corner of the screen
14+
- Pings are reported from the client's FishNet RTT and refreshed every few seconds
15+
16+
## Configuration
17+
18+
Settings are stored at:
19+
20+
```
21+
<game folder>/UserData/S1DS-PlayerList.json
22+
```
23+
24+
The file is created with defaults on first launch. Available options:
25+
26+
| Key | Default | Description |
27+
|-----|---------|-------------|
28+
| `toggleKey` | `"F8"` | Key to hold to show the overlay. Any [Unity `KeyCode`](https://docs.unity3d.com/ScriptReference/KeyCode.html) name is accepted (e.g. `"Tab"`, `"F8"`, `"BackQuote"`). |
29+
30+
Example:
31+
32+
```json
33+
{
34+
"toggleKey": "F8"
35+
}
36+
```
37+
38+
## Build
39+
40+
```bash
41+
dotnet build S1DS-PlayerList.csproj -c Mono_Client
42+
dotnet build S1DS-PlayerList.csproj -c Mono_Server
43+
```
44+
45+
Build output lands in `bin/Mono_Client/netstandard2.1/` and `bin/Mono_Server/netstandard2.1/`. If a deployment path is configured the DLL is also copied there automatically.
46+
47+
## Setup
48+
49+
### Inside the DedicatedServerMod repo
50+
51+
No extra configuration is needed. The project automatically inherits game paths from the root `local.build.props` and resolves the S1DS API DLLs from the repo's `bin/` directory.
52+
53+
### Standalone (own repo / separate folder)
54+
55+
1. Copy `local.build.props.example``local.build.props` in this directory.
56+
2. Set `MonoClientGamePath` / `MonoServerGamePath` to your Schedule I install.
57+
3. Ensure the S1DS mod (`DedicatedServerMod_Mono_Client.dll` / `DedicatedServerMod_Mono_Server.dll`) is present in the game's `Mods/` folder **or** in your deployment path — the build looks in the deployment path first, then falls back to `<GamePath>/Mods`.
58+
4. (Optional) Set `ClientDeploymentPath` / `ServerDeploymentPath` to auto-copy the built DLL after build.
59+
60+
`local.build.props` is git-ignored and never committed. See `local.build.props.example` for the full annotated template.
61+
62+
#### Available properties
63+
64+
| Property | Required | Description |
65+
|----------|----------|-------------|
66+
| `MonoClientGamePath` | **Yes** | Schedule I **client** install directory (contains `Schedule I_Data/Managed/`, `MelonLoader/`, and `Mods/`). |
67+
| `MonoServerGamePath` | **Yes** | Schedule I **dedicated server** install directory. Can be the same path as the client. |
68+
| `ClientDeploymentPath` | No | After a successful `Mono_Client` build, copy the DLL here. Defaults to `<MonoClientGamePath>/Mods`. Also used as the first search location for `DedicatedServerMod_Mono_Client.dll`. |
69+
| `ServerDeploymentPath` | No | After a successful `Mono_Server` build, copy the DLL here. Defaults to `<MonoServerGamePath>/Mods`. Also used as the first search location for `DedicatedServerMod_Mono_Server.dll`. |
70+
71+
#### Minimal example
72+
73+
```xml
74+
<!-- local.build.props -->
75+
<Project>
76+
<PropertyGroup>
77+
<MonoClientGamePath>/path/to/Schedule I</MonoClientGamePath>
78+
<MonoServerGamePath>/path/to/Schedule I</MonoServerGamePath>
79+
<!-- optional: override the default Mods/ deployment targets -->
80+
<!-- <ClientDeploymentPath>/path/to/client/Mods</ClientDeploymentPath> -->
81+
<!-- <ServerDeploymentPath>/path/to/server/Mods</ServerDeploymentPath> -->
82+
</PropertyGroup>
83+
</Project>
84+
```
85+
86+
## Notes
87+
88+
- Does not reference the root `DedicatedServerMod.csproj` — compiles against the pre-built DLLs in the game install.
89+
- If `local.build.props` is configured, the built DLL is copied into the matching game `Mods` folder after build.
90+
- The project file selects the client or server source file based on the build configuration, so each side gets a clean mod class without any `#if CLIENT` / `#if SERVER` guards.

S1DS-PlayerList.csproj

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<!--
3+
Local build configuration.
4+
Import order:
5+
1. local.build.props in this directory – used when checked out as a standalone project
6+
2. ../../local.build.props – fallback when nested inside the DedicatedServerMod repo
7+
Only one is imported (the first that exists).
8+
-->
9+
<Import Project="local.build.props" Condition="Exists('local.build.props')" />
10+
<Import Project="../../local.build.props" Condition="!Exists('local.build.props') and Exists('../../local.build.props')" />
11+
12+
<PropertyGroup>
13+
<TargetFramework>netstandard2.1</TargetFramework>
14+
<LangVersion>default</LangVersion>
15+
<Nullable>disable</Nullable>
16+
<ImplicitUsings>disable</ImplicitUsings>
17+
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
18+
<AssemblyName>S1DS-PlayerList</AssemblyName>
19+
<RootNamespace>S1DS.PlayerList</RootNamespace>
20+
<Configurations>Mono_Client;Mono_Server</Configurations>
21+
</PropertyGroup>
22+
23+
<PropertyGroup>
24+
<MonoClientGamePath Condition="'$(MonoClientGamePath)' == ''">$(MonoGamePath)</MonoClientGamePath>
25+
<MonoServerGamePath Condition="'$(MonoServerGamePath)' == ''">$(MonoGamePath)</MonoServerGamePath>
26+
</PropertyGroup>
27+
28+
<PropertyGroup Condition="'$(Configuration)'=='Mono_Client'">
29+
<GamePath>$(MonoClientGamePath)</GamePath>
30+
<ManagedPath>$([System.IO.Path]::Combine('$(GamePath)', 'Schedule I_Data', 'Managed'))</ManagedPath>
31+
<MelonLoaderPath>$([System.IO.Path]::Combine('$(GamePath)', 'MelonLoader', 'net35'))</MelonLoaderPath>
32+
<ModsPath>$([System.IO.Path]::Combine('$(GamePath)', 'Mods'))</ModsPath>
33+
<DefineConstants>MONO;CLIENT</DefineConstants>
34+
<OutputPath>bin\$(Configuration)\</OutputPath>
35+
<DeploymentPath Condition="'$(ClientDeploymentPath)' != ''">$(ClientDeploymentPath)</DeploymentPath>
36+
<DeploymentPath Condition="'$(ClientDeploymentPath)' == ''">$(ModsPath)</DeploymentPath>
37+
<!-- Look for S1DS DLL in the deployment path first (it's installed there), fall back to game Mods/ -->
38+
<S1DSModSearchPath Condition="'$(ClientDeploymentPath)' != ''">$(ClientDeploymentPath)</S1DSModSearchPath>
39+
<S1DSModSearchPath Condition="'$(ClientDeploymentPath)' == ''">$(ModsPath)</S1DSModSearchPath>
40+
</PropertyGroup>
41+
42+
<PropertyGroup Condition="'$(Configuration)'=='Mono_Server'">
43+
<GamePath>$(MonoServerGamePath)</GamePath>
44+
<ManagedPath>$([System.IO.Path]::Combine('$(GamePath)', 'Schedule I_Data', 'Managed'))</ManagedPath>
45+
<MelonLoaderPath>$([System.IO.Path]::Combine('$(GamePath)', 'MelonLoader', 'net35'))</MelonLoaderPath>
46+
<ModsPath>$([System.IO.Path]::Combine('$(GamePath)', 'Mods'))</ModsPath>
47+
<DefineConstants>MONO;SERVER</DefineConstants>
48+
<OutputPath>bin\$(Configuration)\</OutputPath>
49+
<DeploymentPath Condition="'$(ServerDeploymentPath)' != ''">$(ServerDeploymentPath)</DeploymentPath>
50+
<DeploymentPath Condition="'$(ServerDeploymentPath)' == ''">$(ModsPath)</DeploymentPath>
51+
<!-- Look for S1DS DLL in the deployment path first (it's installed there), fall back to game Mods/ -->
52+
<S1DSModSearchPath Condition="'$(ServerDeploymentPath)' != ''">$(ServerDeploymentPath)</S1DSModSearchPath>
53+
<S1DSModSearchPath Condition="'$(ServerDeploymentPath)' == ''">$(ModsPath)</S1DSModSearchPath>
54+
</PropertyGroup>
55+
56+
<ItemGroup>
57+
<!-- Newtonsoft.Json is provided by MelonLoader at runtime; reference here is compile-time only -->
58+
<PackageReference Include="Newtonsoft.Json" Version="13.0.3">
59+
<PrivateAssets>all</PrivateAssets>
60+
<ExcludeAssets>runtime</ExcludeAssets>
61+
</PackageReference>
62+
</ItemGroup>
63+
64+
<ItemGroup Condition="'$(Configuration)'=='Mono_Client'">
65+
<Compile Include="S1DSPlayerListClientMod.cs" />
66+
<Reference Include="MelonLoader">
67+
<HintPath>$(MelonLoaderPath)/MelonLoader.dll</HintPath>
68+
</Reference>
69+
<Reference Include="DedicatedServerMod_Mono_Client">
70+
<HintPath>$(S1DSModSearchPath)/DedicatedServerMod_Mono_Client.dll</HintPath>
71+
</Reference>
72+
<Reference Include="FishNet.Runtime">
73+
<HintPath>$(ManagedPath)/FishNet.Runtime.dll</HintPath>
74+
</Reference>
75+
<Reference Include="UnityEngine.CoreModule">
76+
<HintPath>$(ManagedPath)/UnityEngine.CoreModule.dll</HintPath>
77+
</Reference>
78+
<Reference Include="UnityEngine.UI">
79+
<HintPath>$(ManagedPath)/UnityEngine.UI.dll</HintPath>
80+
</Reference>
81+
<Reference Include="UnityEngine.UIModule">
82+
<HintPath>$(ManagedPath)/UnityEngine.UIModule.dll</HintPath>
83+
</Reference>
84+
<Reference Include="UnityEngine.TextRenderingModule">
85+
<HintPath>$(ManagedPath)/UnityEngine.TextRenderingModule.dll</HintPath>
86+
</Reference>
87+
<Reference Include="UnityEngine.InputLegacyModule">
88+
<HintPath>$(ManagedPath)/UnityEngine.InputLegacyModule.dll</HintPath>
89+
</Reference>
90+
</ItemGroup>
91+
92+
<ItemGroup Condition="'$(Configuration)'=='Mono_Server'">
93+
<Compile Include="S1DSPlayerListServerMod.cs" />
94+
<Reference Include="MelonLoader">
95+
<HintPath>$(MelonLoaderPath)/MelonLoader.dll</HintPath>
96+
</Reference>
97+
<Reference Include="DedicatedServerMod_Mono_Server">
98+
<HintPath>$(S1DSModSearchPath)/DedicatedServerMod_Mono_Server.dll</HintPath>
99+
</Reference>
100+
<Reference Include="FishNet.Runtime">
101+
<HintPath>$(ManagedPath)/FishNet.Runtime.dll</HintPath>
102+
</Reference>
103+
<Reference Include="UnityEngine.CoreModule">
104+
<HintPath>$(ManagedPath)/UnityEngine.CoreModule.dll</HintPath>
105+
</Reference>
106+
</ItemGroup>
107+
108+
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
109+
<MakeDir Condition="'$(DeploymentPath)' != '' and !Exists('$(DeploymentPath)')" Directories="$(DeploymentPath)" />
110+
<Copy Condition="'$(DeploymentPath)' != ''" SourceFiles="$(TargetPath)" DestinationFolder="$(DeploymentPath)" SkipUnchangedFiles="false" Retries="5" RetryDelayMilliseconds="1000" />
111+
</Target>
112+
</Project>

S1DS-PlayerList.sln

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
Microsoft Visual Studio Solution File, Format Version 12.00
2+
# Visual Studio Version 17
3+
VisualStudioVersion = 17.5.2.0
4+
MinimumVisualStudioVersion = 10.0.40219.1
5+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "S1DS-PlayerList", "S1DS-PlayerList.csproj", "{1C22568E-F242-E0A6-65EE-A362E1A09ADB}"
6+
EndProject
7+
Global
8+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
9+
Debug|Any CPU = Debug|Any CPU
10+
Release|Any CPU = Release|Any CPU
11+
EndGlobalSection
12+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
13+
{1C22568E-F242-E0A6-65EE-A362E1A09ADB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
14+
{1C22568E-F242-E0A6-65EE-A362E1A09ADB}.Debug|Any CPU.Build.0 = Debug|Any CPU
15+
{1C22568E-F242-E0A6-65EE-A362E1A09ADB}.Release|Any CPU.ActiveCfg = Release|Any CPU
16+
{1C22568E-F242-E0A6-65EE-A362E1A09ADB}.Release|Any CPU.Build.0 = Release|Any CPU
17+
EndGlobalSection
18+
GlobalSection(SolutionProperties) = preSolution
19+
HideSolutionNode = FALSE
20+
EndGlobalSection
21+
GlobalSection(ExtensibilityGlobals) = postSolution
22+
SolutionGuid = {3436DE9D-4C50-4E23-8990-1F2E5A966B33}
23+
EndGlobalSection
24+
EndGlobal

0 commit comments

Comments
 (0)