sf_api/gamestate/
idle.rs

1#![allow(clippy::module_name_repetitions)]
2use chrono::{DateTime, Local};
3use enum_map::{Enum, EnumMap};
4use num_bigint::BigInt;
5use strum::EnumIter;
6
7use super::ServerTime;
8
9/// The idle clicker game where you invest money and get runes by sacrificing
10#[derive(Debug, Clone, Default)]
11#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
12pub struct IdleGame {
13    /// The current amount of money the player
14    pub current_money: BigInt,
15    /// The current amount of runes the player
16    pub current_runes: BigInt,
17    /// The amount of times the player reset their idle game
18    pub resets: u32,
19    /// Runes you get, when you sacrifice
20    pub sacrifice_runes: BigInt,
21    /// The time at which new items will be present in the shop
22    pub merchant_new_goods: DateTime<Local>,
23    /// I think this the total amount of money you have sacrificed, or the last
24    /// plus X, or something related to that. I am not sure and I do not
25    /// really care
26    pub total_sacrificed: BigInt,
27    // Slightly larger than current_money, but I have no Idea why.
28    _current_money_2: BigInt,
29    /// Information about all the possible buildings
30    pub buildings: EnumMap<IdleBuildingType, IdleBuilding>,
31}
32
33/// A single building in the idle game
34#[derive(Debug, Clone, Default)]
35#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
36pub struct IdleBuilding {
37    /// The current level of this building
38    pub level: u32,
39    /// The amount of money this earns on the next gather
40    pub earning: BigInt,
41    /// The time at which this building will gather resources
42    pub next_gather: Option<DateTime<Local>>,
43    /// The next time at which this building will gather resources
44    pub next_next_gather: Option<DateTime<Local>>,
45    /// Has the upgrade for this building been bought?
46    pub golden: bool,
47    /// The price to upgrade this building once
48    pub upgrade_cost: BigInt,
49    /// The price to upgrade this building 10x
50    pub upgrade_cost_10x: BigInt,
51    /// The price to upgrade this building 25x
52    pub upgrade_cost_25x: BigInt,
53    /// The price to upgrade this building 100x
54    pub upgrade_cost_100x: BigInt,
55}
56
57impl IdleGame {
58    pub(crate) fn parse_idle_game(
59        data: &[BigInt],
60        server_time: ServerTime,
61    ) -> Option<IdleGame> {
62        if data.len() < 118 {
63            return None;
64        }
65
66        let mut res = IdleGame {
67            resets: data.get(2)?.try_into().ok()?,
68            merchant_new_goods: server_time.convert_to_local(
69                data.get(63)?.try_into().ok()?,
70                "trader time",
71            )?,
72            current_money: data.get(72)?.clone(),
73            total_sacrificed: data.get(73)?.clone(),
74            _current_money_2: data.get(74)?.clone(),
75            sacrifice_runes: data.get(75)?.clone(),
76            current_runes: data.get(76)?.clone(),
77            buildings: EnumMap::default(),
78        };
79
80        // We could do this above.. but I do not want to..
81        for (pos, building) in
82            res.buildings.as_mut_array().iter_mut().enumerate()
83        {
84            building.level = data.get(pos + 3)?.try_into().ok()?;
85            building.earning.clone_from(data.get(pos + 13)?);
86            building.next_gather = server_time.convert_to_local(
87                data.get(pos + 23)?.try_into().ok()?,
88                "next gather time",
89            );
90            building.next_next_gather = server_time.convert_to_local(
91                data.get(pos + 33)?.try_into().ok()?,
92                "next next gather time",
93            );
94            building.golden = data.get(pos + 53)? == &1.into();
95            building.upgrade_cost.clone_from(data.get(pos + 78)?);
96            building.upgrade_cost_10x.clone_from(data.get(pos + 88)?);
97            building.upgrade_cost_25x.clone_from(data.get(pos + 98)?);
98            building.upgrade_cost_100x.clone_from(data.get(pos + 108)?);
99        }
100        Some(res)
101    }
102}
103
104/// The type of a building in the idle game
105#[derive(Debug, Clone, Copy, Enum, EnumIter, PartialEq, Eq, Hash)]
106#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
107#[allow(missing_docs)]
108pub enum IdleBuildingType {
109    Seat = 1,
110    PopcornStand,
111    ParkingLot,
112    Trap,
113    Drinks,
114    DeadlyTrap,
115    VIPSeat,
116    Snacks,
117    StrayingMonsters,
118    Toilet,
119}