Compare commits
22 Commits
Author | SHA1 | Date | |
---|---|---|---|
1a0ec08ce2 | |||
784a1aaea1 | |||
e415653865 | |||
8428d6e027 | |||
400318bb63 | |||
79cd101467 | |||
7e1f68e6f8 | |||
b3b518dc42 | |||
58881b06db | |||
bc4318bd6b | |||
57aaaf1baa | |||
e1617fb880 | |||
fa85946421 | |||
889b09d67c | |||
07456d152e | |||
d76f9e0465 | |||
a9971097b2 | |||
15308b2b2b | |||
d942f55585 | |||
187b1f5a9e | |||
54743a90b3 | |||
be93aaf4ed |
6
.gitmodules
vendored
Normal file
6
.gitmodules
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
[submodule "nulllib"]
|
||||||
|
path = nulllib
|
||||||
|
url = https://gitea.protogen.io/nullbite/nulllib-lua
|
||||||
|
[submodule ".vim/figuradocs"]
|
||||||
|
path = .vim/figuradocs
|
||||||
|
url = https://github.com/GrandpaScout/FiguraRewriteVSDocs
|
520
.luarc.json
Normal file
520
.luarc.json
Normal file
@ -0,0 +1,520 @@
|
|||||||
|
{
|
||||||
|
/*==============================================================================================*\
|
||||||
|
|* WORKSPACE: Controls workspace behavior. *|
|
||||||
|
\*==============================================================================================*/
|
||||||
|
"workspace": {
|
||||||
|
"library": [
|
||||||
|
"nulllib",
|
||||||
|
".vim/figuradocs/src/.vscode/docs",
|
||||||
|
".vscode/docs",
|
||||||
|
"../../avatars/.vscode/docs",
|
||||||
|
"../../../avatars/.vscode/docs",
|
||||||
|
"../../../../avatars/.vscode/docs",
|
||||||
|
"../../../../../avatars/.vscode/docs",
|
||||||
|
"../../../../../../avatars/.vscode/docs"
|
||||||
|
],
|
||||||
|
|
||||||
|
// Figura does not use third-party libraries.
|
||||||
|
"checkThirdParty": false,
|
||||||
|
"userThirdParty": [],
|
||||||
|
|
||||||
|
// Modify ignored files
|
||||||
|
"ignoreDir": [".**"], // Directories starting with `.` are ignored.
|
||||||
|
"useGitIgnore": true, // Ignore the same files as Git.
|
||||||
|
"ignoreSubmodules": true, // Git submodules are ignored.
|
||||||
|
|
||||||
|
// Include all file schemes
|
||||||
|
"supportScheme": ["file", "untitled", "git"],
|
||||||
|
|
||||||
|
// Avoid excessive memory usage.
|
||||||
|
"maxPreload": 5000,
|
||||||
|
"preloadFileSize": 500
|
||||||
|
},
|
||||||
|
|
||||||
|
/*==============================================================================================*\
|
||||||
|
|* RUNTIME: Controls the emulated Lua runtime. *|
|
||||||
|
\*==============================================================================================*/
|
||||||
|
"runtime": {
|
||||||
|
// Figura uses Lua 5.2
|
||||||
|
"version": "Lua 5.2",
|
||||||
|
|
||||||
|
// Change built-in features of Lua to fit Figura's implementation.
|
||||||
|
"builtin": {
|
||||||
|
"basic": "disable", // Figura reworks and removes many of the functions in this library.
|
||||||
|
"bit": "disable", // `bit` is LuaJIT only.
|
||||||
|
"bit32": "enable", //
|
||||||
|
"builtin": "enable", // TODO: Turn this off if the Lua server ever supports ops on types.
|
||||||
|
"coroutine": "disable", // `coroutine` does not exist in Figura.
|
||||||
|
"debug": "disable", // `debug` does not exist in Figura.
|
||||||
|
"ffi": "disable", // `ffi` is LuaJIT only.
|
||||||
|
"io": "disable", // `io` does not exist in Figura.
|
||||||
|
"jit": "disable", // `jit` is, you guessed it, LuaJIT only.
|
||||||
|
"math": "enable", //
|
||||||
|
"os": "disable", // `os` does not exist in Figura.
|
||||||
|
"package": "disable", // `package` does not exist in Figura. `require` is reworked.
|
||||||
|
"string": "enable", //
|
||||||
|
"table": "enable", //
|
||||||
|
"table.clear": "disable", // `table.clear` is LuaJIT only.
|
||||||
|
"table.new": "disable", // `table.new` is LuaJIT only.
|
||||||
|
"utf8": "disable" // `utf8` is Lua 5.3+ only.
|
||||||
|
},
|
||||||
|
|
||||||
|
// Figura's require only allows direct paths.
|
||||||
|
"path": ["?.lua"],
|
||||||
|
"pathStrict": false,
|
||||||
|
|
||||||
|
// Internal crap.
|
||||||
|
"fileEncoding": "utf8",
|
||||||
|
"meta": "${version} ${language} ${encoding}",
|
||||||
|
|
||||||
|
// Figura does not use non-standard features.
|
||||||
|
"nonstandardSymbol": [],
|
||||||
|
"plugin": "",
|
||||||
|
"pluginArgs": [],
|
||||||
|
"special": {},
|
||||||
|
"unicodeName": false
|
||||||
|
},
|
||||||
|
|
||||||
|
/*==============================================================================================*\
|
||||||
|
|* COMPLETION: Controls auto-completion and suggestion behavior. *|
|
||||||
|
\*==============================================================================================*/
|
||||||
|
"completion": {
|
||||||
|
// Enable completion changes.
|
||||||
|
"enable": true,
|
||||||
|
|
||||||
|
// Modify visible snippets.
|
||||||
|
"keywordSnippet": "Both", // Show snippets for both keywords and control blocks.
|
||||||
|
"callSnippet": "Disable", // Disable seperate call snippets as they clutter suggestions.
|
||||||
|
|
||||||
|
// Show parameter names on function suggestions.
|
||||||
|
"showParams": true,
|
||||||
|
|
||||||
|
// Automatically try to `require` words that look like file names.
|
||||||
|
"autoRequire": true,
|
||||||
|
|
||||||
|
// Shows context for hovered function calls by showing the first few lines of the function.
|
||||||
|
// You can disable this by setting this to 0. Enable by setting to the amount of visbile lines.
|
||||||
|
"displayContext": 0,
|
||||||
|
|
||||||
|
// The character used as the postfix operator for suggestions.
|
||||||
|
"postfix": "@",
|
||||||
|
|
||||||
|
// The character used as the path seperator of requires.
|
||||||
|
"requireSeparator": ".",
|
||||||
|
|
||||||
|
// Disable word suggestions as they are mostly useless.
|
||||||
|
"showWord": "Disable",
|
||||||
|
"workspaceWord": false
|
||||||
|
},
|
||||||
|
|
||||||
|
/*==============================================================================================*\
|
||||||
|
|* DIAGNOSTICS: Controls active diagnostics and the behavior of those diagnostics. *|
|
||||||
|
\*==============================================================================================*/
|
||||||
|
"diagnostics": {
|
||||||
|
// Enable diagnostics.
|
||||||
|
"enable": true,
|
||||||
|
|
||||||
|
// Slow down diagnostics on files that are not currently active to save resources.
|
||||||
|
"workspaceDelay": 5000,
|
||||||
|
"workspaceRate": 25,
|
||||||
|
|
||||||
|
// Sets the severity of diagnostics to better fit Figura's environment.
|
||||||
|
// Removing diagnostics from this list does not disable them, use the "disable" list below if
|
||||||
|
// you wish to do that instead.
|
||||||
|
"severity": {
|
||||||
|
// Ambiguity
|
||||||
|
"ambiguity-1": "Warning", // Requires ambiguous operators to be ordered with `(...)`.
|
||||||
|
"count-down-loop": "Error", // Don't allow for loops that could be infinite.
|
||||||
|
"different-requires": "Error", // Requires in Figura are very specific.
|
||||||
|
"newfield-call": "Warning", // If parentheses are found at the start of a line, it will...
|
||||||
|
"newline-call": "Warning", // ...be treated as a function call for the variable before it.
|
||||||
|
|
||||||
|
// Await
|
||||||
|
"await-in-sync": "Error", // Async functions can only be called in async contexts.
|
||||||
|
"not-yieldable": "Error", // `coroutine.yield` can only be used in coroutines.
|
||||||
|
|
||||||
|
// Code Style
|
||||||
|
"codestyle-check": "Information", // Checks code style for consistency.
|
||||||
|
"spell-check": "Hint", // Check spelling.
|
||||||
|
|
||||||
|
// Duplicate
|
||||||
|
"duplicate-index": "Warning", // Duplicate table indexes will conflict.
|
||||||
|
"duplicate-set-field": "Warning", // Duplicate class indexes will conflict.
|
||||||
|
|
||||||
|
// Global
|
||||||
|
"global-in-nil-env": "Error", // Attempting to make a global with a missing _ENV fails.
|
||||||
|
"lowercase-global": "Information", // This is likely caused by not making a variable local.
|
||||||
|
"undefined-env-child": "Warning", // Basically `undefined-global`, but for new _ENVs.
|
||||||
|
"undefined-global": "Warning", // Detects attempt to use undefined global variables.
|
||||||
|
|
||||||
|
// Luadoc
|
||||||
|
"circle-doc-class": "Error", // Circular references cause a class to be useless.
|
||||||
|
"doc-field-no-class": "Error", // `@field`s need a `@class` to work.
|
||||||
|
"duplicate-doc-alias": "Warning", // Duplicate `@alias` names may conflict.
|
||||||
|
"duplicate-doc-field": "Warning", // Duplicate `@field` names in a class may conflict.
|
||||||
|
"duplicate-doc-param": "Warning", // Duplicate `@param` names in a function may conflict.
|
||||||
|
"undefined-doc-class": "Warning", // Duplicate `@class` names may conflict.
|
||||||
|
"undefined-doc-name": "Error", // Undefined type annotations act like the `table` type.
|
||||||
|
"undefined-doc-param": "Warning", // `@param`s need a matching parameter to annotate.
|
||||||
|
"unknown-cast-variable": "Error", // Undefined variables cannot be typecasted.
|
||||||
|
"unknown-diag-code": "Information", // `@diagnostic` only accepts valid diagnostic codes.
|
||||||
|
"unknown-operator": "Error", // Lua cannot have new `@operator`s added to it.
|
||||||
|
|
||||||
|
// Redefined
|
||||||
|
"redefined-local": "Warning", // It is pointless to redefine a local variable.
|
||||||
|
|
||||||
|
// Strict
|
||||||
|
"close-non-object": "Error", // Non-object values cannot be closed.
|
||||||
|
"deprecated": "Warning", // Deprecated features are not meant to be used in code.
|
||||||
|
"discard-returns": "Warning", // Some functions cannot discard their return values.
|
||||||
|
|
||||||
|
// Strong
|
||||||
|
"no-unknown": "Warning", // If a varaible's type cannot be inferred, it cannot safely be used.
|
||||||
|
|
||||||
|
// Type Check
|
||||||
|
"assign-type-mismatch": "Warning", // Types of both values in an assignment must match.
|
||||||
|
"cast-local-type": "Warning", // Casts can only be to matching types.
|
||||||
|
"cast-type-mismatch": "Warning", // Casts can only be to matching types.
|
||||||
|
"need-check-nil": "Warning", // Require a check if a value is *possibly* nil.
|
||||||
|
"param-type-mismatch": "Warning", // Require call arguments to match function parameters.
|
||||||
|
"return-type-mismatch": "Warning", // Require functions to return the correct type of value.
|
||||||
|
"undefined-field": "Warning", // Undefined fields have no known type and are not safe.
|
||||||
|
|
||||||
|
// Unbalanced
|
||||||
|
"missing-parameter": "Error", // Functions must receive at least the minimum arguments.
|
||||||
|
"missing-return": "Warning", // Functions with a `@return` require a return statement.
|
||||||
|
"missing-return-value": "Warning", // Functions with a `@return` require a return value.
|
||||||
|
"redundant-parameter": "Warning", // Functions must receive at most the maximum arguments.
|
||||||
|
"redundant-return-value": "Warning", // Functions must return at most the maximum returns.
|
||||||
|
"redundant-value": "Warning", // Unbalanced assignments can cause useless values.
|
||||||
|
"unbalanced-assignments": "Warning", // Unbalanced assignments can cause undefined variables.
|
||||||
|
|
||||||
|
// Unused
|
||||||
|
"code-after-break": "Information", // Code after a break statement will never run.
|
||||||
|
"empty-block": "Hint", // Empty blocks create clutter.
|
||||||
|
"redundant-return": "Warning", // Empty returns at the end of a function are redundant.
|
||||||
|
"trailing-space": "Hint", // Disallows trailing spaces in code.
|
||||||
|
"unreachable-code": "Information", // If code is unreachable, it is useless.
|
||||||
|
"unused-function": "Hint", // Unused functions cause clutter.
|
||||||
|
"unused-label": "Hint", // Unused labels cause clutter.
|
||||||
|
"unused-local": "Hint", // Unused variables cause clutter.
|
||||||
|
"unused-vararg": "Hint" // Unused varargs cause clutter.
|
||||||
|
},
|
||||||
|
"neededFileStatus": {
|
||||||
|
"codestyle-check": "Any"
|
||||||
|
},
|
||||||
|
|
||||||
|
// Diagnostics that are deemed useless in Figura's environment.
|
||||||
|
// Remove the `/ /;` before an option to disable it. Re-add it to enable it.
|
||||||
|
"disable": [
|
||||||
|
// Ambiguity
|
||||||
|
//;"ambiguity-1",
|
||||||
|
//;"count-down-loop",
|
||||||
|
//;"different-requires",
|
||||||
|
//;"newfield-call",
|
||||||
|
//;"newline-call",
|
||||||
|
|
||||||
|
// Await
|
||||||
|
"await-in-sync", // Nothing in Figura is true async.
|
||||||
|
"not-yieldable", // `coroutine.yield` does not exist in Figura.
|
||||||
|
|
||||||
|
// Code Style
|
||||||
|
"codestyle-check", // Code style checking is completely subjective.
|
||||||
|
"spell-check", // Who needs spell check? Lmao.
|
||||||
|
|
||||||
|
// Duplicate
|
||||||
|
//;"duplicate-index",
|
||||||
|
//;"duplicate-set-field",
|
||||||
|
|
||||||
|
// Global
|
||||||
|
//;"global-in-nil-env",
|
||||||
|
//;"lowercase-global",
|
||||||
|
//;"undefined-env-child",
|
||||||
|
//;"undefined-global",
|
||||||
|
|
||||||
|
// Luadoc
|
||||||
|
//;"circle-doc-class",
|
||||||
|
//;"doc-field-no-class",
|
||||||
|
//;"duplicate-doc-alias",
|
||||||
|
//;"duplicate-doc-field",
|
||||||
|
//;"duplicate-doc-param",
|
||||||
|
//;"undefined-doc-class",
|
||||||
|
//;"undefined-doc-name",
|
||||||
|
//;"undefined-doc-param",
|
||||||
|
//;"unknown-cast-variable",
|
||||||
|
//;"unknown-diag-code",
|
||||||
|
//;"unknown-operator",
|
||||||
|
|
||||||
|
// Redefined
|
||||||
|
//;"redefined-local",
|
||||||
|
|
||||||
|
// Strict
|
||||||
|
"close-non-object", // <close> is Lua 5.4+ only.
|
||||||
|
//;"deprecated",
|
||||||
|
//;"discard-returns",
|
||||||
|
|
||||||
|
// Strong
|
||||||
|
"no-unknown", // Too strict for Figura scripters.
|
||||||
|
|
||||||
|
// Type Check
|
||||||
|
//;"assign-type-mismatch",
|
||||||
|
"cast-local-type", // Allow casting as a way of forcibly changing a variable's type.
|
||||||
|
"cast-type-mismatch", // Allow casting as a way of forcibly changing a variable's type.
|
||||||
|
"need-check-nil", // Too strict for Figura scripters.
|
||||||
|
//;"param-type-mismatch",
|
||||||
|
//;"return-type-mismatch",
|
||||||
|
//;"undefined-field",
|
||||||
|
|
||||||
|
// Unbalanced
|
||||||
|
//;"missing-parameter",
|
||||||
|
//;"missing-return",
|
||||||
|
//;"missing-return-value",
|
||||||
|
//;"redundant-parameter",
|
||||||
|
//;"redundant-return-value",
|
||||||
|
//;"redundant-value",
|
||||||
|
//;"unbalanced-assignments",
|
||||||
|
|
||||||
|
// Unused
|
||||||
|
//;"code-after-break",
|
||||||
|
//;"empty-block",
|
||||||
|
//;"redundant-return",
|
||||||
|
"trailing-space" // Personal preference.
|
||||||
|
//;"unreachable-code",
|
||||||
|
//;"unused-function",
|
||||||
|
//;"unused-label",
|
||||||
|
//;"unused-local",
|
||||||
|
//;"unused-vararg"
|
||||||
|
],
|
||||||
|
|
||||||
|
// Group severity is not used by the docs.
|
||||||
|
"groupSeverity": {
|
||||||
|
"ambiguity": "Fallback",
|
||||||
|
"await": "Fallback",
|
||||||
|
"codestyle": "Fallback",
|
||||||
|
"duplicate": "Fallback",
|
||||||
|
"global": "Fallback",
|
||||||
|
"luadoc": "Fallback",
|
||||||
|
"redefined": "Fallback",
|
||||||
|
"strict": "Fallback",
|
||||||
|
"strong": "Fallback",
|
||||||
|
"type-check": "Fallback",
|
||||||
|
"unbalanced": "Fallback",
|
||||||
|
"unused": "Fallback"
|
||||||
|
},
|
||||||
|
"groupFileStatus": {
|
||||||
|
"ambiguity": "Fallback",
|
||||||
|
"await": "Fallback",
|
||||||
|
"codestyle": "Fallback",
|
||||||
|
"duplicate": "Fallback",
|
||||||
|
"global": "Fallback",
|
||||||
|
"luadoc": "Fallback",
|
||||||
|
"redefined": "Fallback",
|
||||||
|
"strict": "Fallback",
|
||||||
|
"strong": "Fallback",
|
||||||
|
"type-check": "Fallback",
|
||||||
|
"unbalanced": "Fallback",
|
||||||
|
"unused": "Fallback"
|
||||||
|
},
|
||||||
|
|
||||||
|
// Allow all schemes.
|
||||||
|
"disableScheme": [],
|
||||||
|
|
||||||
|
// Don't run diagnostics on library files and ignored files.
|
||||||
|
"ignoredFiles": "Opened",
|
||||||
|
"libraryFiles": "Opened",
|
||||||
|
|
||||||
|
// The docs handle global variables themselves.
|
||||||
|
"globals": [],
|
||||||
|
|
||||||
|
// All local variables must be checked (except for the empty variable "_")
|
||||||
|
"unusedLocalExclude": []
|
||||||
|
},
|
||||||
|
|
||||||
|
/*==============================================================================================*\
|
||||||
|
|* FORMAT: Controls the formatter and code checking options. *|
|
||||||
|
\*==============================================================================================*/
|
||||||
|
"format": {
|
||||||
|
// Only use the formatter for code checking.
|
||||||
|
"enable": false,
|
||||||
|
|
||||||
|
// Formatter settings.
|
||||||
|
"defaultConfig": {
|
||||||
|
"align_call_args": "false",
|
||||||
|
"align_chained_expression_statement": "false",
|
||||||
|
"align_function_define_params": "false",
|
||||||
|
"align_table_field_to_first_field": "false",
|
||||||
|
"call_arg_parentheses": "keep",
|
||||||
|
"class_name_define_style": "pascal_case",
|
||||||
|
"continuation_indent_size": "2",
|
||||||
|
"continuous_assign_statement_align_to_equal_sign": "true",
|
||||||
|
"continuous_assign_table_field_align_to_equal_sign": "true",
|
||||||
|
"detect_end_of_line": "true",
|
||||||
|
"do_statement_no_indent": "false",
|
||||||
|
"enable_check_codestyle": "true",
|
||||||
|
"enable_name_style_check": "true",
|
||||||
|
"end_of_line": "lf",
|
||||||
|
"function_name_define_style": "camel_case",
|
||||||
|
"function_param_name_style": "snake_case",
|
||||||
|
"global_variable_name_define_style": "upper_case",
|
||||||
|
"if_branch_comments_after_block_no_indent": "false",
|
||||||
|
"if_condition_no_continuation_indent": "false",
|
||||||
|
"indent_size": "2",
|
||||||
|
"indent_style": "space",
|
||||||
|
"insert_final_newline": "true",
|
||||||
|
"keep_line_after_do_statement": "keepLine",
|
||||||
|
"keep_line_after_expression_statement": "keepLine",
|
||||||
|
"keep_line_after_for_statement": "keepLine",
|
||||||
|
"keep_line_after_function_define_statement": "keepLine",
|
||||||
|
"keep_line_after_if_statement": "keepLine",
|
||||||
|
"keep_line_after_local_or_assign_statement": "keepLine",
|
||||||
|
"keep_line_after_repeat_statement": "keepLine",
|
||||||
|
"keep_line_after_while_statement": "keepLine",
|
||||||
|
"keep_one_space_between_namedef_and_attribute": "true",
|
||||||
|
"keep_one_space_between_table_and_bracket": "false",
|
||||||
|
"label_no_indent": "false",
|
||||||
|
"local_assign_continuation_align_to_first_expression": "false",
|
||||||
|
"local_function_name_define_style": "camel_case",
|
||||||
|
"local_name_define_style": "snake_case",
|
||||||
|
"long_chain_expression_allow_one_space_after_colon": "false",
|
||||||
|
"max_continuous_line_distance": "0",
|
||||||
|
"max_line_length": "100",
|
||||||
|
"module_name_define_style": "same('this')|same(filename, snake_case|pascal_case|camel_case)",
|
||||||
|
"quote_style": "double",
|
||||||
|
"remove_empty_header_and_footer_lines_in_function": "true",
|
||||||
|
"remove_expression_list_finish_comma": "true",
|
||||||
|
"require_module_name_style": "off",
|
||||||
|
"space_before_function_open_parenthesis": "false",
|
||||||
|
"space_before_open_square_bracket": "false",
|
||||||
|
"space_inside_function_call_parentheses": "false",
|
||||||
|
"space_inside_function_param_list_parentheses": "false",
|
||||||
|
"space_inside_square_brackets": "false",
|
||||||
|
"statement_inline_comment_space": "1",
|
||||||
|
"table_append_expression_no_space": "true",
|
||||||
|
"table_field_name_define_style": "snake_case",
|
||||||
|
"table_seperator_style": "comma",
|
||||||
|
"trailing_table_separator": "smart"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/*==============================================================================================*\
|
||||||
|
|* HINT: Controls the behavior of inline hints. *|
|
||||||
|
\*==============================================================================================*/
|
||||||
|
"hint": {
|
||||||
|
// Enable inline hints.
|
||||||
|
"enable": true,
|
||||||
|
|
||||||
|
// Show an inline hint at assignment.
|
||||||
|
"setType": true,
|
||||||
|
|
||||||
|
// Parameter settings.
|
||||||
|
"paramName": "All", // Show the name of parameters in function calls.
|
||||||
|
"paramType": true, // Show the type of parameters in function definitions.
|
||||||
|
|
||||||
|
// Show a virtual "await" next to called async functions.
|
||||||
|
"await": true,
|
||||||
|
|
||||||
|
// Show virtual number indexes if it may be hard to count them.
|
||||||
|
"arrayIndex": "Auto",
|
||||||
|
|
||||||
|
// Show a virtual semicolon to seperate statements on the same line.
|
||||||
|
"semicolon": "Disable"
|
||||||
|
},
|
||||||
|
|
||||||
|
/*==============================================================================================*\
|
||||||
|
|* HOVER: Controls the behavior of hover hints. *|
|
||||||
|
\*==============================================================================================*/
|
||||||
|
"hover": {
|
||||||
|
// Enable hover hints.
|
||||||
|
"enable": true,
|
||||||
|
|
||||||
|
// Allows large enum lists to be visible.
|
||||||
|
"enumsLimit": 100,
|
||||||
|
|
||||||
|
// Stops enum lists from making huge inline hints.
|
||||||
|
"expandAlias": false,
|
||||||
|
|
||||||
|
// Allows large tables to be visible.
|
||||||
|
"previewFields": 100,
|
||||||
|
|
||||||
|
// Allow viewing the raw form of a value.
|
||||||
|
"viewNumber": true,
|
||||||
|
"viewString": true,
|
||||||
|
"viewStringMax": 1024
|
||||||
|
},
|
||||||
|
|
||||||
|
/*==============================================================================================*\
|
||||||
|
|* TYPE: Controls type casting behavior. *|
|
||||||
|
\*==============================================================================================*/
|
||||||
|
"type": {
|
||||||
|
// Allows casting between `number` and `integer` (since they are the same thing in Lua.)
|
||||||
|
"castNumberToInteger": true,
|
||||||
|
|
||||||
|
// Allow "casting out" nil. (i.e: You can assign `number` to `number|nil`.)
|
||||||
|
"weakNilCheck": true,
|
||||||
|
|
||||||
|
// Disallow forced narrowing of union types. You must explicitly narrow with code.
|
||||||
|
"weakUnionCheck": false
|
||||||
|
},
|
||||||
|
|
||||||
|
/*==============================================================================================*\
|
||||||
|
|* SEMANTIC: Controls semantic coloring. *|
|
||||||
|
\*==============================================================================================*/
|
||||||
|
"semantic": {
|
||||||
|
// Enable semantic coloring.
|
||||||
|
"enable": true,
|
||||||
|
|
||||||
|
// Enable coloring for type annotations.
|
||||||
|
"annotation": true,
|
||||||
|
|
||||||
|
// VSCode already handles keyword coloring.
|
||||||
|
"keyword": false,
|
||||||
|
|
||||||
|
// Enable coloring for variables.
|
||||||
|
"variable": true
|
||||||
|
},
|
||||||
|
|
||||||
|
/*==============================================================================================*\
|
||||||
|
|* SIGNATURE HELP: No clue lol. *|
|
||||||
|
\*==============================================================================================*/
|
||||||
|
"signatureHelp": {
|
||||||
|
// Enables this, whatever it is.
|
||||||
|
"enable": true
|
||||||
|
},
|
||||||
|
|
||||||
|
/*==============================================================================================*\
|
||||||
|
|* SPELL: Controls the spell-check dictionary. *|
|
||||||
|
\*==============================================================================================*/
|
||||||
|
"spell": {
|
||||||
|
// Custom words for spell-check.
|
||||||
|
"dict": [
|
||||||
|
"figura"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
/*==============================================================================================*\
|
||||||
|
|* TELEMETRY: Big brother is watching. *|
|
||||||
|
\*==============================================================================================*/
|
||||||
|
"telemetry": {
|
||||||
|
// If you wish to send telemetry data, you can enable this.
|
||||||
|
"enable": false
|
||||||
|
},
|
||||||
|
|
||||||
|
/*==============================================================================================*\
|
||||||
|
|* WINDOW: Controls the VSCode window's behavior. *|
|
||||||
|
\*==============================================================================================*/
|
||||||
|
"window": {
|
||||||
|
// Show workspace loading progress in the taskbar.
|
||||||
|
"progressBar": true,
|
||||||
|
|
||||||
|
// Show a funny little "😺Lua" indicator in the status bar while the Lua server is running.
|
||||||
|
"statusBar": true
|
||||||
|
},
|
||||||
|
|
||||||
|
/*==============================================================================================*\
|
||||||
|
|* MISC: Controls other features and behaviors. *|
|
||||||
|
\*==============================================================================================*/
|
||||||
|
"misc": {
|
||||||
|
// Startup parameters for the Lua language server.
|
||||||
|
"parameters": []
|
||||||
|
}
|
||||||
|
}
|
1
.vim/figuradocs
Submodule
1
.vim/figuradocs
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit a0c2690a3f71db97e0603347bdc20b8e7b2cd8e0
|
5
avatar.json
Normal file
5
avatar.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"name": "Yzum <3",
|
||||||
|
"author": "NullBite",
|
||||||
|
"autoScripts": ["script"]
|
||||||
|
}
|
4
export.sh
Executable file
4
export.sh
Executable file
@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
rm yzum.zip
|
||||||
|
git submodule update --init --recursive
|
||||||
|
find . -mindepth 1 -maxdepth 1 -not \( -name '*.xcf' -o -name '.*' -o -name '*.md' -o -name '*.sh' \) -exec apack yzum.zip '{}' +
|
1
nulllib
Submodule
1
nulllib
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit a65b6b323dc7c3c80f0305b28f126cd9d2b317ac
|
File diff suppressed because one or more lines are too long
693
script.lua
693
script.lua
@ -1,312 +1,41 @@
|
|||||||
-- vim: set foldmethod=marker ts=4 sw=4 :
|
-- vim: set foldmethod=marker ts=4 sw=4 :
|
||||||
-- from figura-protogen commit f3687a4
|
-- from figura-protogen commit f3687a4
|
||||||
--- Initial definitions ---
|
--- Initial definitions ---
|
||||||
|
-- rewrite compat
|
||||||
|
model=models.player_model
|
||||||
|
ping=pings
|
||||||
|
|
||||||
-- Texture dimensions --
|
-- Texture dimensions --
|
||||||
TEXTURE_WIDTH = 128
|
TEXTURE_WIDTH = 128
|
||||||
TEXTURE_HEIGHT = 128
|
TEXTURE_HEIGHT = 128
|
||||||
|
|
||||||
-- utility functions -- {{{
|
PartsManager=require("nulllib.PartsManager")
|
||||||
|
UVManager=require("nulllib.UVManager")
|
||||||
|
logging=require("nulllib.logging")
|
||||||
|
nmath=require("nulllib.math")
|
||||||
|
timers=require("nulllib.timers")
|
||||||
|
util=require("nulllib.util")
|
||||||
|
sharedstate=require("nulllib.sharedstate")
|
||||||
|
sharedconfig=require("nulllib.sharedconfig")
|
||||||
|
|
||||||
--- Create a string representation of a table
|
wave=nmath.wave
|
||||||
--- @param o table
|
lerp=math.lerp
|
||||||
function dumpTable(o)
|
|
||||||
if type(o) == 'table' then
|
|
||||||
local s = '{ '
|
|
||||||
local first_loop=true
|
|
||||||
for k,v in pairs(o) do
|
|
||||||
if not first_loop then
|
|
||||||
s = s .. ', '
|
|
||||||
end
|
|
||||||
first_loop=false
|
|
||||||
if type(k) ~= 'number' then k = '"'..k..'"' end
|
|
||||||
s = s .. '['..k..'] = ' .. dumpTable(v)
|
|
||||||
end
|
|
||||||
return s .. '} '
|
|
||||||
else
|
|
||||||
return tostring(o)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
do
|
-- Master config -- {{{
|
||||||
local function format_any_value(obj, buffer)
|
|
||||||
local _type = type(obj)
|
|
||||||
if _type == "table" then
|
|
||||||
buffer[#buffer + 1] = '{"'
|
|
||||||
for key, value in next, obj, nil do
|
|
||||||
buffer[#buffer + 1] = tostring(key) .. '":'
|
|
||||||
format_any_value(value, buffer)
|
|
||||||
buffer[#buffer + 1] = ',"'
|
|
||||||
end
|
|
||||||
buffer[#buffer] = '}' -- note the overwrite
|
|
||||||
elseif _type == "string" then
|
|
||||||
buffer[#buffer + 1] = '"' .. obj .. '"'
|
|
||||||
elseif _type == "boolean" or _type == "number" then
|
|
||||||
buffer[#buffer + 1] = tostring(obj)
|
|
||||||
else
|
|
||||||
buffer[#buffer + 1] = '"???' .. _type .. '???"'
|
|
||||||
end
|
|
||||||
end
|
|
||||||
--- Dumps object as UNSAFE json, i stole this from stackoverflow so i could use json.tool to format it so it's easier to read
|
|
||||||
function dumpJSON(obj)
|
|
||||||
if obj == nil then return "null" else
|
|
||||||
local buffer = {}
|
|
||||||
format_any_value(obj, buffer)
|
|
||||||
return table.concat(buffer)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
---@param uv table
|
|
||||||
function UV(uv)
|
|
||||||
return vectors.of({
|
|
||||||
uv[1]/TEXTURE_WIDTH,
|
|
||||||
uv[2]/TEXTURE_HEIGHT
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
---@param inputstr string
|
|
||||||
---@param sep string
|
|
||||||
function splitstring (inputstr, sep)
|
|
||||||
if sep == nil then
|
|
||||||
sep = "%s"
|
|
||||||
end
|
|
||||||
local t={}
|
|
||||||
for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
|
|
||||||
table.insert(t, str)
|
|
||||||
end
|
|
||||||
return t
|
|
||||||
end
|
|
||||||
|
|
||||||
---@param input string
|
|
||||||
function unstring(input)
|
|
||||||
if input=="nil" then
|
|
||||||
return nil
|
|
||||||
elseif input == "true" or input == "false" then
|
|
||||||
return input=="true"
|
|
||||||
elseif tonumber(input) ~= nil then
|
|
||||||
return tonumber(input)
|
|
||||||
else
|
|
||||||
return input
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
---@param func function
|
|
||||||
---@param table table
|
|
||||||
function map(func, table)
|
|
||||||
local t={}
|
|
||||||
for k, v in pairs(table) do
|
|
||||||
t[k]=func(v)
|
|
||||||
end
|
|
||||||
return t
|
|
||||||
end
|
|
||||||
|
|
||||||
---@param func function
|
|
||||||
---@param table table
|
|
||||||
function filter(func, table)
|
|
||||||
local t={}
|
|
||||||
for k, v in pairs(table) do
|
|
||||||
if func(v) then
|
|
||||||
t[k]=v
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return t
|
|
||||||
end
|
|
||||||
|
|
||||||
---@param tbl table
|
|
||||||
---@param val any
|
|
||||||
function has_value(tbl, val)
|
|
||||||
for _, v in pairs(tbl) do
|
|
||||||
if v==val then return true end
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Unordered reduction, only use when working with dictionaries and
|
|
||||||
--- execution order does not matter
|
|
||||||
---@param tbl table Table to reduce
|
|
||||||
---@param func function Function used to reduce table
|
|
||||||
---@param init any Initial operand for reduce function
|
|
||||||
function reduce(func, tbl, init)
|
|
||||||
local result = init
|
|
||||||
local first_loop = true
|
|
||||||
for _, v in pairs(tbl) do
|
|
||||||
if first_loop and init == nil then
|
|
||||||
result=v
|
|
||||||
else
|
|
||||||
result = func(result, v)
|
|
||||||
end
|
|
||||||
first_loop=false
|
|
||||||
end
|
|
||||||
return result
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Ordered reduction, does not work with dictionaries
|
|
||||||
---@param tbl table Table to reduce
|
|
||||||
---@param func function Function used to reduce table
|
|
||||||
---@param init any Initial operand for reduce function
|
|
||||||
function ireduce(func, tbl, init)
|
|
||||||
local result = init
|
|
||||||
local first_loop = true
|
|
||||||
for _, v in ipairs(tbl) do
|
|
||||||
if first_loop and init == nil then
|
|
||||||
result=v
|
|
||||||
else
|
|
||||||
result = func(result, v)
|
|
||||||
end
|
|
||||||
first_loop=false
|
|
||||||
end
|
|
||||||
return result
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Merge two tables. First table value takes precedence when conflict occurs.
|
|
||||||
---@param tb1 table
|
|
||||||
---@param tb2 table
|
|
||||||
function mergeTable(tb1, tb2)
|
|
||||||
local t={}
|
|
||||||
for k, v in pairs(tb1) do
|
|
||||||
t[k]=v
|
|
||||||
end
|
|
||||||
for k, v in pairs(tb2) do
|
|
||||||
if type(k)=="number" then
|
|
||||||
table.insert(t, v)
|
|
||||||
else
|
|
||||||
if t[k]==nil then
|
|
||||||
t[k]=v
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return t
|
|
||||||
end
|
|
||||||
|
|
||||||
function debugPrint(var)
|
|
||||||
print(dumpTable(var))
|
|
||||||
return var
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Recursively walk a model tree and return a table containing the group and each of its sub-groups
|
|
||||||
--- @param group table The group to recurse
|
|
||||||
--- @return table Resulting table
|
|
||||||
function recurseModelGroup(group)
|
|
||||||
local t={}
|
|
||||||
table.insert(t, group)
|
|
||||||
if group.getType()=="GROUP" then
|
|
||||||
for k, v in pairs(group.getChildren()) do
|
|
||||||
for _, v2 in pairs(recurseModelGroup(v)) do
|
|
||||||
table.insert(t, v2)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return t
|
|
||||||
end
|
|
||||||
-- }}}
|
|
||||||
|
|
||||||
-- Timer (not mine lol) -- {{{
|
|
||||||
do
|
|
||||||
local timers = {}
|
|
||||||
function wait(ticks,next)
|
|
||||||
table.insert(timers, {t=world.getTime()+ticks,n=next})
|
|
||||||
end
|
|
||||||
function tick()
|
|
||||||
for key,timer in pairs(timers) do
|
|
||||||
if world.getTime() >= timer.t then
|
|
||||||
timer.n()
|
|
||||||
table.remove(timers,key)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- named timers (this one is mine but heavily based on the other) --
|
|
||||||
-- if timer is armed twice before expiring it will only be called once) --
|
|
||||||
do
|
|
||||||
local timers = {}
|
|
||||||
function namedWait(ticks, next, name)
|
|
||||||
-- main difference, this will overwrite an existing timer with
|
|
||||||
-- the same name
|
|
||||||
timers[name]={t=world.getTime()+ticks,n=next}
|
|
||||||
end
|
|
||||||
function tick()
|
|
||||||
for key, timer in pairs(timers) do
|
|
||||||
if world.getTime() >= timer.t then
|
|
||||||
timer.n()
|
|
||||||
timers[key]=nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- named cooldowns
|
|
||||||
do
|
|
||||||
local timers={}
|
|
||||||
function cooldown(ticks, name)
|
|
||||||
if timers[name] == nil then
|
|
||||||
timers[name]={t=world.getTime()+ticks}
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
function tick()
|
|
||||||
for key, timer in pairs(timers) do
|
|
||||||
if world.getTime() >= timer.t then
|
|
||||||
timers[key]=nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function rateLimit(ticks, next, name)
|
|
||||||
if cooldown(ticks+1, name) then
|
|
||||||
namedWait(ticks, next, name)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- }}}
|
|
||||||
|
|
||||||
-- syncState {{{
|
|
||||||
function syncState()
|
|
||||||
ping.syncState(setLocalState())
|
|
||||||
end
|
|
||||||
|
|
||||||
do
|
|
||||||
local pm_refresh=false
|
|
||||||
function pmRefresh()
|
|
||||||
pm_refresh=true
|
|
||||||
end
|
|
||||||
|
|
||||||
function doPmRefresh()
|
|
||||||
if pm_refresh then
|
|
||||||
PartsManager.refreshAll()
|
|
||||||
pm_refresh=false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function ping.syncState(tbl)
|
|
||||||
for k, v in pairs(tbl) do
|
|
||||||
local_state[k]=v
|
|
||||||
end
|
|
||||||
pmRefresh()
|
|
||||||
end
|
|
||||||
-- }}}
|
|
||||||
|
|
||||||
-- Math {{{
|
|
||||||
--- Sine function with period and amplitude
|
|
||||||
--- @param x number Input value
|
|
||||||
--- @param period number Period of sine wave
|
|
||||||
--- @param amp number Peak amplitude of sine wave
|
|
||||||
function wave(x, period, amp) return math.sin((2/period)*math.pi*(x%period))*amp end
|
|
||||||
function lerp(a, b, t) return a + ((b - a) * t) end
|
|
||||||
-- }}}
|
|
||||||
|
|
||||||
-- Master and local state variables -- {{{
|
|
||||||
-- Local State (these are copied by pings at runtime) --
|
-- Local State (these are copied by pings at runtime) --
|
||||||
|
---@deprecated use sharedstate or sharedconfig
|
||||||
local_state={}
|
local_state={}
|
||||||
|
---@deprecated use sharedstate or sharedconfig
|
||||||
old_state={}
|
old_state={}
|
||||||
-- master state variables and configuration (do not access within pings) --
|
-- master state variables and configuration (do not access within pings) --
|
||||||
do
|
do
|
||||||
local is_host=client.isHost()
|
local function refresh_armor()
|
||||||
|
if player:isLoaded() then PartsManager.refreshPartList(VANILLA_GROUPS.ARMOR) end
|
||||||
|
end
|
||||||
|
local function refresh_tail()
|
||||||
|
if player:isLoaded() then PartsManager.refreshPart(model.Body_Tail) end
|
||||||
|
end
|
||||||
|
|
||||||
local defaults={
|
local defaults={
|
||||||
["armor_enabled"]=true,
|
["armor_enabled"]=true,
|
||||||
["vanilla_enabled"]=false,
|
["vanilla_enabled"]=false,
|
||||||
@ -314,275 +43,117 @@ do
|
|||||||
["print_settings"]=false,
|
["print_settings"]=false,
|
||||||
["tail_enabled"]=true,
|
["tail_enabled"]=true,
|
||||||
}
|
}
|
||||||
function setLocalState()
|
local callbacks={
|
||||||
if is_host then
|
["armor_enabled"]=refresh_armor,
|
||||||
for k, v in pairs(skin_state) do
|
["tail_enabled"]=refresh_tail
|
||||||
local_state[k]=v
|
}
|
||||||
end
|
|
||||||
else
|
sharedconfig.load_defaults(defaults, callbacks)
|
||||||
for k, v in pairs(defaults) do
|
|
||||||
if local_state[k] == nil then local_state[k]=v end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return local_state
|
|
||||||
end
|
|
||||||
if is_host then
|
|
||||||
local savedData=data.loadAll()
|
|
||||||
if savedData == nil then
|
|
||||||
for k, v in pairs(defaults) do
|
|
||||||
data.save(k, v)
|
|
||||||
end
|
|
||||||
savedData=data.loadAll()
|
|
||||||
end
|
|
||||||
skin_state=mergeTable(
|
|
||||||
map(unstring,data.loadAll()),
|
|
||||||
defaults)
|
|
||||||
else
|
|
||||||
skin_state=defaults
|
|
||||||
end
|
|
||||||
setLocalState()
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function printSettings()
|
function printSettings()
|
||||||
print("Settings:")
|
print("Settings:")
|
||||||
for k, v in pairs(skin_state) do
|
printTable(sharedconfig.load())
|
||||||
print(tostring(k)..": "..tostring(v))
|
|
||||||
end
|
end
|
||||||
end
|
if sharedconfig.load("print_settings") then
|
||||||
if skin_state.print_settings==true then
|
|
||||||
printSettings()
|
printSettings()
|
||||||
end
|
end
|
||||||
|
|
||||||
function setState(name, state)
|
|
||||||
if state == nil then
|
|
||||||
skin_state[name]=not skin_state[name]
|
|
||||||
else
|
|
||||||
skin_state[name]=state
|
|
||||||
end
|
|
||||||
data.save(name, skin_state[name])
|
|
||||||
end
|
|
||||||
|
|
||||||
-- }}}
|
|
||||||
|
|
||||||
-- PartsManager -- {{{
|
|
||||||
do
|
|
||||||
PartsManager={}
|
|
||||||
local pm={}
|
|
||||||
|
|
||||||
--- ensure part is initialized
|
|
||||||
local function initPart(part)
|
|
||||||
local part_key=tostring(part)
|
|
||||||
if pm[part_key] == nil then
|
|
||||||
pm[part_key]={}
|
|
||||||
end
|
|
||||||
pm[part_key].part=part
|
|
||||||
if pm[part_key].functions == nil then
|
|
||||||
pm[part_key].functions = {}
|
|
||||||
end
|
|
||||||
if pm[part_key].init==nil then
|
|
||||||
pm[part_key].init="true"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
--- Add function to part in PartsManager.
|
|
||||||
--- @param part table Any object with a setEnabled() method.
|
|
||||||
--- @param func function Function to add to model part's function chain.
|
|
||||||
--- @param init? boolean Default value for chain. Should only be set once, subsequent uses overwrite the entire chain's initial value.
|
|
||||||
function PartsManager.addPartFunction(part, func, init)
|
|
||||||
initPart(part)
|
|
||||||
local part_key=tostring(part)
|
|
||||||
if init ~= nil then
|
|
||||||
pm[part_key].init=init
|
|
||||||
end
|
|
||||||
table.insert(pm[part_key]["functions"], func)
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Set initial value for chain.
|
|
||||||
--- @param part table Any object with a setEnabled() method.
|
|
||||||
--- @param init? boolean Default value for chain. Should only be set once, subsequent uses overwrite the entire chain's initial value.
|
|
||||||
function PartsManager.setInitialValue(part, init)
|
|
||||||
assert(init~=nil)
|
|
||||||
initPart(part)
|
|
||||||
local part_key=tostring(part)
|
|
||||||
pm[part_key].init=init
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Set initial value for chain on all objects in table.
|
|
||||||
--- @param group table A table containing objects with a setEnabled() method.
|
|
||||||
--- @param init? boolean Default value for chain. Should only be set once, subsequent uses overwrite the entire chain's initial value.
|
|
||||||
function PartsManager.setGroupInitialValue(group, init)
|
|
||||||
assert(init~=nil)
|
|
||||||
for _, v in pairs(group) do
|
|
||||||
PartsManager.setInitialValue(v, init)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Evaluate a part's chain to determine if it should be visible.
|
|
||||||
--- @param part table An object managed by PartsManager.
|
|
||||||
function PartsManager.evaluatePart(part)
|
|
||||||
local part_key=tostring(part)
|
|
||||||
assert(pm[part_key] ~= nil)
|
|
||||||
|
|
||||||
local evalFunc=function(x, y) return y(x) end
|
|
||||||
local init=pm[part_key].init
|
|
||||||
return ireduce(evalFunc, pm[part_key].functions, true)
|
|
||||||
end
|
|
||||||
local evaluatePart=PartsManager.evaluatePart
|
|
||||||
|
|
||||||
--- Refresh (enable or disable) a part based on the result of it's chain.
|
|
||||||
--- @param part table An object managed by PartsManager.
|
|
||||||
function PartsManager.refreshPart(part)
|
|
||||||
local part_enabled=evaluatePart(part)
|
|
||||||
part.setEnabled(part_enabled)
|
|
||||||
return part_enabled
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Refresh all parts managed by PartsManager.
|
|
||||||
function PartsManager.refreshAll()
|
|
||||||
for _, v in pairs(pm) do
|
|
||||||
PartsManager.refreshPart(v.part)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Add function to list of parts in PartsManager
|
|
||||||
--- @param group table A table containing objects with a setEnabled() method.
|
|
||||||
--- @param func function Function to add to each model part's function chain.
|
|
||||||
--- @param default? boolean Default value for chain. Should only be set once, subsequent uses overwrite the entire chain's initial value.
|
|
||||||
function PartsManager.addPartGroupFunction(group, func, default)
|
|
||||||
for _, v in ipairs(group) do
|
|
||||||
PartsManager.addPartFunction(v, func, default)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-- }}}
|
|
||||||
|
|
||||||
-- UVManager {{{
|
|
||||||
do
|
|
||||||
local mt={}
|
|
||||||
UVManager = {
|
|
||||||
step=vectors.of{u=0, v=0},
|
|
||||||
offset=vectors.of{u=0, v=0},
|
|
||||||
positions={}
|
|
||||||
}
|
|
||||||
mt.__index=UVManager
|
|
||||||
function UVManager.new(self, step, offset, positions)
|
|
||||||
local t={}
|
|
||||||
if step ~= nil then t.step=vectors.of(step) end
|
|
||||||
if offset ~= nil then t.offset=vectors.of(offset) end
|
|
||||||
if positions ~= nil then t.positions=positions end
|
|
||||||
t=setmetatable(t, mt)
|
|
||||||
return t
|
|
||||||
end
|
|
||||||
function UVManager.getUV(self, input)
|
|
||||||
local vec={}
|
|
||||||
local stp=self.step
|
|
||||||
local offset=self.offset
|
|
||||||
if type(input) == "string" then
|
|
||||||
if self.positions[input] == nil then return nil end
|
|
||||||
vec=vectors.of(self.positions[input])
|
|
||||||
else
|
|
||||||
vec=vectors.of(input)
|
|
||||||
end
|
|
||||||
local u=offset.u+(vec.u*stp.u)
|
|
||||||
local v=offset.v+(vec.v*stp.v)
|
|
||||||
return UV{u, v}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-- }}}
|
-- }}}
|
||||||
|
|
||||||
-- Part groups {{{
|
-- Part groups {{{
|
||||||
VANILLA_GROUPS={
|
VANILLA_GROUPS={
|
||||||
["HEAD"]={vanilla_model.HEAD, vanilla_model.HAT},
|
["HEAD"]={vanilla_model.HEAD, vanilla_model.HAT},
|
||||||
["TORSO"]={vanilla_model.TORSO, vanilla_model.JACKET},
|
["TORSO"]={vanilla_model.BODY, vanilla_model.JACKET},
|
||||||
["LEFT_ARM"]={vanilla_model.LEFT_ARM, vanilla_model.LEFT_SLEEVE},
|
["LEFT_ARM"]={vanilla_model.LEFT_ARM, vanilla_model.LEFT_SLEEVE},
|
||||||
["RIGHT_ARM"]={vanilla_model.RIGHT_ARM, vanilla_model.RIGHT_SLEEVE},
|
["RIGHT_ARM"]={vanilla_model.RIGHT_ARM, vanilla_model.RIGHT_SLEEVE},
|
||||||
["LEFT_LEG"]={vanilla_model.LEFT_LEG, vanilla_model.LEFT_PANTS_LEG},
|
["LEFT_LEG"]={vanilla_model.LEFT_LEG, vanilla_model.LEFT_PANTS},
|
||||||
["RIGHT_LEG"]={vanilla_model.RIGHT_LEG, vanilla_model.RIGHT_PANTS_LEG},
|
["RIGHT_LEG"]={vanilla_model.RIGHT_LEG, vanilla_model.RIGHT_PANTS},
|
||||||
["OUTER"]={ vanilla_model.HAT, vanilla_model.JACKET, vanilla_model.LEFT_SLEEVE, vanilla_model.RIGHT_SLEEVE, vanilla_model.LEFT_PANTS_LEG, vanilla_model.RIGHT_PANTS_LEG },
|
["OUTER"]={ vanilla_model.HAT, vanilla_model.JACKET, vanilla_model.LEFT_SLEEVE, vanilla_model.RIGHT_SLEEVE, vanilla_model.LEFT_PANTS, vanilla_model.RIGHT_PANTS },
|
||||||
["INNER"]={ vanilla_model.HEAD, vanilla_model.TORSO, vanilla_model.LEFT_ARM, vanilla_model.RIGHT_ARM, vanilla_model.LEFT_LEG, vanilla_model.RIGHT_LEG },
|
["INNER"]={ vanilla_model.HEAD, vanilla_model.BODY, vanilla_model.LEFT_ARM, vanilla_model.RIGHT_ARM, vanilla_model.LEFT_LEG, vanilla_model.RIGHT_LEG },
|
||||||
["ALL"]={},
|
["ALL"]={},
|
||||||
["ARMOR"]={}
|
["ARMOR"]={vanilla_model.HELMET, vanilla_model.LEGGINGS, vanilla_model.BOOTS, vanilla_model.CHESTPLATE}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, v in pairs(VANILLA_GROUPS.INNER) do table.insert(VANILLA_GROUPS.ALL,v) end
|
for _, v in pairs(VANILLA_GROUPS.INNER) do table.insert(VANILLA_GROUPS.ALL,v) end
|
||||||
for _, v in pairs(VANILLA_GROUPS.OUTER) do table.insert(VANILLA_GROUPS.ALL,v) end
|
for _, v in pairs(VANILLA_GROUPS.OUTER) do table.insert(VANILLA_GROUPS.ALL,v) end
|
||||||
for _, v in pairs(armor_model) do table.insert(VANILLA_GROUPS.ARMOR, v) end
|
|
||||||
|
|
||||||
MAIN_GROUPS={model.Head, model.RightArm, model.LeftArm, model.RightLeg, model.LeftLeg, model.Body } -- RightArm LeftArm RightLeg LeftLeg Body Head
|
MAIN_GROUPS={model.Head, model.RightArm, model.LeftArm, model.RightLeg, model.LeftLeg, model.Body } -- RightArm LeftArm RightLeg LeftLeg Body Head
|
||||||
TAIL_BONES={model.Body_Tail, model.Body_Tail.Tail2, model.Body_Tail.Tail2.Tail3, model.Body_Tail.Tail2.Tail3.Tail4}
|
TAIL_BONES={model.Body_Tail, model.Body_Tail.Tail2, model.Body_Tail.Tail2.Tail3, model.Body_Tail.Tail2.Tail3.Tail4}
|
||||||
|
|
||||||
TAIL_ROT={vectors.of{37.5, 0, 0}, vectors.of{-17.5, 0, 0}, vectors.of{-17.5, 0, 0}, vectors.of{-15, 0, 0}}
|
TAIL_ROT={vec( 37.5, 0, 0 ), vec( -17.5, 0, 0 ), vec( -17.5, 0, 0 ), vec( -15, 0, 0 )}
|
||||||
-- }}}
|
-- }}}
|
||||||
|
|
||||||
-- Enable commands -- {{{
|
-- -- Enable commands -- {{{
|
||||||
chat_prefix="$"
|
-- chat_prefix="$"
|
||||||
chat.setFiguraCommandPrefix(chat_prefix)
|
-- chat.setFiguraCommandPrefix(chat_prefix)
|
||||||
function onCommand(input)
|
-- function onCommand(input)
|
||||||
local pfx=chat_prefix
|
-- local pfx=chat_prefix
|
||||||
input=splitstring(input)
|
-- input=splitstring(input)
|
||||||
if input[1] == chat_prefix .. "vanilla" then
|
-- if input[1] == chat_prefix .. "vanilla" then
|
||||||
setVanilla()
|
-- setVanilla()
|
||||||
print("Vanilla skin is now " .. (skin_state.vanilla_enabled and "enabled" or "disabled"))
|
-- print("Vanilla skin is now " .. (skin_state.vanilla_enabled and "enabled" or "disabled"))
|
||||||
end
|
-- end
|
||||||
if input[1] == chat_prefix .. "toggle_custom" then
|
-- if input[1] == chat_prefix .. "toggle_custom" then
|
||||||
for key, value in pairs(model) do
|
-- for key, value in pairs(model) do
|
||||||
value.setEnabled(not value.getEnabled())
|
-- value.setEnabled(not value.getEnabled())
|
||||||
end
|
-- end
|
||||||
end
|
-- end
|
||||||
if input[1] == chat_prefix .. "toggle_outer" then
|
-- if input[1] == chat_prefix .. "toggle_outer" then
|
||||||
for k, v in pairs(VANILLA_GROUPS.OUTER) do
|
-- for k, v in pairs(VANILLA_GROUPS.OUTER) do
|
||||||
v.setEnabled(not v.getEnabled())
|
-- v.setEnabled(not v.getEnabled())
|
||||||
end
|
-- end
|
||||||
end
|
-- end
|
||||||
if input[1] == chat_prefix .. "toggle_inner" then
|
-- if input[1] == chat_prefix .. "toggle_inner" then
|
||||||
for k, v in pairs(VANILLA_GROUPS.INNER) do
|
-- for k, v in pairs(VANILLA_GROUPS.INNER) do
|
||||||
v.setEnabled(not v.getEnabled())
|
-- v.setEnabled(not v.getEnabled())
|
||||||
end
|
-- end
|
||||||
end
|
-- end
|
||||||
if input[1] == chat_prefix .. "test_expression" then
|
-- if input[1] == chat_prefix .. "test_expression" then
|
||||||
setExpression(input[2], input[3])
|
-- setExpression(input[2], input[3])
|
||||||
print(input[2] .. " " .. input[3])
|
-- print(input[2] .. " " .. input[3])
|
||||||
end
|
-- end
|
||||||
if input[1] == chat_prefix .. "snore" then
|
-- if input[1] == chat_prefix .. "snore" then
|
||||||
if input[2] == "toggle" or #input==1 then
|
-- if input[2] == "toggle" or #input==1 then
|
||||||
setSnoring()
|
-- setSnoring()
|
||||||
log("Snoring is now " .. (skin_state.snore_enabled and "enabled" or "disabled"))
|
-- log("Snoring is now " .. (skin_state.snore_enabled and "enabled" or "disabled"))
|
||||||
end
|
-- end
|
||||||
end
|
-- end
|
||||||
if input[1] == chat_prefix .. "armor" then
|
-- if input[1] == chat_prefix .. "armor" then
|
||||||
setArmor()
|
-- setArmor()
|
||||||
log("Armor is now " .. (skin_state.armor_enabled and "enabled" or "disabled"))
|
-- log("Armor is now " .. (skin_state.armor_enabled and "enabled" or "disabled"))
|
||||||
end
|
-- end
|
||||||
if input[1] == chat_prefix .. "settings" then
|
-- if input[1] == chat_prefix .. "settings" then
|
||||||
if #input==1 then
|
-- if #input==1 then
|
||||||
printSettings()
|
-- printSettings()
|
||||||
elseif #input==2 then
|
-- elseif #input==2 then
|
||||||
log(tostring(skin_state[input[2]]))
|
-- log(tostring(skin_state[input[2]]))
|
||||||
elseif #input==3 then
|
-- elseif #input==3 then
|
||||||
if skin_state[input[2]] ~= nil then
|
-- if skin_state[input[2]] ~= nil then
|
||||||
setState(input[2], unstring(input[3]))
|
-- setState(input[2], unstring(input[3]))
|
||||||
log(tostring(input[2]) .. " is now " .. tostring(skin_state[input[2]]))
|
-- log(tostring(input[2]) .. " is now " .. tostring(skin_state[input[2]]))
|
||||||
syncState()
|
-- syncState()
|
||||||
else
|
-- else
|
||||||
log(tostring(input[2]) .. ": no such setting")
|
-- log(tostring(input[2]) .. ": no such setting")
|
||||||
end
|
-- end
|
||||||
end
|
-- end
|
||||||
end
|
-- end
|
||||||
if input[1] == chat_prefix .. "pv" then
|
-- if input[1] == chat_prefix .. "pv" then
|
||||||
setState("vanilla_partial")
|
-- setState("vanilla_partial")
|
||||||
syncState()
|
-- syncState()
|
||||||
end
|
-- end
|
||||||
end
|
-- end
|
||||||
--}}}
|
-- --}}}
|
||||||
|
|
||||||
-- PartsManager Rules {{{
|
-- PartsManager Rules {{{
|
||||||
do
|
do
|
||||||
local can_modify_vanilla=meta.getCanModifyVanilla()
|
local can_modify_vanilla=avatar:canEditVanillaModel()
|
||||||
local function forceVanilla()
|
local function forceVanilla()
|
||||||
return not can_modify_vanilla or local_state.vanilla_enabled
|
return not can_modify_vanilla or sharedconfig.load("vanilla_enabled")
|
||||||
end
|
end
|
||||||
|
|
||||||
local function vanillaPartial()
|
local function vanillaPartial()
|
||||||
return not local_state.vanilla_enabled and local_state.vanilla_partial
|
return not sharedconfig.load("vanilla_enabled") and sharedconfig.load("vanilla_partial")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@ -591,49 +162,57 @@ do
|
|||||||
local vanilla_partial_disabled=MAIN_GROUPS
|
local vanilla_partial_disabled=MAIN_GROUPS
|
||||||
|
|
||||||
-- Vanilla state
|
-- Vanilla state
|
||||||
PM.addPartGroupFunction(VANILLA_GROUPS.ALL, function() return false end)
|
PM.addPartListFunction(VANILLA_GROUPS.ALL, function() return false end)
|
||||||
PM.addPartGroupFunction(VANILLA_GROUPS.ALL, function(last) return last or forceVanilla() end)
|
PM.addPartListFunction(VANILLA_GROUPS.ALL, function(last) return last or forceVanilla() end)
|
||||||
|
|
||||||
PM.addPartGroupFunction(VANILLA_GROUPS.ALL, function(last) return last or vanillaPartial() end)
|
PM.addPartListFunction(VANILLA_GROUPS.ALL, function(last) return last or vanillaPartial() end)
|
||||||
|
|
||||||
-- disable cape if tail enabled
|
-- disable cape if tail enabled
|
||||||
PM.addPartFunction(vanilla_model.CAPE, function(last) return last and not local_state.tail_enabled end)
|
PM.addPartFunction(vanilla_model.CAPE, function(last) return last and not sharedconfig.load("tail_enabled") end)
|
||||||
|
|
||||||
-- Custom state
|
-- Custom state
|
||||||
PM.addPartGroupFunction(vanilla_partial_disabled, function(last) return last and not vanillaPartial() end)
|
PM.addPartListFunction(vanilla_partial_disabled, function(last) return last and not vanillaPartial() end)
|
||||||
PM.addPartGroupFunction(MAIN_GROUPS, function(last) return last and not forceVanilla() end)
|
PM.addPartListFunction(MAIN_GROUPS, function(last) return last and not forceVanilla() end)
|
||||||
|
|
||||||
-- enable tail
|
-- enable tail
|
||||||
PM.addPartFunction(model.Body_Tail, function(last) return last and local_state.tail_enabled end)
|
PM.addPartFunction(model.Body_Tail, function(last) return last and sharedconfig.load("tail_enabled") end)
|
||||||
|
|
||||||
-- Armor state
|
-- Armor state
|
||||||
PM.addPartGroupFunction(VANILLA_GROUPS.ARMOR, function(last) return last and local_state.armor_enabled end)
|
PM.addPartListFunction(VANILLA_GROUPS.ARMOR, function(last) return last and sharedconfig.load("armor_enabled") end)
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
-- }}}
|
-- }}}
|
||||||
|
|
||||||
-- Action Wheel {{{
|
-- -- Action Wheel {{{
|
||||||
do
|
-- do
|
||||||
local slot_1_item = item_stack.createItem("minecraft:netherite_helmet")
|
-- local slot_1_item = item_stack.createItem("minecraft:netherite_helmet")
|
||||||
action_wheel.SLOT_1.setTitle('Toggle Armor')
|
-- action_wheel.SLOT_1.setTitle('Toggle Armor')
|
||||||
action_wheel.SLOT_1.setFunction(function() setArmor() end)
|
-- action_wheel.SLOT_1.setFunction(function() setArmor() end)
|
||||||
action_wheel.SLOT_1.setItem(slot_1_item)
|
-- action_wheel.SLOT_1.setItem(slot_1_item)
|
||||||
end
|
-- end
|
||||||
|
|
||||||
|
|
||||||
function setArmor()
|
function setArmor()
|
||||||
setState("armor_enabled")
|
sharedconfig.save("armor_enabled", not sharedconfig.load("armor_enabled"))
|
||||||
syncState()
|
|
||||||
end
|
end
|
||||||
-- }}}
|
-- }}}
|
||||||
|
|
||||||
function player_init()
|
function player_init()
|
||||||
for k, v in pairs(reduce(mergeTable, map(recurseModelGroup, model))) do
|
-- for k, v in pairs(reduce(mergeTable, map(recurseModelGroup, model))) do
|
||||||
v.setEnabled(true)
|
-- v.setEnabled(true)
|
||||||
|
-- end
|
||||||
|
-- syncState()
|
||||||
|
events.ENTITY_INIT:remove("player_init")
|
||||||
|
PartsManager.refreshAll()
|
||||||
end
|
end
|
||||||
setLocalState()
|
|
||||||
syncState()
|
events.ENTITY_INIT:register(function() return player_init() end, "player_init")
|
||||||
|
|
||||||
|
if avatar:canEditVanillaModel() then
|
||||||
|
vanilla_model.PLAYER:setVisible(false)
|
||||||
|
else
|
||||||
|
model:setVisible(false)
|
||||||
end
|
end
|
||||||
|
|
||||||
anim_tick=0
|
anim_tick=0
|
||||||
@ -650,19 +229,23 @@ function animateTail(val)
|
|||||||
local per_x=20*6
|
local per_x=20*6
|
||||||
for k, v in pairs(TAIL_BONES) do
|
for k, v in pairs(TAIL_BONES) do
|
||||||
local cascade=(k-1)*12
|
local cascade=(k-1)*12
|
||||||
TAIL_BONES[k].setRot(vectors.of{TAIL_ROT[k].x + wave(val-cascade, per_x, 3), TAIL_ROT[k].y + wave(val-cascade, per_y, 17.5), TAIL_ROT[k].z})
|
TAIL_BONES[k]:setRot(vec( TAIL_ROT[k].x + wave(val-cascade, per_x, 3), TAIL_ROT[k].y + wave(val-cascade, per_y, 17.5), TAIL_ROT[k].z ))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function tick()
|
function tick()
|
||||||
if world.getTime() % (20*10) == 0 then
|
if world.getTime() % (20*10) == 0 then
|
||||||
syncState()
|
-- TODO fix
|
||||||
|
-- syncState()
|
||||||
end
|
end
|
||||||
animateTick()
|
animateTick()
|
||||||
|
|
||||||
doPmRefresh()
|
-- TODO fix
|
||||||
|
-- doPmRefresh()
|
||||||
end
|
end
|
||||||
|
events.TICK:register(function() if player then tick() end end, "main_tick")
|
||||||
|
|
||||||
function render(delta)
|
function render(delta)
|
||||||
animateTail(lerp(old_state.anim_cycle, anim_cycle, delta))
|
animateTail(lerp(old_state.anim_cycle, anim_cycle, delta))
|
||||||
end
|
end
|
||||||
|
events.RENDER:register(function(delta) if player then render(delta) end end, "main_render")
|
||||||
|
BIN
texture.png
(Stored with Git LFS)
BIN
texture.png
(Stored with Git LFS)
Binary file not shown.
BIN
texture.xcf
(Stored with Git LFS)
BIN
texture.xcf
(Stored with Git LFS)
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user