You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

171 lines
5.0 KiB

  1. package gamesrv
  2. import (
  3. "errors"
  4. "fmt"
  5. "strconv"
  6. "time"
  7. "github.com/arnaucube/gogame/constants"
  8. "github.com/arnaucube/gogame/database"
  9. "github.com/arnaucube/gogame/models"
  10. "github.com/arnaucube/gogame/utils"
  11. "gopkg.in/mgo.v2/bson"
  12. )
  13. type Service struct {
  14. db *database.Db
  15. }
  16. func New(db *database.Db) *Service {
  17. return &Service{
  18. db,
  19. }
  20. }
  21. // CreatePlanet is used when a user conquers a planet
  22. func (srv Service) CreatePlanet(userId bson.ObjectId) (*models.SolarSystem, *models.Planet, error) {
  23. size := int64(250) // TODO get rand inside a range
  24. name := "planetname" // TODO get random name
  25. newPlanet := models.Planet{
  26. Size: size,
  27. Name: name,
  28. OwnerId: userId,
  29. }
  30. // in case that wants to start with resources plants
  31. newPlanet.Buildings = make(map[string]int64)
  32. newPlanet.Buildings["metalmine"] = 1
  33. newPlanet.Buildings["crystalmine"] = 1
  34. newPlanet.Buildings["deuteriummine"] = 1
  35. newPlanet.Buildings["energymine"] = 1
  36. err := srv.db.Planets.Insert(newPlanet)
  37. if err != nil {
  38. return nil, nil, err
  39. }
  40. var planet *models.Planet
  41. err = srv.db.Planets.Find(bson.M{"ownerid": newPlanet.OwnerId}).One(&planet)
  42. if err != nil {
  43. return nil, nil, err
  44. }
  45. // now put the planet in a solar system
  46. // get random solar system
  47. systemPosition := utils.RandInRange(0, constants.GALAXYSIZE)
  48. solarSystem, err := srv.PutPlanetInSolarSystem(systemPosition, planet)
  49. // TODO if error is returned because there is no empty slots for planets in the solar system in systemPosition, get another systemPosition and try again
  50. return solarSystem, planet, err
  51. }
  52. func (srv Service) PutPlanetInSolarSystem(position int64, planet *models.Planet) (*models.SolarSystem, error) {
  53. var solarSystem models.SolarSystem
  54. err := srv.db.SolarSystems.Find(bson.M{"position": position}).One(&solarSystem)
  55. if err != nil {
  56. // solar system non existing yet
  57. // create a solarsystem with empty planets
  58. var emptyPlanets []string
  59. for i := 0; i < constants.SOLARSYSTEMSIZE; i++ {
  60. emptyPlanets = append(emptyPlanets, "empty")
  61. }
  62. newSolarSystem := models.SolarSystem{
  63. Position: position,
  64. Planets: emptyPlanets[:15],
  65. }
  66. err = srv.db.SolarSystems.Insert(newSolarSystem)
  67. if err != nil {
  68. return nil, err
  69. }
  70. err := srv.db.SolarSystems.Find(bson.M{"position": position}).One(&solarSystem)
  71. return &solarSystem, err
  72. }
  73. // get free slots in solarSystem
  74. posInSolarSystem := utils.RandInRange(0, constants.SOLARSYSTEMSIZE)
  75. if solarSystem.Planets[posInSolarSystem] != "" {
  76. // not empty slot, take another one TODO
  77. // if there are no empty slots, return error
  78. fmt.Println("not empty slot")
  79. }
  80. // store planet in solar system
  81. solarSystem.Planets[posInSolarSystem] = planet.Id.String()
  82. err = srv.db.SolarSystems.Update(bson.M{"position": position}, solarSystem)
  83. return &solarSystem, err
  84. }
  85. // CheckCurrentBuild checks if the planet has a ongoing building in process, and if has finished
  86. // in case that has finished, updates it in db
  87. func (srv Service) CheckCurrentBuild(planet *models.Planet) (bool, error) {
  88. if planet.CurrentBuild.Title != "" {
  89. // the planet is building something, check if has ended
  90. if planet.CurrentBuild.Ends.Unix() < time.Now().Unix() {
  91. // upgrade level of building in planet
  92. planet.Buildings[planet.CurrentBuild.Building] += 1
  93. // build end
  94. planet.CurrentBuild.Title = ""
  95. planet.CurrentBuild.Building = ""
  96. // store in db
  97. err := srv.db.Planets.Update(bson.M{"_id": planet.Id}, planet)
  98. if err != nil {
  99. return true, err
  100. }
  101. return false, nil
  102. }
  103. return true, nil
  104. }
  105. return false, nil
  106. }
  107. func (srv Service) GetBuildings(user *models.User, planetid bson.ObjectId) (*models.Planet, error) {
  108. var planet models.Planet
  109. err := srv.db.Planets.Find(bson.M{"_id": planetid, "ownerid": user.Id}).One(&planet)
  110. if err != nil {
  111. return nil, err
  112. }
  113. _, err = srv.CheckCurrentBuild(&planet)
  114. return &planet, err
  115. }
  116. func (srv Service) UpgradeBuilding(user *models.User, planetid bson.ObjectId, building string) (*models.Planet, error) {
  117. // get planet
  118. var planet models.Planet
  119. err := srv.db.Planets.Find(bson.M{"_id": planetid}).One(&planet)
  120. if err != nil {
  121. return nil, err
  122. }
  123. busy, err := srv.CheckCurrentBuild(&planet)
  124. if err != nil {
  125. return nil, err
  126. }
  127. if busy {
  128. return nil, errors.New("busy")
  129. }
  130. // get current building level, and get the needed resources for next level
  131. resourcesNeeded, err := user.GetBuildingCost(planet, building)
  132. if err != nil {
  133. return nil, err
  134. }
  135. // get time cost of the build
  136. timei64 := models.ConstructionTime(resourcesNeeded, planet.Buildings[building]+1)
  137. endsTime := time.Now().Add(time.Second * time.Duration(timei64))
  138. // if user have enough resources to upgrade the building, upgrade the building
  139. err = user.SpendResources(resourcesNeeded)
  140. if err != nil {
  141. return nil, err
  142. }
  143. // add current task to planet
  144. planet.CurrentBuild.Building = building
  145. planet.CurrentBuild.Title = building + " - Level " + strconv.Itoa(int(planet.Buildings[building]))
  146. planet.CurrentBuild.Ends = endsTime
  147. // store planet in db
  148. err = srv.db.Planets.Update(bson.M{"_id": planet.Id}, planet)
  149. return &planet, nil
  150. }