chat wheelu

This commit is contained in:
ntr 2019-10-18 15:38:40 +11:00
parent 189d1023c6
commit ddca205f0c
11 changed files with 143 additions and 39 deletions

View File

@ -12,6 +12,9 @@ export const setAnimText = value => ({ type: 'SET_ANIM_TEXT', value });
export const setDemo = value => ({ type: 'SET_DEMO', value }); export const setDemo = value => ({ type: 'SET_DEMO', value });
export const setChatShow = value => ({ type: 'SET_CHAT_SHOW', value }); export const setChatShow = value => ({ type: 'SET_CHAT_SHOW', value });
export const setChatWheel = value => ({ type: 'SET_CHAT_WHEEL', value });
export const setInstanceChat = value => ({ type: 'SET_INSTANCE_CHAT', value });
export const setActiveItem = value => ({ type: 'SET_ACTIVE_VAR', value }); export const setActiveItem = value => ({ type: 'SET_ACTIVE_VAR', value });
export const setActiveSkill = (constructId, skill) => ({ type: 'SET_ACTIVE_SKILL', value: constructId ? { constructId, skill } : null }); export const setActiveSkill = (constructId, skill) => ({ type: 'SET_ACTIVE_SKILL', value: constructId ? { constructId, skill } : null });
export const setCombiner = value => ({ type: 'SET_COMBINER', value: Array.from(value) }); export const setCombiner = value => ({ type: 'SET_COMBINER', value: Array.from(value) });

View File

@ -8,18 +8,20 @@ const addState = connect(
const { const {
ws, ws,
chatShow, chatShow,
chatWheel,
instance, instance,
} = state; } = state;
function sendChat(i) { function sendInstanceChat(instance, i) {
// return ws.sendChat(i); return ws.sendInstanceChat(instance, i);
} }
return { return {
instance, instance,
chatShow, chatShow,
chatWheel,
sendChat, sendInstanceChat,
}; };
}, },
@ -38,31 +40,21 @@ function Chat(args) {
const { const {
instance, instance,
chatShow, chatShow,
chatWheel,
sendChat, sendInstanceChat,
setChatShow, setChatShow,
} = args; } = args;
const chat = [
'gl',
'hf',
'gg',
'thx',
'nice',
'hmm',
'ok',
'...',
];
function onClick(i) { function onClick(i) {
sendChat(i); sendInstanceChat(instance.id, i);
setChatShow(false); setChatShow(false);
return true; return true;
} }
return ( return (
<div class={`instance-ctrl-btns chat`}> <div class={`instance-ctrl-btns chat`}>
{chat.map((c, i) => <button key={i} onClick={() => onClick(i)} >{c}</button>)} {chatWheel.map((c, i) => <button key={i} onClick={() => onClick(i)} >{c}</button>)}
</div> </div>
); );
} }

View File

