diff --git a/Cargo.lock b/Cargo.lock index cc3a4bc..213acda 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -56,12 +56,6 @@ version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "330a5ed07fa54e4702c9d6c4174f74427fc0ef6e214bbd677ae50a5099946470" -[[package]] -name = "arrayref" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" - [[package]] name = "arrayvec" version = "0.7.8" @@ -98,9 +92,9 @@ checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" [[package]] name = "base64" -version = "0.22.1" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +checksum = "ac07cdecf99051d9a5238b80f35af32cdeba5b336e55d957b318b50137e18da5" [[package]] name = "bitflags" @@ -116,15 +110,15 @@ checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8" [[package]] name = "blake3" -version = "1.5.5" +version = "1.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8ee0c1824c4dea5b5f81736aff91bae041d2c07ee1192bec91054e10e3e601e" +checksum = "6d9e454fc11f76977dc803893aff6304ed33d6a26efae8696573bea74baa27ae" dependencies = [ - "arrayref", "arrayvec", "cc", "cfg-if", "constant_time_eq", + "cpufeatures", ] [[package]] @@ -202,18 +196,18 @@ dependencies = [ [[package]] name = "clap" -version = "4.6.5" +version = "4.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301b56658598e48f3648647ac6fc887be7e7108eddfa4e9b63fcf3ec58c0cadf" +checksum = "473c7e07f409a8d772161724aa8db6a765a2532a70f9667eeb7b49d3d02fbdca" dependencies = [ "clap_builder", ] [[package]] name = "clap_builder" -version = "4.6.5" +version = "4.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94a65403d1a1bd28f7dc68eb8506e8874808ee5eecb59298de588e2e1407a078" +checksum = "7b48fea5a88e9ae728a2dcbedbfc0e730f7d60da42e1cb049a83c9fb8b789889" dependencies = [ "anstyle", "clap_lex", @@ -242,9 +236,9 @@ checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" [[package]] name = "constant_time_eq" -version = "0.3.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" +checksum = "3d52eff69cd5e647efe296129160853a42795992097e8af39800e1060caeea9b" [[package]] name = "countme" @@ -252,6 +246,15 @@ version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7704b5fdd17b18ae31c4c1da5a2e0305a2bf17b5249300a9ee9ed7b72114c636" +[[package]] +name = "cpufeatures" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca28b0ae3115b884660db4118d803791fd6756b6e88f39c0f3f7859060d7566" +dependencies = [ + "libc", +] + [[package]] name = "crc32fast" version = "1.5.0" @@ -1155,9 +1158,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "serde" -version = "1.0.228" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba" dependencies = [ "serde_core", "serde_derive", @@ -1165,22 +1168,22 @@ dependencies = [ [[package]] name = "serde_core" -version = "1.0.228" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.228" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" dependencies = [ "proc-macro2", "quote", - "syn 2.0.118", + "syn 3.0.4", ] [[package]] @@ -1808,7 +1811,7 @@ dependencies = [ [[package]] name = "zerosyntax-analysis" -version = "1.3.1" +version = "1.3.2" dependencies = [ "criterion", "rowan", @@ -1820,7 +1823,7 @@ dependencies = [ [[package]] name = "zerosyntax-schema" -version = "1.3.1" +version = "1.3.2" dependencies = [ "serde", "serde_json", @@ -1828,7 +1831,7 @@ dependencies = [ [[package]] name = "zerosyntax-server" -version = "1.3.1" +version = "1.3.2" dependencies = [ "anyhow", "base64", @@ -1854,7 +1857,7 @@ dependencies = [ [[package]] name = "zerosyntax-syntax" -version = "1.3.1" +version = "1.3.2" dependencies = [ "criterion", "logos", @@ -1863,7 +1866,7 @@ dependencies = [ [[package]] name = "zerosyntax-w3d" -version = "1.3.1" +version = "1.3.2" dependencies = [ "glam", "image", diff --git a/Cargo.toml b/Cargo.toml index aa99fa6..d73ddf8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ resolver = "2" members = ["crates/schema", "crates/syntax", "crates/analysis", "crates/w3d", "crates/server"] [workspace.package] -version = "1.3.1" +version = "1.3.2" edition = "2021" license = "MIT" repository = "https://github.com/ViTeXFTW/ZeroSyntaxV2" @@ -33,7 +33,7 @@ tokio = { version = "1", features = ["full"] } ropey = "1" dashmap = "6" percent-encoding = "2" -base64 = "0.22" +base64 = "0.23" glam = "0.27" image = { version = "0.24.9", default-features = false, features = ["dds", "png", "tga"] } @@ -47,7 +47,7 @@ clap = { version = "4", default-features = false, features = [ ] } rusqlite = { version = "0.31", features = ["bundled"] } postcard = { version = "1.1", default-features = false, features = ["use-std"] } -blake3 = "=1.5.5" +blake3 = "=1.8.7" # benches criterion = "0.8" diff --git a/README.md b/README.md index 28dd129..e5273d4 100644 --- a/README.md +++ b/README.md @@ -1,110 +1,125 @@ -# ZeroSyntax v2 +
+
+
+
+
+` in this file** as a quick fix. A misspelled code produces an `unknown-suppression` hint.
+
+Available codes are:
+- Structure and definitions: `syntax`, `stray-field`, `unknown-block`,
+ `overrides`, `duplicate-definition`, `unknown-field`.
+- Values: `missing-condition`, `missing-value`, `bad-bool`, `non-positive`,
+ `bad-percent`, `bad-color`, `bad-coord`, `bad-number`, `bad-enum`, `bad-flag`,
+ `bad-prefixed`.
+- References and assets: `unresolved-reference`, `unknown-model`,
+ `unknown-model-member`, `unknown-audio-file`, `unknown-texture`.
+- Modules: `missing-module-tag`, `unknown-module`, `unknown-module-tag`,
+ `module-wrong-slot`, `duplicate-module-tag`, `editor-default-module`,
+ `default-modules-not-removed`.
+- Map checks: `map-forward-reference`, `map-projectile-object`,
+ `unreachable-set`.
+- Pragmas: `unknown-suppression`.
+
+
+
+## ⚠️ License & Notice
+ZeroSyntaxV2 is available under the [MIT License](./LICENSE)
+
+ZeroSyntaxV2 is an unofficial community project and is not affiliated with, endorsed by, or sponsored by Electronic Arts. Command & Conquer and related names are trademarks of their respective owners.
diff --git a/crates/analysis/src/completion.rs b/crates/analysis/src/completion.rs
index 2c3965b..6dfa969 100644
--- a/crates/analysis/src/completion.rs
+++ b/crates/analysis/src/completion.rs
@@ -6,14 +6,14 @@
//! * after `=` -> enum/bitflag members, `Yes`/`No`, module names, or (with the
//! workspace index) names of the referenced definition kind.
-use zerosyntax_schema::{AudioExtension, ValueType};
+use zerosyntax_schema::{AudioExtension, RefKind, ValueType};
use zerosyntax_syntax::ast::{Block, Field, Module};
use zerosyntax_syntax::{Parse, SyntaxKind, SyntaxNode};
use crate::index::AssetKind;
use crate::model::{
- is_model_asset_type, is_model_member_type, model_member_ini_name, models_for_source,
- scope_schema,
+ is_model_asset_type, is_model_member_type, model_member_mode, model_member_names,
+ models_for_source, scope_schema,
};
use crate::{Analyzer, WorkspaceIndex};
@@ -35,6 +35,8 @@ pub struct Completion {
pub label: String,
pub kind: CompletionKind,
pub detail: Option,
+ /// Optional Markdown shown by an LSP client alongside the selected item.
+ pub documentation: Option,
/// Optional LSP snippet string. When the client supports snippets, the
/// server uses this as `insertText` with `InsertTextFormat::SNIPPET`
/// instead of the plain `label`. `$0` marks the final cursor position;
@@ -52,9 +54,10 @@ pub fn complete(
file: Option<&str>,
) -> Vec {
let root = parse.syntax();
- let ctx = classify_position(analyzer, &root, offset);
+ let ctx = classify_position(analyzer, &root, offset, file);
match ctx {
PosContext::TopLevel => top_level_completions(analyzer),
+ PosContext::ObjectName => object_name_completions(index),
PosContext::FieldKey(scope_node) => field_key_completions(analyzer, &scope_node),
PosContext::FieldValue {
scope_node,
@@ -83,6 +86,11 @@ pub fn complete(
enum PosContext {
TopLevel,
+ /// Completing a top-level Object name in a map override layer. Existing
+ /// objects are useful override targets, but this is deliberately a
+ /// completion context rather than a Reference value: map files may also
+ /// introduce entirely new object names.
+ ObjectName,
/// Completing a field/slot keyword inside this scope node.
FieldKey(SyntaxNode),
/// Completing the value of `key` inside this scope node; `value_index` is
@@ -108,7 +116,12 @@ enum PosContext {
},
}
-fn classify_position(analyzer: &Analyzer, root: &SyntaxNode, offset: u32) -> PosContext {
+fn classify_position(
+ analyzer: &Analyzer,
+ root: &SyntaxNode,
+ offset: u32,
+ file: Option<&str>,
+) -> PosContext {
let off = rowan::TextSize::from(offset.min(root.text_range().end().into()));
let element = root.covering_element(rowan::TextRange::empty(off));
let node = match &element {
@@ -252,6 +265,9 @@ fn classify_position(analyzer: &Analyzer, root: &SyntaxNode, offset: u32) -> Pos
if offset <= u32::from(kw.text_range().end()) {
return PosContext::TopLevel;
}
+ if file.is_some_and(is_override_layer) && kw.text().eq_ignore_ascii_case("Object") {
+ return PosContext::ObjectName;
+ }
}
}
return PosContext::FieldKey(block_node);
@@ -261,6 +277,26 @@ fn classify_position(analyzer: &Analyzer, root: &SyntaxNode, offset: u32) -> Pos
PosContext::TopLevel
}
+fn is_override_layer(file: &str) -> bool {
+ file.rsplit(['/', '\\']).next().is_some_and(|name| {
+ name.eq_ignore_ascii_case("map.ini") || name.eq_ignore_ascii_case("solo.ini")
+ })
+}
+
+fn object_name_completions(index: Option<&WorkspaceIndex>) -> Vec {
+ index
+ .into_iter()
+ .flat_map(|idx| idx.override_target_names(RefKind::Object))
+ .map(|name| Completion {
+ label: name.to_string(),
+ kind: CompletionKind::Reference,
+ detail: Some("Object (override target)".into()),
+ documentation: None,
+ insert: None,
+ })
+ .collect()
+}
+
fn field_key_completions(analyzer: &Analyzer, scope_node: &SyntaxNode) -> Vec {
let scope = scope_schema(analyzer, scope_node);
let mut out: Vec = scope
@@ -270,6 +306,7 @@ fn field_key_completions(analyzer: &Analyzer, scope_node: &SyntaxNode) -> Vec Vec Vec, Option<&str>),
index: Option<&WorkspaceIndex>,
- source: Option<&zerosyntax_schema::ModelSource>,
+ field: Option<&Field>,
) -> Option> {
let index = index?;
if !index.has_model_assets() {
return None;
}
- let ty = token_value_type(ty, value_index);
+ let (value_index, current_token, first_token) = position;
+ let ty = field_schema
+ .value_type
+ .variant_for_first_token(first_token)?
+ .token_type_at(value_index)?;
+ let (ty, prefix) = match ty {
+ ValueType::Prefixed { prefix, value_type } => (value_type.as_ref(), Some(prefix)),
+ _ => (ty, None),
+ };
if is_model_asset_type(ty) {
return Some(
index
@@ -428,6 +486,7 @@ fn model_asset_completions(
label: name.to_string(),
kind: CompletionKind::W3dModel,
detail: Some("W3D model".into()),
+ documentation: None,
insert: None,
})
.collect(),
@@ -436,33 +495,52 @@ fn model_asset_completions(
if !is_model_member_type(ty) {
return None;
}
+ let mode = model_member_mode(field_schema.model_member_mode, field);
let mut seen = std::collections::HashSet::new();
- let out = models_for_source(analyzer, scope_node, source, index)
- .into_iter()
- .flat_map(|model| {
- index
- .model_members(&model)
- .map(|member| model_member_ini_name(member).to_string())
- .collect::>()
- })
- .filter(|member| seen.insert(member.to_ascii_lowercase()))
- .map(|member| Completion {
- label: member,
- kind: CompletionKind::Reference,
- detail: Some("W3D model member".into()),
- insert: None,
- })
- .collect();
+ let out = models_for_source(
+ analyzer,
+ scope_node,
+ field_schema.model_source.as_ref(),
+ index,
+ )
+ .into_iter()
+ .flat_map(|model| {
+ index
+ .model_members(&model)
+ .flat_map(|member| {
+ model_member_names(member, mode)
+ .into_iter()
+ .map(move |name| {
+ (
+ name.to_string(),
+ mode.is_some() && name != member.rsplit('.').next().unwrap_or(member),
+ )
+ })
+ })
+ .collect::>()
+ })
+ .filter(|(member, _)| seen.insert(member.to_ascii_lowercase()))
+ .map(|(member, family)| Completion {
+ insert: prefix
+ .filter(|prefix| {
+ !current_token
+ .and_then(|t| t.split_once(':'))
+ .is_some_and(|(actual, _)| actual.eq_ignore_ascii_case(prefix))
+ })
+ .map(|prefix| format!("{prefix}:{member}")),
+ detail: Some(if family {
+ "W3D numbered bone family (01, 02, ...)".into()
+ } else {
+ "W3D model member".into()
+ }),
+ label: member,
+ kind: CompletionKind::Reference,
+ documentation: None,
+ })
+ .collect();
Some(out)
}
-fn token_value_type(ty: &ValueType, value_index: usize) -> &ValueType {
- match ty {
- ValueType::TokenList { tokens } => tokens.get(value_index).unwrap_or(ty),
- _ => ty,
- }
-}
-
/// Build a single-token snippet placeholder for a value type, used when
/// generating a full-sequence snippet for TokenList or structured types.
/// `n` is the tab-stop index (1-based).
@@ -472,7 +550,7 @@ fn type_snippet_placeholder(ty: &ValueType, n: usize) -> String {
if prefix.eq_ignore_ascii_case("Bone")
&& matches!(
value_type.as_ref(),
- ValueType::AsciiString | ValueType::QuotedString
+ ValueType::AsciiString | ValueType::QuotedString | ValueType::W3dModelMember
)
{
format!("{prefix}:${{{n}:NONE}}")
@@ -624,6 +702,7 @@ fn completions_for_type(
label: "".into(),
kind: CompletionKind::Value,
detail: Some(format!("{} tokens", tokens.len())),
+ documentation: None,
insert: Some(snippet),
},
);
@@ -636,18 +715,21 @@ fn completions_for_type(
label: "R: G: B:".into(),
kind: CompletionKind::Value,
detail: Some("color".into()),
+ documentation: None,
insert: Some("R:${1:255} G:${2:255} B:${3:255}".into()),
}],
ValueType::Coord2D => vec![Completion {
label: "X: Y:".into(),
kind: CompletionKind::Value,
detail: Some("2D coordinate".into()),
+ documentation: None,
insert: Some("X:${1:0} Y:${2:0}".into()),
}],
ValueType::Coord3D => vec![Completion {
label: "X: Y: Z:".into(),
kind: CompletionKind::Value,
detail: Some("3D coordinate".into()),
+ documentation: None,
insert: Some("X:${1:0} Y:${2:0} Z:${3:0}".into()),
}],
ValueType::Bool => ["Yes", "No"]
@@ -656,6 +738,7 @@ fn completions_for_type(
label: v.to_string(),
kind: CompletionKind::Value,
detail: None,
+ documentation: None,
insert: None,
})
.collect(),
@@ -668,6 +751,7 @@ fn completions_for_type(
label: m.name.clone(),
kind: CompletionKind::EnumMember,
detail: Some(value_set.clone()),
+ documentation: None,
insert: None,
})
.collect()
@@ -681,6 +765,7 @@ fn completions_for_type(
label: n.to_string(),
kind: CompletionKind::Reference,
detail: Some(format!("{ref_kind:?}")),
+ documentation: None,
insert: None,
})
.collect()
@@ -692,6 +777,7 @@ fn completions_for_type(
label: n.to_string(),
kind: CompletionKind::Reference,
detail: Some(format!("{ref_kind:?} (engine builtin)")),
+ documentation: None,
insert: None,
}));
out
@@ -768,6 +854,7 @@ fn asset_completions(
label,
kind: CompletionKind::Reference,
detail: Some(detail.to_string()),
+ documentation: None,
insert: None,
})
.collect()
@@ -791,6 +878,7 @@ fn top_level_completions(analyzer: &Analyzer) -> Vec {
label: b.name.clone(),
kind: CompletionKind::Block,
detail: Some("block".into()),
+ documentation: None,
insert,
}
})
@@ -818,6 +906,7 @@ fn module_name_completions(
label: m.name.clone(),
kind: CompletionKind::Module,
detail: Some("module".into()),
+ documentation: None,
insert,
}
})
@@ -1032,6 +1121,73 @@ mod tests {
);
}
+ #[test]
+ fn map_object_header_suggests_existing_objects_without_requiring_one() {
+ let a = Analyzer::embedded();
+ let mut index = WorkspaceIndex::new();
+ let base = a.parse("Object AmericaVehicleHumvee\nEnd\n");
+ index.set_file(
+ "data/INI/Object.ini",
+ crate::index::definitions_in(&a, &base, "data/INI/Object.ini"),
+ );
+ let map_only = a.parse("Object MapOnlyObject\nEnd\n");
+ index.set_file(
+ "maps/other/map.ini",
+ crate::index::definitions_in(&a, &map_only, "maps/other/map.ini"),
+ );
+
+ // `NewMapObject` intentionally does not exist in the index: an Object
+ // header in map.ini may define a new template as well as override one.
+ let src = "Object NewMapObject\nEnd\n";
+ let offset = "Object New".len() as u32;
+ let out = complete(
+ &a,
+ &a.parse(src),
+ offset,
+ Some(&index),
+ Some("maps/map.ini"),
+ );
+ assert!(
+ out.iter().any(|item| item.label == "AmericaVehicleHumvee"),
+ "{out:?}"
+ );
+ assert!(
+ !out.iter().any(|item| item.label == "MapOnlyObject"),
+ "{out:?}"
+ );
+
+ let blank_header = "Object \nEnd\n";
+ let blank_out = complete(
+ &a,
+ &a.parse(blank_header),
+ "Object ".len() as u32,
+ Some(&index),
+ Some("maps/map.ini"),
+ );
+ assert!(
+ blank_out
+ .iter()
+ .any(|item| item.label == "AmericaVehicleHumvee"),
+ "{blank_out:?}"
+ );
+
+ // This is a completion-only affordance; typing a new name remains
+ // valid and produces no unknown-reference diagnostic.
+ assert!(crate::diagnostics::diagnose(
+ &a,
+ &a.parse(src),
+ Some(&index),
+ Some("maps/map.ini")
+ )
+ .iter()
+ .all(|diagnostic| diagnostic.code != "unresolved-reference"));
+
+ let non_map = complete(&a, &a.parse(src), offset, Some(&index), Some("Object.ini"));
+ assert!(!non_map
+ .iter()
+ .any(|item| item.label == "AmericaVehicleHumvee"));
+ }
+
#[test]
fn remove_module_completion_excludes_later_declarations() {
let a = Analyzer::embedded();
@@ -1045,6 +1201,25 @@ mod tests {
assert!(!out.iter().any(|item| item.label == "ModuleTag_Later"));
}
+ #[test]
+ fn remove_module_completion_documents_the_defining_module() {
+ let a = Analyzer::embedded();
+ let defs =
+ a.parse("Object Tank\n Behavior = PhysicsBehavior ModuleTag_Physics\n End\nEnd\n");
+ let mut index = WorkspaceIndex::new();
+ index.set_file_tags("base.ini", crate::index::module_tags_in(&a, &defs));
+ let src = "Object Tank\n RemoveModule \nEnd\n";
+ let offset = "Object Tank\n RemoveModule ".len() as u32;
+ let item = complete(&a, &a.parse(src), offset, Some(&index), Some("map.ini"))
+ .into_iter()
+ .find(|item| item.label == "ModuleTag_Physics")
+ .expect("module tag completion");
+ assert_eq!(
+ item.documentation.as_deref(),
+ Some("```ini\nBehavior = PhysicsBehavior ModuleTag_Physics\n```")
+ );
+ }
+
#[test]
fn enum_value_suggests_members() {
let src = "Weapon AK47\n DeathType = \nEnd\n";
diff --git a/crates/analysis/src/diagnostics.rs b/crates/analysis/src/diagnostics.rs
index b6e3a70..1566f6d 100644
--- a/crates/analysis/src/diagnostics.rs
+++ b/crates/analysis/src/diagnostics.rs
@@ -22,8 +22,8 @@ use zerosyntax_syntax::{Parse, SyntaxKind, SyntaxNode, SyntaxToken};
use crate::index::{AssetKind, ModelMemberStrictness};
use crate::model::{
- is_model_asset_type, is_model_member_type, model_member_matches, models_for_source,
- module_fits_slot, scope_schema, ScopeSchema,
+ is_model_asset_type, is_model_member_type, model_member_matches, model_member_mode,
+ models_for_source, module_fits_slot, scope_schema, ScopeSchema,
};
use crate::{Analyzer, Span, WorkspaceIndex};
@@ -1069,7 +1069,7 @@ impl<'a> Ctx<'a> {
Some(tag.text_range().start().into()),
)
.iter()
- .any(|known| known.eq_ignore_ascii_case(tag_name))
+ .any(|known| known.name.eq_ignore_ascii_case(tag_name))
{
self.error(
&tag,
@@ -1093,43 +1093,22 @@ impl<'a> Ctx<'a> {
return;
}
let tokens = field.value_tokens();
- match &schema_field.value_type {
- ValueType::W3dModelList => {
- for tok in &tokens {
- self.validate_model_asset_token(
- &schema_field.value_type,
- tok,
- scope_node,
- schema_field.model_source.as_ref(),
- );
- }
- }
- ValueType::TokenList { tokens: specs } => {
- let mut i = 0;
- for spec in specs {
- let Some(tok) = tokens.get(i) else { break };
- let (ty, tok, consumed) = split_prefixed_token(&tokens[i..], spec)
- .map(|(ty, tok)| (ty, tok, 2))
- .unwrap_or((spec, tok, 1));
- self.validate_model_asset_token(
- ty,
- tok,
- scope_node,
- schema_field.model_source.as_ref(),
- );
- i += consumed;
- }
- }
- ty => {
- if let Some(tok) = tokens.first() {
- let (ty, tok) = split_prefixed_token(&tokens, ty).unwrap_or((ty, tok));
- self.validate_model_asset_token(
- ty,
- tok,
- scope_node,
- schema_field.model_source.as_ref(),
- );
- }
+ let input = tokens.iter().map(|t| unquote(t.text())).collect::>();
+ let mode = model_member_mode(schema_field.model_member_mode, Some(field));
+ for (i, tok) in tokens.iter().enumerate() {
+ let ty = if matches!(schema_field.value_type, ValueType::W3dModelList) {
+ Some(&schema_field.value_type)
+ } else {
+ schema_field.value_type.token_type_at_input(&input, i)
+ };
+ if let Some(ty) = ty {
+ self.validate_model_asset_token(
+ ty,
+ tok,
+ scope_node,
+ schema_field.model_source.as_ref(),
+ mode,
+ );
}
}
}
@@ -1197,6 +1176,7 @@ impl<'a> Ctx<'a> {
tok: &SyntaxToken,
scope_node: &SyntaxNode,
source: Option<&zerosyntax_schema::ModelSource>,
+ mode: Option,
) {
let Some(index) = self.index else { return };
let raw = unquote(tok.text());
@@ -1244,7 +1224,7 @@ impl<'a> Ctx<'a> {
checked_any_model = true;
if index
.model_members(&model)
- .any(|member| model_member_matches(member, value))
+ .any(|member| model_member_matches(member, value, mode))
{
if index.model_member_strictness() == ModelMemberStrictness::Compatible {
return;
@@ -2560,6 +2540,7 @@ End
parse_fn: String::new(),
doc: None,
model_source: None,
+ model_member_mode: None,
};
for parser in eager {
field.parse_fn = parser.into();
diff --git a/crates/analysis/src/index.rs b/crates/analysis/src/index.rs
index d035d4a..298fd4d 100644
--- a/crates/analysis/src/index.rs
+++ b/crates/analysis/src/index.rs
@@ -64,6 +64,10 @@ pub struct ModuleTagDefinition {
pub object: String,
pub name: String,
pub span: Span,
+ /// The defining module header, shown when this tag is offered as a
+ /// RemoveModule completion.
+ #[serde(default)]
+ pub snippet: String,
#[serde(default)]
pub is_reference: bool,
}
@@ -86,6 +90,14 @@ struct NameEntry {
struct ModuleTagEntry {
name: String,
location: Location,
+ snippet: String,
+}
+
+/// A module tag that is valid at a `RemoveModule`/`ReplaceModule` site.
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub struct EffectiveModuleTag<'a> {
+ pub name: &'a str,
+ pub snippet: &'a str,
}
/// Workspace-wide symbol table, grouped by reference kind then name.
@@ -574,6 +586,7 @@ impl WorkspaceIndex {
.push(ModuleTagEntry {
name: tag.name,
location,
+ snippet: tag.snippet,
});
}
}
@@ -648,7 +661,7 @@ impl WorkspaceIndex {
name: &str,
file: Option<&str>,
before: Option,
- ) -> Vec<&'a str> {
+ ) -> Vec> {
let mut out = self
.object_tags
.get(&name.to_ascii_lowercase())
@@ -659,13 +672,25 @@ impl WorkspaceIndex {
tag.location.file == file && tag.location.span.start >= before
})
})
- .map(|tag| tag.name.as_str())
+ .map(|tag| EffectiveModuleTag {
+ name: tag.name.as_str(),
+ snippet: tag.snippet.as_str(),
+ })
.collect::>();
let is_new_override = file.is_some_and(|file| self.is_new_override_object(name, file));
if is_new_override {
- out.extend(self.module_tags_for_object("DefaultThingTemplate"));
+ out.extend(
+ self.object_tags
+ .get("defaultthingtemplate")
+ .into_iter()
+ .flatten()
+ .map(|tag| EffectiveModuleTag {
+ name: tag.name.as_str(),
+ snippet: tag.snippet.as_str(),
+ }),
+ );
let mut seen = std::collections::HashSet::new();
- out.retain(|tag| seen.insert(tag.to_ascii_lowercase()));
+ out.retain(|tag| seen.insert(tag.name.to_ascii_lowercase()));
}
out
}
@@ -782,6 +807,23 @@ impl WorkspaceIndex {
.flat_map(|n| n.values().map(|e| e.display.as_str()))
}
+ /// Names that have at least one definition outside a map/solo override
+ /// layer. These are valid targets for a map Object override; names that
+ /// exist solely in an override layer are new map-local templates instead.
+ pub fn override_target_names(&self, kind: RefKind) -> impl Iterator- {
+ self.by_kind
+ .get(&kind)
+ .into_iter()
+ .flat_map(|names| names.values())
+ .filter(|entry| {
+ entry
+ .locations
+ .iter()
+ .any(|loc| !is_override_layer(&loc.file))
+ })
+ .map(|entry| entry.display.as_str())
+ }
+
/// All reference sites for `name` of `kind` (case-insensitive).
pub fn reference_sites(&self, kind: RefKind, name: &str) -> &[Location] {
self.sites
@@ -1132,11 +1174,19 @@ pub fn module_tags_in(_analyzer: &Analyzer, parse: &Parse) -> Vec
{
+ format!("{} = {} {}", slot.text(), module_name.text(), tag.text())
+ }
+ _ => tag.text().to_string(),
+ };
out.push(ModuleTagDefinition {
object: name_lower.clone(),
name: tag.text().to_string(),
span: tag.text_range().into(),
+ snippet,
is_reference: false,
});
}
@@ -1153,6 +1203,7 @@ pub fn module_tags_in(_analyzer: &Analyzer, parse: &Parse) -> Vec bool {
}
pub(crate) fn model_member_ini_name(member: &str) -> &str {
+ let member = member.rsplit('.').next().unwrap_or(member);
let trimmed = member.trim_end_matches(|c: char| c.is_ascii_digit());
if trimmed.is_empty() {
member
@@ -160,8 +161,66 @@ pub(crate) fn model_member_ini_name(member: &str) -> &str {
}
}
-pub(crate) fn model_member_matches(member: &str, value: &str) -> bool {
- member.eq_ignore_ascii_case(value) || model_member_ini_name(member).eq_ignore_ascii_case(value)
+/// Resolve a contextual mode once, using the entire field (including tokens
+/// after the cursor). Colon-separated values may occupy one or two tokens.
+pub(crate) fn model_member_mode(
+ mode: Option,
+ field: Option<&AstField>,
+) -> Option {
+ use zerosyntax_schema::ModelMemberMode;
+ if mode != Some(ModelMemberMode::RandomBone) {
+ return mode;
+ }
+ let tokens = field.map(AstField::value_tokens).unwrap_or_default();
+ for (i, token) in tokens.iter().enumerate() {
+ let Some((key, value)) = token.text().split_once(':') else {
+ continue;
+ };
+ if !key.eq_ignore_ascii_case("RandomBone") {
+ continue;
+ }
+ let value = if value.is_empty() {
+ tokens.get(i + 1).map(|t| t.text()).unwrap_or("")
+ } else {
+ value
+ };
+ if value.eq_ignore_ascii_case("Yes") {
+ return Some(ModelMemberMode::Indexed);
+ }
+ if value.eq_ignore_ascii_case("No") {
+ return Some(ModelMemberMode::Exact);
+ }
+ }
+ // While the controlling value is incomplete, offer both legal forms.
+ Some(ModelMemberMode::ExactOrIndexed)
+}
+
+pub(crate) fn model_member_names(
+ member: &str,
+ mode: Option,
+) -> Vec<&str> {
+ use zerosyntax_schema::ModelMemberMode;
+ let short = member.rsplit('.').next().unwrap_or(member);
+ let base = short.strip_suffix("01").filter(|base| !base.is_empty());
+ match mode {
+ None => vec![model_member_ini_name(short)],
+ Some(ModelMemberMode::Exact) => vec![short],
+ Some(ModelMemberMode::Indexed) => base.into_iter().collect(),
+ Some(ModelMemberMode::ExactOrIndexed | ModelMemberMode::RandomBone) => {
+ std::iter::once(short).chain(base).collect()
+ }
+ }
+}
+
+pub(crate) fn model_member_matches(
+ member: &str,
+ value: &str,
+ mode: Option,
+) -> bool {
+ (mode.is_none() && member.eq_ignore_ascii_case(value))
+ || model_member_names(member, mode)
+ .iter()
+ .any(|name| name.eq_ignore_ascii_case(value))
}
/// Models referenced by W3D-model-typed fields visible from `scope_node`:
diff --git a/crates/analysis/tests/bone_names.rs b/crates/analysis/tests/bone_names.rs
new file mode 100644
index 0000000..aef1658
--- /dev/null
+++ b/crates/analysis/tests/bone_names.rs
@@ -0,0 +1,47 @@
+use zerosyntax_analysis::{completion::complete, index::ModelAsset, Analyzer, WorkspaceIndex};
+
+#[test]
+fn bone_completions_deduplicate_aliases_and_preserve_prefix_insertion() {
+ let analyzer = Analyzer::embedded();
+ let mut index = WorkspaceIndex::new();
+ index.set_file_models(
+ "good.w3d",
+ vec![ModelAsset {
+ name: "Good".into(),
+ members: vec![
+ "Good.Fire01".into(),
+ "Fire01".into(),
+ "FIRE01".into(),
+ "Fire02".into(),
+ ],
+ }],
+ );
+ for (value, expected_insert) in [
+ ("$", Some("Bone:Fire01")),
+ ("Bone:$", None),
+ ("Bone: $", None),
+ ("Bone: F$", None),
+ ("Bone:F$", None),
+ ] {
+ let marked = format!("Object Tank\n Draw = W3DModelDraw Tag\n DefaultConditionState\n Model = Good\n End\n End\n Behavior = TransitionDamageFX Damage\n DamagedParticleSystem1 = {value} RandomBone:No PSys:Smoke\n End\nEnd\n");
+ let offset = marked.find('$').unwrap();
+ let src = marked.replace('$', "");
+ let out = complete(
+ &analyzer,
+ &analyzer.parse(&src),
+ offset as u32,
+ Some(&index),
+ None,
+ );
+ let matches = out
+ .iter()
+ .filter(|item| item.label.eq_ignore_ascii_case("Fire01"))
+ .collect::>();
+ assert_eq!(matches.len(), 1, "{value}: {out:?}");
+ assert_eq!(matches[0].insert.as_deref(), expected_insert, "{value}");
+ assert!(
+ !out.iter().any(|item| item.label.contains("Good.")),
+ "{value}: {out:?}"
+ );
+ }
+}
diff --git a/crates/analysis/tests/spec.rs b/crates/analysis/tests/spec.rs
index 385e9af..317278d 100644
--- a/crates/analysis/tests/spec.rs
+++ b/crates/analysis/tests/spec.rs
@@ -63,6 +63,14 @@ struct Spec {
audio_assets: Vec,
#[serde(default)]
texture_assets: Vec,
+ #[serde(default)]
+ model_assets: Vec,
+}
+
+#[derive(Deserialize)]
+struct ModelSpec {
+ name: String,
+ members: Vec,
}
#[derive(Deserialize)]
@@ -400,6 +408,16 @@ fn specs_hold() {
let mut index = WorkspaceIndex::new();
index.set_file(&name, definitions_in(&analyzer, &parse, &name));
index.set_file_tags(&name, module_tags_in(&analyzer, &parse));
+ index.set_file_models(
+ "spec-models",
+ spec.model_assets
+ .iter()
+ .map(|model| zerosyntax_analysis::index::ModelAsset {
+ name: model.name.clone(),
+ members: model.members.clone(),
+ })
+ .collect(),
+ );
index.set_file_assets(
"spec-assets",
spec.audio_assets
diff --git a/crates/analysis/tests/spec/BoneNames.ini b/crates/analysis/tests/spec/BoneNames.ini
new file mode 100644
index 0000000..43ce254
--- /dev/null
+++ b/crates/analysis/tests/spec/BoneNames.ini
@@ -0,0 +1,24 @@
+ParticleSystem Smoke
+End
+Object Tank
+ Draw = W3DModelDraw Tag
+ DefaultConditionState
+ Model = Good
+ ParticleSysBone = $1Fire01 Smoke
+ ParticleSysBone = Fire Smoke
+ WeaponFireFXBone = PRIMARY $2Fire
+ WeaponRecoilBone = SECONDARY Fire02
+ ParticleSysBone = fire02 Smoke
+ End
+ End
+ Behavior = TransitionDamageFX DamageTag
+ DamagedParticleSystem1 = Bone:$3Fire01 RandomBone:No PSys:Smoke
+ DamagedParticleSystem2 = Bone: $4Fire RandomBone: Yes PSys:Smoke
+ DamagedParticleSystem3 = Bone:Fire RandomBone:No PSys:Smoke
+ DamagedParticleSystem4 = Bone:Solo RandomBone:Yes PSys:Smoke
+ End
+ Behavior = BoneFXUpdate BoneTag
+ DamagedParticleSystem1 = Bone:$5Fire02 OnlyOnce:No 0 0 PSys:Smoke
+ DamagedParticleSystem2 = Bone: Fire OnlyOnce:No 0 0 PSys:Smoke
+ End
+End
diff --git a/crates/analysis/tests/spec/BoneNames.spec.toml b/crates/analysis/tests/spec/BoneNames.spec.toml
new file mode 100644
index 0000000..5ca9733
--- /dev/null
+++ b/crates/analysis/tests/spec/BoneNames.spec.toml
@@ -0,0 +1,90 @@
+no_errors = true
+
+[[model_assets]]
+name = "Good"
+members = ["Fire01", "Fire02", "Good.Fire01", "Good.Fire02", "Fire1", "Solo"]
+
+[[complete]]
+at = "$1"
+includes = ["Fire01", "Fire02", "Fire1", "Solo"]
+excludes = ["Fire", "Good.Fire01", "Good.Fire"]
+
+[[complete]]
+at = "$2"
+includes = ["Fire", "Fire01", "Fire02", "Solo"]
+excludes = ["Good.Fire", "Good.Fire01"]
+
+[[complete]]
+at = "$3"
+includes = ["Fire01", "Fire02"]
+excludes = ["Fire", "Good.Fire01"]
+
+[[complete]]
+at = "$4"
+includes = ["Fire"]
+excludes = ["Fire01", "Fire02", "Solo", "Good.Fire"]
+
+[[diag]]
+severity = "warning"
+code = "unknown-model-member"
+on = "Fire"
+nth = 1
+
+[[diag]]
+severity = "warning"
+code = "unknown-model-member"
+on = "Bone:Fire"
+
+[[complete]]
+at = "$5"
+includes = ["Fire01", "Fire02"]
+excludes = ["Fire", "Good.Fire01"]
+
+[[diag]]
+severity = "warning"
+code = "unknown-model-member"
+on = "Fire01"
+absent = true
+
+[[diag]]
+severity = "warning"
+code = "unknown-model-member"
+on = "Fire"
+nth = 2
+absent = true
+
+[[diag]]
+severity = "warning"
+code = "unknown-model-member"
+on = "Fire02"
+absent = true
+
+[[diag]]
+severity = "warning"
+code = "unknown-model-member"
+on = "fire02"
+absent = true
+
+[[diag]]
+severity = "warning"
+code = "unknown-model-member"
+on = "Bone:Fire01"
+absent = true
+
+[[diag]]
+severity = "warning"
+code = "unknown-model-member"
+on = "Fire"
+nth = 3
+absent = true
+
+[[diag]]
+severity = "warning"
+code = "unknown-model-member"
+on = "Bone:Solo"
+
+[[diag]]
+severity = "warning"
+code = "unknown-model-member"
+on = "Fire"
+nth = 4
diff --git a/crates/schema/schema.json b/crates/schema/schema.json
index 29c8c19..07e0e01 100644
--- a/crates/schema/schema.json
+++ b/crates/schema/schema.json
@@ -18562,6 +18562,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -18579,6 +18580,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -18596,6 +18598,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -18613,6 +18616,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -18630,6 +18634,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -18697,6 +18702,7 @@
]
},
"parse_fn": "parseParticleSysBone",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -18827,6 +18833,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -18844,6 +18851,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -18861,6 +18869,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -18878,6 +18887,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -18895,6 +18905,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -18962,6 +18973,7 @@
]
},
"parse_fn": "parseParticleSysBone",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -19095,6 +19107,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -19112,6 +19125,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -19129,6 +19143,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -19146,6 +19161,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -19163,6 +19179,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -19230,6 +19247,7 @@
]
},
"parse_fn": "parseParticleSysBone",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -21267,6 +21285,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseFXList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -21305,6 +21324,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseFXList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -21343,6 +21363,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseFXList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -21381,6 +21402,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseFXList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -21419,6 +21441,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseFXList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -21457,6 +21480,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseFXList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -21495,6 +21519,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseFXList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -21533,6 +21558,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseFXList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -21571,6 +21597,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseFXList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -21609,6 +21636,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseFXList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -21647,6 +21675,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseFXList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -21685,6 +21714,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseFXList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -21723,6 +21753,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseFXList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -21761,6 +21792,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseFXList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -21799,6 +21831,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseFXList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -21837,6 +21870,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseFXList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -21875,6 +21909,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseFXList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -21913,6 +21948,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseFXList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -21951,6 +21987,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseFXList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -21989,6 +22026,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseFXList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -22027,6 +22065,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseFXList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -22065,6 +22104,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseFXList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -22103,6 +22143,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseFXList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -22141,6 +22182,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseFXList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -22179,6 +22221,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseFXList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -22217,6 +22260,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseFXList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -22255,6 +22299,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseFXList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -22293,6 +22338,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseFXList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -22331,6 +22377,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseFXList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -22369,6 +22416,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseFXList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -22407,6 +22455,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseFXList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -22445,6 +22494,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseFXList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -22483,6 +22533,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseObjectCreationList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -22521,6 +22572,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseObjectCreationList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -22559,6 +22611,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseObjectCreationList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -22597,6 +22650,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseObjectCreationList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -22635,6 +22689,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseObjectCreationList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -22673,6 +22728,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseObjectCreationList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -22711,6 +22767,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseObjectCreationList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -22749,6 +22806,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseObjectCreationList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -22787,6 +22845,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseObjectCreationList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -22825,6 +22884,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseObjectCreationList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -22863,6 +22923,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseObjectCreationList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -22901,6 +22962,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseObjectCreationList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -22939,6 +23001,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseObjectCreationList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -22977,6 +23040,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseObjectCreationList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -23015,6 +23079,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseObjectCreationList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -23053,6 +23118,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseObjectCreationList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -23091,6 +23157,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseObjectCreationList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -23129,6 +23196,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseObjectCreationList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -23167,6 +23235,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseObjectCreationList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -23205,6 +23274,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseObjectCreationList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -23243,6 +23313,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseObjectCreationList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -23281,6 +23352,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseObjectCreationList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -23319,6 +23391,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseObjectCreationList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -23357,6 +23430,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseObjectCreationList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -23395,6 +23469,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseObjectCreationList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -23433,6 +23508,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseObjectCreationList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -23471,6 +23547,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseObjectCreationList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -23509,6 +23586,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseObjectCreationList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -23547,6 +23625,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseObjectCreationList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -23585,6 +23664,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseObjectCreationList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -23623,6 +23703,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseObjectCreationList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -23661,6 +23742,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseObjectCreationList",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -23699,6 +23781,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseParticleSystem",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -23737,6 +23820,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseParticleSystem",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -23775,6 +23859,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseParticleSystem",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -23813,6 +23898,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseParticleSystem",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -23851,6 +23937,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseParticleSystem",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -23889,6 +23976,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseParticleSystem",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -23927,6 +24015,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseParticleSystem",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -23965,6 +24054,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseParticleSystem",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -24003,6 +24093,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseParticleSystem",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -24041,6 +24132,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseParticleSystem",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -24079,6 +24171,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseParticleSystem",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -24117,6 +24210,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseParticleSystem",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -24155,6 +24249,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseParticleSystem",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -24193,6 +24288,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseParticleSystem",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -24231,6 +24327,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseParticleSystem",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -24269,6 +24366,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseParticleSystem",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -24307,6 +24405,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseParticleSystem",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -24345,6 +24444,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseParticleSystem",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -24383,6 +24483,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseParticleSystem",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -24421,6 +24522,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseParticleSystem",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -24459,6 +24561,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseParticleSystem",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -24497,6 +24600,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseParticleSystem",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -24535,6 +24639,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseParticleSystem",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -24573,6 +24678,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseParticleSystem",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -24611,6 +24717,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseParticleSystem",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -24649,6 +24756,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseParticleSystem",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -24687,6 +24795,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseParticleSystem",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -24725,6 +24834,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseParticleSystem",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -24763,6 +24873,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseParticleSystem",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -24801,6 +24912,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseParticleSystem",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -24839,6 +24951,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseParticleSystem",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -24877,6 +24990,7 @@
]
},
"parse_fn": "BoneFXUpdateModuleData::parseParticleSystem",
+ "model_member_mode": "exact",
"doc": null
}
],
@@ -46239,7 +46353,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -46296,6 +46410,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseFXList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -46310,7 +46425,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -46367,6 +46482,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseFXList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -46381,7 +46497,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -46438,6 +46554,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseFXList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -46452,7 +46569,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -46509,6 +46626,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseFXList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -46523,7 +46641,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -46580,6 +46698,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseFXList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -46594,7 +46713,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -46651,6 +46770,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseFXList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -46665,7 +46785,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -46722,6 +46842,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseFXList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -46736,7 +46857,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -46793,6 +46914,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseFXList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -46807,7 +46929,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -46864,6 +46986,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseFXList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -46878,7 +47001,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -46935,6 +47058,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseFXList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -46949,7 +47073,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -47006,6 +47130,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseFXList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -47020,7 +47145,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -47077,6 +47202,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseFXList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -47091,7 +47217,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -47148,6 +47274,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseFXList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -47162,7 +47289,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -47219,6 +47346,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseFXList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -47233,7 +47361,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -47290,6 +47418,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseFXList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -47304,7 +47433,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -47361,6 +47490,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseFXList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -47375,7 +47505,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -47432,6 +47562,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseFXList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -47446,7 +47577,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -47503,6 +47634,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseFXList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -47517,7 +47649,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -47574,6 +47706,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseFXList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -47588,7 +47721,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -47645,6 +47778,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseFXList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -47659,7 +47793,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -47716,6 +47850,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseFXList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -47730,7 +47865,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -47787,6 +47922,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseFXList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -47801,7 +47937,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -47858,6 +47994,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseFXList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -47872,7 +48009,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -47929,6 +48066,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseFXList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -47943,7 +48081,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -48000,6 +48138,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseFXList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -48014,7 +48153,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -48071,6 +48210,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseFXList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -48085,7 +48225,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -48142,6 +48282,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseFXList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -48156,7 +48297,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -48213,6 +48354,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseFXList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -48227,7 +48369,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -48284,6 +48426,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseFXList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -48298,7 +48441,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -48355,6 +48498,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseFXList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -48369,7 +48513,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -48426,6 +48570,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseFXList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -48440,7 +48585,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -48497,6 +48642,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseFXList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -48511,7 +48657,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -48568,6 +48714,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseFXList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -48582,7 +48729,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -48639,6 +48786,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseFXList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -48653,7 +48801,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -48710,6 +48858,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseFXList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -48724,7 +48873,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -48781,6 +48930,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseFXList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -48795,7 +48945,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -48852,6 +49002,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseObjectCreationList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -48866,7 +49017,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -48923,6 +49074,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseObjectCreationList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -48937,7 +49089,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -48994,6 +49146,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseObjectCreationList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -49008,7 +49161,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -49065,6 +49218,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseObjectCreationList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -49079,7 +49233,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -49136,6 +49290,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseObjectCreationList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -49150,7 +49305,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -49207,6 +49362,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseObjectCreationList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -49221,7 +49377,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -49278,6 +49434,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseObjectCreationList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -49292,7 +49449,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -49349,6 +49506,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseObjectCreationList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -49363,7 +49521,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -49420,6 +49578,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseObjectCreationList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -49434,7 +49593,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -49491,6 +49650,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseObjectCreationList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -49505,7 +49665,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -49562,6 +49722,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseObjectCreationList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -49576,7 +49737,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -49633,6 +49794,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseObjectCreationList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -49647,7 +49809,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -49704,6 +49866,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseObjectCreationList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -49718,7 +49881,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -49775,6 +49938,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseObjectCreationList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -49789,7 +49953,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -49846,6 +50010,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseObjectCreationList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -49860,7 +50025,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -49917,6 +50082,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseObjectCreationList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -49931,7 +50097,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -49988,6 +50154,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseObjectCreationList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -50002,7 +50169,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -50059,6 +50226,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseObjectCreationList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -50073,7 +50241,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -50130,6 +50298,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseObjectCreationList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -50144,7 +50313,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -50201,6 +50370,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseObjectCreationList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -50215,7 +50385,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -50272,6 +50442,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseObjectCreationList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -50286,7 +50457,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -50343,6 +50514,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseObjectCreationList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -50357,7 +50529,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -50414,6 +50586,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseObjectCreationList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -50428,7 +50601,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -50485,6 +50658,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseObjectCreationList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -50499,7 +50673,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -50556,6 +50730,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseObjectCreationList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -50570,7 +50745,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -50627,6 +50802,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseObjectCreationList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -50641,7 +50817,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -50698,6 +50874,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseObjectCreationList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -50712,7 +50889,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -50769,6 +50946,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseObjectCreationList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -50783,7 +50961,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -50840,6 +51018,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseObjectCreationList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -50854,7 +51033,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -50911,6 +51090,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseObjectCreationList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -50925,7 +51105,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -50982,6 +51162,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseObjectCreationList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -50996,7 +51177,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -51053,6 +51234,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseObjectCreationList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -51067,7 +51249,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -51124,6 +51306,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseObjectCreationList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -51138,7 +51321,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -51195,6 +51378,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseObjectCreationList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -51209,7 +51393,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -51266,6 +51450,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseObjectCreationList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -51280,7 +51465,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -51337,6 +51522,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseObjectCreationList",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -51351,7 +51537,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -51408,6 +51594,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseParticleSystem",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -51422,7 +51609,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -51479,6 +51666,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseParticleSystem",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -51493,7 +51681,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -51550,6 +51738,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseParticleSystem",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -51564,7 +51753,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -51621,6 +51810,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseParticleSystem",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -51635,7 +51825,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -51692,6 +51882,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseParticleSystem",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -51706,7 +51897,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -51763,6 +51954,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseParticleSystem",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -51777,7 +51969,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -51834,6 +52026,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseParticleSystem",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -51848,7 +52041,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -51905,6 +52098,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseParticleSystem",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -51919,7 +52113,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -51976,6 +52170,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseParticleSystem",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -51990,7 +52185,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -52047,6 +52242,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseParticleSystem",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -52061,7 +52257,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -52118,6 +52314,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseParticleSystem",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -52132,7 +52329,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -52189,6 +52386,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseParticleSystem",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -52203,7 +52401,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -52260,6 +52458,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseParticleSystem",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -52274,7 +52473,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -52331,6 +52530,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseParticleSystem",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -52345,7 +52545,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -52402,6 +52602,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseParticleSystem",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -52416,7 +52617,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -52473,6 +52674,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseParticleSystem",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -52487,7 +52689,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -52544,6 +52746,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseParticleSystem",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -52558,7 +52761,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -52615,6 +52818,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseParticleSystem",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -52629,7 +52833,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -52686,6 +52890,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseParticleSystem",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -52700,7 +52905,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -52757,6 +52962,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseParticleSystem",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -52771,7 +52977,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -52828,6 +53034,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseParticleSystem",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -52842,7 +53049,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -52899,6 +53106,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseParticleSystem",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -52913,7 +53121,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -52970,6 +53178,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseParticleSystem",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -52984,7 +53193,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -53041,6 +53250,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseParticleSystem",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -53055,7 +53265,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -53112,6 +53322,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseParticleSystem",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -53126,7 +53337,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -53183,6 +53394,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseParticleSystem",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -53197,7 +53409,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -53254,6 +53466,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseParticleSystem",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -53268,7 +53481,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -53325,6 +53538,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseParticleSystem",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -53339,7 +53553,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -53396,6 +53610,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseParticleSystem",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -53410,7 +53625,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -53467,6 +53682,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseParticleSystem",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -53481,7 +53697,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -53538,6 +53754,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseParticleSystem",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -53552,7 +53769,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -53609,6 +53826,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseParticleSystem",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -53623,7 +53841,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -53680,6 +53898,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseParticleSystem",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -53694,7 +53913,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -53751,6 +53970,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseParticleSystem",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -53765,7 +53985,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -53822,6 +54042,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseParticleSystem",
+ "model_member_mode": "random_bone",
"doc": null
},
{
@@ -53836,7 +54057,7 @@
"kind": "prefixed",
"prefix": "Bone",
"value_type": {
- "kind": "ascii_string"
+ "kind": "w3d_model_member"
}
},
{
@@ -53893,6 +54114,7 @@
]
},
"parse_fn": "TransitionDamageFXModuleData::parseParticleSystem",
+ "model_member_mode": "random_bone",
"doc": null
}
],
@@ -55507,6 +55729,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -55524,6 +55747,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -55541,6 +55765,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -55558,6 +55783,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -55575,6 +55801,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -55642,6 +55869,7 @@
]
},
"parse_fn": "parseParticleSysBone",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -55772,6 +56000,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -55789,6 +56018,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -55806,6 +56036,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -55823,6 +56054,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -55840,6 +56072,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -55907,6 +56140,7 @@
]
},
"parse_fn": "parseParticleSysBone",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -56040,6 +56274,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -56057,6 +56292,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -56074,6 +56310,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -56091,6 +56328,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -56108,6 +56346,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -56175,6 +56414,7 @@
]
},
"parse_fn": "parseParticleSysBone",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -56562,6 +56802,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -56579,6 +56820,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -56596,6 +56838,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -56613,6 +56856,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -56630,6 +56874,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -56697,6 +56942,7 @@
]
},
"parse_fn": "parseParticleSysBone",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -56827,6 +57073,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -56844,6 +57091,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -56861,6 +57109,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -56878,6 +57127,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -56895,6 +57145,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -56962,6 +57213,7 @@
]
},
"parse_fn": "parseParticleSysBone",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -57095,6 +57347,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -57112,6 +57365,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -57129,6 +57383,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -57146,6 +57401,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -57163,6 +57419,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -57230,6 +57487,7 @@
]
},
"parse_fn": "parseParticleSysBone",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -57537,6 +57795,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -57554,6 +57813,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -57571,6 +57831,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -57588,6 +57849,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -57605,6 +57867,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -57672,6 +57935,7 @@
]
},
"parse_fn": "parseParticleSysBone",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -57802,6 +58066,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -57819,6 +58084,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -57836,6 +58102,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -57853,6 +58120,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -57870,6 +58138,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -57937,6 +58206,7 @@
]
},
"parse_fn": "parseParticleSysBone",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -58070,6 +58340,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -58087,6 +58358,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -58104,6 +58376,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -58121,6 +58394,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -58138,6 +58412,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -58205,6 +58480,7 @@
]
},
"parse_fn": "parseParticleSysBone",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -58633,6 +58909,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -58650,6 +58927,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -58667,6 +58945,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -58684,6 +58963,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -58701,6 +58981,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -58768,6 +59049,7 @@
]
},
"parse_fn": "parseParticleSysBone",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -58898,6 +59180,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -58915,6 +59198,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -58932,6 +59216,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -58949,6 +59234,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -58966,6 +59252,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -59033,6 +59320,7 @@
]
},
"parse_fn": "parseParticleSysBone",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -59166,6 +59454,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -59183,6 +59472,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -59200,6 +59490,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -59217,6 +59508,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -59234,6 +59526,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -59301,6 +59594,7 @@
]
},
"parse_fn": "parseParticleSysBone",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -59729,6 +60023,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -59746,6 +60041,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -59763,6 +60059,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -59780,6 +60077,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -59797,6 +60095,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -59864,6 +60163,7 @@
]
},
"parse_fn": "parseParticleSysBone",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -59994,6 +60294,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -60011,6 +60312,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -60028,6 +60330,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -60045,6 +60348,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -60062,6 +60366,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -60129,6 +60434,7 @@
]
},
"parse_fn": "parseParticleSysBone",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -60262,6 +60568,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -60279,6 +60586,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -60296,6 +60604,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -60313,6 +60622,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -60330,6 +60640,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -60397,6 +60708,7 @@
]
},
"parse_fn": "parseParticleSysBone",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -60748,6 +61060,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -60765,6 +61078,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -60782,6 +61096,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -60799,6 +61114,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -60816,6 +61132,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -60883,6 +61200,7 @@
]
},
"parse_fn": "parseParticleSysBone",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -61013,6 +61331,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -61030,6 +61349,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -61047,6 +61367,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -61064,6 +61385,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -61081,6 +61403,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -61148,6 +61471,7 @@
]
},
"parse_fn": "parseParticleSysBone",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -61281,6 +61605,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -61298,6 +61623,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -61315,6 +61641,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -61332,6 +61659,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -61349,6 +61677,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -61416,6 +61745,7 @@
]
},
"parse_fn": "parseParticleSysBone",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -61689,6 +62019,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -61706,6 +62037,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -61723,6 +62055,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -61740,6 +62073,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -61757,6 +62091,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -61824,6 +62159,7 @@
]
},
"parse_fn": "parseParticleSysBone",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -61954,6 +62290,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -61971,6 +62308,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -61988,6 +62326,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -62005,6 +62344,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -62022,6 +62362,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -62089,6 +62430,7 @@
]
},
"parse_fn": "parseParticleSysBone",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -62222,6 +62564,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -62239,6 +62582,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -62256,6 +62600,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -62273,6 +62618,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -62290,6 +62636,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -62357,6 +62704,7 @@
]
},
"parse_fn": "parseParticleSysBone",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -62664,6 +63012,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -62681,6 +63030,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -62698,6 +63048,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -62715,6 +63066,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -62732,6 +63084,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -62799,6 +63152,7 @@
]
},
"parse_fn": "parseParticleSysBone",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -62929,6 +63283,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -62946,6 +63301,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -62963,6 +63319,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -62980,6 +63337,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -62997,6 +63355,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -63064,6 +63423,7 @@
]
},
"parse_fn": "parseParticleSysBone",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -63197,6 +63557,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -63214,6 +63575,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -63231,6 +63593,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -63248,6 +63611,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -63265,6 +63629,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -63332,6 +63697,7 @@
]
},
"parse_fn": "parseParticleSysBone",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -63746,6 +64112,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -63763,6 +64130,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -63780,6 +64148,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -63797,6 +64166,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -63814,6 +64184,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -63881,6 +64252,7 @@
]
},
"parse_fn": "parseParticleSysBone",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -64011,6 +64383,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -64028,6 +64401,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -64045,6 +64419,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -64062,6 +64437,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -64079,6 +64455,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -64146,6 +64523,7 @@
]
},
"parse_fn": "parseParticleSysBone",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -64279,6 +64657,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -64296,6 +64675,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -64313,6 +64693,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -64330,6 +64711,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -64347,6 +64729,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -64414,6 +64797,7 @@
]
},
"parse_fn": "parseParticleSysBone",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -65007,6 +65391,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -65024,6 +65409,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -65041,6 +65427,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -65058,6 +65445,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -65075,6 +65463,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -65142,6 +65531,7 @@
]
},
"parse_fn": "parseParticleSysBone",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -65272,6 +65662,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -65289,6 +65680,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -65306,6 +65698,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -65323,6 +65716,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -65340,6 +65734,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -65407,6 +65802,7 @@
]
},
"parse_fn": "parseParticleSysBone",
+ "model_member_mode": "exact",
"doc": null
},
{
@@ -65540,6 +65936,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -65557,6 +65954,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -65574,6 +65972,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -65591,6 +65990,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -65608,6 +66008,7 @@
]
},
"parse_fn": "parseWeaponBoneName",
+ "model_member_mode": "exact_or_indexed",
"doc": null
},
{
@@ -65675,6 +66076,7 @@
]
},
"parse_fn": "parseParticleSysBone",
+ "model_member_mode": "exact",
"doc": null
},
{
diff --git a/crates/schema/src/lib.rs b/crates/schema/src/lib.rs
index 76686c1..cf85d13 100644
--- a/crates/schema/src/lib.rs
+++ b/crates/schema/src/lib.rs
@@ -159,6 +159,22 @@ pub struct Field {
pub doc: Option,
#[serde(default)]
pub model_source: Option,
+ /// Engine lookup semantics for the model-member token in this field.
+ /// Omitted for fields whose lookup has not yet been audited.
+ #[serde(default, skip_serializing_if = "Option::is_none")]
+ pub model_member_mode: Option,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
+#[serde(rename_all = "snake_case")]
+pub enum ModelMemberMode {
+ Exact,
+ /// Enumerates base01, base02, ... starting at 01.
+ Indexed,
+ /// Enumerates numbered bones, with an unadorned-name fallback.
+ ExactOrIndexed,
+ /// TransitionDamageFX: selected by the field's RandomBone:Yes/No value.
+ RandomBone,
}
/// Selects the Object whose W3D models own a model-member field.
@@ -529,6 +545,7 @@ mod tests {
parse_fn: "parseReal".into(),
doc: None,
model_source: None,
+ model_member_mode: None,
}],
module_slots: vec![],
sub_blocks: vec![],
@@ -1435,7 +1452,7 @@ mod tests {
&ValueType::OneOf {
variants: vec![
token_list(vec![
- prefixed("Bone", ValueType::AsciiString),
+ prefixed("Bone", ValueType::W3dModelMember),
prefixed("RandomBone", ValueType::Bool),
prefixed(prefix, reference(ref_kind)),
]),
diff --git a/crates/server/src/cache.rs b/crates/server/src/cache.rs
index 7ac239b..e5f35fa 100644
--- a/crates/server/src/cache.rs
+++ b/crates/server/src/cache.rs
@@ -17,7 +17,7 @@ const STORE_FILE: &str = "index-v1.sqlite3";
const STORE_VERSION: i64 = 1;
/// Bump when `CachedEntry` serialization or any extractor feeding it changes.
/// SQL layout changes instead bump `STORE_VERSION` and the store filename.
-const PRODUCER_ABI: &[u8] = b"zerosyntax-physical-input-v2";
+const PRODUCER_ABI: &[u8] = b"zerosyntax-physical-input-v3";
const BUSY_TIMEOUT: Duration = Duration::from_secs(2);
const TOUCH_INTERVAL_SECS: i64 = 24 * 60 * 60;
const MAX_AGE_SECS: i64 = 30 * 24 * 60 * 60;
diff --git a/crates/server/src/convert.rs b/crates/server/src/convert.rs
index b3cd75d..e5ae144 100644
--- a/crates/server/src/convert.rs
+++ b/crates/server/src/convert.rs
@@ -177,6 +177,12 @@ pub fn to_lsp_completion(c: Completion, snippets_supported: bool) -> CompletionI
"model": c.label,
})
});
+ let documentation = c.documentation.map(|value| {
+ Documentation::MarkupContent(MarkupContent {
+ kind: MarkupKind::Markdown,
+ value,
+ })
+ });
CompletionItem {
label: c.label,
kind: Some(match c.kind {
@@ -189,6 +195,7 @@ pub fn to_lsp_completion(c: Completion, snippets_supported: bool) -> CompletionI
CompletionKind::W3dModel => CompletionItemKind::REFERENCE,
}),
detail: c.detail,
+ documentation,
data,
insert_text,
insert_text_format,
@@ -354,6 +361,7 @@ mod tests {
label: "AVTank".into(),
kind: CompletionKind::W3dModel,
detail: Some("W3D model".into()),
+ documentation: None,
insert: None,
},
false,
@@ -365,6 +373,26 @@ mod tests {
assert!(item.documentation.is_none());
}
+ #[test]
+ fn completion_documentation_is_sent_as_markdown() {
+ let item = to_lsp_completion(
+ Completion {
+ label: "ModuleTag_Physics".into(),
+ kind: CompletionKind::Reference,
+ detail: Some("module tag".into()),
+ documentation: Some(
+ "```ini\nBehavior = PhysicsBehavior ModuleTag_Physics\n```".into(),
+ ),
+ insert: None,
+ },
+ false,
+ );
+ assert!(matches!(
+ item.documentation,
+ Some(Documentation::MarkupContent(_))
+ ));
+ }
+
#[test]
fn splice_reproduces_next_from_prev() {
let tok = |dl, ds, len, ty| SemanticToken {
diff --git a/crates/server/tests/e2e.py b/crates/server/tests/e2e.py
index 9f1c9f1..2fa9a5c 100644
--- a/crates/server/tests/e2e.py
+++ b/crates/server/tests/e2e.py
@@ -482,6 +482,23 @@ def latest_burst_diag(message):
assert targets[0]["range"]["start"]["line"] == 1, targets
print("OK: RemoveModule tag resolves to its module definition")
+ # A RemoveModule completion identifies the module that owns each tag.
+ send({"jsonrpc": "2.0", "id": 69, "method": "textDocument/completion",
+ "params": {"textDocument": {"uri": module_map_uri},
+ "position": {"line": 3, "character": len(" RemoveModule ")}}})
+ module_completion = wait_for(
+ lambda m: m.get("id") == 69 and "result" in m,
+ "RemoveModule completion result",
+ )
+ module_items = module_completion["result"]
+ if isinstance(module_items, dict):
+ module_items = module_items.get("items", [])
+ target_item = next(item for item in module_items if item["label"] == "ModuleTag_Target")
+ assert target_item["documentation"]["kind"] == "markdown", target_item
+ assert target_item["documentation"]["value"].startswith("```ini\n"), target_item
+ assert "Behavior = DestroyDie ModuleTag_Target" in target_item["documentation"]["value"]
+ print("OK: RemoveModule completion previews its defining module")
+
send({"jsonrpc": "2.0", "id": 70, "method": "textDocument/references",
"params": {"textDocument": {"uri": module_map_uri},
"position": {"line": 3, "character": 16},
diff --git a/editors/vscode/README.md b/editors/vscode/README.md
index 49cb224..892d8b1 100644
--- a/editors/vscode/README.md
+++ b/editors/vscode/README.md
@@ -26,8 +26,17 @@ Open the folder containing your project rather than a single file. ZeroSyntax
indexes the workspace so definitions, references, rename, and completion work
across its INI files.
-When editing `map.ini` or `solo.ini`, configure **ZeroSyntax v2: Base Ini Roots**
-with any game or mod folders and `.big` archives that load before the map. This
+When you first open an INI file, click **Select Game Folder** in the setup
+notification and browse to your Zero Hour installation folder. You can also run
+**ZeroSyntax: Select Game Folder** from the Command Palette at any time to add
+a game or mod folder. The folder is added to `zerosyntax.baseIniRoots` without
+replacing existing entries, and indexing starts automatically without a restart.
+It is saved in user settings for reuse across projects, unless the workspace
+already overrides this setting; in that case, the workspace setting is updated.
+
+Use **ZeroSyntax v2: Base Ini Roots** in Settings to manage additional roots,
+reorder or remove entries, or add individual `.big` archives that load before
+`map.ini` or `solo.ini`. This
prevents false unresolved-reference warnings and enables W3D model, bone,
WAV/MP3 audio, and TGA/DDS texture checks. Configure every loaded game/mod root;
asset warnings activate per kind once any matching asset is indexed. DDS-only
diff --git a/editors/vscode/package-lock.json b/editors/vscode/package-lock.json
index badd0a5..de24600 100644
--- a/editors/vscode/package-lock.json
+++ b/editors/vscode/package-lock.json
@@ -1,28 +1,28 @@
{
"name": "zerosyntax-vscode",
- "version": "1.0.4",
+ "version": "1.0.5",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "zerosyntax-vscode",
- "version": "1.0.4",
+ "version": "1.0.5",
"license": "MIT",
"dependencies": {
- "vscode-languageclient": "^10.1.0"
+ "vscode-languageclient": "^10.1.1"
},
"devDependencies": {
"@types/mocha": "^10.0.10",
- "@types/node": "^26.2.0",
- "@types/vscode": "^1.84.0",
+ "@types/node": "^26.4.1",
+ "@types/vscode": "^1.136.0",
"@vscode/test-electron": "^3.1.0",
"@vscode/vsce": "^3.9.2",
"esbuild": "^0.28.2",
- "mocha": "^11.8.0",
+ "mocha": "^12.0.0",
"typescript": "^7.0.2"
},
"engines": {
- "vscode": "^1.84.0"
+ "vscode": "^1.136.0"
}
},
"node_modules/@azu/format-text": {
@@ -677,80 +677,6 @@
"node": ">=18"
}
},
- "node_modules/@isaacs/cliui": {
- "version": "8.0.2",
- "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
- "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "string-width": "^5.1.2",
- "string-width-cjs": "npm:string-width@^4.2.0",
- "strip-ansi": "^7.0.1",
- "strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
- "wrap-ansi": "^8.1.0",
- "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@isaacs/cliui/node_modules/ansi-styles": {
- "version": "6.2.3",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz",
- "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
- }
- },
- "node_modules/@isaacs/cliui/node_modules/emoji-regex": {
- "version": "9.2.2",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
- "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@isaacs/cliui/node_modules/string-width": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
- "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "eastasianwidth": "^0.2.0",
- "emoji-regex": "^9.2.2",
- "strip-ansi": "^7.0.1"
- },
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/@isaacs/cliui/node_modules/wrap-ansi": {
- "version": "8.1.0",
- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
- "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ansi-styles": "^6.1.0",
- "string-width": "^5.0.1",
- "strip-ansi": "^7.0.1"
- },
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
- }
- },
"node_modules/@nodelib/fs.scandir": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@@ -789,17 +715,6 @@
"node": ">= 8"
}
},
- "node_modules/@pkgjs/parseargs": {
- "version": "0.11.0",
- "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
- "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
- "dev": true,
- "license": "MIT",
- "optional": true,
- "engines": {
- "node": ">=14"
- }
- },
"node_modules/@secretlint/config-creator": {
"version": "10.2.2",
"resolved": "https://registry.npmjs.org/@secretlint/config-creator/-/config-creator-10.2.2.tgz",
@@ -1079,9 +994,9 @@
"license": "MIT"
},
"node_modules/@types/node": {
- "version": "26.2.0",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-26.2.0.tgz",
- "integrity": "sha512-5IviulTZeRNp2vAJ514cc/HUlY5nZ9fCbq9DMyC52BrhFZACo3nI0R7qBxhQmo/d27NFe96ur/b7Wwxklda+kg==",
+ "version": "26.4.1",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-26.4.1.tgz",
+ "integrity": "sha512-k97ENvZWtvA6yqz5/FS6a7duDgOPEeOQOc2iKS/nY6mX6qJUKtLnWzQS+Xj6tXweyj6ZcTAK2Qecetnvi9nCLA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1103,9 +1018,9 @@
"license": "MIT"
},
"node_modules/@types/vscode": {
- "version": "1.125.0",
- "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.125.0.tgz",
- "integrity": "sha512-0icm/ZQAaism87P0ekHqi4/Ju9du+Tm0RUW+y7vqRsxY2cY0FNRX1nAnaW7nT6npPt2tfHiheZ55Zm9UhqonFA==",
+ "version": "1.136.0",
+ "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.136.0.tgz",
+ "integrity": "sha512-DO746VAfnHk8+Y8CsUKYMm2rjWD0mxEuYBZI+ssaqJY7yvLJPf9lcwxSSz9W60gbdvdcGyvHQxHTyByfF9mVqg==",
"dev": true,
"license": "MIT"
},
@@ -1871,15 +1786,15 @@
"license": "BSD-2-Clause"
},
"node_modules/brace-expansion": {
- "version": "5.0.7",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.7.tgz",
- "integrity": "sha512-7oFy703dxfY3/NLxC1fh2SUCQ0H9rmAY+5EpDVfXjUTTs+HEwR2nYaqLv+GWcTsumwxPfiz6CzCNkwXwBUwqCA==",
+ "version": "5.0.9",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz",
+ "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==",
"license": "MIT",
"dependencies": {
"balanced-match": "^4.0.2"
},
"engines": {
- "node": "18 || 20 || >=22"
+ "node": "20 || >=22"
}
},
"node_modules/braces": {
@@ -1992,19 +1907,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/camelcase": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
- "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
@@ -2067,16 +1969,16 @@
}
},
"node_modules/chokidar": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
- "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz",
+ "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "readdirp": "^4.0.1"
+ "readdirp": "^5.0.0"
},
"engines": {
- "node": ">= 14.16.0"
+ "node": ">= 20.19.0"
},
"funding": {
"url": "https://paulmillr.com/funding/"
@@ -2119,44 +2021,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/cliui": {
- "version": "8.0.1",
- "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
- "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "string-width": "^4.2.0",
- "strip-ansi": "^6.0.1",
- "wrap-ansi": "^7.0.0"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/cliui/node_modules/ansi-regex": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/cliui/node_modules/strip-ansi": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
- "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ansi-regex": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/cockatiel": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/cockatiel/-/cockatiel-3.2.1.tgz",
@@ -2217,21 +2081,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/cross-spawn": {
- "version": "7.0.6",
- "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
- "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "path-key": "^3.1.0",
- "shebang-command": "^2.0.0",
- "which": "^2.0.1"
- },
- "engines": {
- "node": ">= 8"
- }
- },
"node_modules/css-select": {
"version": "5.2.2",
"resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz",
@@ -2280,19 +2129,6 @@
}
}
},
- "node_modules/decamelize": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz",
- "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/decompress-response": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
@@ -2386,9 +2222,9 @@
}
},
"node_modules/diff": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz",
- "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==",
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-9.0.0.tgz",
+ "integrity": "sha512-svtcdpS8CgJyqAjEQIXdb3OjhFVVYjzGAPO8WGCmRbrml64SPw/jJD4GoE98aR7r25A0XcgrK3F02yw9R/vhQw==",
"dev": true,
"license": "BSD-3-Clause",
"engines": {
@@ -2469,13 +2305,6 @@
"node": ">= 0.4"
}
},
- "node_modules/eastasianwidth": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
- "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/ecdsa-sig-formatter": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
@@ -2652,29 +2481,6 @@
"@esbuild/win32-x64": "0.28.2"
}
},
- "node_modules/escalade": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
- "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/escape-string-regexp": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
- "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/expand-template": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
@@ -2767,33 +2573,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/flat": {
- "version": "5.0.2",
- "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz",
- "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==",
- "dev": true,
- "license": "BSD-3-Clause",
- "bin": {
- "flat": "cli.js"
- }
- },
- "node_modules/foreground-child": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz",
- "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "cross-spawn": "^7.0.6",
- "signal-exit": "^4.0.1"
- },
- "engines": {
- "node": ">=14"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
"node_modules/form-data": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz",
@@ -2844,16 +2623,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/get-caller-file": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
- "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
- "dev": true,
- "license": "ISC",
- "engines": {
- "node": "6.* || 8.* || >= 10.*"
- }
- },
"node_modules/get-east-asian-width": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.6.0.tgz",
@@ -3038,16 +2807,6 @@
"node": ">= 0.4"
}
},
- "node_modules/he": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
- "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
- "dev": true,
- "license": "MIT",
- "bin": {
- "he": "bin/he"
- }
- },
"node_modules/hosted-git-info": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz",
@@ -3303,16 +3062,6 @@
"node": ">=8"
}
},
- "node_modules/is-plain-obj": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
- "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/is-unicode-supported": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
@@ -3349,13 +3098,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/isexe": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
- "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
- "dev": true,
- "license": "ISC"
- },
"node_modules/istextorbinary": {
"version": "9.5.0",
"resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-9.5.0.tgz",
@@ -3374,22 +3116,6 @@
"url": "https://bevry.me/fund"
}
},
- "node_modules/jackspeak": {
- "version": "3.4.3",
- "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
- "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
- "dev": true,
- "license": "BlueOak-1.0.0",
- "dependencies": {
- "@isaacs/cliui": "^8.0.2"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- },
- "optionalDependencies": {
- "@pkgjs/parseargs": "^0.11.0"
- }
- },
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -3651,23 +3377,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/log-symbols": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
- "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "chalk": "^4.1.0",
- "is-unicode-supported": "^0.1.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/lru-cache": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
@@ -3814,12 +3523,12 @@
}
},
"node_modules/minimatch": {
- "version": "10.2.5",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz",
- "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==",
+ "version": "10.2.6",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz",
+ "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==",
"license": "BlueOak-1.0.0",
"dependencies": {
- "brace-expansion": "^5.0.5"
+ "brace-expansion": "^5.0.8"
},
"engines": {
"node": "18 || 20 || >=22"
@@ -3858,119 +3567,57 @@
"optional": true
},
"node_modules/mocha": {
- "version": "11.8.0",
- "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.8.0.tgz",
- "integrity": "sha512-VyCeUdGN3A9lmCTTgG4yuvY9ixxaDk+xt2R/7/+1AP6EqNG+G9OKkzBwhVtVYoNX8YsxNSgAl8mOv3IAeOpFbw==",
+ "version": "12.0.0",
+ "resolved": "https://registry.npmjs.org/mocha/-/mocha-12.0.0.tgz",
+ "integrity": "sha512-NYNh5IFt6WYqm9bi4601m7vix8MZdXC0DwS4gY6WhXO2RgJWhivhISVmq1oklCif18OSI9l+vx5Mdm5oh1XGiQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"browser-stdout": "^1.3.1",
- "chokidar": "^4.0.1",
+ "chokidar": "^5.0.0",
"debug": "^4.3.5",
- "diff": "^7.0.0",
- "escape-string-regexp": "^4.0.0",
+ "diff": "^9.0.0",
"find-up": "^5.0.0",
- "glob": "^10.4.5",
- "he": "^1.2.0",
+ "glob": "^13.0.0",
"is-path-inside": "^3.0.3",
- "js-yaml": "^4.1.0",
- "log-symbols": "^4.1.0",
- "minimatch": "^9.0.5",
+ "is-unicode-supported": "^0.1.0",
+ "js-yaml": "^5.0.0",
+ "minimatch": "^10.2.2",
"ms": "^2.1.3",
"picocolors": "^1.1.1",
- "serialize-javascript": "^6.0.2",
- "strip-json-comments": "^3.1.1",
+ "serialize-javascript": "^7.0.2",
+ "strip-json-comments": "^5.0.3",
"supports-color": "^8.1.1",
- "workerpool": "^9.2.0",
- "yargs": "^17.7.2",
- "yargs-parser": "^21.1.1",
- "yargs-unparser": "^2.0.0"
+ "workerpool": "^10.0.0"
},
"bin": {
- "_mocha": "bin/_mocha",
"mocha": "bin/mocha.js"
},
"engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ "node": "^20.19.0 || >=22.12.0"
}
},
- "node_modules/mocha/node_modules/balanced-match": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
- "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/mocha/node_modules/brace-expansion": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.2.tgz",
- "integrity": "sha512-w5JZcKgdhDOgOwm8H+KgbosopHMuGcl6qbulwjtz3SM7I7P3yW1eAjzMPLrIE+NQ9vjgANKHWeMHnrT0OXW1oA==",
+ "node_modules/mocha/node_modules/js-yaml": {
+ "version": "5.4.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-5.4.1.tgz",
+ "integrity": "sha512-28R/k+NAjeuf7+CKlTxWZVExJGwVVLwY06DgEnOMz2gEpfNkDcD7QvyiVPT0xy0XXhU8vHsd4Ot42OOPdJG7dQ==",
"dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/puzrin"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/nodeca"
+ }
+ ],
"license": "MIT",
"dependencies": {
- "balanced-match": "^1.0.0"
- }
- },
- "node_modules/mocha/node_modules/glob": {
- "version": "10.5.0",
- "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz",
- "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==",
- "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "foreground-child": "^3.1.0",
- "jackspeak": "^3.1.2",
- "minimatch": "^9.0.4",
- "minipass": "^7.1.2",
- "package-json-from-dist": "^1.0.0",
- "path-scurry": "^1.11.1"
+ "argparse": "^2.0.1"
},
"bin": {
- "glob": "dist/esm/bin.mjs"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/mocha/node_modules/lru-cache": {
- "version": "10.4.3",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
- "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
- "dev": true,
- "license": "ISC"
- },
- "node_modules/mocha/node_modules/minimatch": {
- "version": "9.0.9",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz",
- "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "brace-expansion": "^2.0.2"
- },
- "engines": {
- "node": ">=16 || 14 >=14.17"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/mocha/node_modules/path-scurry": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
- "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
- "dev": true,
- "license": "BlueOak-1.0.0",
- "dependencies": {
- "lru-cache": "^10.2.0",
- "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
- },
- "engines": {
- "node": ">=16 || 14 >=14.18"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
+ "js-yaml": "bin/js-yaml.mjs"
}
},
"node_modules/mocha/node_modules/supports-color": {
@@ -4304,13 +3951,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/package-json-from-dist": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
- "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
- "dev": true,
- "license": "BlueOak-1.0.0"
- },
"node_modules/pako": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
@@ -4419,16 +4059,6 @@
"node": ">=8"
}
},
- "node_modules/path-key": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
- "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/path-scurry": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz",
@@ -4602,16 +4232,6 @@
],
"license": "MIT"
},
- "node_modules/randombytes": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
- "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "safe-buffer": "^5.1.0"
- }
- },
"node_modules/rc": {
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
@@ -4723,29 +4343,19 @@
"license": "MIT"
},
"node_modules/readdirp": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz",
- "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==",
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.1.1.tgz",
+ "integrity": "sha512-Kko+Y5XQ6fM+Ce3dq3m9YGxnacYZYl9cA1wZjaF3Vbry2L3i1qVg8+CAgNPsXRArPMUMCaOR7oa9Nqntc43JKA==",
"dev": true,
"license": "MIT",
"engines": {
- "node": ">= 14.18.0"
+ "node": ">= 20.19.0"
},
"funding": {
"type": "individual",
"url": "https://paulmillr.com/funding/"
}
},
- "node_modules/require-directory": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
- "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/require-from-string": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
@@ -4894,13 +4504,13 @@
}
},
"node_modules/serialize-javascript": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz",
- "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==",
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-7.1.1.tgz",
+ "integrity": "sha512-k3CMsaIvvdSwm8oLB4MXSl0wH2/cwlH7xGcnRd2DaeRmBkbzYmyT8j0tsX60DwD1eRwHTpNpH8ljKu9oUT1MeQ==",
"dev": true,
"license": "BSD-3-Clause",
- "dependencies": {
- "randombytes": "^2.1.0"
+ "engines": {
+ "node": ">=20.0.0"
}
},
"node_modules/setimmediate": {
@@ -4910,29 +4520,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/shebang-command": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
- "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "shebang-regex": "^3.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/shebang-regex": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
- "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/side-channel": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz",
@@ -5183,45 +4770,6 @@
"node": ">=8"
}
},
- "node_modules/string-width-cjs": {
- "name": "string-width",
- "version": "4.2.3",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
- "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "emoji-regex": "^8.0.0",
- "is-fullwidth-code-point": "^3.0.0",
- "strip-ansi": "^6.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/string-width-cjs/node_modules/ansi-regex": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/string-width-cjs/node_modules/strip-ansi": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
- "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ansi-regex": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/string-width/node_modules/ansi-regex": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
@@ -5261,38 +4809,14 @@
"url": "https://github.com/chalk/strip-ansi?sponsor=1"
}
},
- "node_modules/strip-ansi-cjs": {
- "name": "strip-ansi",
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
- "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ansi-regex": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/strip-ansi-cjs/node_modules/ansi-regex": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/strip-json-comments": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
- "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-5.0.3.tgz",
+ "integrity": "sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw==",
"dev": true,
"license": "MIT",
"engines": {
- "node": ">=8"
+ "node": ">=14.16"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
@@ -5673,49 +5197,49 @@
}
},
"node_modules/vscode-jsonrpc": {
- "version": "9.0.1",
- "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-9.0.1.tgz",
- "integrity": "sha512-rfuA6T75H6m5EkbhtEPzre9pT0HPcDI2MMy4+nPFIBks5J8JBAUHD4tRYSgaBOijIEC7SRkC1kKyXTLqbmh9jw==",
+ "version": "9.0.2",
+ "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-9.0.2.tgz",
+ "integrity": "sha512-SbQSV9yRemARxeXw6LU5sS6Zq0e9/DgCCX5yelH263ZQWukbTk8EF8fjTrr1dziasf4GwlJbvTwFnTrnQFWZXQ==",
"license": "MIT",
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/vscode-languageclient": {
- "version": "10.1.0",
- "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-10.1.0.tgz",
- "integrity": "sha512-XXRx6lqVitQy/oOLr9MfNYRG+MbQkhXkDaxbQMiKxEm8zZNfheRFUKNb8UYNh2stn9btl2wQM5wZFJjJvoc+jA==",
+ "version": "10.1.1",
+ "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-10.1.1.tgz",
+ "integrity": "sha512-EbwIF+KUbwxD5jumQNpiBCv7BJM3Rierv4hcbw/p5jdsnwFFpR/B2VmwqfH4p5XsK46nkH3ugA3WtwJekHHJEw==",
"license": "MIT",
"dependencies": {
- "minimatch": "^10.2.5",
+ "minimatch": "^10.2.6",
"semver": "^7.8.1",
- "vscode-languageserver-protocol": "3.18.2",
- "vscode-languageserver-textdocument": "1.0.13"
+ "vscode-languageserver-protocol": "3.18.3",
+ "vscode-languageserver-textdocument": "1.0.14"
},
"engines": {
"vscode": "^1.91.0"
}
},
"node_modules/vscode-languageserver-protocol": {
- "version": "3.18.2",
- "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.18.2.tgz",
- "integrity": "sha512-XRyDbT0Pp3sSNti3JmxVEUMySWCSi1hhM+/KUlCy1hV1zmrqpM1OwO12EAki8blhmLuIMpaJrYbo0OzGVfK2Qg==",
+ "version": "3.18.3",
+ "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.18.3.tgz",
+ "integrity": "sha512-DF49+WeV5py4zO5hhobp60jjsDSK0lAqA0OuKBLBvp423HPWQcCbhZz3JgyfIewsEz2f8U+X75xNIFHdiXZm2w==",
"license": "MIT",
"dependencies": {
- "vscode-jsonrpc": "9.0.1",
- "vscode-languageserver-types": "3.18.0"
+ "vscode-jsonrpc": "9.0.2",
+ "vscode-languageserver-types": "3.18.3"
}
},
"node_modules/vscode-languageserver-textdocument": {
- "version": "1.0.13",
- "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.13.tgz",
- "integrity": "sha512-nx0ZHwMGIsVkzFG3/VLeJYBLTaFBRuNdGDvevvjuoayU5EOS2fEYazOhtCM3PI9ClMMg5igc0uwXtAq4tJj+Dw==",
+ "version": "1.0.14",
+ "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.14.tgz",
+ "integrity": "sha512-EQyqJMi552E4ZTf46izQ4Fj6XquqxCySR3J5ZSD1SisMf6RfpeOWHxGBE8Gr6V0/3GHIGdAzDn8F8+1nTGCnoQ==",
"license": "MIT"
},
"node_modules/vscode-languageserver-types": {
- "version": "3.18.0",
- "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.18.0.tgz",
- "integrity": "sha512-8TsGPNMIMiiBdkORgRSvLjuiEIiAFtO+KssmYWxQ+uSVvlf7RjK8YKCOjPzZ+YA04jXEV7+7LvkSmHkhpNS99g==",
+ "version": "3.18.3",
+ "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.18.3.tgz",
+ "integrity": "sha512-XIlzJ7Qp/jzSI1ds7/FwPAWrPeTZA7pAtlW4hdJ1J6xXWJL6dR9QYnDhJOdLzdKhUQ5Mm6mvUMw+3DcOQQasPw==",
"license": "MIT"
},
"node_modules/whatwg-encoding": {
@@ -5742,112 +5266,13 @@
"node": ">=18"
}
},
- "node_modules/which": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
- "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "isexe": "^2.0.0"
- },
- "bin": {
- "node-which": "bin/node-which"
- },
- "engines": {
- "node": ">= 8"
- }
- },
"node_modules/workerpool": {
- "version": "9.3.4",
- "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-9.3.4.tgz",
- "integrity": "sha512-TmPRQYYSAnnDiEB0P/Ytip7bFGvqnSU6I2BcuSw7Hx+JSg/DsUi5ebYfc8GYaSdpuvOcEs6dXxPurOYpe9QFwg==",
+ "version": "10.0.3",
+ "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-10.0.3.tgz",
+ "integrity": "sha512-6z2Iis68Wqth93/G/wJP9u+R3O+d2XTlgWChGCwuT1qLbBsOYueGRZuJ++v3mtDP5KjYdy+WzvWC+VWETSVXJA==",
"dev": true,
"license": "Apache-2.0"
},
- "node_modules/wrap-ansi": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
- "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ansi-styles": "^4.0.0",
- "string-width": "^4.1.0",
- "strip-ansi": "^6.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
- }
- },
- "node_modules/wrap-ansi-cjs": {
- "name": "wrap-ansi",
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
- "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ansi-styles": "^4.0.0",
- "string-width": "^4.1.0",
- "strip-ansi": "^6.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
- }
- },
- "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
- "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ansi-regex": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/wrap-ansi/node_modules/ansi-regex": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/wrap-ansi/node_modules/strip-ansi": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
- "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ansi-regex": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
@@ -5896,16 +5321,6 @@
"node": ">=4.0"
}
},
- "node_modules/y18n": {
- "version": "5.0.8",
- "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
- "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
- "dev": true,
- "license": "ISC",
- "engines": {
- "node": ">=10"
- }
- },
"node_modules/yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
@@ -5913,51 +5328,6 @@
"dev": true,
"license": "ISC"
},
- "node_modules/yargs": {
- "version": "17.7.3",
- "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.3.tgz",
- "integrity": "sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "cliui": "^8.0.1",
- "escalade": "^3.1.1",
- "get-caller-file": "^2.0.5",
- "require-directory": "^2.1.1",
- "string-width": "^4.2.3",
- "y18n": "^5.0.5",
- "yargs-parser": "^21.1.1"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/yargs-parser": {
- "version": "21.1.1",
- "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
- "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
- "dev": true,
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/yargs-unparser": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz",
- "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "camelcase": "^6.0.0",
- "decamelize": "^4.0.0",
- "flat": "^5.0.2",
- "is-plain-obj": "^2.1.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
"node_modules/yauzl": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/yauzl/-/yauzl-3.4.0.tgz",
diff --git a/editors/vscode/package.json b/editors/vscode/package.json
index 1221f0d..4a1bb52 100644
--- a/editors/vscode/package.json
+++ b/editors/vscode/package.json
@@ -11,7 +11,7 @@
"publisher": "ViTeXFTW",
"icon": "icon/ZeroSyntaxLogo256.png",
"engines": {
- "vscode": "^1.84.0"
+ "vscode": "^1.136.0"
},
"categories": [
"Programming Languages",
@@ -26,6 +26,10 @@
],
"contributes": {
"commands": [
+ {
+ "command": "zerosyntax.selectGameDirectory",
+ "title": "ZeroSyntax: Select Game Folder"
+ },
{
"command": "zerosyntax.clearIndexCache",
"title": "ZeroSyntax: Clear Index Cache"
@@ -102,7 +106,7 @@
"items": {
"type": "string"
},
- "markdownDescription": "Directories or `.big` archives containing base game/mod INI files and game assets. INI definitions are treated as already loaded before `map.ini`/`solo.ini`; W3D, WAV/MP3, and TGA/DDS assets power completions and diagnostics. Configure all loaded roots to avoid partial-index warnings. Changing this reindexes in the background."
+ "markdownDescription": "Directories or `.big` archives containing base game/mod INI files and game assets. Use **ZeroSyntax: Select Game Folder** to browse for your installation or mod folder. INI definitions are treated as already loaded before `map.ini`/`solo.ini`; W3D, WAV/MP3, and TGA/DDS assets power completions and diagnostics. Configure all loaded roots to avoid partial-index warnings. Changing this reindexes in the background."
},
"zerosyntax.progress.mode": {
"type": "string",
@@ -161,21 +165,21 @@
"compile:dev": "tsc --noEmit && esbuild src/extension.ts --bundle --sourcemap --platform=node --external:vscode --outfile=out/extension.js",
"compile:test": "tsc -p ./tsconfig.test.json",
"watch": "esbuild src/extension.ts --bundle --platform=node --external:vscode --outfile=out/extension.js --watch",
- "vscode:prepublish": "node -e \"const fs=require('fs');fs.mkdirSync('icon',{recursive:true});fs.copyFileSync('../../icon/ZeroSyntaxLogo256.png','icon/ZeroSyntaxLogo256.png')\" && npm run compile",
+ "vscode:prepublish": "node -e \"const fs=require('fs');fs.mkdirSync('icon',{recursive:true});fs.copyFileSync('../../resources/ZeroSyntaxLogo256.png','icon/ZeroSyntaxLogo256.png')\" && npm run compile",
"package": "vsce package --allow-missing-repository",
"test": "npm run compile && npm run compile:test && node ./out-test/src/test/runTest.js"
},
"dependencies": {
- "vscode-languageclient": "^10.1.0"
+ "vscode-languageclient": "^10.1.1"
},
"devDependencies": {
"@types/mocha": "^10.0.10",
- "@types/node": "^26.2.0",
- "@types/vscode": "^1.84.0",
+ "@types/node": "^26.4.1",
+ "@types/vscode": "^1.136.0",
"@vscode/test-electron": "^3.1.0",
"@vscode/vsce": "^3.9.2",
"esbuild": "^0.28.2",
- "mocha": "^11.8.0",
+ "mocha": "^12.0.0",
"typescript": "^7.0.2"
}
}
diff --git a/editors/vscode/src/extension.ts b/editors/vscode/src/extension.ts
index f3021b9..615671b 100644
--- a/editors/vscode/src/extension.ts
+++ b/editors/vscode/src/extension.ts
@@ -84,6 +84,7 @@ export function activate(context: vscode.ExtensionContext) {
});
context.subscriptions.push(
+ vscode.commands.registerCommand("zerosyntax.selectGameDirectory", selectGameDirectory),
vscode.commands.registerCommand("zerosyntax.openIndexCacheLocation", async () => {
const cachePath = await client?.sendRequest("zerosyntax/indexCachePath");
if (!cachePath) {
@@ -191,7 +192,11 @@ function resolveServerPath(context: vscode.ExtensionContext): string | undefined
}
async function maybeShowBaseIniRootsHint(document: vscode.TextDocument) {
- if (baseIniRootsHintShown || !isMapLayerDocument(document)) {
+ if (
+ baseIniRootsHintShown ||
+ document.uri.scheme !== "file" ||
+ document.languageId !== "generals-ini"
+ ) {
return;
}
@@ -201,12 +206,16 @@ async function maybeShowBaseIniRootsHint(document: vscode.TextDocument) {
}
baseIniRootsHintShown = true;
- const configure = "Configure base INI roots";
- const choice = await vscode.window.showWarningMessage(
- "ZeroSyntax v2: map/solo.ini diagnostics are limited until base game or mod INIs are configured.",
- configure
+ const selectDirectory = "Select Game Folder";
+ const openSettings = "Open Settings";
+ const choice = await vscode.window.showInformationMessage(
+ "ZeroSyntax v2: select your Zero Hour installation folder to enable game asset completions, model previews, and base game reference checks.",
+ selectDirectory,
+ openSettings
);
- if (choice === configure) {
+ if (choice === selectDirectory) {
+ await vscode.commands.executeCommand("zerosyntax.selectGameDirectory");
+ } else if (choice === openSettings) {
await vscode.commands.executeCommand(
"workbench.action.openSettings",
"zerosyntax.baseIniRoots"
@@ -214,6 +223,48 @@ async function maybeShowBaseIniRootsHint(document: vscode.TextDocument) {
}
}
+async function selectGameDirectory() {
+ try {
+ const selected = await vscode.window.showOpenDialog({
+ title: "Select your Zero Hour installation or mod folder",
+ canSelectFiles: false,
+ canSelectFolders: true,
+ canSelectMany: false,
+ openLabel: "Use Game Folder",
+ });
+ if (!selected?.[0]) {
+ return;
+ }
+
+ // Match the configuration sent to the server. Read it after the dialog so
+ // edits made while the picker is open are preserved.
+ const configuration = vscode.workspace.getConfiguration("zerosyntax");
+ const roots = configuration.get("baseIniRoots", []);
+ const directory = selected[0].fsPath;
+ const normalize = (root: string) => {
+ const normalized = path.normalize(root).replace(/[\\/]+$/, "");
+ return process.platform === "win32" ? normalized.toLowerCase() : normalized;
+ };
+ if (roots.some((root) => normalize(root) === normalize(directory))) {
+ void vscode.window.showInformationMessage("ZeroSyntax v2: this game folder is already configured.");
+ return;
+ }
+
+ const inspected = configuration.inspect("baseIniRoots");
+ const target = inspected?.workspaceValue !== undefined
+ ? vscode.ConfigurationTarget.Workspace
+ : vscode.ConfigurationTarget.Global;
+ await configuration.update("baseIniRoots", [...roots, directory], target);
+ void vscode.window.showInformationMessage(
+ "ZeroSyntax v2: game folder added. Game data will be indexed in the background."
+ );
+ } catch (error) {
+ void vscode.window.showErrorMessage(
+ `ZeroSyntax v2: could not configure the game folder. ${error instanceof Error ? error.message : String(error)}`
+ );
+ }
+}
+
function setting(key: string, fallback: T): T {
const current = vscode.workspace.getConfiguration("zerosyntax");
const inspected = current.inspect(key);
@@ -230,14 +281,6 @@ function setting(key: string, fallback: T): T {
return vscode.workspace.getConfiguration("zerosyntax").get(key, fallback);
}
-function isMapLayerDocument(document: vscode.TextDocument): boolean {
- if (document.uri.scheme !== "file" || document.languageId !== "generals-ini") {
- return false;
- }
- const name = path.basename(document.uri.fsPath).toLowerCase();
- return name === "map.ini" || name === "solo.ini";
-}
-
class BigIniDocumentProvider implements vscode.TextDocumentContentProvider {
constructor(private readonly getClient: () => LanguageClient | undefined) {}
diff --git a/editors/vscode/src/test/suite/index.ts b/editors/vscode/src/test/suite/index.ts
index b2e40f8..0f6f400 100644
--- a/editors/vscode/src/test/suite/index.ts
+++ b/editors/vscode/src/test/suite/index.ts
@@ -8,12 +8,13 @@ export function run(): Promise {
ui: "tdd",
});
+ mocha.addFile(path.resolve(__dirname, "setup.test.js"));
mocha.addFile(path.resolve(__dirname, "smoke.test.js"));
return new Promise((resolve, reject) => {
mocha.run((failures) => {
if (failures > 0) {
- reject(new Error(`${failures} VS Code smoke test(s) failed`));
+ reject(new Error(`${failures} VS Code extension test(s) failed`));
} else {
resolve();
}
diff --git a/editors/vscode/src/test/suite/setup.test.ts b/editors/vscode/src/test/suite/setup.test.ts
new file mode 100644
index 0000000..8c8d302
--- /dev/null
+++ b/editors/vscode/src/test/suite/setup.test.ts
@@ -0,0 +1,253 @@
+import * as assert from "assert";
+import * as fs from "fs";
+import * as path from "path";
+import * as vm from "vm";
+import type * as vscode from "vscode";
+import type { activate } from "../../extension";
+
+const selectCommand = "zerosyntax.selectGameDirectory";
+const gameFolder = path.resolve("Game Folder");
+const modArchive = path.resolve("Mod.big");
+const document = {
+ languageId: "generals-ini",
+ uri: { scheme: "file", fsPath: path.resolve("Object.ini") },
+};
+
+// Load a fresh extension for each test, with an isolated VS Code boundary.
+// Exercise its registered commands/events without a real picker, server, or
+// changes to the extension host's settings. The type import above also makes
+// compile:test emit the production extension beside the test output.
+function setup(options: {
+ roots?: string[];
+ workspaceRoots?: string[];
+ platform?: "win32" | "linux";
+ visible?: boolean;
+} = {}) {
+ const state = {
+ roots: options.roots ?? [],
+ selected: [{ fsPath: gameFolder }] as { fsPath: string }[] | undefined,
+ choice: undefined as string | undefined,
+ saveError: undefined as Error | undefined,
+ beforeSelection: () => {},
+ };
+ const updates: { key: string; value: string[]; target: number }[] = [];
+ const notifications: { message: string; actions: string[] }[] = [];
+ const errors: string[] = [];
+ const dialogs: vscode.OpenDialogOptions[] = [];
+ const executed: { name: string; args: unknown[] }[] = [];
+ const commands = new Map Promise>();
+ let openDocument: (doc: typeof document) => void = () => assert.fail("open listener missing");
+ const disposable = { dispose() {} };
+ const api = {
+ ConfigurationTarget: { Global: 1, Workspace: 2 },
+ CodeActionKind: { QuickFix: {} },
+ window: {
+ visibleTextEditors: options.visible ? [{ document }] : [],
+ async showOpenDialog(dialog: vscode.OpenDialogOptions) {
+ dialogs.push(dialog);
+ state.beforeSelection();
+ return state.selected;
+ },
+ async showInformationMessage(message: string, ...actions: string[]) {
+ notifications.push({ message, actions });
+ return actions.length ? state.choice : undefined;
+ },
+ async showErrorMessage(message: string) { errors.push(message); },
+ },
+ workspace: {
+ getConfiguration(section: string) {
+ assert.strictEqual(section, "zerosyntax");
+ return {
+ get(key: string, fallback: unknown) {
+ if (key === "server.path") { return "test-server"; }
+ return key === "baseIniRoots" ? state.roots : fallback;
+ },
+ inspect(key: string) {
+ return key === "baseIniRoots" ? { workspaceValue: options.workspaceRoots } : undefined;
+ },
+ async update(key: string, value: string[], target: number) {
+ if (state.saveError) { throw state.saveError; }
+ updates.push({ key, value, target });
+ state.roots = value;
+ },
+ };
+ },
+ createFileSystemWatcher: () => disposable,
+ registerTextDocumentContentProvider: () => disposable,
+ onDidChangeConfiguration: () => disposable,
+ onDidOpenTextDocument(handler: typeof openDocument) {
+ openDocument = handler;
+ return disposable;
+ },
+ },
+ languages: { registerCodeActionsProvider: () => disposable },
+ commands: {
+ registerCommand(name: string, handler: () => Promise) {
+ commands.set(name, handler);
+ return disposable;
+ },
+ async executeCommand(name: string, ...args: unknown[]) {
+ executed.push({ name, args });
+ await commands.get(name)?.();
+ },
+ },
+ };
+ const filename = path.resolve(__dirname, "../../extension.js");
+ const extensionModule = { exports: {} as { activate: typeof activate } };
+ const evaluate = vm.runInThisContext(
+ `(function(require, module, exports, process) { ${fs.readFileSync(filename, "utf8")}\n})`,
+ { filename }
+ );
+ evaluate((name: string) => {
+ if (name === "vscode") { return api; }
+ if (name === "vscode-languageclient/node") {
+ return { LanguageClient: class { start() {} }, TransportKind: { stdio: 0 } };
+ }
+ if (name === "path" && options.platform) {
+ return options.platform === "win32" ? path.win32 : path.posix;
+ }
+ return require(name);
+ }, extensionModule, extensionModule.exports, { platform: options.platform ?? process.platform });
+ extensionModule.exports.activate({ subscriptions: [] } as unknown as vscode.ExtensionContext);
+ return {
+ state, updates, notifications, errors, dialogs, executed,
+ open: (doc = document) => openDocument(doc),
+ async select() {
+ const command = commands.get(selectCommand);
+ assert.ok(command, "game-folder command must be registered");
+ await command();
+ },
+ };
+}
+
+// Document-open handlers intentionally return void; flush their async work.
+const settle = () => new Promise((resolve) => setImmediate(resolve));
+
+suite("Game folder setup", () => {
+ test("uses a folder-only picker and appends to user settings", async () => {
+ const app = setup({ roots: [modArchive] });
+ await app.select();
+ assert.strictEqual(app.dialogs[0].canSelectFiles, false);
+ assert.strictEqual(app.dialogs[0].canSelectFolders, true);
+ assert.strictEqual(app.dialogs[0].canSelectMany, false);
+ assert.deepStrictEqual(app.updates, [
+ { key: "baseIniRoots", value: [modArchive, gameFolder], target: 1 },
+ ]);
+ assert.match(app.notifications[0].message, /indexed in the background/);
+ });
+
+ for (const roots of [[], [modArchive]]) {
+ test(`respects ${roots.length ? "populated" : "empty"} workspace overrides`, async () => {
+ const app = setup({ roots, workspaceRoots: roots });
+ await app.select();
+ assert.deepStrictEqual(app.updates, [
+ { key: "baseIniRoots", value: [...roots, gameFolder], target: 2 },
+ ]);
+ });
+ }
+
+ for (const selected of [undefined, []]) {
+ test(`cancelling with ${selected === undefined ? "undefined" : "no selections"} changes nothing`, async () => {
+ const app = setup({ roots: [modArchive] });
+ app.state.selected = selected;
+ await app.select();
+ assert.deepStrictEqual(app.state.roots, [modArchive]);
+ assert.deepStrictEqual(app.updates, []);
+ assert.deepStrictEqual(app.notifications, []);
+ assert.deepStrictEqual(app.errors, []);
+ });
+ }
+
+ test("preserves settings changed while the picker is open", async () => {
+ const app = setup();
+ app.state.beforeSelection = () => { app.state.roots = [modArchive]; };
+ await app.select();
+ assert.deepStrictEqual(app.updates[0].value, [modArchive, gameFolder]);
+ });
+
+ test("does not duplicate Windows paths with different case or separators", async () => {
+ const app = setup({ roots: ["c:/games/zero hour/"], platform: "win32" });
+ app.state.selected = [{ fsPath: "C:\\Games\\Zero Hour" }];
+ await app.select();
+ assert.deepStrictEqual(app.updates, []);
+ assert.match(app.notifications[0].message, /already configured/);
+ });
+
+ test("normalizes POSIX paths without folding their case", async () => {
+ const app = setup({ roots: ["/games/ZeroHour/"], platform: "linux" });
+ app.state.selected = [{ fsPath: "/games/ZeroHour" }];
+ await app.select();
+ assert.strictEqual(app.updates.length, 0);
+ app.state.selected = [{ fsPath: "/games/zerohour" }];
+ await app.select();
+ assert.deepStrictEqual(app.updates[0].value, ["/games/ZeroHour/", "/games/zerohour"]);
+ });
+
+ test("reports save failures without claiming success", async () => {
+ const app = setup();
+ app.state.saveError = new Error("Settings are read-only");
+ await app.select();
+ assert.deepStrictEqual(app.updates, []);
+ assert.deepStrictEqual(app.notifications, []);
+ assert.strictEqual(app.errors.length, 1);
+ assert.match(app.errors[0], /Settings are read-only/);
+ });
+
+ test("offers setup for ordinary INIs and routes the picker action", async () => {
+ const app = setup();
+ app.state.choice = "Select Game Folder";
+ app.open();
+ await settle();
+ assert.deepStrictEqual(app.notifications[0].actions, ["Select Game Folder", "Open Settings"]);
+ assert.deepStrictEqual(app.executed, [{ name: selectCommand, args: [] }]);
+ assert.strictEqual(app.updates.length, 1);
+ });
+
+ test("routes the Settings action to base INI roots", async () => {
+ const app = setup();
+ app.state.choice = "Open Settings";
+ app.open();
+ await settle();
+ assert.deepStrictEqual(app.executed, [
+ { name: "workbench.action.openSettings", args: ["zerosyntax.baseIniRoots"] },
+ ]);
+ assert.deepStrictEqual(app.dialogs, []);
+ });
+
+ test("prompts once per activation even for concurrent opens and dismissal", async () => {
+ const app = setup();
+ app.open();
+ app.open();
+ await settle();
+ app.open();
+ await settle();
+ assert.strictEqual(app.notifications.length, 1);
+ assert.deepStrictEqual(app.executed, []);
+ assert.deepStrictEqual(app.updates, []);
+ });
+
+ test("checks editors already visible at activation", async () => {
+ const app = setup({ visible: true });
+ await settle();
+ assert.strictEqual(app.notifications.length, 1);
+ });
+
+ test("skips unrelated languages and virtual documents without consuming the hint", async () => {
+ const app = setup();
+ app.open({ ...document, languageId: "plaintext" });
+ app.open({ ...document, uri: { ...document.uri, scheme: "big" } });
+ await settle();
+ assert.deepStrictEqual(app.notifications, []);
+ app.open();
+ await settle();
+ assert.strictEqual(app.notifications.length, 1);
+ });
+
+ test("does not prompt when base roots are configured", async () => {
+ const app = setup({ roots: [modArchive], visible: true });
+ app.open();
+ await settle();
+ assert.deepStrictEqual(app.notifications, []);
+ assert.deepStrictEqual(app.executed, []);
+ });
+});
diff --git a/icon/ZeroSyntaxLogo256.png b/resources/ZeroSyntaxLogo256.png
similarity index 100%
rename from icon/ZeroSyntaxLogo256.png
rename to resources/ZeroSyntaxLogo256.png
diff --git a/resources/readme-examples/model_completion_example.png b/resources/readme-examples/model_completion_example.png
new file mode 100644
index 0000000..1cf9e74
Binary files /dev/null and b/resources/readme-examples/model_completion_example.png differ
diff --git a/resources/readme-examples/reference_diagnostic_value.png b/resources/readme-examples/reference_diagnostic_value.png
new file mode 100644
index 0000000..8b9e998
Binary files /dev/null and b/resources/readme-examples/reference_diagnostic_value.png differ
diff --git a/resources/readme-examples/snippet_example.gif b/resources/readme-examples/snippet_example.gif
new file mode 100644
index 0000000..a610bd9
Binary files /dev/null and b/resources/readme-examples/snippet_example.gif differ
diff --git a/resources/readme-examples/value_diagnostic_percentage.png b/resources/readme-examples/value_diagnostic_percentage.png
new file mode 100644
index 0000000..dcf5ff6
Binary files /dev/null and b/resources/readme-examples/value_diagnostic_percentage.png differ
diff --git a/resources/readme-examples/vscode_install_example.png b/resources/readme-examples/vscode_install_example.png
new file mode 100644
index 0000000..ee8c93f
Binary files /dev/null and b/resources/readme-examples/vscode_install_example.png differ