tengu_api/state/
scenes.rs1use super::DojosAccount;
2use crate::consts::{SCENE_COUNT_MAX, SCENE_ROLL_COUNT, SCENE_SECTIONS_PER_SCENE};
3use solana_program::program_error::ProgramError;
4use steel::*;
5
6#[repr(C)]
7#[derive(Clone, Copy, Debug, PartialEq, bytemuck::Pod, bytemuck::Zeroable)]
8pub struct Scenes {
9 pub dojo: Pubkey,
10 pub section_counts: [[u64; SCENE_SECTIONS_PER_SCENE]; SCENE_COUNT_MAX],
11 pub reserved1: u64,
12 pub reserved2: u64,
13}
14
15account!(DojosAccount, Scenes);
16
17impl Scenes {
18 pub fn assert_dojo(&self, dojo_pda: &Pubkey) -> Result<(), ProgramError> {
19 if self.dojo != *dojo_pda {
20 return Err(ProgramError::InvalidAccountData);
21 }
22 Ok(())
23 }
24
25 pub fn is_unlocked(&self, scene_id: u64) -> bool {
26 if scene_id as usize >= SCENE_COUNT_MAX {
27 return false;
28 }
29 self.section_counts[scene_id as usize]
30 .iter()
31 .all(|&c| c >= 1)
32 }
33
34 pub fn can_salvage(&self, scene_id: u64, section_id: u64) -> bool {
35 self.can_salvage_count(scene_id, section_id, 1)
36 }
37
38 pub fn can_salvage_count(&self, scene_id: u64, section_id: u64, count: u64) -> bool {
40 if scene_id as usize >= SCENE_COUNT_MAX {
41 return false;
42 }
43 if section_id as usize >= SCENE_SECTIONS_PER_SCENE {
44 return false;
45 }
46 if count == 0 {
47 return false;
48 }
49 self.section_counts[scene_id as usize][section_id as usize] >= 1 + count
50 }
51
52 pub fn increment_section(&mut self, scene_id: u64, section_id: u64) {
53 if (scene_id as usize) < SCENE_COUNT_MAX && (section_id as usize) < SCENE_SECTIONS_PER_SCENE
54 {
55 self.section_counts[scene_id as usize][section_id as usize] =
56 self.section_counts[scene_id as usize][section_id as usize].saturating_add(1);
57 }
58 }
59
60 pub fn decrement_section(&mut self, scene_id: u64, section_id: u64) {
61 self.decrement_section_by(scene_id, section_id, 1);
62 }
63
64 pub fn decrement_section_by(&mut self, scene_id: u64, section_id: u64, n: u64) {
65 if (scene_id as usize) < SCENE_COUNT_MAX && (section_id as usize) < SCENE_SECTIONS_PER_SCENE
66 {
67 let c = &mut self.section_counts[scene_id as usize][section_id as usize];
68 *c = c.saturating_sub(n);
69 }
70 }
71
72 pub fn unlock_scene(&mut self, scene_id: u64) {
74 if (scene_id as usize) < SCENE_COUNT_MAX {
75 for s in 0..SCENE_SECTIONS_PER_SCENE {
76 self.section_counts[scene_id as usize][s] = 1;
77 }
78 }
79 }
80
81 pub fn derive_scene_section(hash: &[u8; 32]) -> (u64, u64) {
84 let v0 = u64::from_le_bytes(hash[0..8].try_into().unwrap());
85 let v1 = u64::from_le_bytes(hash[8..16].try_into().unwrap());
86 let scene_id = 1 + (v0 % SCENE_ROLL_COUNT);
87 let section_id = v1 % SCENE_SECTIONS_PER_SCENE as u64;
88 (scene_id, section_id)
89 }
90}