allow invisible tokens

This commit is contained in:
Rusty Striker 2025-07-18 14:51:26 +03:00
parent 5979e53d91
commit 23e23ad1a2
Signed by: RustyStriker
GPG key ID: 87E4D691632DFF15
4 changed files with 48 additions and 19 deletions

View file

@ -70,6 +70,7 @@ pub enum Request {
SpawnToken {
map_id: usize,
character: String,
visible_to_players: bool,
x: f32,
y: f32,
img_path: String,

View file

@ -26,6 +26,7 @@ impl<'a, C: Character<A> + Serialize + Deserialize<'a>, A: entry::GameEntry + Se
img_source: "assets/pf2r/tokens/adams.png".to_string(),
x: 2.0,
y: 2.0,
visible_to_players: true,
},
);
tokens.insert(
@ -35,6 +36,7 @@ impl<'a, C: Character<A> + Serialize + Deserialize<'a>, A: entry::GameEntry + Se
img_source: "assets/pf2r/tokens/tim.png".to_string(),
x: 0.0,
y: 2.0,
visible_to_players: true,
},
);
let mut scenes = HashMap::new();
@ -103,9 +105,10 @@ impl<'a, C: Character<A> + Serialize + Deserialize<'a>, A: entry::GameEntry + Se
if let Some(ti) = token { Some(ti) } else { None }
}
pub fn available_tokens(&self, scene: usize) -> Vec<usize> {
pub fn available_tokens(&self, scene: usize, admin: bool) -> Vec<usize> {
self.scenes
.get(&scene)
.filter(|&s| s.visible_to_users || admin)
.map(|s| s.map.as_ref())
.flatten()
// this map feels stupid but keys() turns into a &usize iterator so :shrug:
@ -113,7 +116,15 @@ impl<'a, C: Character<A> + Serialize + Deserialize<'a>, A: entry::GameEntry + Se
.unwrap_or(Vec::new())
}
pub fn create_token(&mut self, scene: usize, character: String, img_source: String, x: f32, y: f32) -> usize {
pub fn create_token(
&mut self,
scene: usize,
character: String,
img_source: String,
x: f32,
y: f32,
visible_to_players: bool,
) -> usize {
let mut id = 0;
let tokens = self
.scenes
@ -132,6 +143,7 @@ impl<'a, C: Character<A> + Serialize + Deserialize<'a>, A: entry::GameEntry + Se
img_source,
x,
y,
visible_to_players,
},
);
id

View file

@ -35,6 +35,8 @@ pub struct TokenInfo {
pub x: f32,
/// Y position, in grid slots units (integers are grid aligned)
pub y: f32,
/// Is the token visible to players or only to admins
pub visible_to_players: bool,
}
// for now this is defined so i could easily modify this later if needed (and only change initializations)

View file

@ -120,7 +120,7 @@ impl GameServer {
api::Request::Message(mut msg) => {
if msg.id == 0 || msg.id > self.chat.len() {
msg.id = self.chat.len() + 1; // set the message id, 0 is invalid
} else if id == self.chat[msg.id - 1].0 || *self.users.get(&id).unwrap_or(&false) {
} else if id == self.chat[msg.id - 1].0 || self.is_admin(&id) {
self.chat[msg.id - 1] = (id.clone(), msg.clone());
} else {
// if its an edit message and editor is not the owner, skip
@ -142,8 +142,10 @@ impl GameServer {
_ = broadcast.send((Some(id), self.get_last_messages(amount)));
}
api::Request::GetTokens { scene } => {
for token_id in self.game.available_tokens(scene) {
if let Some(ti) = self.game.token_info(0, token_id) {
for token_id in self.game.available_tokens(scene, self.is_admin(&id)) {
if let Some(ti) = self.game.token_info(0, token_id) &&
(ti.visible_to_players)
{
_ = broadcast.send((
Some(id.clone()),
api::Response::SpawnToken(SpawnToken {
@ -162,10 +164,9 @@ impl GameServer {
}
}
api::Request::CreateScene { title } => {
if *self.users.get(&id).unwrap_or(&false) {
if self.is_admin(&id) {
self.game.create_scene(title);
let admin = *self.users.get(&id).unwrap_or(&false);
let scenes = self.get_scene_list(admin);
let scenes = self.get_scene_list(true);
_ = broadcast.send((Some(id), scenes));
}
}
@ -174,7 +175,7 @@ impl GameServer {
grid_offset,
scene,
} => {
if *self.users.get(&id).unwrap_or(&false) {
if self.is_admin(&id) {
if let Some(s) = self.game.get_scene_mut(scene) {
if let Some(map) = s.map.as_mut() {
map.grid_cell_size = grid_cell_size;
@ -188,15 +189,14 @@ impl GameServer {
}
}
api::Request::SceneSetVisible { scene, visible } => {
if *self.users.get(&id).unwrap_or(&false) {
if self.is_admin(&id) {
self.game.scene_visible(scene, visible);
_ = broadcast.send((None, self.get_scene_list(false)));
_ = broadcast.send((Some(id), self.get_scene_list(true)));
}
}
api::Request::GetSceneList => {
let admin = *self.users.get(&id).unwrap_or(&false);
_ = broadcast.send((Some(id.clone()), self.get_scene_list(admin)));
_ = broadcast.send((Some(id.clone()), self.get_scene_list(self.is_admin(&id))));
}
api::Request::SpawnToken {
map_id,
@ -204,11 +204,19 @@ impl GameServer {
x,
y,
img_path,
visible_to_players,
} => {
if *self.users.get(&id).unwrap_or(&false) {
let token_id = self.game.create_token(map_id, character, img_path.clone(), x, y);
if self.is_admin(&id) {
let scene_visible = self.game.get_scene(map_id).map(|s| s.visible_to_users).unwrap_or(false);
let token_id =
self.game
.create_token(map_id, character, img_path.clone(), x, y, visible_to_players);
_ = broadcast.send((
None, // TODO: add the option to spawn the token hidden
if visible_to_players && scene_visible {
None
} else {
Some(id)
},
api::Response::SpawnToken(SpawnToken {
token_id,
x,
@ -222,6 +230,7 @@ impl GameServer {
// TODO: add check to make sure the actor is authorized to move the token
if self.game.move_token(0, token_id, x, y) {
// TODO: maybe chage move_token to return optional x,y values if succeeded to make sure the token is where it was going to be
// TODO: Check if the token is visible to players and if not, only update it's position to admins or something
_ = broadcast.send((None, api::Response::MoveToken { token_id, x, y }));
}
}
@ -244,7 +253,7 @@ impl GameServer {
}
api::Request::CreateCharacter => {
// check if user is admin
if self.users.get(&id).map(|a| *a).unwrap_or(false) {
if self.is_admin(&id) {
let new_id = self.game.create_character();
// return the new id with the character i think
_ = broadcast.send((Some(id), api::Response::CharacterCreated(new_id)));
@ -263,7 +272,7 @@ impl GameServer {
_ = broadcast.send((Some(id), api::Response::Shutdown));
}
api::Request::Shutdown => {
if *self.users.get(&id).unwrap_or(&false) {
if self.is_admin(&id) {
break;
}
}
@ -322,16 +331,17 @@ impl GameServer {
}
fn get_scene(&self, user_id: &str, scene_id: usize) -> Option<api::Response> {
let admin = self.is_admin(user_id);
if self
.game
.get_scene(scene_id)
.map(|s| s.visible_to_users)
.unwrap_or(false) ||
*self.users.get(user_id).unwrap_or(&false)
admin
{
let scene_tokens = self
.game
.available_tokens(scene_id)
.available_tokens(scene_id, admin)
.iter()
.map(|&id| self.game.token_info(scene_id, id).map(|info| (id, info)))
.flatten()
@ -354,4 +364,8 @@ impl GameServer {
None
}
}
fn is_admin(&self, id: &str) -> bool {
self.users.get(id).map(|a| *a).unwrap_or(false)
}
}