@ -13,6 +13,7 @@ const addState = connect(
const { const {
ws, ws,
instance, instance,
instanceChat,
account, account,
chatShow, chatShow,
} = state; } = state;
@ -20,6 +21,7 @@ const addState = connect(
return { return {
chatShow, chatShow,
instance, instance,
instanceChat,
account, account,
}; };
}, },
@ -29,6 +31,7 @@ function Controls(args) {
const { const {
account, account,
instance, instance,
instanceChat,
chatShow, chatShow,
} = args; } = args;
@ -65,14 +68,14 @@ function Controls(args) {
const bottom = chatShow const bottom = chatShow
? <Chat /> ? <Chat />
: <PlayerBox player={player} isPlayer={true} />; : <PlayerBox player={player} isPlayer={true} chat={instanceChat && instanceChat[player.id]} />;
return ( return (
<aside> <aside>
{timer} {timer}
<div class="controls instance-ctrl"> <div class="controls instance-ctrl">
<InstanceCtrlTopBtns /> <InstanceCtrlTopBtns />
<PlayerBox player={opponent} /> <PlayerBox player={opponent} chat={instanceChat && instanceChat[opponent.id]}/>
{bottom} {bottom}
<InstanceCtrlBtns /> <InstanceCtrlBtns />
</div> </div>

View File

@ -56,6 +56,7 @@ function Scoreboard(args) {
const { const {
isPlayer, isPlayer,
player, player,
chat,
} = args; } = args;
const scoreText = () => { const scoreText = () => {
@ -73,14 +74,14 @@ function Scoreboard(args) {
<div class="score">{scoreText()}</div> <div class="score">{scoreText()}</div>
<div class="name">{player.name}</div> <div class="name">{player.name}</div>
<Img img={player.img} id={player.id} /> <Img img={player.img} id={player.id} />
<div class="msg">&nbsp;</div> <div class="msg">{chat || '\u00A0'}</div>
</div> </div>
); );
} }
return ( return (
<div class={`player-box bottom ${player.ready ? 'ready' : ''}`}> <div class={`player-box bottom ${player.ready ? 'ready' : ''}`}>
<div class="msg">&nbsp;</div> <div class="msg">{chat || '\u00A0'}</div>
<div class="score">{scoreText()}</div> <div class="score">{scoreText()}</div>
<div class="name">{player.name}</div> <div class="name">{player.name}</div>
<Img img={player.img} id={player.id} /> <Img img={player.img} id={player.id} />

View File

@ -212,6 +212,14 @@ function registerEvents(store) {
return store.dispatch(actions.setInstance(v)); return store.dispatch(actions.setInstance(v));
} }
function setInstanceChat(v) {
return store.dispatch(actions.setInstanceChat(v));
}
function setChatWheel(v) {
return store.dispatch(actions.setChatWheel(v));
}
function setItemInfo(v) { function setItemInfo(v) {
return store.dispatch(actions.setItemInfo(v)); return store.dispatch(actions.setItemInfo(v));
} }
@ -318,12 +326,14 @@ function registerEvents(store) {
setAccountInstances, setAccountInstances,
setActiveItem, setActiveItem,
setActiveSkill, setActiveSkill,
setChatWheel,
setDemo, setDemo,
setConstructList, setConstructList,
setNewConstruct, setNewConstruct,
setGame, setGame,
setEmail, setEmail,
setInstance, setInstance,
setInstanceChat,
setItemInfo, setItemInfo,
setInvite, setInvite,
setPing, setPing,

View File

@ -25,6 +25,8 @@ module.exports = {
demo: createReducer(null, 'SET_DEMO'), demo: createReducer(null, 'SET_DEMO'),
chatShow: createReducer(null, 'SET_CHAT_SHOW'), chatShow: createReducer(null, 'SET_CHAT_SHOW'),
chatWheel: createReducer([], 'SET_CHAT_WHEEL'),
combiner: createReducer([], 'SET_COMBINER'), combiner: createReducer([], 'SET_COMBINER'),
constructs: createReducer([], 'SET_CONSTRUCTS'), constructs: createReducer([], 'SET_CONSTRUCTS'),
constructEditId: createReducer(null, 'SET_CONSTRUCT_EDIT_ID'), constructEditId: createReducer(null, 'SET_CONSTRUCT_EDIT_ID'),
@ -34,6 +36,7 @@ module.exports = {
invite: createReducer(null, 'SET_INVITE'), invite: createReducer(null, 'SET_INVITE'),
info: createReducer(null, 'SET_INFO'), info: createReducer(null, 'SET_INFO'),
instance: createReducer(null, 'SET_INSTANCE'), instance: createReducer(null, 'SET_INSTANCE'),
instanceChat: createReducer(null, 'SET_INSTANCE_CHAT'),
instances: createReducer([], 'SET_INSTANCES'), instances: createReducer([], 'SET_INSTANCES'),
itemEquip: createReducer(null, 'SET_ITEM_EQUIP'), itemEquip: createReducer(null, 'SET_ITEM_EQUIP'),
itemInfo: createReducer({ combos: [], items: [] }, 'SET_ITEM_INFO'), itemInfo: createReducer({ combos: [], items: [] }, 'SET_ITEM_INFO'),

View File

@ -67,6 +67,10 @@ function createSocket(events) {
send(['InstanceState', { instance_id: instanceId }]); send(['InstanceState', { instance_id: instanceId }]);
} }
function sendInstanceChat(instanceId, index) {
send(['InstanceChat', { instance_id: instanceId, index }]);
}
function sendVboxAccept(instanceId, group, index) { function sendVboxAccept(instanceId, group, index) {
send(['VboxAccept', { instance_id: instanceId, group, index }]); send(['VboxAccept', { instance_id: instanceId, group, index }]);
events.clearInstance(); events.clearInstance();
@ -253,8 +257,11 @@ function createSocket(events) {
QueueJoined: () => events.notify('you have joined the pvp queue'), QueueJoined: () => events.notify('you have joined the pvp queue'),
InviteRequested: () => events.notify('pvp queue request received'), InviteRequested: () => events.notify('pvp queue request received'),
Invite: code => events.setInvite(code), Invite: code => events.setInvite(code),
InstanceChat: chat => events.setInstanceChat(chat),
ChatWheel: wheel => events.setChatWheel(wheel),
Joining: () => events.notify('searching for instance...'), Joining: () => events.notify('searching for instance...'),
Processing: () => true,
Error: errHandler, Error: errHandler,
}; };
@ -358,6 +365,7 @@ function createSocket(events) {
sendInstanceState, sendInstanceState,
sendInstanceInvite, sendInstanceInvite,
sendInstanceJoin, sendInstanceJoin,
sendInstanceChat,
sendVboxAccept, sendVboxAccept,
sendVboxApply, sendVboxApply,

View File

@ -65,6 +65,19 @@ pub fn select(db: &Db, id: Uuid) -> Result<Account, Error> {
Account::try_from(row) Account::try_from(row)
} }
pub fn chat_wheel(_db: &Db, _id: Uuid) -> Result<Vec<String>, Error> {
return Ok(vec![
"gl".to_string(),
"hf".to_string(),
"gg".to_string(),
"thx".to_string(),
"nice".to_string(),
"hmm".to_string(),
"ok".to_string(),
"...".to_string(),
])
}
pub fn select_name(db: &Db, name: &String) -> Result<Account, Error> { pub fn select_name(db: &Db, name: &String) -> Result<Account, Error> {
let query = " let query = "
SELECT id, name, balance, subscribed, img SELECT id, name, balance, subscribed, img

View File

@ -58,7 +58,9 @@ pub enum Event {
Invite(Id), Invite(Id),
Join(Id, String), Join(Id, String),
Joined(Id), Joined(Id),
Chat(Id, Uuid, String)
Chat(Id, Uuid, String),
ChatClear(Id, Uuid),
} }
struct WsClient { struct WsClient {
@ -66,6 +68,7 @@ struct WsClient {
account: Option<Uuid>, account: Option<Uuid>,
tx: Sender<RpcMessage>, tx: Sender<RpcMessage>,
subs: HashSet<Uuid>, subs: HashSet<Uuid>,
chat: Option<(Uuid, String)>,
pvp: bool, pvp: bool,
invite: Option<String>, invite: Option<String>,
} }
@ -121,7 +124,15 @@ impl Events {
None => None, None => None,
}; };
let client = WsClient { id, tx, account: account_id, subs: HashSet::new(), pvp: false, invite: None }; let client = WsClient { id,
tx,
account: account_id,
subs: HashSet::new(),
pvp: false,
invite: None,
chat: None,
};
self.clients.insert(id, client); self.clients.insert(id, client);
info!("clients={:?}", self.clients.len()); info!("clients={:?}", self.clients.len());
@ -216,7 +227,7 @@ impl Events {
} }
// create the req for the already queued opponent // create the req for the already queued opponent
if let Some(opp_req) = match self.clients.iter_mut().find(|(_c_id, c)| c.pvp) { if let Some(opp_req) = match self.clients.iter_mut().find(|(c_id, c)| c.pvp && **c_id != id) {
Some((q_id, q)) => { Some((q_id, q)) => {
q.pvp = false; q.pvp = false;
Some(PvpRequest { id: *q_id, account: q.account.unwrap(), tx: q.tx.clone() }) Some(PvpRequest { id: *q_id, account: q.account.unwrap(), tx: q.tx.clone() })
@ -292,6 +303,52 @@ impl Events {
return Ok(()); return Ok(());
}, },
Event::Chat(id, instance, msg) => {
// set the chat state of this connection
{
let c = self.clients.get_mut(&id)
.ok_or(format_err!("connection not found id={:?}", id))?;
if c.chat.is_some() {
return Err(err_msg("you must wait"));
}
c.chat = Some((instance, msg));
}
// now collect all listeners of this instance
let chat_state: HashMap<Uuid, String> = self.clients.iter()
.filter(|(_id, c)| c.account.is_some())
.filter(|(_id, c)| match c.chat {
Some(ref chat) => chat.0 == instance,
None => false,
})
.map(|(_id, c)| (c.account.unwrap(), c.chat.clone().unwrap().1))
.collect();
return self.event(Event::Push(instance, RpcMessage::InstanceChat(chat_state)));
},
Event::ChatClear(id, instance) => {
{
match self.clients.get_mut(&id) {
Some(c) => c.chat = None,
None => (),
};
}
let chat_state: HashMap<Uuid, String> = self.clients.iter()
.filter(|(_id, c)| c.account.is_some())
.filter(|(_id, c)| match c.chat {
Some(ref chat) => chat.0 == instance,
None => false,
})
.map(|(_id, c)| (c.account.unwrap(), c.chat.clone().unwrap().1))
.collect();
return self.event(Event::Push(instance, RpcMessage::InstanceChat(chat_state)));
}
} }
} }
} }

View File

@ -1,4 +1,5 @@
use std::fs::File; use std::fs::File;
use std::collections::{HashMap};
use uuid::Uuid; use uuid::Uuid;
@ -31,6 +32,8 @@ enum InstancePhase {
Finished, Finished,
} }
pub type ChatState = HashMap<Uuid, String>;
#[derive(Debug,Clone,Serialize,Deserialize)] #[derive(Debug,Clone,Serialize,Deserialize)]
struct Round { struct Round {
game_id: Option<Uuid>, game_id: Option<Uuid>,

View File

@ -1,5 +1,7 @@
use std::time::{Instant}; use std::time::{Instant};
use std::thread::spawn; use std::thread::{spawn, sleep};
use std::time;
use std::str; use std::str;
use uuid::Uuid; use uuid::Uuid;
@ -21,7 +23,7 @@ use account;
use construct::{Construct}; use construct::{Construct};
use events::{Event}; use events::{Event};
use game::{Game, game_state, game_skill, game_skill_clear, game_ready}; use game::{Game, game_state, game_skill, game_skill_clear, game_ready};
use instance::{Instance, instance_state, instance_practice, instance_ready, instance_abandon, demo}; use instance::{Instance, ChatState, instance_state, instance_practice, instance_ready, instance_abandon, demo};
use item::{Item, ItemInfoCtr, item_info}; use item::{Item, ItemInfoCtr, item_info};
use mtx; use mtx;
use mail; use mail;
@ -50,6 +52,8 @@ pub enum RpcMessage {
ItemInfo(ItemInfoCtr), ItemInfo(ItemInfoCtr),
InstanceState(Instance), InstanceState(Instance),
InstanceChat(ChatState),
ChatWheel(Vec<String>),
EmailState(Option<Email>), EmailState(Option<Email>),
SubscriptionState(Option<Subscription>), SubscriptionState(Option<Subscription>),
@ -66,6 +70,8 @@ pub enum RpcMessage {
Invite(String), Invite(String),
Joining(()), Joining(()),
Processing(()),
Error(String), Error(String),
} }
@ -102,6 +108,7 @@ pub enum RpcRequest {
InstanceAbandon { instance_id: Uuid }, InstanceAbandon { instance_id: Uuid },
InstanceReady { instance_id: Uuid }, InstanceReady { instance_id: Uuid },
InstanceState { instance_id: Uuid }, InstanceState { instance_id: Uuid },
InstanceChat { instance_id: Uuid, index: usize },
VboxAccept { instance_id: Uuid, group: usize, index: usize }, VboxAccept { instance_id: Uuid, group: usize, index: usize },
VboxDiscard { instance_id: Uuid }, VboxDiscard { instance_id: Uuid },
@ -164,21 +171,22 @@ impl Connection {
return Err(err_msg("subscribe to unlock chat")) return Err(err_msg("subscribe to unlock chat"))
} }
let chat = vec![ let wheel = account::chat_wheel(&db, account.id)?;
"gl",
"hf",
"gg",
"thx",
"nice",
"hmm",
"ok",
"...",
];
self.events.send(Event::Chat(self.id, instance_id, chat[index]))?; if let Some(c) = wheel.get(index) {
self.events.send(Event::Chat(self.id, instance_id, c.to_string()))?;
} else {
return Err(err_msg("invalid chat index"));
}
// evnts sends to subs let events_tx = self.events.clone();
Ok(RpcMessage::Joining(())) let id = self.id;
spawn(move || {
sleep(time::Duration::from_secs(3));
events_tx.send(Event::ChatClear(id, instance_id)).unwrap();
});
Ok(RpcMessage::Processing(()))
}, },
_ => { _ => {
// all good, let's make a tx and process // all good, let's make a tx and process
@ -337,6 +345,9 @@ impl Handler for Connection {
let team = account::team(&mut tx, &a).unwrap(); let team = account::team(&mut tx, &a).unwrap();
self.send(RpcMessage::AccountTeam(team)).unwrap(); self.send(RpcMessage::AccountTeam(team)).unwrap();
let wheel = account::chat_wheel(&db, a.id).unwrap();
self.send(RpcMessage::ChatWheel(wheel)).unwrap();
// tx should do nothing // tx should do nothing
tx.commit().unwrap(); tx.commit().unwrap();
} else { } else {