diff options
author | metamuffin <metamuffin@disroot.org> | 2025-10-06 14:04:52 +0200 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2025-10-06 14:04:52 +0200 |
commit | a5814a2a81c0ea7bcf6d56626ff7167af78d63a6 (patch) | |
tree | 7896236b46c4c696aace17816cf71e433156355f | |
parent | f4bce8374988cd0f18d21bf43c649bc4b34ccf74 (diff) | |
download | hurrycurry-a5814a2a81c0ea7bcf6d56626ff7167af78d63a6.tar hurrycurry-a5814a2a81c0ea7bcf6d56626ff7167af78d63a6.tar.bz2 hurrycurry-a5814a2a81c0ea7bcf6d56626ff7167af78d63a6.tar.zst |
Collapse anywhere passive recipes
-rw-r--r-- | server/protocol/src/book.rs | 12 | ||||
-rw-r--r-- | server/tools/src/diagram_dot.rs | 24 | ||||
-rw-r--r-- | server/tools/src/diagram_svg.rs | 16 | ||||
-rw-r--r-- | server/tools/src/recipe_diagram.rs | 28 |
4 files changed, 60 insertions, 20 deletions
diff --git a/server/protocol/src/book.rs b/server/protocol/src/book.rs index 7c529f22..1654e014 100644 --- a/server/protocol/src/book.rs +++ b/server/protocol/src/book.rs @@ -69,8 +69,20 @@ pub struct DiagramEdge { pub src: usize, pub dst: usize, pub label: Option<Message>, + pub style: EdgeStyle, } +#[derive(Debug, Clone, Serialize, Deserialize)] +pub enum EdgeStyle { + Regular, + ProcessPassive, +} + +impl EdgeStyle { + pub fn is_regular(&self) -> bool { + matches!(self, Self::Regular) + } +} impl NodeStyle { pub fn is_procuct(&self) -> bool { matches!( diff --git a/server/tools/src/diagram_dot.rs b/server/tools/src/diagram_dot.rs index b3e54881..f86a2d4e 100644 --- a/server/tools/src/diagram_dot.rs +++ b/server/tools/src/diagram_dot.rs @@ -19,7 +19,7 @@ use anyhow::{Result, bail}; use hurrycurry_protocol::{ Gamedata, Message, - book::{Diagram, NodeStyle}, + book::{Diagram, DiagramNode, NodeStyle}, }; use std::{ fmt::Write, @@ -27,6 +27,8 @@ use std::{ process::{Command, Stdio}, }; +use crate::diagram_svg::{edge_color, node_color}; + pub fn diagram_dot_svg(data: &Gamedata, diagram: &Diagram) -> Result<String> { let mut child = Command::new("dot") .arg("-Tsvg") @@ -52,7 +54,7 @@ pub fn diagram_dot(data: &Gamedata, diagram: &Diagram, use_position: bool) -> Re if use_position { attrs.push(format!("pos=\"{},{}!\"", n.position.x, n.position.y)); } - node_style(&mut attrs, &n.style); + node_style(&mut attrs, &n); match &n.label { Message::Text(text) => { attrs.push(format!("label=\"{text}\"")); @@ -84,20 +86,22 @@ pub fn diagram_dot(data: &Gamedata, diagram: &Diagram, use_position: bool) -> Re writeln!(out, "k{i} [{}]", attrs.join(" "))?; } for edge in &diagram.edges { - writeln!(out, "k{} -> k{}", edge.src, edge.dst)?; + let color = edge_color(edge); + writeln!(out, "k{} -> k{} [color=\"{color}\"]", edge.src, edge.dst)?; } writeln!(out, "}}")?; Ok(out) } -fn node_style(attrs: &mut Vec<String>, style: &NodeStyle) { - let (shape, color) = match style { - NodeStyle::FinalProduct => ("circle", "#555"), - NodeStyle::IntermediateProduct => ("circle", "#333"), - NodeStyle::ProcessActive => ("box", "#47c42b"), - NodeStyle::ProcessPassive => ("box", "#c4a32b"), - NodeStyle::ProcessInstant => ("box", "#5452d8"), +fn node_style(attrs: &mut Vec<String>, node: &DiagramNode) { + let shape = match node.style { + NodeStyle::FinalProduct => "circle", + NodeStyle::IntermediateProduct => "circle", + NodeStyle::ProcessActive => "box", + NodeStyle::ProcessPassive => "box", + NodeStyle::ProcessInstant => "box", }; + let color = node_color(node); attrs.push(format!("shape={shape}")); attrs.push("style=filled".to_owned()); attrs.push(format!("fillcolor=\"{color}\"")); diff --git a/server/tools/src/diagram_svg.rs b/server/tools/src/diagram_svg.rs index 0fc75668..fe3d9de4 100644 --- a/server/tools/src/diagram_svg.rs +++ b/server/tools/src/diagram_svg.rs @@ -19,7 +19,7 @@ use anyhow::Result; use hurrycurry_protocol::{ Gamedata, Message, - book::{Diagram, DiagramNode, NodeStyle}, + book::{Diagram, DiagramEdge, DiagramNode, EdgeStyle, NodeStyle}, glam::Vec2, }; use std::fmt::Write; @@ -80,16 +80,18 @@ pub fn diagram_svg(data: &Gamedata, diagram: &Diagram) -> Result<String> { let tip2 = dst + (dir + dir.perp() * -0.5) * 10.; dst += dir * 5.; // prevent miter line cap from peeking out + let color = edge_color(edge); + // line path writeln!( out, - r#"<path fill="none" stroke="black" stroke-width="2" d="M{} {} L{} {}" />"#, + r#"<path fill="none" stroke="{color}" stroke-width="2" d="M{} {} L{} {}" />"#, src.x, src.y, dst.x, dst.y, )?; // tip path writeln!( out, - r#"<path fill="black" stroke="none" d="M{} {} L{} {} L{} {} Z" />"#, + r#"<path fill="{color}" stroke="none" d="M{} {} L{} {} L{} {} Z" />"#, tip0.x, tip0.y, tip1.x, tip1.y, tip2.x, tip2.y )?; } @@ -110,7 +112,7 @@ fn node_edge_connect_pos(src: &DiagramNode, dst: &DiagramNode) -> Vec2 { } } -fn node_color(node: &DiagramNode) -> &'static str { +pub(crate) fn node_color(node: &DiagramNode) -> &'static str { match node.style { NodeStyle::FinalProduct => "#555", NodeStyle::IntermediateProduct => "#333", @@ -119,6 +121,12 @@ fn node_color(node: &DiagramNode) -> &'static str { NodeStyle::ProcessInstant => "#5452d8", } } +pub(crate) fn edge_color(edge: &DiagramEdge) -> &'static str { + match edge.style { + EdgeStyle::Regular => "#000000", + EdgeStyle::ProcessPassive => "#c4a32b", + } +} fn image_node(out: &mut String, node: &DiagramNode, path: String) -> Result<()> { if matches!( diff --git a/server/tools/src/recipe_diagram.rs b/server/tools/src/recipe_diagram.rs index ec7656b9..903b869a 100644 --- a/server/tools/src/recipe_diagram.rs +++ b/server/tools/src/recipe_diagram.rs @@ -19,7 +19,7 @@ use anyhow::Result; use hurrycurry_protocol::{ Gamedata, ItemIndex, Message, Recipe, RecipeIndex, - book::{Diagram, DiagramEdge, DiagramNode, NodeStyle}, + book::{Diagram, DiagramEdge, DiagramNode, EdgeStyle, NodeStyle}, glam::Vec2, }; use hurrycurry_server::data::Serverdata; @@ -98,16 +98,29 @@ pub(crate) fn recipe_diagram( let index = diag.nodes.len(); let recipe = data.recipe(r.index); - if matches!(recipe, Recipe::Instant { .. }) && r.outputs.len() == 1 && r.inputs.len() >= 1 { + if matches!(recipe, Recipe::Instant { .. }) && r.inputs.len() >= 1 && r.outputs.len() >= 1 { for i in r.inputs { diag.edges.push(DiagramEdge { src: item_index[&i], dst: item_index[&r.outputs[0]], label: None, + style: EdgeStyle::Regular, }); } continue; } + if matches!(recipe, Recipe::Passive { tile: None, .. }) + && r.inputs.len() == 1 + && r.outputs.len() == 1 + { + diag.edges.push(DiagramEdge { + src: item_index[&r.inputs[0]], + dst: item_index[&r.outputs[0]], + label: None, + style: EdgeStyle::ProcessPassive, + }); + continue; + } let (kind, style) = match recipe { Recipe::Passive { .. } => ("Passive", NodeStyle::ProcessPassive), @@ -129,6 +142,7 @@ pub(crate) fn recipe_diagram( src: item_index[&i], dst: index, label: None, + style: EdgeStyle::Regular, }); } for o in r.outputs { @@ -136,6 +150,7 @@ pub(crate) fn recipe_diagram( src: index, dst: item_index[&o], label: None, + style: EdgeStyle::Regular, }); } } @@ -173,10 +188,10 @@ fn merge_combine_clusters(diag: &mut Diagram) { if outputs .iter() - .all(|&(_, i)| diag.nodes[i].style.is_procuct()) - && inputs - .iter() - .all(|&(_, i)| diag.nodes[i].style.is_procuct()) + .all(|&(ei, ni)| diag.nodes[ni].style.is_procuct() && diag.edges[ei].style.is_regular()) + && inputs.iter().all(|&(ei, ni)| { + diag.nodes[ni].style.is_procuct() && diag.edges[ei].style.is_regular() + }) { let mut to_remove = inputs .iter() @@ -199,6 +214,7 @@ fn merge_combine_clusters(diag: &mut Diagram) { src: input.1, dst: output.1, label: None, + style: EdgeStyle::Regular, }); } } |