account.go 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. package world
  2. import "path/filepath"
  3. import "gitlab.com/beoran/woe/sitef"
  4. import "gitlab.com/beoran/woe/monolog"
  5. import "fmt"
  6. import "errors"
  7. type Privilege int
  8. const (
  9. PRIVILEGE_ZERO = Privilege(iota * 100)
  10. PRIVILEGE_NORMAL
  11. PRIVILEGE_MASTER
  12. PRIVILEGE_LORD
  13. PRIVILEGE_IMPLEMENTOR
  14. )
  15. type Named struct {
  16. Name string
  17. }
  18. type Account struct {
  19. Name string
  20. Hash string
  21. Algo string
  22. Email string
  23. Points int
  24. Privilege Privilege
  25. CharacterNames []string
  26. characters []*Character
  27. }
  28. func SavePathForXML(dirname string, typename string, name string) string {
  29. return filepath.Join(dirname, typename, name+".xml")
  30. }
  31. func SavePathFor(dirname string, typename string, name string) string {
  32. return filepath.Join(dirname, typename, name+".sitef")
  33. }
  34. func NewAccount(name string, pass string, email string, points int) *Account {
  35. hash := WoeCryptPassword(pass, "")
  36. return &Account{name, hash, "woe", email, points, PRIVILEGE_NORMAL, nil, nil}
  37. // return &Account{name, pass, "plain", email, points, PRIVILEGE_NORMAL, nil, nil}
  38. }
  39. // Export an account to a "universal" map
  40. func (me *Account) ToUniMap() map[string]interface{} {
  41. res := make(map[string]interface{})
  42. return res
  43. }
  44. // Password Challenge for an account.
  45. func (me *Account) Challenge(challenge string) bool {
  46. if me.Algo == "plain" {
  47. return me.Hash == challenge
  48. } else if me.Algo == "woe" {
  49. return WoeCryptChallenge(me.Hash, challenge)
  50. }
  51. // implement beter passwd encryption later
  52. return false
  53. }
  54. // Add a character to an account.
  55. func (me *Account) AddCharacter(chara *Character) {
  56. me.characters = append(me.characters, chara)
  57. }
  58. // Save an account as a sitef file.
  59. func (me *Account) Save(dirname string) (err error) {
  60. path := SavePathFor(dirname, "account", me.Name)
  61. rec := sitef.NewRecord()
  62. rec.Put("name", me.Name)
  63. rec.Put("hash", me.Hash)
  64. rec.Put("algo", me.Algo)
  65. rec.Put("email", me.Email)
  66. rec.PutInt("points", me.Points)
  67. rec.PutInt("privilege", int(me.Privilege))
  68. rec.PutInt("characters", len(me.characters))
  69. for i, chara := range me.characters {
  70. key := fmt.Sprintf("characters[%d]", i)
  71. rec.Put(key, chara.ID)
  72. }
  73. monolog.Debug("Saving Acccount record: %s %v", path, rec)
  74. return sitef.SaveRecord(path, *rec)
  75. }
  76. // Load an account from a sitef file.
  77. func LoadAccount(dirname string, name string) (account *Account, err error) {
  78. path := SavePathFor(dirname, "account", name)
  79. records, err := sitef.ParseFilename(path)
  80. if err != nil {
  81. return nil, err
  82. }
  83. if len(records) < 1 {
  84. return nil, errors.New("No record found!")
  85. }
  86. record := records[0]
  87. monolog.Info("Loading Account record: %s %v", path, record)
  88. account = new(Account)
  89. account.Name = record.Get("name")
  90. account.Hash = record.Get("hash")
  91. account.Algo = record.Get("algo")
  92. account.Email = record.Get("email")
  93. account.Points = record.GetIntDefault("points", 0)
  94. account.Privilege = Privilege(record.GetIntDefault("privilege",
  95. int(PRIVILEGE_NORMAL)))
  96. nchars := record.GetIntDefault("characters", 0)
  97. account.characters = make([]*Character, 0, nchars)
  98. monolog.Info("Try to load %d characters:\n", nchars)
  99. for index := 0; index < nchars; index++ {
  100. chid := record.GetArrayIndex("characters", index)
  101. monolog.Info("Loading character: %d %s\n", index, chid)
  102. ch, err := account.LoadCharacter(dirname, chid)
  103. if err != nil {
  104. monolog.Error("Could not load character %s: %s", chid, err.Error())
  105. // return nil, err
  106. } else {
  107. account.characters = append(account.characters, ch)
  108. }
  109. }
  110. /* Todo: load characters here... */
  111. monolog.Info("Loaded Account: %s %v", path, account)
  112. return account, nil
  113. }
  114. func (me *Account) NumCharacters() int {
  115. return len(me.characters)
  116. }
  117. func (me *Account) GetCharacter(index int) *Character {
  118. return me.characters[index]
  119. }
  120. func (me *Account) FindCharacter(character *Character) (index int) {
  121. for k, c := range me.characters {
  122. if c == character {
  123. return k
  124. }
  125. }
  126. return -1
  127. }
  128. // Delete a character from this account.
  129. func (me *Account) DeleteCharacter(dirname string, character *Character) bool {
  130. if i := me.FindCharacter(character); i < 0 {
  131. monolog.Warning("Could not find character: %v %d", character, i)
  132. return false
  133. } else {
  134. copy(me.characters[i:], me.characters[i+1:])
  135. newlen := len(me.characters) - 1
  136. me.characters[newlen] = nil
  137. me.characters = me.characters[:newlen]
  138. }
  139. /// Save self so the deletion is correctly recorded.
  140. me.Save(dirname)
  141. return character.Delete(dirname)
  142. }
  143. func (me *Account) CharacterEntitylikeSlice() EntitylikeSlice {
  144. els := make(EntitylikeSlice, 0, 16)
  145. for i := 0; i < me.NumCharacters(); i++ {
  146. chara := me.GetCharacter(i)
  147. els = append(els, chara)
  148. }
  149. return els
  150. }