tengu_api/state/
scenes.rs1use super::DojosAccount;
2use crate::consts::{SCENE_COUNT, SCENE_COUNT_MAX, 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 pub reserved3: u64,
14 pub reserved4: u64,
15}
16
17account!(DojosAccount, Scenes);
18
19impl Scenes {
20 pub fn assert_dojo(&self, dojo_pda: &Pubkey) -> Result<(), ProgramError> {
21 if self.dojo != *dojo_pda {
22 return Err(ProgramError::InvalidAccountData);
23 }
24 Ok(())
25 }
26
27 pub fn is_unlocked(&self, scene_id: u64) -> bool {
28 if scene_id as usize >= SCENE_COUNT_MAX {
29 return false;
30 }
31 self.section_counts[scene_id as usize]
32 .iter()
33 .all(|&c| c >= 1)
34 }
35
36 pub fn can_salvage(&self, scene_id: u64, section_id: u64) -> bool {
37 self.can_salvage_count(scene_id, section_id, 1)
38 }
39
40 pub fn can_salvage_count(&self, scene_id: u64, section_id: u64, count: u64) -> bool {
42 if scene_id as usize >= SCENE_COUNT_MAX {
43 return false;
44 }
45 if section_id as usize >= SCENE_SECTIONS_PER_SCENE {
46 return false;
47 }
48 if count == 0 {
49 return false;
50 }
51 self.section_counts[scene_id as usize][section_id as usize] >= 1 + count
52 }
53
54 pub fn increment_section(&mut self, scene_id: u64, section_id: u64) {
55 if (scene_id as usize) < SCENE_COUNT_MAX && (section_id as usize) < SCENE_SECTIONS_PER_SCENE
56 {
57 self.section_counts[scene_id as usize][section_id as usize] =
58 self.section_counts[scene_id as usize][section_id as usize].saturating_add(1);
59 }
60 }
61
62 pub fn decrement_section(&mut self, scene_id: u64, section_id: u64) {
63 self.decrement_section_by(scene_id, section_id, 1);
64 }
65
66 pub fn decrement_section_by(&mut self, scene_id: u64, section_id: u64, n: u64) {
67 if (scene_id as usize) < SCENE_COUNT_MAX && (section_id as usize) < SCENE_SECTIONS_PER_SCENE
68 {
69 let c = &mut self.section_counts[scene_id as usize][section_id as usize];
70 *c = c.saturating_sub(n);
71 }
72 }
73
74 pub fn unlock_scene(&mut self, scene_id: u64) {
76 if (scene_id as usize) < SCENE_COUNT_MAX {
77 for s in 0..SCENE_SECTIONS_PER_SCENE {
78 self.section_counts[scene_id as usize][s] = 1;
79 }
80 }
81 }
82
83 pub fn derive_scene_section(hash: &[u8; 32]) -> (u64, u64) {
86 let v0 = u64::from_le_bytes(hash[0..8].try_into().unwrap());
87 let v1 = u64::from_le_bytes(hash[8..16].try_into().unwrap());
88 let scene_id = 1 + (v0 % SCENE_COUNT);
89 let section_id = v1 % SCENE_SECTIONS_PER_SCENE as u64;
90 (scene_id, section_id)
91 }
92}