@@ -11,6 +11,7 @@ import (
1111 "strconv"
1212 "strings"
1313
14+ "github.com/MikelCalvo/go-metin2-server/internal/accountstore"
1415 authflow "github.com/MikelCalvo/go-metin2-server/internal/auth"
1516 "github.com/MikelCalvo/go-metin2-server/internal/authboot"
1617 "github.com/MikelCalvo/go-metin2-server/internal/boot"
@@ -39,13 +40,24 @@ var (
3940type loginKeyGenerator func () (uint32 , error )
4041
4142func NewAuthSessionFactory () service.SessionFactory {
42- return newAuthSessionFactory (loginticket .NewFileStore (defaultTicketStoreDir ()), randomLoginKey )
43+ return newAuthSessionFactoryWithAccountStore (
44+ loginticket .NewFileStore (defaultTicketStoreDir ()),
45+ accountstore .NewFileStore (defaultAccountStoreDir ()),
46+ randomLoginKey ,
47+ )
4348}
4449
4550func newAuthSessionFactory (store loginticket.Store , generateLoginKey loginKeyGenerator ) service.SessionFactory {
51+ return newAuthSessionFactoryWithAccountStore (store , accountstore .NewFileStore (defaultAccountStoreDir ()), generateLoginKey )
52+ }
53+
54+ func newAuthSessionFactoryWithAccountStore (store loginticket.Store , accounts accountstore.Store , generateLoginKey loginKeyGenerator ) service.SessionFactory {
4655 if store == nil {
4756 store = loginticket .NewFileStore (defaultTicketStoreDir ())
4857 }
58+ if accounts == nil {
59+ accounts = accountstore .NewFileStore (defaultAccountStoreDir ())
60+ }
4961 if generateLoginKey == nil {
5062 generateLoginKey = randomLoginKey
5163 }
@@ -62,7 +74,11 @@ func newAuthSessionFactory(store loginticket.Store, generateLoginKey loginKeyGen
6274 return authflow.Result {Accepted : false , FailureStatus : "WRONGPWD" }
6375 }
6476
65- loginKey , ok := issueLoginTicket (store , packet .Login , generateLoginKey )
77+ characters , ok := loadOrCreateAccountCharacters (accounts , packet .Login )
78+ if ! ok {
79+ return authflow.Result {Accepted : false , FailureStatus : "FAILED" }
80+ }
81+ loginKey , ok := issueLoginTicket (store , packet .Login , characters , generateLoginKey )
6682 if ! ok {
6783 return authflow.Result {Accepted : false , FailureStatus : "FAILED" }
6884 }
@@ -75,10 +91,18 @@ func newAuthSessionFactory(store loginticket.Store, generateLoginKey loginKeyGen
7591}
7692
7793func NewGameSessionFactory (cfg config.Service ) (service.SessionFactory , error ) {
78- return newGameSessionFactory (cfg , loginticket .NewFileStore (defaultTicketStoreDir ()))
94+ return newGameSessionFactoryWithAccountStore (
95+ cfg ,
96+ loginticket .NewFileStore (defaultTicketStoreDir ()),
97+ accountstore .NewFileStore (defaultAccountStoreDir ()),
98+ )
7999}
80100
81101func newGameSessionFactory (cfg config.Service , store loginticket.Store ) (service.SessionFactory , error ) {
102+ return newGameSessionFactoryWithAccountStore (cfg , store , accountstore .NewFileStore (defaultAccountStoreDir ()))
103+ }
104+
105+ func newGameSessionFactoryWithAccountStore (cfg config.Service , store loginticket.Store , accounts accountstore.Store ) (service.SessionFactory , error ) {
82106 advertisedPort , err := parsePort (cfg .LegacyAddr )
83107 if err != nil {
84108 return nil , err
@@ -92,6 +116,9 @@ func newGameSessionFactory(cfg config.Service, store loginticket.Store) (service
92116 if store == nil {
93117 store = loginticket .NewFileStore (defaultTicketStoreDir ())
94118 }
119+ if accounts == nil {
120+ accounts = accountstore .NewFileStore (defaultAccountStoreDir ())
121+ }
95122
96123 return func () service.SessionFlow {
97124 var sessionTicket loginticket.Ticket
@@ -127,6 +154,9 @@ func newGameSessionFactory(cfg config.Service, store loginticket.Store) (service
127154 if ! ok {
128155 return worldentry.CreateResult {Accepted : false , FailureType : failureType }
129156 }
157+ if ! saveAccountCharacters (accounts , sessionTicket .Login , sessionTicket .Characters ) {
158+ return worldentry.CreateResult {Accepted : false , FailureType : 0 }
159+ }
130160 return worldentry.CreateResult {
131161 Accepted : true ,
132162 Player : ticketPlayerCreateSuccessPacket (created , packet .Index , advertisedAddr , advertisedPort ),
@@ -190,7 +220,10 @@ func defaultKeyComplete() control.KeyCompletePacket {
190220 }
191221}
192222
193- func issueLoginTicket (store loginticket.Store , login string , generateLoginKey loginKeyGenerator ) (uint32 , bool ) {
223+ func issueLoginTicket (store loginticket.Store , login string , characters []loginticket.Character , generateLoginKey loginKeyGenerator ) (uint32 , bool ) {
224+ if len (characters ) == 0 {
225+ characters = stubCharacters ()
226+ }
194227 for range 8 {
195228 loginKey , err := generateLoginKey ()
196229 if err != nil || loginKey == 0 {
@@ -200,7 +233,7 @@ func issueLoginTicket(store loginticket.Store, login string, generateLoginKey lo
200233 err = store .Issue (loginticket.Ticket {
201234 Login : login ,
202235 LoginKey : loginKey ,
203- Characters : stubCharacters ( ),
236+ Characters : cloneCharacters ( characters ),
204237 })
205238 if err == nil {
206239 return loginKey , true
@@ -214,6 +247,40 @@ func issueLoginTicket(store loginticket.Store, login string, generateLoginKey lo
214247 return 0 , false
215248}
216249
250+ func loadOrCreateAccountCharacters (store accountstore.Store , login string ) ([]loginticket.Character , bool ) {
251+ if store == nil {
252+ return cloneCharacters (stubCharacters ()), true
253+ }
254+ account , err := store .Load (login )
255+ if err == nil {
256+ return cloneCharacters (account .Characters ), true
257+ }
258+ if ! errors .Is (err , accountstore .ErrAccountNotFound ) {
259+ return nil , false
260+ }
261+ characters := cloneCharacters (stubCharacters ())
262+ if err := store .Save (accountstore.Account {Login : login , Characters : characters }); err != nil {
263+ return nil , false
264+ }
265+ return cloneCharacters (characters ), true
266+ }
267+
268+ func saveAccountCharacters (store accountstore.Store , login string , characters []loginticket.Character ) bool {
269+ if store == nil {
270+ return true
271+ }
272+ return store .Save (accountstore.Account {Login : login , Characters : cloneCharacters (characters )}) == nil
273+ }
274+
275+ func cloneCharacters (characters []loginticket.Character ) []loginticket.Character {
276+ if len (characters ) == 0 {
277+ return nil
278+ }
279+ cloned := make ([]loginticket.Character , len (characters ))
280+ copy (cloned , characters )
281+ return cloned
282+ }
283+
217284func randomLoginKey () (uint32 , error ) {
218285 var raw [4 ]byte
219286 for range 8 {
@@ -549,6 +616,10 @@ func defaultTicketStoreDir() string {
549616 return filepath .Join (os .TempDir (), "go-metin2-server-login-tickets" )
550617}
551618
619+ func defaultAccountStoreDir () string {
620+ return filepath .Join (os .TempDir (), "go-metin2-server-accounts" )
621+ }
622+
552623func sequentialBytes32 (start byte ) [32 ]byte {
553624 var out [32 ]byte
554625 for i := range out {
0 commit comments