add player for host
This commit is contained in:
parent
08db7f9bfc
commit
11bc54f996
|
|
@ -13,7 +13,7 @@ use crate::{
|
|||
player::PlayerId,
|
||||
};
|
||||
|
||||
use super::{CharacterState, PlayerState};
|
||||
use super::{CharacterState, PlayerState, PublicIdentity};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub enum HostMessage {
|
||||
|
|
@ -55,6 +55,7 @@ impl From<HostDayMessage> for HostGameMessage {
|
|||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub enum HostLobbyMessage {
|
||||
GetState,
|
||||
ManufacturePlayer(PublicIdentity),
|
||||
Kick(PlayerId),
|
||||
SetPlayerNumber(PlayerId, NonZeroU8),
|
||||
GetGameSettings,
|
||||
|
|
|
|||
|
|
@ -155,6 +155,18 @@ impl Lobby {
|
|||
|
||||
async fn next_inner(&mut self, msg: Message) -> Result<Option<GameRunner>, GameError> {
|
||||
match msg {
|
||||
Message::Host(HostMessage::Lobby(HostLobbyMessage::ManufacturePlayer(public))) => {
|
||||
log::info!("adding player {public:?} by host request");
|
||||
self.players_in_lobby.push((
|
||||
Identification {
|
||||
player_id: PlayerId::new(),
|
||||
public,
|
||||
},
|
||||
None,
|
||||
));
|
||||
self.send_lobby_info_to_clients().await;
|
||||
self.send_lobby_info_to_host().await.log_debug();
|
||||
}
|
||||
Message::Host(HostMessage::Lobby(HostLobbyMessage::SetQrMode(mode))) => {
|
||||
self.qr_mode = mode;
|
||||
self.send_lobby_info_to_host().await.log_debug();
|
||||
|
|
@ -235,7 +247,7 @@ impl Lobby {
|
|||
return Ok(None);
|
||||
}
|
||||
if let Some(sender) = self.joined_players.get_sender(identity.player_id).await {
|
||||
self.players_in_lobby.push((identity, sender.clone()));
|
||||
self.players_in_lobby.push((identity, Some(sender.clone())));
|
||||
self.send_lobby_info_to_clients().await;
|
||||
self.send_lobby_info_to_host().await?;
|
||||
}
|
||||
|
|
@ -321,10 +333,10 @@ impl Lobby {
|
|||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct LobbyPlayers(Vec<(Identification, Sender<ServerMessage>)>);
|
||||
pub struct LobbyPlayers(Vec<(Identification, Option<Sender<ServerMessage>>)>);
|
||||
|
||||
impl Deref for LobbyPlayers {
|
||||
type Target = Vec<(Identification, Sender<ServerMessage>)>;
|
||||
type Target = Vec<(Identification, Option<Sender<ServerMessage>>)>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
|
|
@ -339,8 +351,6 @@ impl DerefMut for LobbyPlayers {
|
|||
|
||||
impl LobbyPlayers {
|
||||
pub fn with_dummies(dummy_count: NonZeroU8) -> Self {
|
||||
let (send, mut recv) = broadcast::channel(100);
|
||||
tokio::spawn(async move { while recv.recv().await.is_ok() {} });
|
||||
Self(
|
||||
(0..dummy_count.get())
|
||||
.map(|p| {
|
||||
|
|
@ -353,7 +363,7 @@ impl LobbyPlayers {
|
|||
number: NonZeroU8::new(p + 1),
|
||||
},
|
||||
},
|
||||
send.clone(),
|
||||
None,
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
|
|
@ -361,6 +371,7 @@ impl LobbyPlayers {
|
|||
}
|
||||
pub fn find(&self, player_id: PlayerId) -> Option<&Sender<ServerMessage>> {
|
||||
self.iter()
|
||||
.filter_map(|(id, s)| s.as_ref().map(|s| (id, s)))
|
||||
.find_map(|(id, s)| (id.player_id == player_id).then_some(s))
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -201,8 +201,7 @@ nav.debug-nav {
|
|||
}
|
||||
|
||||
.submenu {
|
||||
background-color: black;
|
||||
border: 1px solid rgba(255, 255, 255, 0.7);
|
||||
// border: 1px solid rgba(255, 255, 255, 0.7);
|
||||
padding: 10px;
|
||||
position: relative;
|
||||
// position: fixed;
|
||||
|
|
@ -829,25 +828,6 @@ input {
|
|||
margin: 10px;
|
||||
}
|
||||
|
||||
.signin {
|
||||
@extend .row-list;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
|
||||
& label {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
& input {
|
||||
height: 2rem;
|
||||
text-align: center;
|
||||
|
||||
&#number {
|
||||
font-size: 2rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.info-update {
|
||||
font-size: 2rem;
|
||||
align-content: stretch;
|
||||
|
|
@ -997,11 +977,17 @@ input {
|
|||
align-items: center;
|
||||
align-content: center;
|
||||
|
||||
&>p {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
&>label {
|
||||
// height: 100%;
|
||||
// width: 100%;
|
||||
flex-grow: 3;
|
||||
}
|
||||
|
||||
&>button {
|
||||
width: max-content;
|
||||
font-size: 3rem;
|
||||
flex-grow: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.setup-slot {
|
||||
|
|
@ -1013,15 +999,23 @@ input {
|
|||
}
|
||||
|
||||
&>.submenu {
|
||||
min-width: 5cm;
|
||||
min-width: 30vw;
|
||||
|
||||
.assign-list {
|
||||
min-width: 5cm;
|
||||
// min-width: 5cm;
|
||||
gap: 10px;
|
||||
|
||||
& .submenu button {
|
||||
width: inherit;
|
||||
width: 5cm;
|
||||
}
|
||||
}
|
||||
|
||||
.assignees {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
gap: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1324,3 +1318,31 @@ input {
|
|||
|
||||
& .next {}
|
||||
}
|
||||
|
||||
.signin {
|
||||
@extend .row-list;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
|
||||
& label {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
& input {
|
||||
height: 2rem;
|
||||
text-align: center;
|
||||
|
||||
&#number {
|
||||
font-size: 2rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.submenu:has(.signin) {
|
||||
position: absolute;
|
||||
width: max-content;
|
||||
|
||||
& input {
|
||||
font-size: 1rem !important;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ use werewolves_proto::{
|
|||
error::GameError,
|
||||
game::{GameOver, GameSettings},
|
||||
message::{
|
||||
CharacterIdentity, CharacterState, PlayerState,
|
||||
CharacterIdentity, CharacterState, PlayerState, PublicIdentity,
|
||||
host::{
|
||||
HostDayMessage, HostGameMessage, HostLobbyMessage, HostMessage, HostNightMessage,
|
||||
ServerToHostMessage,
|
||||
|
|
@ -662,12 +662,17 @@ impl Host {
|
|||
}
|
||||
});
|
||||
});
|
||||
let on_add_player = crate::callback::send_fn(
|
||||
|msg: PublicIdentity| HostMessage::Lobby(HostLobbyMessage::ManufacturePlayer(msg)),
|
||||
self.send.clone(),
|
||||
);
|
||||
html! {
|
||||
<Settings
|
||||
settings={settings}
|
||||
on_start={on_start}
|
||||
on_update={on_changed}
|
||||
players_in_lobby={players.clone()}
|
||||
on_add_player={on_add_player}
|
||||
qr_mode_button={qr_mode_toggle}
|
||||
/>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,12 +5,12 @@ use convert_case::{Case, Casing};
|
|||
use werewolves_proto::{
|
||||
error::GameError,
|
||||
game::{GameSettings, OrRandom, SetupRole, SetupSlot, SlotId},
|
||||
message::{Identification, PlayerState},
|
||||
message::{Identification, PlayerState, PublicIdentity},
|
||||
role::RoleTitle,
|
||||
};
|
||||
use yew::prelude::*;
|
||||
|
||||
use crate::components::{Button, ClickableField, Identity};
|
||||
use crate::components::{Button, ClickableField, Identity, client::Signin};
|
||||
|
||||
#[derive(Debug, PartialEq, Properties)]
|
||||
pub struct SettingsProps {
|
||||
|
|
@ -18,6 +18,7 @@ pub struct SettingsProps {
|
|||
pub players_in_lobby: Rc<[PlayerState]>,
|
||||
pub on_update: Callback<GameSettings>,
|
||||
pub on_start: Callback<()>,
|
||||
pub on_add_player: Callback<PublicIdentity>,
|
||||
pub qr_mode_button: Html,
|
||||
}
|
||||
|
||||
|
|
@ -28,6 +29,7 @@ pub fn Settings(
|
|||
players_in_lobby,
|
||||
on_update,
|
||||
on_start,
|
||||
on_add_player,
|
||||
qr_mode_button,
|
||||
}: &SettingsProps,
|
||||
) -> Html {
|
||||
|
|
@ -72,6 +74,7 @@ pub fn Settings(
|
|||
.map(|slot| {
|
||||
html! {
|
||||
<SettingsSlot
|
||||
all_players={players.clone()}
|
||||
players_for_assign={players_for_assign.clone()}
|
||||
roles_in_setup={roles_in_setup.clone()}
|
||||
slot={slot.clone()}
|
||||
|
|
@ -248,6 +251,11 @@ pub fn Settings(
|
|||
}
|
||||
};
|
||||
|
||||
let add_player_open = use_state(|| false);
|
||||
let add_player_opts = html! {
|
||||
<Signin callback={on_add_player.clone()}/>
|
||||
};
|
||||
|
||||
html! {
|
||||
<div class="settings">
|
||||
<div class="top-settings">
|
||||
|
|
@ -257,6 +265,12 @@ pub fn Settings(
|
|||
{clear_all_assignments}
|
||||
{clear_bad_assigned}
|
||||
</div>
|
||||
<ClickableField
|
||||
options={add_player_opts}
|
||||
state={add_player_open}
|
||||
>
|
||||
{"add player"}
|
||||
</ClickableField>
|
||||
<p>{format!("min roles for setup: {}", settings.min_players_needed())}</p>
|
||||
<p>{format!("current role count: {}", settings.slots().len())}</p>
|
||||
<div class="roles-add-list">
|
||||
|
|
@ -291,6 +305,7 @@ pub struct SettingsSlotProps {
|
|||
pub roles_in_setup: Rc<[RoleTitle]>,
|
||||
pub slot: SetupSlot,
|
||||
pub update: Callback<SettingSlotAction>,
|
||||
pub all_players: Rc<[Identification]>,
|
||||
}
|
||||
|
||||
#[function_component]
|
||||
|
|
@ -300,6 +315,7 @@ pub fn SettingsSlot(
|
|||
roles_in_setup,
|
||||
slot,
|
||||
update,
|
||||
all_players,
|
||||
}: &SettingsSlotProps,
|
||||
) -> Html {
|
||||
let open = use_state(|| false);
|
||||
|
|
@ -321,6 +337,19 @@ pub fn SettingsSlot(
|
|||
let assign_to = assign_to_submenu(players_for_assign, slot, &update, &open.setter());
|
||||
let options =
|
||||
setup_options_for_slot(slot, &update, roles_in_setup, apprentice_open, open.clone());
|
||||
let assign_text = slot
|
||||
.assign_to
|
||||
.as_ref()
|
||||
.and_then(|assign_to| all_players.iter().find(|p| p.player_id == *assign_to))
|
||||
.map(|assign_to| {
|
||||
html! {
|
||||
<>
|
||||
<span>{"assigned to"}</span>
|
||||
<Identity ident={assign_to.public.clone()} />
|
||||
</>
|
||||
}
|
||||
})
|
||||
.unwrap_or_else(|| html! {{"assign"}});
|
||||
html! {
|
||||
<>
|
||||
<Button on_click={on_kick}>
|
||||
|
|
@ -331,7 +360,7 @@ pub fn SettingsSlot(
|
|||
state={assign_open}
|
||||
class={classes!("assign-list")}
|
||||
>
|
||||
{"assign"}
|
||||
{assign_text}
|
||||
</ClickableField>
|
||||
{options}
|
||||
</>
|
||||
|
|
@ -357,7 +386,7 @@ fn assign_to_submenu(
|
|||
update: &Callback<SettingSlotAction>,
|
||||
assign_setter: &UseStateSetter<bool>,
|
||||
) -> Html {
|
||||
players
|
||||
let buttons = players
|
||||
.iter()
|
||||
.map(|p| {
|
||||
let slot = slot.clone();
|
||||
|
|
@ -376,7 +405,13 @@ fn assign_to_submenu(
|
|||
</Button>
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
.collect::<Html>();
|
||||
|
||||
html! {
|
||||
<div class="assignees">
|
||||
{buttons}
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
fn setup_options_for_slot(
|
||||
|
|
|
|||
Loading…
Reference in New Issue