feat(client): net primitives — DmResponse, NarrateResult, DmTransport, ProxyConfig

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-10 09:54:03 -05:00
parent b4d22f5c5f
commit 18a18820fe
10 changed files with 126 additions and 0 deletions

View File

@@ -0,0 +1,25 @@
class_name DmResponse
extends RefCounted
## The raw outcome of one HTTP attempt, independent of any game meaning.
## `status` is 0 when the transport never reached the server; `body` is the
## parsed JSON dict, or null when the body was absent or not JSON.
var status: int
var body # Variant: parsed JSON (Dictionary) or null
var transport_ok: bool
var error: String
func _init(p_status := 0, p_body = null, p_transport_ok := false, p_error := "") -> void:
status = p_status
body = p_body
transport_ok = p_transport_ok
error = p_error
static func ok(p_status: int, p_body) -> DmResponse:
return DmResponse.new(p_status, p_body, true, "")
static func failed(p_error: String) -> DmResponse:
return DmResponse.new(0, null, false, p_error)

View File

@@ -0,0 +1 @@
uid://bdy2347pcqm4v

View File

@@ -0,0 +1,10 @@
class_name DmTransport
extends RefCounted
## The network seam. DmService talks to this, never to HTTPRequest directly, so
## the loop logic is testable with an injected fake. Concrete transports
## override post_json. The base returns a failed response (rather than assert())
## so a missing override is a loud, catchable failure in tests.
func post_json(_path: String, _body: Dictionary) -> DmResponse:
push_error("DmTransport.post_json must be overridden")
return DmResponse.failed("transport not implemented")

View File

@@ -0,0 +1 @@
uid://crgmujan6vj2l

View File

@@ -0,0 +1,18 @@
class_name NarrateResult
extends RefCounted
## The game-meaningful result of one narrate call. `facts` are the [FACT:]
## strings the caller applies to the canon log; empty when degraded.
var display_text: String
var facts: Array
var degraded: bool
func _init(p_display_text := "", p_facts := [], p_degraded := false) -> void:
display_text = p_display_text
facts = p_facts
degraded = p_degraded
static func fallback(line: String) -> NarrateResult:
return NarrateResult.new(line, [], true)

View File

@@ -0,0 +1 @@
uid://dye0nd5h05cks

View File

@@ -0,0 +1,14 @@
class_name ProxyConfig
extends RefCounted
## The client's one piece of network config: the proxy base URL. Never a key,
## never a model name (charter §4). Overridable per environment via project
## settings; defaults to the dev proxy.
const SETTING := "coc_rpg/proxy_base_url"
const DEFAULT := "http://localhost:8000"
static func base_url() -> String:
var v = ProjectSettings.get_setting(SETTING, DEFAULT)
var s := str(v)
return s if s != "" else DEFAULT

View File

@@ -0,0 +1 @@
uid://n7p287j05isf