feat(weather): add weather selector API and UI controls for 7 atmospheric states
This commit is contained in:
1 parent
a11d6ce7c9
commit
df9f4f9082
2 files changed
+68
No files matched your search
@@ -118,6 +118,8 @@ internal sealed class DebugApiServer(PrivateServerConfig config, GameSessionHub
|
|||||||
await WriteJsonAsync(ctx, TimeStatus(), token);
|
await WriteJsonAsync(ctx, TimeStatus(), token);
|
||||||
else if (method == "POST" && path == "/api/time/set")
|
else if (method == "POST" && path == "/api/time/set")
|
||||||
await WriteJsonAsync(ctx, await TimeSetAsync(await ReadBodyAsync(ctx.Request, token), token), token);
|
await WriteJsonAsync(ctx, await TimeSetAsync(await ReadBodyAsync(ctx.Request, token), token), token);
|
||||||
|
else if (method == "POST" && path == "/api/weather/set")
|
||||||
|
await WriteJsonAsync(ctx, await WeatherSetAsync(await ReadBodyAsync(ctx.Request, token), token), token);
|
||||||
else if (method == "POST" && path == "/api/world/switch-scene")
|
else if (method == "POST" && path == "/api/world/switch-scene")
|
||||||
await WriteJsonAsync(ctx, await SwitchSceneAsync(await ReadBodyAsync(ctx.Request, token), token), token);
|
await WriteJsonAsync(ctx, await SwitchSceneAsync(await ReadBodyAsync(ctx.Request, token), token), token);
|
||||||
else if (method == "POST" && path == "/api/unstuck/blackscreen")
|
else if (method == "POST" && path == "/api/unstuck/blackscreen")
|
||||||
@@ -865,6 +867,41 @@ internal sealed class DebugApiServer(PrivateServerConfig config, GameSessionHub
|
|||||||
return new { ok = true, hour, minute, fix };
|
return new { ok = true, hour, minute, fix };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task<object> WeatherSetAsync(string json, CancellationToken token)
|
||||||
|
{
|
||||||
|
var session = hub.Current;
|
||||||
|
if (session is null)
|
||||||
|
return new { ok = false, error = "no live game session (is the client in the world?)" };
|
||||||
|
|
||||||
|
uint weatherId = 1, transition = 5;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var doc = JsonDocument.Parse(string.IsNullOrWhiteSpace(json) ? "{}" : json);
|
||||||
|
var root = doc.RootElement;
|
||||||
|
if (root.TryGetProperty("weatherId", out var pw))
|
||||||
|
weatherId = pw.GetUInt32();
|
||||||
|
if (root.TryGetProperty("transition", out var pt))
|
||||||
|
transition = pt.GetUInt32();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return new { ok = false, error = $"bad request: {ex.Message}" };
|
||||||
|
}
|
||||||
|
|
||||||
|
var state = GameRouter.GetStateIfExists(session);
|
||||||
|
if (state is null)
|
||||||
|
return new { ok = false, error = "no live game session (is the client in the world?)" };
|
||||||
|
lock (state.SyncRoot)
|
||||||
|
{
|
||||||
|
state.WeatherId = weatherId;
|
||||||
|
state.WeatherTransitionSeconds = transition;
|
||||||
|
state.HasExplicitWeather = true;
|
||||||
|
}
|
||||||
|
await GameRouter.PushSessionWeatherAsync(session);
|
||||||
|
session.Log.Info($"[DEBUG-API] weather set id={weatherId} transition={transition}s");
|
||||||
|
return new { ok = true, weatherId, transition };
|
||||||
|
}
|
||||||
|
|
||||||
private async Task<object> UnstuckBlackScreenAsync(CancellationToken token)
|
private async Task<object> UnstuckBlackScreenAsync(CancellationToken token)
|
||||||
{
|
{
|
||||||
var session = hub.Current;
|
var session = hub.Current;
|
||||||
|
|||||||
@@ -39,6 +39,25 @@
|
|||||||
<div class="muted">00:00 — night · 06:00 — morning · 12:00 — noon · 18:00 — evening · 23:59 — night</div>
|
<div class="muted">00:00 — night · 06:00 — morning · 12:00 — noon · 18:00 — evening · 23:59 — night</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="card">
|
||||||
|
<h2>Weather / Atmosphere (สภาพอากาศ)</h2>
|
||||||
|
<div>
|
||||||
|
<button style="background:#fbc02d;color:#222;font-weight:bold" onclick="setWeather(1)">☀️ Sunny (แดดออก)</button>
|
||||||
|
<button style="background:#78909c" onclick="setWeather(2)">⛅ Cloudy (มีเมฆมาก)</button>
|
||||||
|
<button style="background:#1976d2" onclick="setWeather(3)">🌧️ Rain (ฝนตก)</button>
|
||||||
|
<button style="background:#512da8" onclick="setWeather(4)">⛈️ Storm (พายุฝนฟ้าคะนอง)</button>
|
||||||
|
<button style="background:#757575" onclick="setWeather(5)">🌫️ Fog (หมอกลงจัด)</button>
|
||||||
|
<button style="background:#455a64" onclick="setWeather(6)">🌥️ Overcast (มืดครึ้ม)</button>
|
||||||
|
<button style="background:#303f9f" onclick="setWeather(7)">🌙 Night / Snow (หิมะ/กลางคืน)</button>
|
||||||
|
</div>
|
||||||
|
<div style="margin-top:8px">
|
||||||
|
Custom Weather ID: <input id="customWeatherId" type="number" style="width:90px" value="1">
|
||||||
|
Transition (sec): <input id="weatherTransition" type="number" style="width:70px" value="5">
|
||||||
|
<button class="ghost" onclick="setCustomWeather()">Apply Custom Weather</button>
|
||||||
|
</div>
|
||||||
|
<div class="muted" style="margin-top:6px">ซิงค์สภาพอากาศของโลกและบรรยากาศ client ทันที</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<h2>Garage (server vehicles)</h2>
|
<h2>Garage (server vehicles)</h2>
|
||||||
<div style="margin-bottom:10px;padding:8px;background:#252932;border-radius:6px">
|
<div style="margin-bottom:10px;padding:8px;background:#252932;border-radius:6px">
|
||||||
@@ -425,6 +444,18 @@ async function toggleClothes() {
|
|||||||
log('toggle clothes: ' + JSON.stringify(r));
|
log('toggle clothes: ' + JSON.stringify(r));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function setWeather(weatherId) {
|
||||||
|
const transition = parseInt(document.getElementById('weatherTransition')?.value || '5', 10);
|
||||||
|
const body = { weatherId: parseInt(weatherId, 10), transition };
|
||||||
|
const r = await api('/api/weather/set', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) });
|
||||||
|
log('set weather: ' + JSON.stringify(r));
|
||||||
|
}
|
||||||
|
|
||||||
|
async function setCustomWeather() {
|
||||||
|
const id = parseInt(document.getElementById('customWeatherId').value || '1', 10);
|
||||||
|
await setWeather(id);
|
||||||
|
}
|
||||||
|
|
||||||
function onEnemyPresetChange() {
|
function onEnemyPresetChange() {
|
||||||
const sel = document.getElementById('enemypreset').value;
|
const sel = document.getElementById('enemypreset').value;
|
||||||
if (sel !== 'custom') {
|
if (sel !== 'custom') {
|
||||||
|
|||||||
Reference in new issue
Block a user