Files
DorkNet/DorkNet.Server/Controllers/API/Settings/V2/SettingsController.cs
T
Alexa d471b418b9 Import march-2020-03-10 from private repo (scrubbed 2026-05-27)
Targets Rec Room 2020.03.10 client (also serves 2020.03.06).

Re-import after adding:
- DorkNet.ClientMod/dorknet-clientmod.json.template — config schema
  the launcher's manifest-driven patcher renders into UserData/.
- tools/build-patcher-zip.ps1 — produces dorknet-clientpatch-{key}.zip
  for v1-march-* Release uploads.
- .github/workflows/release.yml — on tag push publishes both
  dorknet-server-march_2020_03_10-win-x64.zip and
  dorknet-clientpatch-march_2020_03_10.zip as Release assets.

Same scrub rules as december; tools/build-patcher-zip.ps1 added to
the maintainer-side allow-list so it survives.
2026-05-27 01:06:12 +03:00

102 lines
3.3 KiB
C#

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using DorkNet.Server.Auth;
using DorkNet.Server.Data;
using DorkNet.Server.Data.Entities;
using System.Text.Json.Serialization;
namespace DorkNet.Server.Controllers.API.Settings.V2;
/// <summary>
/// api.rec.net/api/settings/v2 — player settings download / set / remove.
/// URL patterns (verified by disassembling RecNet.Settings$$DowloadLocalPlayerSettings
/// at RVA 0xAF55B0 and RecNet.Settings$$StoreLocalPlayerSetting at RVA 0xAF5650):
///
/// GET api/settings/v2/ — returns List&lt;{Key, Value}&gt;
/// POST api/settings/v2/set — body { Key, Value } (set or update one)
/// POST api/settings/v2/remove — body { Key } (delete one)
///
/// The CLIENT side parses the GET response with Util.DeserializeList&lt;Setting&gt;
/// and reads each entry's "Key" and "Value" fields (verified by string literal
/// references in the deserializer body — both are PascalCase).
///
/// Returning a Dictionary&lt;string,string&gt; here serializes as "{}"
/// when empty, which the client casts to a List and dies with
/// InvalidCastException: Unable to cast object of type 'Dictionary`2' to
/// type 'List`1'. Always return a real List.
/// </summary>
[ApiController]
[Route("api/[controller]/v2")]
[Authorize]
public class SettingsController(DorkNetDbContext db) : ControllerBase
{
private long CurrentPlayerId => this.RequireCurrentPlayerId();
[HttpGet]
[HttpGet("get")]
public async Task<IActionResult> GetSettings()
{
var settings = await db.PlayerSettings
.Where(s => s.PlayerId == CurrentPlayerId)
.Select(s => new SettingDto { Key = s.Key, Value = s.Value })
.ToListAsync();
return Ok(settings);
}
[HttpPost("set")]
public async Task<ActionResult> SetSetting([FromBody] SetSettingRequest req)
{
var existing = await db.PlayerSettings
.FirstOrDefaultAsync(s => s.PlayerId == CurrentPlayerId && s.Key == req.Key);
if (existing is null)
{
db.PlayerSettings.Add(new PlayerSettingEntity
{
PlayerId = CurrentPlayerId,
Key = req.Key,
Value = req.Value,
});
}
else
{
existing.Value = req.Value;
}
await db.SaveChangesAsync();
return Ok(new SettingDto { Key = req.Key, Value = req.Value });
}
[HttpPost("remove")]
public async Task<ActionResult> RemoveSetting([FromBody] SetSettingRequest req)
{
var existing = await db.PlayerSettings
.FirstOrDefaultAsync(s => s.PlayerId == CurrentPlayerId && s.Key == req.Key);
if (existing is not null)
{
db.PlayerSettings.Remove(existing);
await db.SaveChangesAsync();
}
return Ok();
}
}
public class SettingDto
{
[JsonPropertyName("Key")]
public string Key { get; set; } = string.Empty;
[JsonPropertyName("Value")]
public string Value { get; set; } = string.Empty;
}
public class SetSettingRequest
{
[JsonPropertyName("Key")]
public string Key { get; set; } = string.Empty;
[JsonPropertyName("Value")]
public string Value { get; set; } = string.Empty;
}