FIRST
CI / Go Backend (push) Canceled after 0s

This commit is contained in:
xyou
2026-08-07 23:39:47 +08:00
parent f2105bf14c
commit 9500c4c80a
52 changed files with 3801 additions and 0 deletions
+26
View File
@@ -0,0 +1,26 @@
package main
import (
"log"
"mrcc/internal/config"
"mrcc/internal/httpserver"
"mrcc/internal/logger"
)
func main() {
cfg := config.Load("auth-service", "8081")
logger.WithService(cfg.Name).Info("starting service", "port", cfg.Port)
srv := httpserver.New(cfg)
// TODO: 注册认证路由
// r := srv.Group("/api/auth")
// r.POST("/register", ...)
// r.POST("/login", ...)
log.Printf("auth-service listening on %s", cfg.Address())
if err := srv.Run(cfg.Address()); err != nil {
log.Fatal(err)
}
}
+27
View File
@@ -0,0 +1,27 @@
package main
import (
"log"
"mrcc/internal/config"
"mrcc/internal/httpserver"
"mrcc/internal/logger"
)
func main() {
cfg := config.Load("blueprint-service", "8083")
logger.WithService(cfg.Name).Info("starting service", "port", cfg.Port)
srv := httpserver.New(cfg)
// TODO: 注册蓝图路由
// r := srv.Group("/api/blueprints")
// r.GET("/", ...)
// r.POST("/", ...)
// r.POST("/:id/buy", ...)
log.Printf("blueprint-service listening on %s", cfg.Address())
if err := srv.Run(cfg.Address()); err != nil {
log.Fatal(err)
}
}
+27
View File
@@ -0,0 +1,27 @@
package main
import (
"log"
"mrcc/internal/config"
"mrcc/internal/httpserver"
"mrcc/internal/logger"
)
func main() {
cfg := config.Load("economy-service", "8082")
logger.WithService(cfg.Name).Info("starting service", "port", cfg.Port)
srv := httpserver.New(cfg)
// TODO: 注册经济路由
// r := srv.Group("/api/user")
// r.GET("/balance", ...)
// r := srv.Group("/api/shop")
// r.GET("/items", ...)
log.Printf("economy-service listening on %s", cfg.Address())
if err := srv.Run(cfg.Address()); err != nil {
log.Fatal(err)
}
}
+27
View File
@@ -0,0 +1,27 @@
package main
import (
"log"
"mrcc/internal/config"
"mrcc/internal/httpserver"
"mrcc/internal/logger"
)
func main() {
cfg := config.Load("match-service", "8084")
logger.WithService(cfg.Name).Info("starting service", "port", cfg.Port)
srv := httpserver.New(cfg)
// TODO: 注册匹配路由
// r := srv.Group("/api/multiplayer")
// r.POST("/match", ...)
// r.POST("/join", ...)
// r.POST("/result", ...)
log.Printf("match-service listening on %s", cfg.Address())
if err := srv.Run(cfg.Address()); err != nil {
log.Fatal(err)
}
}
+167
View File
@@ -0,0 +1,167 @@
package main
import (
"log"
"net/http"
"sync"
"time"
"github.com/gin-gonic/gin"
"github.com/gorilla/websocket"
"mrcc/internal/config"
"mrcc/internal/httpserver"
"mrcc/internal/logger"
"mrcc/pkg/response"
)
// === 数据结构骨架(对照开发文档 18.5 节)===
type RoomStatus string
const (
RoomCreated RoomStatus = "created"
RoomWaiting RoomStatus = "waiting"
RoomPlaying RoomStatus = "playing"
RoomFinished RoomStatus = "finished"
)
// Player 玩家连接
type Player struct {
UserID string `json:"user_id"`
Username string `json:"username"`
Conn *websocket.Conn `json:"-"`
IsReady bool `json:"is_ready"`
JoinedAt time.Time `json:"joined_at"`
SendQueue chan []byte `json:"-"`
}
// Room 房间
type Room struct {
ID string `json:"id"`
Status RoomStatus `json:"status"`
HostUserID string `json:"host_user_id"`
MaxPlayers int `json:"max_players"`
Players map[string]*Player `json:"players"`
CreatedAt time.Time `json:"created_at"`
mu sync.RWMutex `json:"-"`
}
// RelayServer 中转服务器
type RelayServer struct {
Rooms map[string]*Room
Players map[string]*Player
Register chan *Player
Unregister chan *Player
mu sync.RWMutex
}
func NewRelayServer() *RelayServer {
return &RelayServer{
Rooms: make(map[string]*Room),
Players: make(map[string]*Player),
Register: make(chan *Player, 64),
Unregister: make(chan *Player, 64),
}
}
var upgrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool {
return true // 开发阶段允许所有来源
},
}
// HandleWS 处理 WebSocket 连接升级
func HandleWS(relay *RelayServer) gin.HandlerFunc {
return func(c *gin.Context) {
userID := c.Query("user_id")
if userID == "" {
userID = "anonymous"
}
conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
if err != nil {
log.Printf("websocket upgrade failed: %v", err)
return
}
player := &Player{
UserID: userID,
Conn: conn,
JoinedAt: time.Now(),
SendQueue: make(chan []byte, 256),
}
relay.Register <- player
log.Printf("player connected: %s", userID)
// TODO: 实现读写 goroutine、房间管理、消息路由、断线重连
// 当前骨架仅保持连接并读取消息
go func() {
defer func() {
relay.Unregister <- player
conn.Close()
}()
for {
_, _, err := conn.ReadMessage()
if err != nil {
break
}
}
}()
}
}
func main() {
cfg := config.Load("relay-server", "8086")
logger.WithService(cfg.Name).Info("starting relay server", "port", cfg.Port)
relay := NewRelayServer()
// 后台处理注册/注销
go func() {
for {
select {
case player := <-relay.Register:
relay.mu.Lock()
relay.Players[player.UserID] = player
relay.mu.Unlock()
log.Printf("player registered: %s", player.UserID)
case player := <-relay.Unregister:
relay.mu.Lock()
delete(relay.Players, player.UserID)
relay.mu.Unlock()
log.Printf("player unregistered: %s", player.UserID)
}
}
}()
srv := httpserver.New(cfg)
// WebSocket 端点
srv.GET("/ws", HandleWS(relay))
// 房间信息端点(骨架)
srv.GET("/rooms", func(c *gin.Context) {
relay.mu.RLock()
defer relay.mu.RUnlock()
rooms := make([]gin.H, 0, len(relay.Rooms))
for id, room := range relay.Rooms {
rooms = append(rooms, gin.H{
"id": id,
"status": room.Status,
"playerCount": len(room.Players),
})
}
response.OK(c, gin.H{"rooms": rooms, "total": len(rooms)})
})
log.Printf("relay-server listening on %s (WS: /ws)", cfg.Address())
if err := srv.Run(cfg.Address()); err != nil {
log.Fatal(err)
}
}
+28
View File
@@ -0,0 +1,28 @@
package main
import (
"log"
"mrcc/internal/config"
"mrcc/internal/httpserver"
"mrcc/internal/logger"
)
func main() {
cfg := config.Load("social-service", "8085")
logger.WithService(cfg.Name).Info("starting service", "port", cfg.Port)
srv := httpserver.New(cfg)
// TODO: 注册社交路由
// r := srv.Group("/api/user")
// r.GET("/profile", ...)
// r.GET("/achievements", ...)
// r := srv.Group("/api/leaderboard")
// r.GET("/", ...)
log.Printf("social-service listening on %s", cfg.Address())
if err := srv.Run(cfg.Address()); err != nil {
log.Fatal(err)
}
}