mirror of
https://github.com/Luzifer/sii.git
synced 2024-12-21 08:21:16 +00:00
Knut Ahlers
b515c32f98
* Add support for multi-job creation Signed-off-by: Knut Ahlers <knut@ahlers.me> * Fix: Ensure at least one unit of cargo is transported Signed-off-by: Knut Ahlers <knut@ahlers.me> * Multi-stop route planning Signed-off-by: Knut Ahlers <knut@ahlers.me> * Linter + fix of weird char deletion Signed-off-by: Knut Ahlers <knut@ahlers.me>
258 lines
7.4 KiB
Go
258 lines
7.4 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/gorilla/mux"
|
|
"github.com/pkg/errors"
|
|
|
|
"github.com/Luzifer/go_helpers/v2/str"
|
|
"github.com/Luzifer/sii"
|
|
)
|
|
|
|
const (
|
|
storeSaveFolder = "sii_editor"
|
|
storeSaveName = "SII Editor"
|
|
)
|
|
|
|
func init() {
|
|
router.HandleFunc("/api/profiles/{profileID}/saves/{saveFolder}", handleGetSaveInfo).Methods(http.MethodGet)
|
|
router.HandleFunc("/api/profiles/{profileID}/saves/{saveFolder}/economy", handleUpdateEconomyInfo).Methods(http.MethodPut)
|
|
router.HandleFunc("/api/profiles/{profileID}/saves/{saveFolder}/fix", handleFixPlayer).Methods(http.MethodPut)
|
|
router.HandleFunc("/api/profiles/{profileID}/saves/{saveFolder}/jobs", handleListJobs).Methods(http.MethodGet)
|
|
router.HandleFunc("/api/profiles/{profileID}/saves/{saveFolder}/jobs", handleAddJob).Methods(http.MethodPost)
|
|
router.HandleFunc("/api/profiles/{profileID}/saves/{saveFolder}/set-trailer", handleSetTrailer).Methods(http.MethodPut)
|
|
}
|
|
|
|
func handleAddJob(w http.ResponseWriter, r *http.Request) {
|
|
var (
|
|
jobs []commSaveJob
|
|
vars = mux.Vars(r)
|
|
)
|
|
|
|
if err := json.NewDecoder(r.Body).Decode(&jobs); err != nil {
|
|
apiGenericError(w, http.StatusBadRequest, errors.Wrap(err, "Unable to decode input data"))
|
|
return
|
|
}
|
|
|
|
game, info, err := loadSave(vars["profileID"], vars["saveFolder"])
|
|
if err != nil {
|
|
apiGenericError(w, http.StatusInternalServerError, errors.Wrap(err, "Unable to load save"))
|
|
return
|
|
}
|
|
|
|
info.SaveName = storeSaveName
|
|
info.FileTime = time.Now().Unix()
|
|
|
|
for i, job := range jobs {
|
|
// Set urgency if it isn't
|
|
if job.Urgency == nil {
|
|
u := int64(0)
|
|
job.Urgency = &u
|
|
}
|
|
|
|
if job.Weight == 0 {
|
|
job.Weight = 10000 // 10 tons as a default
|
|
}
|
|
|
|
if job.Weight < 100 {
|
|
// User clearly did't want 54kg but 54 tons! (If not: screw em)
|
|
job.Weight *= 1000
|
|
}
|
|
|
|
if job.Distance == 0 {
|
|
job.Distance = 100 // If the user did not provide distance use 100km as a default
|
|
}
|
|
|
|
if err = addJobToGame(game, job, i); err != nil {
|
|
apiGenericError(w, http.StatusInternalServerError, errors.Wrap(err, "Unable to add job"))
|
|
return
|
|
}
|
|
}
|
|
|
|
// Write the save-game
|
|
if err = storeSave(vars["profileID"], storeSaveFolder, game, info); err != nil {
|
|
apiGenericError(w, http.StatusInternalServerError, errors.Wrap(err, "Unable to store save"))
|
|
return
|
|
}
|
|
|
|
apiGenericJSONResponse(w, http.StatusOK, map[string]interface{}{"success": true})
|
|
}
|
|
|
|
func handleFixPlayer(w http.ResponseWriter, r *http.Request) {
|
|
var (
|
|
fixType = fixAll
|
|
vars = mux.Vars(r)
|
|
)
|
|
|
|
if v := r.FormValue("type"); v != "" {
|
|
fixType = v
|
|
}
|
|
|
|
game, info, err := loadSave(vars["profileID"], vars["saveFolder"])
|
|
if err != nil {
|
|
apiGenericError(w, http.StatusInternalServerError, errors.Wrap(err, "Unable to load save"))
|
|
return
|
|
}
|
|
|
|
info.SaveName = storeSaveName
|
|
info.FileTime = time.Now().Unix()
|
|
|
|
if err = fixPlayerTruck(game, fixType); err != nil {
|
|
apiGenericError(w, http.StatusInternalServerError, errors.Wrap(err, "Unable to apply fixes"))
|
|
return
|
|
}
|
|
|
|
if err = storeSave(vars["profileID"], storeSaveFolder, game, info); err != nil {
|
|
apiGenericError(w, http.StatusInternalServerError, errors.Wrap(err, "Unable to store save"))
|
|
return
|
|
}
|
|
|
|
apiGenericJSONResponse(w, http.StatusOK, map[string]interface{}{"success": true})
|
|
}
|
|
|
|
func handleGetSaveInfo(w http.ResponseWriter, r *http.Request) {
|
|
var vars = mux.Vars(r)
|
|
|
|
game, _, err := loadSave(vars["profileID"], vars["saveFolder"])
|
|
if err != nil {
|
|
apiGenericError(w, http.StatusInternalServerError, errors.Wrap(err, "Unable to load save"))
|
|
return
|
|
}
|
|
|
|
info, err := commSaveDetailsFromUnit(game)
|
|
if err != nil {
|
|
apiGenericError(w, http.StatusInternalServerError, errors.Wrap(err, "Unable to gather info"))
|
|
return
|
|
}
|
|
|
|
apiGenericJSONResponse(w, http.StatusOK, info)
|
|
}
|
|
|
|
func handleListJobs(w http.ResponseWriter, r *http.Request) {
|
|
var (
|
|
result []commSaveJob
|
|
vars = mux.Vars(r)
|
|
undiscovered = r.FormValue("undiscovered") == "true"
|
|
)
|
|
|
|
game, _, err := loadSave(vars["profileID"], vars["saveFolder"])
|
|
if err != nil {
|
|
apiGenericError(w, http.StatusInternalServerError, errors.Wrap(err, "Unable to load save"))
|
|
return
|
|
}
|
|
|
|
economy := game.BlocksByClass("economy")[0].(*sii.Economy)
|
|
var visitedCities []string
|
|
for _, p := range economy.VisitedCities {
|
|
visitedCities = append(visitedCities, p.Target)
|
|
}
|
|
|
|
for _, cb := range game.BlocksByClass("company") {
|
|
c := cb.(*sii.Company)
|
|
|
|
cityName := strings.TrimPrefix(c.CityPtr().Target, "city.") // The "VisitedCities" pointers are kinda broken and do not contain the "city." part
|
|
if !str.StringInSlice(cityName, visitedCities) && !undiscovered {
|
|
continue
|
|
}
|
|
|
|
for _, b := range c.JobOffer {
|
|
j := b.Resolve().(*sii.JobOfferData)
|
|
|
|
if j.Target == "" || *j.ExpirationTime < economy.GameTime {
|
|
continue
|
|
}
|
|
|
|
result = append(result, commSaveJob{
|
|
OriginReference: c.Name(),
|
|
TargetReference: strings.Join([]string{"company", "volatile", j.Target}, "."),
|
|
CargoReference: j.Cargo.Target,
|
|
Distance: j.ShortestDistanceKM,
|
|
Urgency: j.Urgency,
|
|
Expires: *j.ExpirationTime - economy.GameTime,
|
|
})
|
|
}
|
|
}
|
|
|
|
apiGenericJSONResponse(w, http.StatusOK, result)
|
|
}
|
|
|
|
func handleSetTrailer(w http.ResponseWriter, r *http.Request) {
|
|
var (
|
|
reference = r.FormValue("ref")
|
|
vars = mux.Vars(r)
|
|
)
|
|
|
|
game, info, err := loadSave(vars["profileID"], vars["saveFolder"])
|
|
if err != nil {
|
|
apiGenericError(w, http.StatusInternalServerError, errors.Wrap(err, "Unable to load save"))
|
|
return
|
|
}
|
|
|
|
if game.BlockByName(reference) == nil {
|
|
apiGenericError(w, http.StatusBadRequest, errors.New("Invalid reference given"))
|
|
return
|
|
}
|
|
|
|
info.SaveName = storeSaveName
|
|
info.FileTime = time.Now().Unix()
|
|
|
|
game.BlocksByClass("player")[0].(*sii.Player).AssignedTrailer = sii.Ptr{Target: reference}
|
|
|
|
if err = storeSave(vars["profileID"], storeSaveFolder, game, info); err != nil {
|
|
apiGenericError(w, http.StatusInternalServerError, errors.Wrap(err, "Unable to store save"))
|
|
return
|
|
}
|
|
|
|
apiGenericJSONResponse(w, http.StatusOK, map[string]interface{}{"success": true})
|
|
}
|
|
|
|
func handleUpdateEconomyInfo(w http.ResponseWriter, r *http.Request) {
|
|
var vars = mux.Vars(r)
|
|
|
|
game, info, err := loadSave(vars["profileID"], vars["saveFolder"])
|
|
if err != nil {
|
|
apiGenericError(w, http.StatusInternalServerError, errors.Wrap(err, "Unable to load save"))
|
|
return
|
|
}
|
|
|
|
info.SaveName = storeSaveName
|
|
info.FileTime = time.Now().Unix()
|
|
|
|
blocks := game.BlocksByClass("economy")
|
|
if len(blocks) != 1 {
|
|
// expecting exactly one economy block
|
|
apiGenericError(w, http.StatusInternalServerError, errors.New("Did not find economy block"))
|
|
return
|
|
}
|
|
economy := blocks[0].(*sii.Economy)
|
|
|
|
if xpRaw := r.FormValue("xp"); xpRaw != "" {
|
|
xp, err := strconv.ParseInt(xpRaw, 10, 64)
|
|
if err != nil {
|
|
apiGenericError(w, http.StatusBadRequest, errors.Wrap(err, "Invalid value to xp parameter"))
|
|
return
|
|
}
|
|
economy.ExperiencePoints = xp
|
|
}
|
|
|
|
if moneyRaw := r.FormValue("money"); moneyRaw != "" {
|
|
money, err := strconv.ParseInt(moneyRaw, 10, 64)
|
|
if err != nil {
|
|
apiGenericError(w, http.StatusBadRequest, errors.Wrap(err, "Invalid value to money parameter"))
|
|
return
|
|
}
|
|
economy.Bank.Resolve().(*sii.Bank).MoneyAccount = money
|
|
}
|
|
|
|
if err = storeSave(vars["profileID"], storeSaveFolder, game, info); err != nil {
|
|
apiGenericError(w, http.StatusInternalServerError, errors.Wrap(err, "Unable to store save"))
|
|
return
|
|
}
|
|
|
|
apiGenericJSONResponse(w, http.StatusOK, map[string]interface{}{"success": true})
|
|
}
|