let gpl = players.byid_mut(player)?;
let pri = piece_pri(&gs.occults, player, gpl, piece, pc);
- let pcs = p.describe_pri(&pri).0;
+ let pcs = p.describe_pri(pc, &pri).0;
pc.held = Some(player);
let pieces = ig.gs.pieces.iter().map(|(piece,p)|{
let &PieceState { pos, face, .. } = p;
let pinfo = ig.ipieces.get(piece)?;
- let desc_html = pinfo.describe_html(None);
+ let desc_html = pinfo.describe_html_infallible(None, p);
let itemname = pinfo.itemname().to_string();
let bbox = pinfo.bbox_approx();
#[allow(irrefutable_let_patterns)]
.remove(piece).ok_or(ME::PieceNotFound)?;
let gs = &mut ig.gs;
let pc = gs.pieces.as_mut(modperm).remove(piece);
- let desc_html = p.describe_html(Some(default()));
+ let desc_html = if let Some(pc) = &pc {
+ p.describe_html_infallible(Some(default()), pc)
+ } else {
+ Html::lit("<piece partially missing from game state!>")
+ };
if let Some(pc) = pc { p.delete_hook(&pc, gs); }
(U{ pcs: vec![(piece, PieceUpdateOp::Delete())],
log: vec![ LogEntry {
let pri = piece_pri(&ig.gs.occults, player, gpl, gpid, pr);
let p = if let Some(p) = ig.ipieces.get(gpid) { p }
else { continue /* was deleted */ };
- let defs = p.make_defs(&pri)?;
+ let defs = p.make_defs(pr, &pri)?;
alldefs.push((pri.id, defs));
let vangle = match pri.angle {
(||{
let pc = spec.clone().load().context("load")?;
let mut uos = vec![];
- let gen_dummy = Generation(1);
- let gpc_dummy = PieceState {
- pos: PosC([0,0]),
- face: default(),
- held: None,
- zlevel: ZLevel { z: default(), zg: gen_dummy },
- pinned: false,
- occult: default(),
- angle: default(),
- gen: gen_dummy,
- lastclient: ClientId(default()),
- gen_before_lastclient: gen_dummy,
- xdata: None,
- };
+ let gpc_dummy = PieceState::dummy();
pc.add_ui_operations(&mut uos, &gpc_dummy).context("add uos")?;
let uos = uos.into_iter().map(|uo| uo.opname).collect::<Vec<_>>();
let spec = spec.clone();
let max_facecols = pieces.iter().map(|s| s.face_cols()).max().unwrap_or(1);
let max_uos = pieces.iter().map(|s| s.uos.len()).max().unwrap_or(0);
+ let gpc_dummy = PieceState::dummy();
+
println!("{}", &HTML_PRELUDE);
println!(r#"<table rules="all">"#);
for s in &pieces {
Html::from_txt(&spec.lib).0);
println!(r#"<th align="left"><kbd>{}</kbd></th>"#,
Html::from_txt(&spec.item).0);
- println!(r#"<th align="left">{}</th>"#, pc.describe_html(None).0);
+ println!(r#"<th align="left">{}</th>"#,
+ pc.describe_html(None, &gpc_dummy)?.0);
let only1 = s.face_cols() == 1;
let getpri = |face: FaceId| PieceRenderInstructions {
id: default(),
&surround.0, &dasharray.0, HELD_SURROUND_COLOUR);
}
let mut html = Html("".into());
- pc.svg_piece(&mut html, &pri)?;
+ pc.svg_piece(&mut html, &gpc_dummy, &pri)?;
println!("{}</svg>", html.0);
}
println!("</td>");
}
// #[throws] doesn't work here - fehler #todo
- fn svg_piece(&self, f: &mut Html, pri: &PieceRenderInstructions)
- -> Result<(),IE>;
+ fn svg_piece(&self, f: &mut Html, gpc: &PieceState,
+ pri: &PieceRenderInstructions) -> Result<(),IE>;
- fn describe_html(&self, face: Option<FaceId>) -> Html;
+ fn describe_html(&self, face: Option<FaceId>, gpc: &PieceState)
+ -> Result<Html,IE>;
fn delete_hook(&self, _p: &PieceState, _gs: &mut GameState)
-> ExecuteGameChangeUpdates {
PreparedPieceState {
pos : self.pos,
held : self.held,
- svg : p.make_defs(pri)?,
+ svg : p.make_defs(self, pri)?,
z : self.zlevel.z.clone(),
zg : self.zlevel.zg,
pinned : self.pinned,
pub fn xdata_mut<T:PieceXData+Default>(&mut self) -> &mut T {
self.xdata.get_mut()?
}
+
+ pub fn dummy() -> Self {
+ let gen_dummy = Generation(1);
+ PieceState {
+ pos: PosC([0,0]),
+ face: default(),
+ held: None,
+ zlevel: ZLevel { z: default(), zg: gen_dummy },
+ pinned: false,
+ occult: default(),
+ angle: default(),
+ gen: gen_dummy,
+ lastclient: ClientId(default()),
+ gen_before_lastclient: gen_dummy,
+ xdata: None,
+ }
+ }
}
pub trait PieceXDataExt {
}
pub trait PieceExt {
- fn make_defs(&self, pri: &PieceRenderInstructions) -> Result<Html, IE>;
- fn describe_pri(&self, pri: &PieceRenderInstructions) -> Html;
+ fn make_defs(&self, gpc: &PieceState, pri: &PieceRenderInstructions)
+ -> Result<Html, IE>;
+ fn describe_html_infallible(&self, face: Option<FaceId>, gpc: &PieceState)
+ -> Html;
+ fn describe_pri(&self, gpc: &PieceState, pri: &PieceRenderInstructions)
+ -> Html;
fn ui_operations(&self, gpc: &PieceState) -> Result<Vec<UoDescription>, IE>;
}
impl<T> PieceExt for T where T: Piece + ?Sized {
#[throws(IE)]
- fn make_defs(&self, pri: &PieceRenderInstructions) -> Html {
+ fn make_defs(&self, gpc: &PieceState, pri: &PieceRenderInstructions)
+ -> Html {
let mut defs = Html(String::new());
let dragraise = match self.thresh_dragraise(pri)? {
Some(n) if n < 0 => throw!(SvgE::NegativeDragraise),
write!(&mut defs.0,
r##"<g id="piece{}" transform="{}" data-dragraise="{}">"##,
pri.id, &transform.0, dragraise)?;
- self.svg_piece(&mut defs, &pri)?;
+ self.svg_piece(&mut defs, gpc, &pri)?;
write!(&mut defs.0, r##"</g>"##)?;
write!(&mut defs.0,
r##"<path id="surround{}" d="{}"/>"##,
defs
}
- fn describe_pri(&self, pri: &PieceRenderInstructions) -> Html {
- self.describe_html(Some(pri.face))
+ fn describe_html_infallible(&self, face: Option<FaceId>, gpc: &PieceState)
+ -> Html {
+ self.describe_html(face, gpc)
+ .unwrap_or_else(|e| {
+ error!("error describing piece: {:?}", e);
+ Html::lit("<internal error describing piece>")
+ })
+ }
+
+ fn describe_pri(&self, gpc: &PieceState, pri: &PieceRenderInstructions)
+ -> Html {
+ self.describe_html_infallible(Some(pri.face), gpc)
}
#[throws(InternalError)]
format!("missing occulter piece {:?} for occid {:?}",
opiece, h.occid));
let oipc = ipieces.get(opiece).ok_or_else(bad)?;
- Ok::<_,IE>(oipc.describe_html(None))
+ let ogpc = gs.pieces.get(opiece).ok_or_else(bad)?;
+ Ok::<_,IE>(oipc.describe_html(None, ogpc)?)
};
let most_obscure = most_obscure.unwrap_or(&OccK::Visible); // no players!
}
OccK::Scrambled | OccK::Displaced{..} => {
let face = ipc.nfaces() - 1;
- let show = ipc.describe_html(Some(face.into()));
+ let show = ipc.describe_html(Some(face.into()), gpc)?;
vec![ LogEntry { html: Html(format!(
"{} moved {} from {} to {}",
who_by.0, &show.0,
#[typetag::serde]
impl Piece for SimpleShape {
#[throws(IE)]
- fn svg_piece(&self, f: &mut Html, pri: &PieceRenderInstructions) {
+ fn svg_piece(&self, f: &mut Html, _gpc: &PieceState,
+ pri: &PieceRenderInstructions) {
self.svg_piece_raw(f, pri, &mut |_|Ok(()))?;
}
- fn describe_html(&self, face: Option<FaceId>) -> Html {
+ #[throws(IE)]
+ fn describe_html(&self, face: Option<FaceId>, _gpc: &PieceState) -> Html {
Html(if_chain! {
if let Some(face) = face;
if let Some(colour) = self.colours.get(face);
impl Piece for Hand {
delegate!{
to self.shape {
- fn svg_piece(&self, f: &mut Html, pri: &PieceRenderInstructions)
- -> Result<(),IE>;
- fn describe_html(&self, face: Option<FaceId>) -> Html;
+ fn svg_piece(&self, f: &mut Html, gpc: &PieceState,
+ pri: &PieceRenderInstructions) -> Result<(),IE>;
+ fn describe_html(&self, face: Option<FaceId>, _gpc: &PieceState)
+ -> Result<Html,IE>;
fn itemname(&self) -> &str;
}
}
fn nfaces(&self) -> RawFaceId { self.faces.len().try_into().unwrap() }
#[throws(IE)]
- fn svg_piece(&self, f: &mut Html, pri: &PieceRenderInstructions) {
+ fn svg_piece(&self, f: &mut Html, _gpc: &PieceState,
+ pri: &PieceRenderInstructions) {
let face = &self.faces[pri.face];
let svgd = &self.svgs[face.svg];
write!(&mut f.0,
face.scale[0], face.scale[1], -face.centre[0], -face.centre[1],
svgd.0)?;
}
- fn describe_html(&self, face: Option<FaceId>) -> Html {
+ #[throws(IE)]
+ fn describe_html(&self, face: Option<FaceId>, _gpc: &PieceState) -> Html {
self.descs[ match face {
Some(face) => self.faces[face].desc,
None => self.desc_hidden,
let ier = ItemEnquiryData {
itemname: k.clone(),
f0bbox,
- f0desc: loaded.describe_html(Some(default())),
+ f0desc: loaded.describe_html(Some(default()), &PieceState::dummy())?,
};
out.push(ier);
}
"{} {} {}",
&who_by.0,
did,
- p.describe_pri(&pri).0
+ p.describe_pri(pc, &pri).0,
))}];
(log, who_by)
}