Nessuna descrizione

object.go 4.0KB

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