Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
59d7dfe
Pivot RedSync toward a CyberpunkMP SDK plugin.
cursoragent Jul 13, 2026
ac311be
Expand RedSyncSystem CMP plugin for local build and smoke test.
cursoragent Jul 13, 2026
a156f14
Add helper script to run local CyberpunkMP server with RedSyncSystem.
cursoragent Jul 13, 2026
b459334
Switch release play path from legacy RedSync to CyberpunkMP cloud.
cursoragent Jul 13, 2026
d871466
Fix Windows PowerShell parse error in CMP setup scripts.
cursoragent Jul 13, 2026
2a5b42f
Add CyberpunkMP client installer for the public v0.1 build.
cursoragent Jul 13, 2026
11c77eb
Fix Input Loader download URL in CMP client installer.
cursoragent Jul 13, 2026
857e782
Fix CMP dep install nesting into existing red4ext folders.
cursoragent Jul 13, 2026
dfb9e11
Fix CMP launch args to match official --ip= / --port= form.
cursoragent Jul 13, 2026
c517eb7
Harden CMP Play.bat arg passing and clarify solo vs connected.
cursoragent Jul 13, 2026
5f4df9f
Keep Play.bat window open so Args line is readable.
cursoragent Jul 13, 2026
6ddb7dd
Document CMP in-game hold-/ connect step.
cursoragent Jul 13, 2026
40122c2
Add CMP auto-connect redscript and install input bindings to r6/input.
cursoragent Jul 13, 2026
3b6d051
Fix CMP v0.1 launch args: use --ip HOST --port PORT tokens.
cursoragent Jul 13, 2026
cb9b436
Launch CMP via temp .bat and kill stale Cyberpunk processes.
cursoragent Jul 13, 2026
5a81312
Remove broken CmpAutoConnect redscript that failed compilation.
cursoragent Jul 13, 2026
317ecfd
Add UPDATE-ME.ps1 self-refresh helper; keep package free of CmpAutoCo…
cursoragent Jul 13, 2026
6c454a4
Fix Fix-Redscript-Compile.bat by moving logic into a .ps1 file.
cursoragent Jul 13, 2026
deebfa3
Add simple PLAY.bat with hardcoded CMP connect args.
cursoragent Jul 13, 2026
f35e343
Fix CMP connect: use IPv4 and remap hold key to F6
cursoragent Jul 13, 2026
8c4e81b
Use official --ip=/--port= launch form in PLAY.bat
cursoragent Jul 13, 2026
f6f1759
Fix CMP Connect key: patch both Input Loader XML paths to F6
cursoragent Jul 13, 2026
ebc64c8
Add working CMP auto-connect redscript (no F6 required)
cursoragent Jul 13, 2026
5309609
Fix CmpAutoConnect redscript compile (ScriptableSystem + DelayCallback)
cursoragent Jul 13, 2026
16591e8
Add local UDP relay so default 127.0.0.1:11778 reaches cloud CMP
cursoragent Jul 13, 2026
7901402
PLAY.bat: all online/ip flag variants + Test menu connect hint
cursoragent Jul 13, 2026
0d12558
Document freeing mouse cursor to click CMP Test Connect menu
cursoragent Jul 13, 2026
746c645
PLAY.bat: kill old game process and require Test menu before connect
cursoragent Jul 13, 2026
86501a1
Retrying auto-connect redscript so Test menu click is not required
cursoragent Jul 13, 2026
9b73759
Remove broken CmpAutoConnect; use Alt+Test menu for connect
cursoragent Jul 13, 2026
fe2d6bb
Fix install next-step text for Test menu connect
cursoragent Jul 13, 2026
5bd92b8
Add external clicker for stuck ImGui Test menu + F10 bind
cursoragent Jul 13, 2026
c9e5347
Revert play path to RedSync cloud; abandon CMP client connect
cursoragent Jul 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
# RedSync

