client niceness"

This commit is contained in:
ntr 2019-04-26 13:08:08 +10:00
parent 471d37c551
commit 95e5d493af
8 changed files with 121 additions and 29 deletions

View File

@ -66,6 +66,17 @@ main {
align-items: flex-start; align-items: flex-start;
} }
tr.right:focus, tr.right:hover {
box-shadow: inset -0.5em 0 0 0 whitesmoke;
}
tr {
transition-property: all;
transition-duration: 0.5s;
transition-delay: 0;
transition-timing-function: ease;
}
button, input { button, input {
font-family: 'Jura'; font-family: 'Jura';
color: whitesmoke; color: whitesmoke;
@ -320,24 +331,30 @@ header {
flex: 1 0 25%; flex: 1 0 25%;
} }
.ready-btn {
flex: 1 0 50%;
}
/* nav hidden on desktop */ /* nav hidden on desktop */
.nav-btn { .nav-btn {
display: none; display: none;
} }
.ready-btn {
flex: 1 0 50%;
}
.ready-btn:hover { .ready-btn:hover {
transition-property: all; transition-property: all;
transition-duration: 2s; transition-duration: 0.5s;
transition-timing-function: ease; transition-timing-function: ease;
color: forestgreen; color: forestgreen;
border-color: forestgreen; border-color: forestgreen;
/*box-shadow: inset -0.5em 0 0 0 forestgreen;*/ /*box-shadow: inset -0.5em 0 0 0 forestgreen;*/
} }
.ready {
color: forestgreen;
box-shadow: inset -0.5em 0 0 0 forestgreen;
}
.instance-ui-btn { .instance-ui-btn {
font-size: 100%; font-size: 100%;
padding: 0; padding: 0;
@ -395,32 +412,33 @@ header {
color: black; color: black;
} }
.vbox-table { table {
table-layout: fixed; table-layout: fixed;
width: 100%; width: 100%;
} }
.vbox-table td { table td {
border: 1px solid whitesmoke; border: 1px solid whitesmoke;
padding: 0.2em; padding: 0.2em;
text-align: center; text-align: center;
height: 40px; height: 40px;
cursor: pointer; cursor: pointer;
text-transform: uppercase; text-transform: uppercase;
}
.vbox-table td {
transition-property: all; transition-property: all;
transition-duration: 0.5s; transition-duration: 0.5s;
transition-delay: 0; transition-delay: 0;
transition-timing-function: ease; transition-timing-function: ease;
} }
.vbox-table td:active { table td:active {
background-color: whitesmoke; background-color: whitesmoke;
color: black; color: black;
} }
.vbox-table td svg { table td svg {
stroke-width: 2px; stroke-width: 2px;
height: 96%; height: 96%;
vertical-align: text-bottom; vertical-align: text-bottom;

View File

@ -155,7 +155,8 @@ function Info(args) {
function scoreBoard() { function scoreBoard() {
const players = instance.players.map((p, i) => const players = instance.players.map((p, i) =>
<tr key={i} > <tr key={i}
className={p.ready ? 'ready' : ''}>
<td>{p.name}</td> <td>{p.name}</td>
<td>{p.score.wins} / {p.score.losses}</td> <td>{p.score.wins} / {p.score.losses}</td>
<td>{p.ready ? 'ready' : ''}</td> <td>{p.ready ? 'ready' : ''}</td>
@ -163,7 +164,7 @@ function Info(args) {
); );
return ( return (
<table className="vbox-table"> <table>
<tbody> <tbody>
{players} {players}
</tbody> </tbody>
@ -171,19 +172,23 @@ function Info(args) {
); );
} }
const scoreBoardEl = activeCryp || info[0]
? null
: scoreBoard();
const infoCryp = activeCryp const infoCryp = activeCryp
? infoCrypElement(player.cryps.find(c => c.id === activeCryp.id)) ? infoCrypElement(player.cryps.find(c => c.id === activeCryp.id))
: null; : null;
const otherInfo = info.length const otherInfo = !info[0]
? infoVar(info) ? infoVar(info)
: null; : null;
const instanceInfoClass = `instance-info ${info.length ? '' : 'hidden'}`; const instanceInfoClass = `instance-info ${!info[0] ? '' : 'hidden'}`;
return ( return (
<div className={instanceInfoClass} > <div className={instanceInfoClass} >
{scoreBoard()} {scoreBoardEl}
{infoCryp} {infoCryp}
{otherInfo} {otherInfo}
</div> </div>

View File

@ -59,7 +59,7 @@ class InstanceCreateForm extends Component {
<input <input
className="login-input" className="login-input"
type="text" type="text"
value={this.state.value} value={this.state.name}
placeholder="name" placeholder="name"
onChange={this.nameChange} onChange={this.nameChange}
/> />

View File

@ -36,9 +36,8 @@ function Menu(args) {
const instancePanels = instances.map(instance => { const instancePanels = instances.map(instance => {
const player = instance.players.find(p => p.id === account.id); const player = instance.players.find(p => p.id === account.id);
const scoreText = player const scoreText = player
? `| ${player.score.wins} : ${player.score.losses}` ? `${player.score.wins} : ${player.score.losses}`
: ''; : '';
const name = `${instance.name} ${scoreText}`;
function instanceClick() { function instanceClick() {
if (!player) return sendInstanceJoin(instance); if (!player) return sendInstanceJoin(instance);
@ -46,12 +45,13 @@ function Menu(args) {
} }
return ( return (
<button <tr key={instance.id}
className={'menu-instance-btn right'} className="right"
key={instance.id} onClick={instanceClick} >
onClick={instanceClick}> <td>{instance.name}</td>
{name} <td>{instance.players.length} / {instance.max_players}</td>
</button> <td>{scoreText}</td>
</tr>
); );
}); });
@ -68,7 +68,18 @@ function Menu(args) {
return ( return (
<section className="menu-instance-list" > <section className="menu-instance-list" >
<table>
<thead>
<tr>
<th>instance name</th>
<th>players</th>
<th>status</th>
</tr>
</thead>
<tbody>
{instancePanels} {instancePanels}
</tbody>
</table>
{mmSet} {mmSet}
<InstanceCreateForm /> <InstanceCreateForm />
</section> </section>

View File

@ -150,7 +150,7 @@ function wsReducer(state = defaultWs, action) {
} }
} }
const defaultInfo = []; const defaultInfo = [null, null];
function infoReducer(state = defaultInfo, action) { function infoReducer(state = defaultInfo, action) {
switch (action.type) { switch (action.type) {
case actions.SET_INFO: case actions.SET_INFO:

View File

@ -17,6 +17,7 @@ use mob::{instance_mobs};
use game::{Game, Phase, Team, game_get, game_write, game_instance_new, game_instance_join, game_global_get, game_global_set}; use game::{Game, Phase, Team, game_get, game_write, game_instance_new, game_instance_join, game_global_get, game_global_set};
use vbox::{Var}; use vbox::{Var};
use rpc::{RpcResult}; use rpc::{RpcResult};
use names::{name};
#[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)] #[derive(Debug,Clone,Copy,PartialEq,Serialize,Deserialize)]
enum InstancePhase { enum InstancePhase {
@ -94,7 +95,7 @@ impl Instance {
self.players = iter::repeat_with(|| { self.players = iter::repeat_with(|| {
let bot_id = Uuid::new_v4(); let bot_id = Uuid::new_v4();
let cryps = instance_mobs(bot_id); let cryps = instance_mobs(bot_id);
let mut p = Player::new(bot_id, self.id, &bot_id.to_string(), cryps).set_bot(true); let mut p = Player::new(bot_id, self.id, &name(), cryps).set_bot(true);
p.set_ready(true); p.set_ready(true);
p p
}) })
@ -105,7 +106,7 @@ impl Instance {
fn add_player(&mut self, player: Player) -> Result<&mut Instance, Error> { fn add_player(&mut self, player: Player) -> Result<&mut Instance, Error> {
match self.players.iter().find(|p| p.id == player.id) { match self.players.iter().find(|p| p.id == player.id) {
Some(p) => return Err(err_msg("already joined")), Some(_p) => return Err(err_msg("already joined")),
None => (), None => (),
}; };
@ -138,11 +139,12 @@ impl Instance {
.position(|p| p.id == player_id) .position(|p| p.id == player_id)
.ok_or(err_msg("player_id not found"))?; .ok_or(err_msg("player_id not found"))?;
if self.players[i].cryps.iter().all(|c| c.skills.len() == 0) { if self.phase != InstancePhase::Lobby && self.players[i].cryps.iter().all(|c| c.skills.len() == 0) {
return Err(err_msg("your cryps have no skills")); return Err(err_msg("your cryps have no skills"));
} }
self.players[i].set_ready(true); let v = !self.players[i].ready;
self.players[i].set_ready(v);
if self.phase == InstancePhase::Lobby && self.can_start() { if self.phase == InstancePhase::Lobby && self.can_start() {
self.start(); self.start();

View File

@ -24,6 +24,7 @@ mod net;
mod skill; mod skill;
mod spec; mod spec;
// mod passives; // mod passives;
mod names;
mod rpc; mod rpc;
mod account; mod account;
mod instance; mod instance;

55
server/src/names.rs Normal file
View File

@ -0,0 +1,55 @@
use rand::prelude::*;
use rand::{thread_rng};
const FIRSTS: [&'static str; 17] = [
"fierce",
"obscure",
"mighty",
"rogue",
"inverted",
"recalcitrant",
"subterranean",
"brewing",
"nocturnal",
"convex",
"concave",
"piscine",
"dub",
"borean",
"lurking",
"leafy",
"nutritious",
];
const LASTS: [&'static str; 16] = [
"kaffe",
"river",
"oak",
"replicant",
"mechanism",
"function",
"shape",
"form",
"poseidon",
"mountain",
"river",
"forest",
"problem",
"warning",
"information",
"witness",
];
pub fn name() -> String {
let mut rng = thread_rng();
let first = rng.gen_range(0, FIRSTS.len() - 1);
let last = rng.gen_range(0, LASTS.len() - 1);
let mut s = String::new();
s.push_str(FIRSTS[first]);
s.push(' ');
s.push_str(LASTS[last]);
s
}