use df_ls_core::{AllowEmpty, Choose, Clamp, Reference, ReferenceTo}; use df_ls_lexical_analysis::test_utils::LexerTestBuilder; use df_ls_structure::*; use df_ls_syntax_analysis::test_utils::SyntaxTestBuilder; #[test] fn test_reaction() { SyntaxTestBuilder::from_lexer_test_builder( LexerTestBuilder::test_source( "reaction_other [OBJECT:REACTION] [REACTION:TAN_A_HIDE] [NAME:tan a hide] [BUILDING:TANNER:CUSTOM_T] [REAGENT:A:1:NONE:NONE:NONE:NONE][USE_BODY_COMPONENT][UNROTTEN] [HAS_MATERIAL_REACTION_PRODUCT:TAN_MAT] In the product, if you want to use the reagent's material itself, use NONE instead of a reaction product class (TAN_MAT in this example). [PRODUCT:100:1:SKIN_TANNED:NONE:GET_MATERIAL_FROM_REAGENT:A:TAN_MAT] [SKILL:TANNER] [AUTOMATIC] [REACTION:RENDER_FAT] [NAME:render fat] [BUILDING:KITCHEN:HOTKEY_KITCHEN_RENDER_FAT] [REAGENT:A:150:GLOB:NONE:NONE:NONE][REACTION_CLASS:FAT][UNROTTEN] [HAS_MATERIAL_REACTION_PRODUCT:RENDER_MAT] [PRODUCT:100:1:GLOB:NONE:GET_MATERIAL_FROM_REAGENT:A:RENDER_MAT] [SKILL:COOK] [AUTOMATIC] [REACTION:MAKE_SOAP_FROM_TALLOW] [NAME:make soap from tallow] [BUILDING:SOAP_MAKER:CUSTOM_T] [REAGENT:LYE:150:LIQUID_MISC:NONE:LYE] [REAGENT:LYE_CONTAINER:1:NONE:NONE:NONE:NONE] [CONTAINS:LYE] [PRESERVE_REAGENT] [DOES_NOT_DETERMINE_PRODUCT_AMOUNT] [REAGENT:TALLOW:150:GLOB:NONE:NONE:NONE][REACTION_CLASS:TALLOW][UNROTTEN] [HAS_MATERIAL_REACTION_PRODUCT:SOAP_MAT] [PRODUCT:100:1:BAR:NONE:GET_MATERIAL_FROM_REAGENT:TALLOW:SOAP_MAT] [PRODUCT_DIMENSION:150] [SKILL:SOAP_MAKING] [SKILL_IP:40] [SKILL_ROLL_RANGE:11:6] [ATTRIBUTE_IP:20] [REACTION:MAKE_SOAP_FROM_OIL] [NAME:make soap from oil] [BUILDING:SOAP_MAKER:CUSTOM_O] [REAGENT:LYE:150:LIQUID_MISC:NONE:LYE] [REAGENT:LYE_CONTAINER:1:NONE:NONE:NONE:NONE] [CONTAINS:LYE] [PRESERVE_REAGENT] [DOES_NOT_DETERMINE_PRODUCT_AMOUNT] [REAGENT:OIL:150:LIQUID_MISC:NONE:NONE:NONE] [UNROTTEN] [HAS_MATERIAL_REACTION_PRODUCT:SOAP_MAT] [REAGENT:OIL_CONTAINER:1:NONE:NONE:NONE:NONE] [CONTAINS:OIL] [PRESERVE_REAGENT] [DOES_NOT_DETERMINE_PRODUCT_AMOUNT] [PRODUCT:100:1:BAR:NONE:GET_MATERIAL_FROM_REAGENT:OIL:SOAP_MAT] [PRODUCT_DIMENSION:150] [SKILL:SOAP_MAKING] [REACTION:MAKE_PEARLASH] [NAME:make pearlash] [BUILDING:KILN:CUSTOM_P] [REAGENT:A:150:BAR:NONE:POTASH:NONE] [PRODUCT:100:1:BAR:NONE:PEARLASH:NONE][PRODUCT_DIMENSION:150] [FUEL] [SKILL:SMELT] [REACTION:PROCESS_PLANT_TO_BAG] [NAME:process plant to bag] [BUILDING:FARMER:CUSTOM_B] [REAGENT:PLANT:1:PLANT:NONE:NONE:NONE] [HAS_MATERIAL_REACTION_PRODUCT:BAG_ITEM] [UNROTTEN] [REAGENT:BAG:1:BOX:NONE:NONE:NONE] [EMPTY] [BAG] [PRESERVE_REAGENT] [DOES_NOT_DETERMINE_PRODUCT_AMOUNT] [PRODUCT:100:5:GET_ITEM_DATA_FROM_REAGENT:PLANT:BAG_ITEM] [PRODUCT_TO_CONTAINER:BAG] [PRODUCT:100:1:SEEDS:NONE:GET_MATERIAL_FROM_REAGENT:PLANT:SEED_MAT] [SKILL:PROCESSPLANTS] [REACTION:TEST_DESCRIPTION] [DESCRIPTION:Make sure multi-line, empty values, and USE_TOOL is accepted] [DESCRIPTION:] [DESCRIPTION:USE_TOOL:EXAMPLE_TOOL] ", ) .add_test_lexer_diagnostics_codes(vec![]) .add_test_lexer_diagnostics_ranges(vec![]), ) .add_test_structure(DFRaw { header: "reaction_other".to_owned(), token_structure: vec![ObjectToken { reaction_tokens: vec![ ReactionToken { reference: Some(ReferenceTo::new("TAN_A_HIDE".to_owned())), name: Some("tan a hide".to_owned()), automatic: Some(()), building: vec![( ReferenceTo::new("TANNER".to_owned()), Choose::Choice1(KeyBindEnum::CustomT) )], skill: Some(SkillEnum::Tanner), reagents: vec![ReagentToken { reference: Some(( ReferenceTo::new("A".to_owned()), 1, Choose::Choice1((NoneEnum::None, NoneEnum::None)), Choose::Choice2((NoneEnum::None, NoneEnum::None)), )), has_material_reaction_product: Some(Reference("TAN_MAT".to_owned())), unrotten: Some(()), use_body_component: Some(()), ..Default::default() }], products: vec![ProductToken { reference: Some(( 100, 1, Choose::Choice1(( ItemReferenceArg { item_type: Reference("SKIN_TANNED".to_owned()), item_subtype: Choose::Choice1(NoSubtypeEnum::None), }, Choose::Choice2(GetMaterialFromReagentArg(( ReferenceTo::new("A".to_owned()), Choose::Choice2(ReferenceTo::new("TAN_MAT".to_owned())), ))), )), )), ..Default::default() }], ..Default::default() }, ReactionToken { reference: Some(ReferenceTo::new("RENDER_FAT".to_owned())), name: Some("render fat".to_owned()), automatic: Some(()), building: vec![( ReferenceTo::new("KITCHEN".to_owned()), Choose::Choice1(KeyBindEnum::HotkeyKitchenRenderFat) )], skill: Some(SkillEnum::Cook), reagents: vec![ReagentToken { reference: Some(( ReferenceTo::new("A".to_owned()), 150, Choose::Choice2(ItemReferenceArg { item_type: Reference("GLOB".to_owned()), item_subtype: Choose::Choice1(NoSubtypeEnum::None), }), Choose::Choice2((NoneEnum::None, NoneEnum::None)), )), has_material_reaction_product: Some(Reference("RENDER_MAT".to_owned())), reaction_class: Some(Reference("FAT".to_owned())), unrotten: Some(()), ..Default::default() }], products: vec![ProductToken { reference: Some(( 100, 1, Choose::Choice1(( ItemReferenceArg { item_type: Reference("GLOB".to_owned()), item_subtype: Choose::Choice1(NoSubtypeEnum::None), }, Choose::Choice2(GetMaterialFromReagentArg(( ReferenceTo::new("A".to_owned()), Choose::Choice2(ReferenceTo::new("RENDER_MAT".to_owned())), ))), )), )), ..Default::default() }], ..Default::default() }, ReactionToken { reference: Some(ReferenceTo::new("MAKE_SOAP_FROM_TALLOW".to_owned())), name: Some("make soap from tallow".to_owned()), building: vec![( ReferenceTo::new("SOAP_MAKER".to_owned()), Choose::Choice1(KeyBindEnum::CustomT) )], attribute_ip: Some(20), skill: Some(SkillEnum::SoapMaking), skill_ip: Some(40), skill_roll_range: Some((Clamp::new(11), 6)), reagents: vec![ ReagentToken { reference: Some(( ReferenceTo::new("LYE".to_owned()), 150, Choose::Choice2(ItemReferenceArg { item_type: Reference("LIQUID_MISC".to_owned()), item_subtype: Choose::Choice1(NoSubtypeEnum::None), }), Choose::Choice1(MaterialTokenArg { material: MaterialTypeEnum::Lye(None), }), )), ..Default::default() }, ReagentToken { reference: Some(( ReferenceTo::new("LYE_CONTAINER".to_owned()), 1, Choose::Choice1((NoneEnum::None, NoneEnum::None)), Choose::Choice2((NoneEnum::None, NoneEnum::None)), )), contains: Some(Reference("LYE".to_owned())), does_not_determine_product_amount: Some(()), preserve_reagent: Some(()), ..Default::default() }, ReagentToken { reference: Some(( ReferenceTo::new("TALLOW".to_owned()), 150, Choose::Choice2(ItemReferenceArg { item_type: Reference("GLOB".to_owned()), item_subtype: Choose::Choice1(NoSubtypeEnum::None), }), Choose::Choice2((NoneEnum::None, NoneEnum::None)), )), has_material_reaction_product: Some(Reference( "SOAP_MAT".to_owned() )), reaction_class: Some(Reference("TALLOW".to_owned())), unrotten: Some(()), ..Default::default() } ], products: vec![ProductToken { reference: Some(( 100, 1, Choose::Choice1(( ItemReferenceArg { item_type: Reference("BAR".to_owned()), item_subtype: Choose::Choice1(NoSubtypeEnum::None), }, Choose::Choice2(GetMaterialFromReagentArg(( ReferenceTo::new("TALLOW".to_owned()), Choose::Choice2(ReferenceTo::new("SOAP_MAT".to_owned())), ))), )), )), product_dimension: Some(150), ..Default::default() }], ..Default::default() }, ReactionToken { reference: Some(ReferenceTo::new("MAKE_SOAP_FROM_OIL".to_owned())), name: Some("make soap from oil".to_owned()), building: vec![( ReferenceTo::new("SOAP_MAKER".to_owned()), Choose::Choice1(KeyBindEnum::CustomO) )], skill: Some(SkillEnum::SoapMaking), reagents: vec![ ReagentToken { reference: Some(( ReferenceTo::new("LYE".to_owned()), 150, Choose::Choice2(ItemReferenceArg { item_type: Reference("LIQUID_MISC".to_owned()), item_subtype: Choose::Choice1(NoSubtypeEnum::None), }), Choose::Choice1(MaterialTokenArg { material: MaterialTypeEnum::Lye(None), }), )), ..Default::default() }, ReagentToken { reference: Some(( ReferenceTo::new("LYE_CONTAINER".to_owned()), 1, Choose::Choice1((NoneEnum::None, NoneEnum::None)), Choose::Choice2((NoneEnum::None, NoneEnum::None)), )), contains: Some(Reference("LYE".to_owned())), does_not_determine_product_amount: Some(()), preserve_reagent: Some(()), ..Default::default() }, ReagentToken { reference: Some(( ReferenceTo::new("OIL".to_owned()), 150, Choose::Choice2(ItemReferenceArg { item_type: Reference("LIQUID_MISC".to_owned()), item_subtype: Choose::Choice1(NoSubtypeEnum::None), }), Choose::Choice2((NoneEnum::None, NoneEnum::None)), )), has_material_reaction_product: Some(Reference( "SOAP_MAT".to_owned() )), unrotten: Some(()), ..Default::default() }, ReagentToken { reference: Some(( ReferenceTo::new("OIL_CONTAINER".to_owned()), 1, Choose::Choice1((NoneEnum::None, NoneEnum::None)), Choose::Choice2((NoneEnum::None, NoneEnum::None)), )), contains: Some(Reference("OIL".to_owned())), does_not_determine_product_amount: Some(()), preserve_reagent: Some(()), ..Default::default() }, ], products: vec![ProductToken { reference: Some(( 100, 1, Choose::Choice1(( ItemReferenceArg { item_type: Reference("BAR".to_owned()), item_subtype: Choose::Choice1(NoSubtypeEnum::None), }, Choose::Choice2(GetMaterialFromReagentArg(( ReferenceTo::new("OIL".to_owned()), Choose::Choice2(ReferenceTo::new("SOAP_MAT".to_owned())), ))), )), )), product_dimension: Some(150), ..Default::default() }], ..Default::default() }, ReactionToken { reference: Some(ReferenceTo::new("MAKE_PEARLASH".to_owned())), name: Some("make pearlash".to_owned()), building: vec![( ReferenceTo::new("KILN".to_owned()), Choose::Choice1(KeyBindEnum::CustomP) )], fuel: Some(()), skill: Some(SkillEnum::Smelt), reagents: vec![ReagentToken { reference: Some(( ReferenceTo::new("A".to_owned()), 150, Choose::Choice2(ItemReferenceArg { item_type: Reference("BAR".to_owned()), item_subtype: Choose::Choice1(NoSubtypeEnum::None), }), Choose::Choice1(MaterialTokenArg { material: MaterialTypeEnum::Potash(Some(NoneEnum::None)), }), )), ..Default::default() }], products: vec![ProductToken { reference: Some(( 100, 1, Choose::Choice1(( ItemReferenceArg { item_type: Reference("BAR".to_owned()), item_subtype: Choose::Choice1(NoSubtypeEnum::None), }, Choose::Choice1(MaterialTokenArg { material: MaterialTypeEnum::Pearlash(Some(NoneEnum::None)) }), )), )), product_dimension: Some(150), ..Default::default() }], ..Default::default() }, ReactionToken { reference: Some(ReferenceTo::new("PROCESS_PLANT_TO_BAG".to_owned())), name: Some("process plant to bag".to_owned()), building: vec![( ReferenceTo::new("FARMER".to_owned()), Choose::Choice1(KeyBindEnum::CustomB) )], skill: Some(SkillEnum::Processplants), reagents: vec![ ReagentToken { reference: Some(( ReferenceTo::new("PLANT".to_owned()), 1, Choose::Choice2(ItemReferenceArg { item_type: Reference("PLANT".to_owned()), item_subtype: Choose::Choice1(NoSubtypeEnum::None), }), Choose::Choice2((NoneEnum::None, NoneEnum::None)), )), has_material_reaction_product: Some(Reference( "BAG_ITEM".to_owned() )), unrotten: Some(()), ..Default::default() }, ReagentToken { reference: Some(( ReferenceTo::new("BAG".to_owned()), 1, Choose::Choice2(ItemReferenceArg { item_type: Reference("BOX".to_owned()), item_subtype: Choose::Choice1(NoSubtypeEnum::None), }), Choose::Choice2((NoneEnum::None, NoneEnum::None)), )), bag: Some(()), does_not_determine_product_amount: Some(()), empty: Some(()), preserve_reagent: Some(()), ..Default::default() } ], products: vec![ ProductToken { reference: Some(( 100, 5, Choose::Choice2(( GetItemDataFromReagentEnum::GetItemDataFromReagent, ReferenceTo::new("PLANT".to_owned()), Choose::Choice2(Reference("BAG_ITEM".to_owned())) )), )), product_to_container: Some(Reference("BAG".to_owned())), ..Default::default() }, ProductToken { reference: Some(( 100, 1, Choose::Choice1(( ItemReferenceArg { item_type: Reference("SEEDS".to_owned()), item_subtype: Choose::Choice1(NoSubtypeEnum::None), }, Choose::Choice2(GetMaterialFromReagentArg(( ReferenceTo::new("PLANT".to_owned()), Choose::Choice2(ReferenceTo::new("SEED_MAT".to_owned())), ))), )), )), ..Default::default() } ], ..Default::default() }, ReactionToken { reference: Some(ReferenceTo::new("TEST_DESCRIPTION".to_owned())), description: vec![ AllowEmpty::Some(Choose::Choice2( "Make sure multi-line, empty values, and USE_TOOL is accepted" .to_owned() )), AllowEmpty::None, AllowEmpty::Some(Choose::Choice1( ReactionDescriptionUseItemTokenArg::UseTool(ReferenceTo::new( "EXAMPLE_TOOL".to_owned() )) )), ], ..Default::default() }, ], ..Default::default() }], }) .add_test_syntax_diagnostics_codes(vec![]) .add_test_syntax_diagnostics_ranges(vec![]) .run_test(); }