Multiplayer framework for **Cyberpunk 2077** (v2.31). Rebrand of the Cyberverse rewrite — client plugin, redscript layer, and a .NET game server with a C++ networking core.
> **Direction change:** RedSync is pivoting to a **[CyberpunkMP](https://github.com/tiltedphoques/CyberpunkMP) plugin**
> (SDK-only). Core multiplayer sync (puppets, movement, animation, appearance, vehicles) is owned by CyberpunkMP.
> See [`cyberpunkmp-plugin/`](cyberpunkmp-plugin/) for the plugin scaffold and migration map.
>
> The standalone RedSync UDP server / RED4ext sync stack in this repo is **legacy** and not the path for full player anim.

Multiplayer-related tooling for **Cyberpunk 2077** (v2.31). Originally a rebrand of the Cyberverse rewrite (client plugin, redscript layer, .NET game server). New work targets the CyberpunkMP plugin model.

> [!NOTE]
> Active development. A self-contained tester package lives in [`release/`](release/) with auto-detect installers. See [Quick start](#quick-start-for-testers).
Expand Down
6 changes: 6 additions & 0 deletions cyberpunkmp-plugin/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
**/bin/
**/obj/
local-plugins/
**/admins.json
**/redsync.json
!RedSyncSystem/redsync.json
49 changes: 49 additions & 0 deletions cyberpunkmp-plugin/MIGRATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Migration map: RedSync host → CyberpunkMP plugin

## Product decision

| Before | After |
|--------|--------|
| RedSync = full multiplayer stack | CyberpunkMP = multiplayer stack |
| RedSync.Server + RED4ext netcode | Abandoned as competing host |
| Jackie/Judy + teleport puppets | CMP puppets / anim / appearance |
| Custom UDP protocol 0x7/0x8 | CMP protobuf + RPC |

## Feature-by-feature

| RedSync piece | Action |
|---------------|--------|
| `shared/protocol`, native GNS, `NetworkGameSystem` sync | **Drop** — CMP replaces |
| Player anim flags / TPP research | **Drop** — CMP core |
| `server/Managed` GameServer | **Freeze** — reference only |
| `server/Managed/Plugins` (.NET host we added) | **Superseded** by CMP plugin loader |
| Admin (`admins.json`, F7, kick/ban) | **Port** into `RedSyncSystem` + CMP admin/web if useful |
| Discord webhook | **Port** into `RedSyncSystem` |
| Spawn anchor | **Evaluate** — port only if CMP lacks equivalent |
| Tester `release/` RedSync client | **Retargeted** — `Setup-CyberpunkMP.bat` / `CyberpunkMP - Play.bat` + `CONNECT-CMP.txt` |
| Redscript combat / nametags | **Keep ideas**; reimplement only as CMP client plugins via RPC |

## Plugin conventions (CMP)

From CMP’s loader:

- Directory: `plugins/<Name>System/`
- DLL: `<Name>System.dll`
- Entry type: `<Name>System.Plugin`
- Static ctor runs at load; wire `Server.PlayerSystem` / `Server.World` events there
- RPC: redscript `ServerRpc` / `ClientRpc` + generated C# (`SdkGenerator`); implement `*_Impl` partials
- Optional: `IWebApiHook` + `assets/` for admin UI widgets

## Suggested delivery order

1. **Scaffold loads** — `RedSyncSystem` logs on load; `plugins` list shows it (CMP admin).
2. **Join/leave Discord (or console) announce** — uses `PlayerJoinEvent` / `PlayerLeftEvent`.
3. **Admin helpers** — thin RPCs for kick/say if CMP API exposes enough.
4. **Client redscript** — only for UX that CMP doesn’t ship.
5. **Retire** standalone RedSync server docs from the “how to play” path.

## Explicit non-goals

- Do not vendor CyberpunkMP native client, archives, or animation controllers.
- Do not reintroduce a second netcode stack beside CMP.
- Do not ship CMP binaries inside this repo.
83 changes: 83 additions & 0 deletions cyberpunkmp-plugin/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# RedSync → CyberpunkMP plugin pivot

RedSync is **no longer developing a competing multiplayer host**.
Player sync (movement, animation, appearance, vehicles) is handled by
**[CyberpunkMP](https://github.com/tiltedphoques/CyberpunkMP)**.

This folder is the start of RedSync as a **CyberpunkMP plugin** that uses only
their published **.NET SDK** + **redscript RPC** surfaces.

## License (read this)

CyberpunkMP’s license allows plugins that:

- use the provided SDK / interfaces
- do **not** modify CyberpunkMP source
- do **not** redistribute CyberpunkMP itself

Example plugins under `code/scripting/EmoteSystem`, `JobSystem`, and
`code/assets/redscript/Plugins` are MIT. Study those patterns; do **not** copy
CMP core (animation controllers, archives, native client).

## What CMP already owns (do not rebuild)

| Area | Owner |
|------|--------|
| Connection / world | CyberpunkMP |
| Remote puppets + appearance | CyberpunkMP |
| Movement + basic animation | CyberpunkMP |
| Vehicles | CyberpunkMP |
| RPC transport | CyberpunkMP |

## What RedSync plugin can add

| Feature | Notes |
|---------|--------|
| Discord join/leave / server log webhook | Port from RedSync `DiscordWebhookTarget` |
| Admin allowlist extras | Kick/ban/announce UX on top of CMP |
| Spawn-anchor style conveniences | If still useful alongside CMP |
| RP / economy / jobs-style gameplay | Same shape as CMP `JobSystem` |
| Custom F10-style UI | Client redscript + `ServerRpc` / `ClientRpc` |

## Layout

```
cyberpunkmp-plugin/
README.md ← this file
MIGRATION.md ← feature migration map
RedSyncSystem/ ← server plugin (loads as plugins/RedSyncSystem/)
client-redscript/ ← optional client RPC / UI scripts for CMP
```

## Build / install (against a CMP server tree)

1. Build or download a CyberpunkMP server that includes `CyberpunkSdk`.
2. Set `CYBERPUNKMP_SDK` to the folder containing `CyberpunkSdk.dll`
(or leave unset to compile against local **SdkStubs** for CI only — do not
deploy stub `CyberpunkSdk.dll` into a live CMP server).
3. Build:

```bash
dotnet build cyberpunkmp-plugin/RedSyncSystem -c Release
```

4. Install **only** the plugin assembly:

```text
<cmp-server>/plugins/RedSyncSystem/RedSyncSystem.dll
```

Loader rules (from CMP): folder name `RedSyncSystem`, assembly
`RedSyncSystem.dll`, type `RedSyncSystem.Plugin`, static constructor runs on load.

5. Optional: set `REDSYNC_DISCORD_WEBHOOK` on the CMP server process for join/leave announces.

## Local build (this machine)

```bash
./cyberpunkmp-plugin/build-local.sh
dotnet run --project cyberpunkmp-plugin/RedSyncSystem.Smoke -c Release
```

Stages `cyberpunkmp-plugin/local-plugins/RedSyncSystem/` (DLL + `redsync.json`).
Copy that folder into a CyberpunkMP server’s `plugins/` directory to load it.
20 changes: 20 additions & 0 deletions cyberpunkmp-plugin/RedSyncSystem.Smoke/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using CyberpunkSdk;
using RedSyncSystem;

internal static class Program
{
private static void Main()
{
Console.WriteLine("RedSyncSystem local smoke test");
_ = Plugin.Instance;
Console.WriteLine($"Config: {PluginConfig.ConfigPath}");

StubPlayerSystem.Instance.SimulateJoin(1, "LocalTester");
StubPlayerSystem.Instance.SimulateLeave(1);
StubWorld.Instance.SimulateTick(0.1f);

Plugin.Instance.Admins.Add("LocalTester");
Console.WriteLine($"IsAdmin(LocalTester)={Plugin.Instance.IsAdmin("LocalTester")}");
Console.WriteLine("Smoke test OK");
}
}
13 changes: 13 additions & 0 deletions cyberpunkmp-plugin/RedSyncSystem.Smoke/Program.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<LangVersion>12</LangVersion>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\RedSyncSystem\RedSyncSystem.csproj" />
<ProjectReference Include="..\SdkStubs\CyberpunkSdk.Stubs.csproj" />
</ItemGroup>
</Project>
131 changes: 131 additions & 0 deletions cyberpunkmp-plugin/RedSyncSystem/AdminAllowlist.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
using System.Text.Json;

namespace RedSyncSystem;

/// <summary>
/// Optional RedSync-side admin allowlist (usernames). CMP may have its own admin;
/// this list is for RedSync plugin features only.
/// </summary>
public sealed class AdminAllowlist
{
private readonly object _lock = new();
private readonly string _path;
private readonly LoggerProxy _log;
private HashSet<string> _admins = new(StringComparer.OrdinalIgnoreCase);

private static readonly JsonSerializerOptions JsonOptions = new()
{
WriteIndented = true,
PropertyNameCaseInsensitive = true
};

public AdminAllowlist(string pluginDirectory, IEnumerable<string>? seed, LoggerProxy log)
{
_log = log;
_path = Path.Combine(pluginDirectory, "admins.json");
Load(seed);
}

public bool IsAdmin(string? name)
{
if (string.IsNullOrWhiteSpace(name))
{
return false;
}

lock (_lock)
{
return _admins.Contains(name.Trim());
}
}

public bool Add(string name)
{
name = name.Trim();
if (string.IsNullOrWhiteSpace(name))
{
return false;
}

lock (_lock)
{
if (!_admins.Add(name))
{
return false;
}

SaveLocked();
return true;
}
}

public bool Remove(string name)
{
name = name.Trim();
lock (_lock)
{
if (!_admins.Remove(name))
{
return false;
}

SaveLocked();
return true;
}
}

public IReadOnlyList<string> List()
{
lock (_lock)
{
return _admins.OrderBy(x => x, StringComparer.OrdinalIgnoreCase).ToList();
}
}

private void Load(IEnumerable<string>? seed)
{
lock (_lock)
{
_admins = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
if (File.Exists(_path))
{
try
{
var names = JsonSerializer.Deserialize<List<string>>(File.ReadAllText(_path), JsonOptions)
?? [];
foreach (var n in names)
{
if (!string.IsNullOrWhiteSpace(n))
{
_admins.Add(n.Trim());
}
}
}
catch (Exception ex)
{
_log.Warn($"admins.json load failed: {ex.Message}");
}
}

if (seed != null)
{
foreach (var n in seed)
{
if (!string.IsNullOrWhiteSpace(n))
{
_admins.Add(n.Trim());
}
}
}

SaveLocked();
_log.Info($"Admin allowlist: {_admins.Count} name(s) ({_path})");
}
}

private void SaveLocked()
{
var list = _admins.OrderBy(x => x, StringComparer.OrdinalIgnoreCase).ToList();
File.WriteAllText(_path, JsonSerializer.Serialize(list, JsonOptions));
}
}
Loading