feat(scum): add map trajectory projection

This commit is contained in:
npc0-hue
2026-07-28 17:13:48 +08:00
parent 7f64765c1c
commit 5b15bd50cb
33 changed files with 1073 additions and 49 deletions
@@ -0,0 +1,66 @@
package api
import (
"net/http"
"strings"
"time"
"browser.local/platform/domain"
"browser.local/platform/dto"
)
// serverGameMapTrajectories godoc
// @Summary Read bounded SCUM map trajectories
// @Description Returns only authorized safe map projections, never raw logs, world coordinates, paths, or Companion connection material.
// @Tags game-map-trajectories
// @Produce json
// @Param id path string true "Server instance ID"
// @Param from query string false "RFC3339 window start"
// @Param to query string false "RFC3339 window end"
// @Param playerId query string false "Comma-separated game player record IDs"
// @Param vehicleId query string false "Comma-separated vehicle IDs"
// @Success 200 {object} dto.GameMapTrajectoryResponse
// @Failure 401 {object} dto.ErrorResponse
// @Failure 403 {object} dto.ErrorResponse
// @Failure 400 {object} dto.ErrorResponse
// @Router /api/v1/server-instances/{id}/game-map-trajectories [get]
func (h *coreHandlers) serverGameMapTrajectories(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
writeMethodNotAllowed(w, http.MethodGet)
return
}
from, err := mapTrajectoryTime(r.URL.Query().Get("from"))
if err != nil {
writeAPIError(w, http.StatusBadRequest, errorCodeBadRequest, "invalid map trajectory from time", nil)
return
}
to, err := mapTrajectoryTime(r.URL.Query().Get("to"))
if err != nil {
writeAPIError(w, http.StatusBadRequest, errorCodeBadRequest, "invalid map trajectory to time", nil)
return
}
value, err := h.core.GetGameMapTrajectoriesForSession(bearerToken(r), domain.GameMapTrajectoryQuery{ServerInstanceID: r.PathValue("id"), From: from, To: to, PlayerRecordIDs: mapTrajectoryIDs(r.URL.Query().Get("playerId")), VehicleIDs: mapTrajectoryIDs(r.URL.Query().Get("vehicleId"))})
if err != nil {
writeServiceError(w, err)
return
}
writeJSON(w, http.StatusOK, dto.GameMapTrajectoryFromDomain(value))
}
func mapTrajectoryTime(value string) (time.Time, error) {
if strings.TrimSpace(value) == "" {
return time.Time{}, nil
}
return time.Parse(time.RFC3339, value)
}
func mapTrajectoryIDs(value string) []string {
if strings.TrimSpace(value) == "" {
return nil
}
result := []string{}
for _, item := range strings.Split(value, ",") {
if item = strings.TrimSpace(item); item != "" {
result = append(result, item)
}
}
return result
}
+1
View File
@@ -98,6 +98,7 @@ func (h *coreHandlers) register(mux *http.ServeMux) {
mux.HandleFunc("/api/v1/server-instances/{id}/game-players/{playerId}/state", h.serverGamePlayerState)
mux.HandleFunc("/api/v1/server-instances/{id}/game-players/{playerId}/state-patches", h.serverGamePlayerStatePatches)
mux.HandleFunc("/api/v1/server-instances/{id}/game-players/{playerId}/state-patches/{patchId}/approve", h.serverGamePlayerStatePatchApprove)
mux.HandleFunc("/api/v1/server-instances/{id}/game-map-trajectories", h.serverGameMapTrajectories)
mux.HandleFunc("/api/v1/server-instances/{id}/game-gifts", h.serverGameGiftCatalogs)
mux.HandleFunc("/api/v1/server-instances/{id}/game-gifts/{catalogId}/publish", h.serverGameGiftCatalogPublish)
mux.HandleFunc("/api/v1/server-instances/{id}/game-gifts/{catalogId}/revisions", h.serverGameGiftCatalogRevisions)