struct ApiPieceOpArgs<'a> {
gs: &'a mut GameState,
player: PlayerId,
- pst: &'a PlayerState,
+ pst: &'a IPlayerState,
piece: PieceId,
p: &'a dyn Piece,
iplayers: &'a SecondarySlotMap<PlayerId, PlayerRecord>,
Insn::AddPlayer(add) => {
// todo some kind of permissions check for player too
let ig = cs.check_acl(ig, PCH::Instance, &[TP::AddPlayer])?.0;
+ let record = AccountRecord::lookup(&add.account)?;
let nick = add.nick.ok_or(ME::ParameterMissing)?;
let logentry = LogEntry {
html: Html(format!("{} added a player: {}", &who,
Ok(tz) => tz,
Err(x) => match x { },
};
- let st = PlayerState {
- tz,
- account: add.account,
+ let gpl = GPlayerState {
nick: nick.to_string(),
};
+ let ipl = IPlayerState {
+ account: add.account,
+ tz,
+ };
let (player, logentry) = ig.player_new(st, tz, logentry)?;
(U{ pcs: vec![],
log: vec![ logentry ],
pub gen : Generation,
pub log : VecDeque<(Generation, Arc<CommittedLogEntry>)>,
pub max_z : ZCoord,
- pub players : DenseSlotMap<PlayerId, String /* nick */>,
+ pub players : DenseSlotMap<PlayerId, GPlayerState>,
+}
+
+#[derive(Debug,Serialize,Deserialize,Clone)]
+pub struct GPlayerState {
+ pub nick: String,
}
#[derive(Debug,Serialize,Deserialize)]
pub struct PlayerRecord {
pub u: PlayerUpdates,
- pub pst: PlayerState,
+ pub pst: IPlayerState,
}
#[derive(Debug,Clone,Serialize,Deserialize)]
-pub struct PlayerState {
+pub struct IPlayerState {
pub acctid: AccountId,
pub tz: Timezone,
}
#[derive(Default)]
pub struct Global {
- // lock hierarchy: games < InstanceContainer < {players, clients}
- // (in order of criticality (perf impact); outermost first, innermost last)
+ // lock hierarchy: all of these are in order of acquisition
+ // (in order of lock acquisition (L first), so also in order of criticality
+ // (perf impact); outermost first, innermost last)
+
+ // slow global locks:
+ save_area_lock : Mutex<Option<File>>,
+ // <- accounts::accounts ->
games : RwLock<HashMap<Arc<InstanceName>,InstanceRef>>,
+
+ // per-game lock:
+ // <- InstanceContainer ->
+ pub shapelibs : RwLock<shapelib::Registry>,
+
+ // inner locks which the game needs:
+ dirty : Mutex<VecDeque<InstanceRef>>,
+ config : RwLock<Arc<ServerConfig>>,
+
+ // fast global lookups
players : RwLock<TokenTable<PlayerId>>,
clients : RwLock<TokenTable<ClientId>>,
- config : RwLock<Arc<ServerConfig>>,
- dirty : Mutex<VecDeque<InstanceRef>>,
- save_area_lock : Mutex<Option<File>>,
- pub shapelibs : RwLock<shapelib::Registry>,
}
#[derive(Debug)]
struct InstanceSaveAccesses<RawTokenStr, PiecesLoadedRef> {
ipieces: PiecesLoadedRef,
tokens_players: Vec<(RawTokenStr, PlayerId)>,
- aplayers: SecondarySlotMap<PlayerId, PlayerState>,
+ aplayers: SecondarySlotMap<PlayerId, IPlayerState>,
acl: Acl<TablePermission>,
}
/// caller is responsible for logging; threading it through
/// proves the caller has a log entry.
#[throws(MgmtError)]
- pub fn player_new(&mut self, newnick: String, newplayer: PlayerState,
+ pub fn player_new(&mut self, newnick: String, newplayer: IPlayerState,
logentry: LogEntry) -> (PlayerId, LogEntry) {
// saving is fallible, but we can't attempt to save unless
// we have a thing to serialise with the player in it
// #[throws(ServerFailure)]
// https://github.com/withoutboats/fehler/issues/62
pub fn player_remove(&mut self, oldplayer: PlayerId)
- -> Result<(Option<String>, Option<PlayerState>),
+ -> Result<(Option<String>, Option<IPlayerState>),
InternalError> {
// We have to filter this player out of everything
// Then save
});
}
- let pl = ig.gs.players.byid_mut(player)?;
+ let gpl = ig.gs.players.byid_mut(player)?;
let ipl = ig.iplayers.byid(player)?;
let tz = &ipl.pst.tz;
let mut pieces : Vec<_> = ig.gs.pieces.iter().collect();
player,
defs : alldefs,
uses,
- nick : ipl.pst.nick.clone(),
+ nick : gpl.nick.clone(),
load : serde_json::to_string(&DataLoad {
players : load_players,
}).map_err(|e| InternalError::JSONEncode(e))?,
// xxx check this on setting access
None
}
- fn server_deliver<'t>(&self, pst: &PlayerState,
+ fn server_deliver<'t>(&self,
+ ipl: &IPlayerState,
+ gpl: &GPlayerState,
token: &'t AccessTokenReport)
-> Result<Option<&'t AccessTokenReport>, TDE> {
Ok(None)
}
- fn client_deliver(&self, pst: &PlayerState, token: &AccessTokenReport)
+ fn client_deliver(&self,
+ pd: &MgmtPlayerDetails,
+ token: &AccessTokenReport)
-> Result<(), TDE> {
panic!()
}
#[typetag::serde]
impl PlayerAccessSpec for UrlOnStdout {
#[throws(TDE)]
- fn server_deliver<'t>(&self, ps: &PlayerState,
+ fn server_deliver<'t>(&self,
+ ipl: &IPlayerState,
+ gpl: &GPlayerState,
token: &'t AccessTokenReport)
-> Option<&'t AccessTokenReport> {
Some(token)
}
#[throws(TDE)]
- fn client_deliver(&self, ps: &PlayerState, token: &AccessTokenReport) {
+ fn client_deliver(&self,
+ pd: &MgmtPlayerDetails,
+ token: &AccessTokenReport) {
println!("access account={} nick={:?} url:\n{}",
- &ps.account, &ps.nick, token.url);
+ &pd.account, &pd.nick, token.url);
}
}