暫無描述

object.go 4.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. package funmow
  2. import (
  3. "fmt"
  4. "sort"
  5. "strings"
  6. )
  7. const (
  8. MatchNone = iota
  9. MatchOne
  10. MatchMany
  11. )
  12. type PlayerMeta struct {
  13. ID DBRef `json:"id"`
  14. Password string `json:"password"`
  15. }
  16. type Object struct {
  17. ID DBRef `json:"id"`
  18. Next DBRef `json:"next"`
  19. Type string `json:"type"`
  20. Name string `json:"name"`
  21. Description string `json:"description"`
  22. Flags map[string]string `json:"flags"`
  23. Owner DBRef `json:"owner"`
  24. db *DB
  25. }
  26. type ObjectFactory struct {
  27. db *DB
  28. }
  29. func NewObjectFactory(db *DB) *ObjectFactory {
  30. return &ObjectFactory{db: db}
  31. }
  32. func (f *ObjectFactory) NewObject() Object {
  33. o := Object{}
  34. o.ID, _ = f.db.Allocate()
  35. o.db = f.db
  36. return o
  37. }
  38. func (f *ObjectFactory) NewExit(name string, next DBRef, owner DBRef) Object {
  39. o := Object{
  40. Type: "exit",
  41. Name: name,
  42. Next: next,
  43. Owner: owner,
  44. db: f.db,
  45. }
  46. o.ID, _ = f.db.Allocate()
  47. return o
  48. }
  49. func (f *ObjectFactory) NewRoom() Object {
  50. o := Object{}
  51. o.ID, _ = f.db.Allocate()
  52. o.Type = "room"
  53. o.db = f.db
  54. return o
  55. }
  56. func (f *ObjectFactory) NewThing() Object {
  57. o := Object{}
  58. o.ID, _ = f.db.Allocate()
  59. o.Type = "thing"
  60. o.db = f.db
  61. return o
  62. }
  63. func (o *Object) Commit() error {
  64. return o.db.StoreObject(*o, o.ID)
  65. }
  66. func (o *Object) Refresh() bool {
  67. refreshed, found := o.db.RetrieveObject(o.ID)
  68. if found {
  69. *o = refreshed
  70. }
  71. return found
  72. }
  73. func (o Object) String() string {
  74. return fmt.Sprintf("id %d: %s", o.ID, o.Name)
  75. }
  76. func (o *Object) Remove(c *Object) error {
  77. return o.db.Unlink(o.ID, c.ID)
  78. }
  79. func (o *Object) Delete() error {
  80. err := o.db.Delete(o.ID)
  81. if err == nil {
  82. *o = Object{}
  83. }
  84. return err
  85. }
  86. func (o *Object) Contains(c *Object) error {
  87. return o.db.Link(o.ID, c.ID, c.Type)
  88. }
  89. func (o *Object) MatchLinkNames(matchName string, player DBRef) ObjectList {
  90. if matchName == "here" {
  91. return ObjectList{*o}
  92. }
  93. if matchName == "me" {
  94. p, found := o.db.Fetch(player)
  95. if !found {
  96. return ObjectList{}
  97. } else {
  98. return ObjectList{p}
  99. }
  100. }
  101. r := make(ObjectList, 0)
  102. children := o.db.GetChildren(o.ID) // map[DBRef]string
  103. for childID, _ := range children {
  104. o, found := o.db.Fetch(childID)
  105. if found {
  106. idName := fmt.Sprintf("#%d", o.ID)
  107. lowerObjectName := strings.ToLower(o.Name)
  108. lowerMatchName := strings.ToLower(matchName)
  109. if strings.HasPrefix(lowerObjectName, lowerMatchName) || matchName == idName {
  110. r = append(r, o)
  111. }
  112. }
  113. }
  114. return r
  115. }
  116. func (o *Object) MatchExitNames(name string) ObjectList { // so much copypasta
  117. r := make(ObjectList, 0)
  118. children := o.db.GetChildren(o.ID) // map[DBRef]string
  119. for childID, childType := range children {
  120. if childType != "exit" {
  121. continue
  122. }
  123. o, found := o.db.Fetch(childID)
  124. if found {
  125. idName := fmt.Sprintf("#%d", childID)
  126. if strings.EqualFold(o.Name, name) || name == idName {
  127. r = append(r, o)
  128. break // have a match. Don't need to look for any more.
  129. }
  130. aliases := strings.Split(o.Name, ";")
  131. for _, v := range aliases {
  132. if v == name {
  133. r = append(r, o)
  134. break // no need to look at other aliases
  135. }
  136. }
  137. }
  138. }
  139. return r
  140. }
  141. func (o *Object) DetailedName() string {
  142. return fmt.Sprintf("%s (#%d)", o.Name, o.ID)
  143. }
  144. func (o *Object) GetLinkNames(matchType string, exclude DBRefList) []string {
  145. r := make([]string, 0)
  146. children := o.db.GetChildren(o.ID) // map[DBRef]string
  147. childLoop:
  148. for childID, linkType := range children {
  149. if matchType != "*" && matchType != linkType {
  150. continue
  151. }
  152. for _, excludeID := range exclude {
  153. if excludeID == childID {
  154. continue childLoop
  155. }
  156. }
  157. o, found := o.db.Fetch(childID)
  158. if found {
  159. if linkType == "player" {
  160. if o.GetFlag("online","false") == "true" {
  161. r = append(r, o.DetailedName())
  162. }
  163. } else if linkType == "exit" {
  164. r = append(r, o.Name)
  165. } else {
  166. r = append(r, o.DetailedName())
  167. }
  168. }
  169. }
  170. sort.Strings(r)
  171. return r
  172. }
  173. func (o *Object) SetFlag(flag string, value string) {
  174. if o.Flags == nil {
  175. o.Flags = make(map[string]string)
  176. }
  177. o.Flags[flag]=value
  178. }
  179. func (o *Object) GetFlag(flag string, defaultValue string) (string) {
  180. if o.Flags == nil {
  181. return defaultValue
  182. }
  183. value, ok := o.Flags[flag]
  184. if !ok {
  185. return defaultValue
  186. }
  187. return value
  188. }
  189. type ObjectList []Object
  190. func (l ObjectList) First() Object {
  191. if len(l) > 0 {
  192. return l[0]
  193. } else {
  194. return Object{}
  195. }
  196. }
  197. func (l ObjectList) ExactlyOne() (Object, int) {
  198. c := len(l)
  199. if c == 0 {
  200. return Object{}, MatchNone
  201. } else if c == 1 {
  202. return l[0], MatchOne
  203. } else {
  204. return Object{}, MatchMany
  205. }
  206. }