-
Notifications
You must be signed in to change notification settings - Fork 82
Expand file tree
/
Copy pathserver_dev.go
More file actions
172 lines (150 loc) · 3.79 KB
/
Copy pathserver_dev.go
File metadata and controls
172 lines (150 loc) · 3.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
package main
import (
"context"
"log"
"os"
"os/signal"
"strconv"
"sync"
"syscall"
"time"
"github.com/Hucaru/Valhalla/common"
)
type devServer struct {
configFile string
wg *sync.WaitGroup
ctx context.Context
cancel context.CancelFunc
loginServer *loginServer
worldServer *worldServer
channelServers []*channelServer
cashShopServer *cashShopServer
}
func newDevServer(configFile string) *devServer {
ctx, cancel := context.WithCancel(context.Background())
return &devServer{
configFile: configFile,
wg: &sync.WaitGroup{},
ctx: ctx,
cancel: cancel,
}
}
func (ds *devServer) run() {
log.Println("===============================================")
log.Println("Dev Server - All-in-One Mode")
log.Println("Starting Login, World, Channel, and CashShop servers")
log.Println("===============================================")
// Signal handler for graceful shutdown
ds.wg.Add(1)
go func() {
defer ds.wg.Done()
sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
select {
case <-sigCh:
log.Println("Shutdown signal received")
ds.shutdown()
case <-ds.ctx.Done():
}
}()
// Start all servers in goroutines
// Login server starts first
ds.wg.Add(1)
go func() {
defer ds.wg.Done()
defer func() {
if r := recover(); r != nil {
log.Println("Login server panic:", r)
}
}()
ds.loginServer = newLoginServer(ds.configFile)
ds.loginServer.run()
}()
// Give login server time to start
time.Sleep(2 * time.Second)
// Start world server
ds.wg.Add(1)
go func() {
defer ds.wg.Done()
defer func() {
if r := recover(); r != nil {
log.Println("World server panic:", r)
}
}()
ds.worldServer = newWorldServer(ds.configFile)
ds.worldServer.run()
}()
// Give world server time to connect to login
time.Sleep(2 * time.Second)
ds.channelServers = make([]*channelServer, *channelPtr)
for i := 0; i < *channelPtr; i++ {
ch := i
cs := newChannelServer(ds.configFile)
cs.config.ListenPort = strconv.Itoa(8685 + ch)
ds.channelServers[ch] = cs
ds.wg.Add(1)
go func(s *channelServer) {
defer ds.wg.Done()
defer func() {
if r := recover(); r != nil {
log.Println("Channel server panic:", r)
}
}()
s.run()
}(cs)
select {
case <-cs.Ready():
log.Printf("Channel %d is ready (port %s)\n", ch, cs.config.ListenPort)
case <-time.After(30 * time.Second):
log.Printf("Timed out waiting for channel %d to become ready\n", ch)
ds.shutdown()
return
case <-ds.ctx.Done():
return
}
}
// Start cashshop server
ds.wg.Add(1)
go func() {
defer ds.wg.Done()
defer func() {
if r := recover(); r != nil {
log.Println("CashShop server panic:", r)
}
}()
ds.cashShopServer = newCashShopServer(ds.configFile)
ds.cashShopServer.run()
}()
log.Println("===============================================")
log.Println("All servers started successfully!")
log.Println("Connect to: 127.0.0.1:8484")
log.Println("Press Ctrl+C to stop all servers")
log.Println("===============================================")
// Wait for all servers to exit
ds.wg.Wait()
log.Println("Dev Server stopped")
}
func (ds *devServer) shutdown() {
log.Println("Shutting down all servers...")
// Trigger shutdown on all servers
// Note: Each server has its own signal handler that will also trigger
// on SIGINT/SIGTERM, so they will shutdown gracefully on their own.
// This is a backup to ensure shutdown is triggered.
if ds.cashShopServer != nil {
ds.cashShopServer.shutdown()
}
for _, cs := range ds.channelServers {
if cs != nil {
cs.shutdown()
}
}
if ds.worldServer != nil {
ds.worldServer.shutdown()
}
if ds.loginServer != nil {
ds.loginServer.shutdown()
}
// Stop the metrics server
common.StopMetrics()
ds.cancel()
}