Skip to main content

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 started it's production cycle. Note
42    /// that this is likely to be in the past for quickly producing
43    /// buildings
44    pub cycle_start: Option<DateTime<Local>>,
45    /// The time at which this building will finish it's current production
46    /// cycle. Note that this is likely to be in the past for quickly producing
47    /// buildings
48    pub cycle_end: Option<DateTime<Local>>,
49    /// Has the upgrade for this building been bought?
50    pub golden: bool,
51    /// The price to upgrade this building once
52    pub upgrade_cost: BigInt,
53    /// The price to upgrade this building 10x
54    pub upgrade_cost_10x: BigInt,
55    /// The price to upgrade this building 25x
56    pub upgrade_cost_25x: BigInt,
57    /// The price to upgrade this building 100x
58    pub upgrade_cost_100x: BigInt,
59}
60
61impl IdleGame {
62    pub(crate) fn parse_idle_game(
63        data: &[BigInt],
64        server_time: ServerTime,
65    ) -> Option<IdleGame> {
66        if data.len() < 118 {
67            return None;
68        }
69
70        let mut res = IdleGame {
71            resets: data.get(2)?.try_into().ok()?,
72            merchant_new_goods: server_time.convert_to_local(
73                data.get(63)?.try_into().ok()?,
74                "trader time",
75            )?,
76            current_money: data.get(72)?.clone(),
77            total_sacrificed: data.get(73)?.clone(),
78            _current_money_2: data.get(74)?.clone(),
79            sacrifice_runes: data.get(75)?.clone(),
80            current_runes: data.get(76)?.clone(),
81            buildings: EnumMap::default(),
82        };
83
84        // We could do this above.. but I do not want to..
85        for (pos, building) in
86            res.buildings.as_mut_array().iter_mut().enumerate()
87        {
88            building.level = data.get(pos + 3)?.try_into().ok()?;
89            building.earning.clone_from(data.get(pos + 13)?);
90            building.cycle_start = server_time.convert_to_local(
91                data.get(pos + 23)?.try_into().ok()?,
92                "idle cycle start time",
93            );
94            building.cycle_end = server_time.convert_to_local(
95                data.get(pos + 33)?.try_into().ok()?,
96                "idle cycle end time",
97            );
98            building.golden = data.get(pos + 53)? == &1.into();
99            building.upgrade_cost.clone_from(data.get(pos + 78)?);
100            building.upgrade_cost_10x.clone_from(data.get(pos + 88)?);
101            building.upgrade_cost_25x.clone_from(data.get(pos + 98)?);
102            building.upgrade_cost_100x.clone_from(data.get(pos + 108)?);
103        }
104        Some(res)
105    }
106}
107
108/// The type of a building in the idle game
109#[derive(Debug, Clone, Copy, Enum, EnumIter, PartialEq, Eq, Hash)]
110#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
111#[allow(missing_docs)]
112pub enum IdleBuildingType {
113    Seat = 1,
114    PopcornStand,
115    ParkingLot,
116    Trap,
117    Drinks,
118    DeadlyTrap,
119    VIPSeat,
120    Snacks,
121    StrayingMonsters,
122    Toilet,
123}