mirror of
https://github.com/Luzifer/sii.git
synced 2024-12-30 12:11:15 +00:00
247 lines
5.9 KiB
Go
247 lines
5.9 KiB
Go
|
package main
|
||
|
|
||
|
import (
|
||
|
"os"
|
||
|
"path"
|
||
|
|
||
|
"github.com/Luzifer/sii"
|
||
|
"github.com/pkg/errors"
|
||
|
)
|
||
|
|
||
|
const (
|
||
|
fixAll = "all"
|
||
|
fixCargoOnly = "cargo"
|
||
|
fixTrailerOnly = "trailer"
|
||
|
fixTruckOnly = "truck"
|
||
|
)
|
||
|
|
||
|
type commSaveDetails struct {
|
||
|
GameTime int64 `json:"game_time"`
|
||
|
|
||
|
ExperiencePoints int64 `json:"experience_points"`
|
||
|
Money int64 `json:"money"`
|
||
|
|
||
|
CargoDamage float32 `json:"cargo_damage"`
|
||
|
TruckWear float32 `json:"truck_wear"`
|
||
|
TrailerAttached bool `json:"trailer_attached"`
|
||
|
TrailerWear float32 `json:"trailer_wear"`
|
||
|
|
||
|
AttachedTrailer string `json:"attached_trailer"`
|
||
|
OwnedTrailers map[string]string `json:"owned_trailers"`
|
||
|
|
||
|
CurrentJob *commSaveJob `json:"current_job"`
|
||
|
}
|
||
|
|
||
|
type commSaveJob struct {
|
||
|
OriginReference string `json:"origin_reference"`
|
||
|
TargetReference string `json:"target_reference"`
|
||
|
CargoReference string `json:"cargo_reference"`
|
||
|
TrailerReference string `json:"trailer_reference"`
|
||
|
Distance int64 `json:"distance"`
|
||
|
Urgency *int64 `json:"urgency,omitempty"`
|
||
|
Weight float32 `json:"weight,omitempty"`
|
||
|
Expires int64 `json:"expires,omitempty"`
|
||
|
}
|
||
|
|
||
|
func commSaveDetailsFromUnit(unit *sii.Unit) (out commSaveDetails, err error) {
|
||
|
var economy *sii.Economy
|
||
|
|
||
|
for _, b := range unit.BlocksByClass("economy") {
|
||
|
if v, ok := b.(*sii.Economy); ok {
|
||
|
economy = v
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if economy == nil {
|
||
|
return out, errors.New("Found no economy object")
|
||
|
}
|
||
|
|
||
|
var (
|
||
|
bank *sii.Bank
|
||
|
job *sii.PlayerJob
|
||
|
player *sii.Player
|
||
|
truck *sii.Vehicle
|
||
|
trailer *sii.Trailer
|
||
|
)
|
||
|
|
||
|
bank = economy.Bank.Resolve().(*sii.Bank)
|
||
|
player = economy.Player.Resolve().(*sii.Player)
|
||
|
|
||
|
out.ExperiencePoints = economy.ExperiencePoints
|
||
|
out.GameTime = economy.GameTime
|
||
|
out.Money = bank.MoneyAccount
|
||
|
out.TrailerAttached = player.AssignedTrailerConnected
|
||
|
|
||
|
if v, ok := player.CurrentJob.Resolve().(*sii.PlayerJob); ok {
|
||
|
job = v
|
||
|
}
|
||
|
|
||
|
if v, ok := player.AssignedTruck.Resolve().(*sii.Vehicle); ok {
|
||
|
truck = v
|
||
|
}
|
||
|
|
||
|
if v, ok := player.AssignedTrailer.Resolve().(*sii.Trailer); ok {
|
||
|
out.AttachedTrailer = player.AssignedTrailer.Target
|
||
|
trailer = v
|
||
|
}
|
||
|
|
||
|
if truck != nil {
|
||
|
for _, pb := range truck.Accessories {
|
||
|
var wear float32
|
||
|
if v, ok := pb.Resolve().(*sii.VehicleAccessory); ok {
|
||
|
wear = v.Wear
|
||
|
}
|
||
|
|
||
|
if v, ok := pb.Resolve().(*sii.VehicleWheelAccessory); ok {
|
||
|
wear = v.Wear
|
||
|
}
|
||
|
|
||
|
if wear > out.TruckWear {
|
||
|
out.TruckWear = wear
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if len(player.Trailers) > 0 {
|
||
|
out.OwnedTrailers = map[string]string{}
|
||
|
for _, tp := range player.Trailers {
|
||
|
if t, ok := tp.Resolve().(*sii.Trailer); ok {
|
||
|
out.OwnedTrailers[t.Name()] = t.CleanedLicensePlate()
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if trailer != nil {
|
||
|
for _, pb := range trailer.Accessories {
|
||
|
var wear float32
|
||
|
if v, ok := pb.Resolve().(*sii.VehicleAccessory); ok {
|
||
|
wear = v.Wear
|
||
|
}
|
||
|
|
||
|
if v, ok := pb.Resolve().(*sii.VehicleWheelAccessory); ok {
|
||
|
wear = v.Wear
|
||
|
}
|
||
|
|
||
|
if wear > out.TrailerWear {
|
||
|
out.TrailerWear = wear
|
||
|
}
|
||
|
}
|
||
|
|
||
|
out.CargoDamage = trailer.CargoDamage
|
||
|
}
|
||
|
|
||
|
if job != nil {
|
||
|
out.CurrentJob = &commSaveJob{
|
||
|
OriginReference: job.SourceCompany.Target,
|
||
|
TargetReference: job.TargetCompany.Target,
|
||
|
CargoReference: job.Cargo.Target,
|
||
|
TrailerReference: job.CompanyTrailer.Target,
|
||
|
Distance: job.PlannedDistanceKM,
|
||
|
Urgency: job.Urgency,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return out, nil
|
||
|
}
|
||
|
|
||
|
func fixPlayerTruck(unit *sii.Unit, fixType string) error {
|
||
|
// In call cases we need the player as the starting point
|
||
|
var player *sii.Player
|
||
|
|
||
|
for _, b := range unit.Entries {
|
||
|
if v, ok := b.(*sii.Player); ok {
|
||
|
player = v
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if player == nil {
|
||
|
return errors.New("Found no player object")
|
||
|
}
|
||
|
|
||
|
// Fix truck
|
||
|
if fixType == fixAll || fixType == fixTruckOnly {
|
||
|
truck := player.AssignedTruck.Resolve().(*sii.Vehicle)
|
||
|
for _, pb := range truck.Accessories {
|
||
|
if v, ok := pb.Resolve().(*sii.VehicleAccessory); ok {
|
||
|
v.Wear = 0
|
||
|
}
|
||
|
|
||
|
if v, ok := pb.Resolve().(*sii.VehicleWheelAccessory); ok {
|
||
|
v.Wear = 0
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Fix trailer
|
||
|
if (fixType == fixAll || fixType == fixTrailerOnly) && player.AssignedTrailer.Resolve() != nil {
|
||
|
trailer := player.AssignedTrailer.Resolve().(*sii.Trailer)
|
||
|
for _, pb := range trailer.Accessories {
|
||
|
if v, ok := pb.Resolve().(*sii.VehicleAccessory); ok {
|
||
|
v.Wear = 0
|
||
|
}
|
||
|
|
||
|
if v, ok := pb.Resolve().(*sii.VehicleWheelAccessory); ok {
|
||
|
v.Wear = 0
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Fix cargo
|
||
|
if (fixType == fixAll || fixType == fixCargoOnly) && player.AssignedTrailer.Resolve() != nil {
|
||
|
trailer := player.AssignedTrailer.Resolve().(*sii.Trailer)
|
||
|
trailer.CargoDamage = 0
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// loadSave reads game- and info- unit and returns them unmodified
|
||
|
func loadSave(profile, save string) (*sii.Unit, *sii.SaveContainer, error) {
|
||
|
var (
|
||
|
saveInfoPath = getSaveFilePath(profile, save, "info.sii")
|
||
|
saveUnitPath = getSaveFilePath(profile, save, "game.sii")
|
||
|
)
|
||
|
|
||
|
infoUnit, err := sii.ReadUnitFile(saveInfoPath)
|
||
|
if err != nil {
|
||
|
return nil, nil, errors.Wrap(err, "Unable to load save-info")
|
||
|
}
|
||
|
|
||
|
var info *sii.SaveContainer
|
||
|
for _, b := range infoUnit.Entries {
|
||
|
if v, ok := b.(*sii.SaveContainer); ok {
|
||
|
info = v
|
||
|
}
|
||
|
}
|
||
|
|
||
|
gameUnit, err := sii.ReadUnitFile(saveUnitPath)
|
||
|
if err != nil {
|
||
|
return nil, info, errors.Wrap(err, "Unable to load save-unit")
|
||
|
}
|
||
|
|
||
|
return gameUnit, info, nil
|
||
|
}
|
||
|
|
||
|
// storeSave writes game- and info- unit without checking for existance!
|
||
|
func storeSave(profile, save string, unit *sii.Unit, info *sii.SaveContainer) error {
|
||
|
var (
|
||
|
saveInfoPath = getSaveFilePath(profile, save, "info.sii")
|
||
|
saveUnitPath = getSaveFilePath(profile, save, "game.sii")
|
||
|
)
|
||
|
|
||
|
if err := os.MkdirAll(path.Dir(saveInfoPath), 0700); err != nil {
|
||
|
return errors.Wrap(err, "Unable to create save-dir")
|
||
|
}
|
||
|
|
||
|
if err := sii.WriteUnitFile(saveInfoPath, &sii.Unit{Entries: []sii.Block{info}}); err != nil {
|
||
|
return errors.Wrap(err, "Unable to write info unit")
|
||
|
}
|
||
|
|
||
|
if err := sii.WriteUnitFile(saveUnitPath, unit); err != nil {
|
||
|
return errors.Wrap(err, "Unable to write game unit")
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|