diff --git a/.github/workflows/version-checker.yml b/.github/workflows/version-checker.yml index e9097073..fbe41136 100644 --- a/.github/workflows/version-checker.yml +++ b/.github/workflows/version-checker.yml @@ -26,8 +26,6 @@ jobs: with: files: | SMLHelper/Properties/AssemblyInfo.cs | /\[assembly: Assembly(?:File)?Version\("([0-9.]+)"\)\]/g - SMLHelper/mod_BelowZero.json | /"Version": "([0-9.]+)",/g - SMLHelper/mod_Subnautica.json | /"Version": "([0-9.]+)",/g master_repo_path: ./master - name: Add annotations diff --git a/Dependencies/Subnautica.exp/Unity.ResourceManager.dll b/Dependencies/Subnautica.exp/Unity.ResourceManager.dll new file mode 100644 index 00000000..4c73c5b9 Binary files /dev/null and b/Dependencies/Subnautica.exp/Unity.ResourceManager.dll differ diff --git a/Dependencies/Subnautica.exp/Unity.TextMeshPro.dll b/Dependencies/Subnautica.exp/Unity.TextMeshPro.dll new file mode 100644 index 00000000..29327b25 Binary files /dev/null and b/Dependencies/Subnautica.exp/Unity.TextMeshPro.dll differ diff --git a/Dependencies/Subnautica.stable/0Harmony.dll b/Dependencies/Subnautica.stable/0Harmony.dll deleted file mode 100644 index eec61353..00000000 Binary files a/Dependencies/Subnautica.stable/0Harmony.dll and /dev/null differ diff --git a/Dependencies/Subnautica.stable/0Harmony.xml b/Dependencies/Subnautica.stable/0Harmony.xml deleted file mode 100644 index d3e2602e..00000000 --- a/Dependencies/Subnautica.stable/0Harmony.xml +++ /dev/null @@ -1,2849 +0,0 @@ - - - - 0Harmony - - - - A patch priority - - - Patch last - - - Patch with very low priority - - - Patch with low priority - - - Patch with lower than normal priority - - - Patch with normal priority - - - Patch with higher than normal priority - - - Patch with high priority - - - Patch with very high priority - - - Patch first - - - Specifies the type of method - - - - This is a normal method - - - This is a getter - - - This is a setter - - - This is a constructor - - - This is a static constructor - - - Specifies the type of argument - - - - This is a normal argument - - - This is a reference argument (ref) - - - This is an out argument (out) - - - This is a pointer argument (&) - - - Specifies the type of patch - - - - Any patch - - - A prefix patch - - - A postfix patch - - - A transpiler - - - A finalizer - - - A reverse patch - - - Specifies the type of reverse patch - - - - Use the unmodified original method - - - Use the original as it is right now including previous patches but excluding future ones - - - The base class for all Harmony annotations (not meant to be used directly) - - - - The common information for all attributes - - - Annotation to define your Harmony patch methods - - - - An empty annotation can be used together with TargetMethod(s) - - - - An annotation that specifies a class to patch - The declaring class - - - - An annotation that specifies a method, property or constructor to patch - The declaring class - The argument types of the method or constructor to patch - - - - An annotation that specifies a method, property or constructor to patch - The declaring class - The name of the method, property or constructor to patch - - - - An annotation that specifies a method, property or constructor to patch - The declaring class - The name of the method, property or constructor to patch - An array of argument types to target overloads - - - - An annotation that specifies a method, property or constructor to patch - The declaring class - The name of the method, property or constructor to patch - An array of argument types to target overloads - An array of extra argument subtypes (ref, out, pointer) - - - - An annotation that specifies a method, property or constructor to patch - The declaring class - The type of entry: method, getter, setter or constructor - - - - An annotation that specifies a method, property or constructor to patch - The declaring class - The type of entry: method, getter, setter or constructor - An array of argument types to target overloads - - - - An annotation that specifies a method, property or constructor to patch - The declaring class - The type of entry: method, getter, setter or constructor - An array of argument types to target overloads - An array of extra argument subtypes (ref, out, pointer) - - - - An annotation that specifies a method, property or constructor to patch - The declaring class - The name of the method, property or constructor to patch - The type of entry: method, getter, setter or constructor - - - - An annotation that specifies a method, property or constructor to patch - The name of the method, property or constructor to patch - - - - An annotation that specifies a method, property or constructor to patch - The name of the method, property or constructor to patch - An array of argument types to target overloads - - - - An annotation that specifies a method, property or constructor to patch - The name of the method, property or constructor to patch - An array of argument types to target overloads - An array of extra argument subtypes (ref, out, pointer) - - - - An annotation that specifies a method, property or constructor to patch - The name of the method, property or constructor to patch - The type of entry: method, getter, setter or constructor - - - - An annotation that specifies a method, property or constructor to patch - The type of entry: method, getter, setter or constructor - - - - An annotation that specifies a method, property or constructor to patch - The type of entry: method, getter, setter or constructor - An array of argument types to target overloads - - - - An annotation that specifies a method, property or constructor to patch - The type of entry: method, getter, setter or constructor - An array of argument types to target overloads - An array of extra argument subtypes (ref, out, pointer) - - - - An annotation that specifies a method, property or constructor to patch - An array of argument types to target overloads - - - - An annotation that specifies a method, property or constructor to patch - An array of argument types to target overloads - An array of extra argument subtypes (ref, out, pointer) - - - - Annotation to define your standin methods for reverse patching - - - - An annotation that specifies the type of reverse patching - - - - A Harmony annotation to define that all methods in a class are to be patched - - - A Harmony annotation - - - A Harmony annotation to define patch priority - The priority - - - - A Harmony annotation - - - A Harmony annotation to define that a patch comes before another patch - The harmony ID of the other patch - - - - A Harmony annotation - - - A Harmony annotation to define that a patch comes after another patch - The harmony ID of the other patch - - - - Specifies the Prepare function in a patch class - - - Specifies the Cleanup function in a patch class - - - Specifies the TargetMethod function in a patch class - - - Specifies the TargetMethods function in a patch class - - - Specifies the Prefix function in a patch class - - - Specifies the Postfix function in a patch class - - - Specifies the Transpiler function in a patch class - - - Specifies the Finalizer function in a patch class - - - A Harmony annotation - - - The name of the original argument - - - The index of the original argument - - - The new name of the original argument - - - An annotation to declare injected arguments by name - - - An annotation to declare injected arguments by index - Zero-based index - - - - An annotation to declare injected arguments by renaming them - Name of the original argument - New name - - - - An annotation to declare injected arguments by index and renaming them - Zero-based index - New name - - - - - Specifies the indices of parameters that are ByRef. - For use with overload only. - - - - - The indices of parameters that are ByRef. - - - - The indices of parameters that are ByRef. - - - - An exception thrown when a patch argument in a Harmony patch is invalid. - - - - - Original method to be patched. - - - - - Patch that was attempted to be applied. - - - - - - - - Constructs a new exception instance. - - Message of the exception. - Original method to be patched. - Patch that was attempted to be applied. - - - - An exception thrown when a reflection member is not found. - - - - - - - The Harmony instance is the main entry to Harmony. After creating one with an unique identifier, it is used to patch and query the current application domain - - - The unique identifier - - - Set to true before instantiating Harmony to debug Harmony - - - Set to false before instantiating Harmony to prevent Harmony from patching other older instances of itself - - - Creates a new Harmony instance - A unique identifier - A Harmony instance - - - - Searches current assembly for Harmony annotations and uses them to create patches - - - - Create a patch processor from an annotated class - The class - - - - Searches an assembly for Harmony annotations and uses them to create patches - The assembly - - - - Creates patches by manually specifying the methods - The original method - An optional prefix method wrapped in a HarmonyMethod object - An optional postfix method wrapped in a HarmonyMethod object - An optional transpiler method wrapped in a HarmonyMethod object - An optional finalizer method wrapped in a HarmonyMethod object - The dynamic method that was created to patch the original method - - - - Patches a foreign method onto a stub method of yours and optionally applies transpilers during the process - The original method/constructor you want to duplicate - Your stub method that will become the original. Needs to have the correct signature (either original or whatever your transpilers generates) - An optional transpiler that will be applied during the process - - - - Creates a new reverse patch instance that allows to copy the IL of original method into another one. - - Original method to copy IL from. - Method to copy IL to. - Reverse patcher instance that you can apply. - - - Unpatches methods - The optional Harmony ID to restrict unpatching to a specific instance - - - - Unpatches a method - The original method - The patch type - The optional Harmony ID to restrict unpatching to a specific instance - - - - Unpatches a method - The original method - The patch method to remove - - - - Test for patches from a specific Harmony ID - The Harmony ID - True if patches for this ID exist - - - - Gets patch information for a given original method - The original method - The patch information - - - - Gets the methods this instance has patched - An enumeration of original methods - - - - Gets all patched methods in the appdomain - An enumeration of original methods - - - - Gets Harmony version for all active Harmony instances - [out] The current Harmony version - A dictionary containing assembly versions keyed by Harmony IDs - - - - - Applies all patches specified in the type. - - The type to scan. - - - - Creates a new Harmony instance and applies all patches specified in the type. - - The type to scan for patches. - The ID for the Harmony instance to create, which will be used. - - - - Applies all patches specified in the assembly. - - The assembly to scan. - The ID for the Harmony instance to create, which will be used. - - - A wrapper around a method to use it as a patch (for example a Prefix) - - - The original method - - - Declaring class - - - Method name - - - Method type - - - Argument types - - - Priority - - - Before parameter - - - After parameter - - - Reverse patch type - - - Default constructor - - - Creates an annotation from a method - The original method - - - - Creates an annotation from a method. - The type - The method name - The optional argument types for overloaded methods - - - - Gets the names of all internal patch info fields - A list of field names - - - - Merges annotations - The annotations - A merged annotation - - - - Returns a string that represents the annotation - A string representation - - - - Annotation extensions - - - Copies annotation information - from - to - - - - Clones an annotation - The annotation to clone - A copy of the annotation - - - - Merges annotations - The master - The detail - A new, merged copy - - - - Gets all annotations on a class - The class - All annotations - - - - Gets all annotations on a class in merged form - The class - The merged HarmonyMethod - - - - Gets all annotations on a method in merged form - The method - The merged HarmonyMethod - - - - Gets all annotations on a method - The method - All annotations - - - - - IL manipulator to create Harmony-style patches - - - - special parameter names that can be used in prefix and postfix methods - - - Mark method for no inlining - The method to change - - - - High-level IL code manipulator for MonoMod that allows to manipulate a method as a stream of CodeInstructions. - - - - - Initialize IL transpiler - - Body of the method to transpile - - - - Adds a transpiler method that edits the IL of the given method - - Transpiler method - Currently not implemented - - - - Processes and writes IL to the provided method body. - Note that this cleans the existing method body (removes insturctions and exception handlers). - - Method body to write to. - Original method that transpiler can optionally call into - - One of IL opcodes contains a CallSide (e.g. calli), which is currently not - fully supported. - - One of IL opcodes with an operand contains a null operand. - - - - Converts all branches to long types. This exists to mimic the behaviour of Harmony 2 - - Enumerable of instructions - Enumerable of fixed instructions - - - Creates a patch sorter - Array of patches that will be sorted - - - Sorts internal PatchSortingWrapper collection and caches the results. - After first run the result is provided from the cache. - The original method - The sorted patch methods - - - Checks if the sorter was created with the same patch list and as a result can be reused to - get the sorted order of the patches. - List of patches to check against - true if equal - - - Removes one unresolved dependency from the least important patch. - - - Outputs all unblocked patches from the waiting list to results list - - - Adds patch to both results list and handled patches set - Patch to add - - - Wrapper used over the Patch object to allow faster dependency access and - dependency removal in case of cyclic dependencies - - - Create patch wrapper object used for sorting - Patch to wrap - - - Determines how patches sort - The other patch - integer to define sort order (-1, 0, 1) - - - Determines whether patches are equal - The other patch - true if equal - - - Hash function - A hash code - - - Bidirectionally registers Patches as after dependencies - List of dependencies to register - - - Bidirectionally registers Patches as before dependencies - List of dependencies to register - - - Bidirectionally removes Patch from after dependencies - Patch to remove - - - Bidirectionally removes Patch from before dependencies - Patch to remove - - - - Patching methods potentially messes up the stack. - Especially calls to GetExecutingAssembly won't turn in correct methods - - - - - Helper wrapper around ILProcessor to allow emitting code at certain positions - - - - - Write method body to a ILDasm -like representation - - Method body to write - String representation of the method body (locals and instruction) - Unexpected exception block type - - - Serializable patch information - - - The prefixes - - - The postfixes - - - The transpilers - - - The finalizers - - - Default constructor - - - Adds a prefix - The patch - The owner (Harmony ID) - The priority - The before parameter - The after parameter - - - - - Adds a prefix method. - - ID of the owner instance - Method to add as prefix - - - Removes a prefix - The owner or (*) for any - - - - Adds a postfix - The patch - The owner (Harmony ID) - The priority - The before parameter - The after parameter - - - - - Adds a postfix - - The owner (Harmony ID) - Method to add as postfix - - - Removes a postfix - The owner or (*) for any - - - - Adds a transpiler - The patch - The owner (Harmony ID) - The priority - The before parameter - The after parameter - - - - - Adds a transpiler - - The owner (Harmony ID) - The method to add as transpiler - - - Removes a transpiler - The owner or (*) for any - - - - Adds a finalizer - The patch - The owner (Harmony ID) - The priority - The before parameter - The after parameter - - - - - Adds a finalizer. - - The owner (Harmony ID) - Method to add as finalizer - - - Removes a finalizer - The owner or (*) for any - - - - Removes a patch - The patch method - - - - A serializable patch - - - Zero-based index - - - The owner (Harmony ID) - - - The priority - - - The before - - - The after - - - The patch method - - - Creates a patch - The patch - Zero-based index - The owner (Harmony ID) - The priority - The before parameter - The after parameter - - - - Gets the patch method - The original method - The patch method - - - - Determines whether patches are equal - The other patch - true if equal - - - - Determines how patches sort - The other patch - integer to define sort order (-1, 0, 1) - - - - Hash function - A hash code - - - - A group of patches - - - The prefixes - - - The postfixes - - - The transpilers - - - The finalizers - - - Gets all owners (Harmony IDs) or all known patches - The patch owners - - - - Creates a group of patches - The prefixes - The postfixes - The transpilers - The transpilers - - - - A patch processor - - - Creates an empty patch processor - The Harmony instance - An optional original method - - - - Creates a patch processor - The Harmony instance - The patch class - The Harmony attributes - - - - Creates a patch processor - The Harmony instance. - The original methods - The optional prefix. - The optional postfix. - The optional transpiler. - The optional finalizer. - - - Add an original method - The method that will be patched. - - - - Sets the original methods - The methods that will be patched. - - - - Add a prefix - The prefix. - - - - Add a prefix - The method. - - - - Add a postfix - The postfix. - - - - Add a postfix - The method. - - - - Add a transpiler - The transpiler. - - - - Add a transpiler - The method. - - - - Add a finalizer - The finalizer. - - - - Add a finalizer - The method. - - - - Gets patch information - The original method - The patch information - - - - Gets Harmony version for all active Harmony instances - [out] The current Harmony version - A dictionary containing assembly versions keyed by Harmony IDs - - - - Returns the methods unmodified list of CodeInstructions - The original method - Optionally an existing generator that will be used to create all local variables and labels contained in the result (if not specified, an internal generator is used) - A list containing all the original CodeInstructions - - - Returns the methods unmodified list of CodeInstructions - The original method - A new generator that now contains all local variables and labels contained in the result - A list containing all the original CodeInstructions - - - Gets all patched original methods - All patched original methods - - - - Gets all patched original methods - All patched original methods - - - - Applies the patch - A list of all created dynamic methods - - - - Unpatches patches of a given type and/or Harmony ID - The patch type - Harmony ID or (*) for any - - - - Unpatches the given patch - The patch - - - - - Get the member specified by the . Throws if the member was not found. - - Thrown if the member described in the couldn't be found. - is - - - A reverse patcher - - - Creates an empty reverse patcher - The Harmony instance - The original method - The stand-in method - - - - Applies the patch - - - - A CodeInstruction match - - - The name of the match - - - The matched opcodes - - - The matched operands - - - The matched labels - - - The matched blocks - - - The jumps from the match - - - The jumps to the match - - - The match predicate - - - Creates a code match - The optional opcode - The optional operand - The optional name - - - - Creates a code match - The CodeInstruction - An optional name - - - - Creates a code match - The predicate - An optional name - - - - Returns a string that represents the match - A string representation - - - - A CodeInstruction matcher - - - The current position - The index or -1 if out of bounds - - - - Gets the number of code instructions in this matcher - The count - - - - Checks whether the position of this CodeMatcher is within bounds - True if this CodeMatcher is valid - - - - Checks whether the position of this CodeMatcher is outside its bounds - True if this CodeMatcher is invalid - - - - Gets the remaining code instructions - The remaining count - - - - Gets the opcode at the current position - The opcode - - - - Gets the operand at the current position - The operand - - - - Gets the labels at the current position - The labels - - - - Gets the exception blocks at the current position - The blocks - - - - Creates an empty code matcher - - - Creates a code matcher from an enumeration of instructions - The instructions (transpiler argument) - An optional IL generator - - - - Makes a clone of this instruction matcher - A copy of this matcher - - - - Gets instructions at the current position - The instruction - - - - Gets instructions at the current position with offset - The offset - The instruction - - - - Gets all instructions - A list of instructions - - - - Gets all instructions as an enumeration - A list of instructions - - - - Gets some instructions counting from current position - Number of instructions - A list of instructions - - - - Gets all instructions within a range - The start index - The end index - A list of instructions - - - - Gets all instructions within a range (relative to current position) - The start offset - The end offset - A list of instructions - - - - Gets a list of all distinct labels - The instructions (transpiler argument) - A list of Labels - - - - Reports a failure - The method involved - The logger - True if current position is invalid and error was logged - - - - Sets an instruction at current position - The instruction to set - The same code matcher - - - - Sets instruction at current position and advances - The instruction - The same code matcher - - - - Sets opcode and operand at current position - The opcode - The operand - The same code matcher - - - - Sets opcode and operand at current position and advances - The opcode - The operand - The same code matcher - - - - Sets opcode at current position and advances - The opcode - The same code matcher - - - - Sets operand at current position and advances - The operand - The same code matcher - - - - Creates a label at current position - [out] The label - The same code matcher - - - - Creates a label at a position - The position - [out] The new label - The same code matcher - - - - Adds an enumeration of labels to current position - The labels - The same code matcher - - - - Adds an enumeration of labels at a position - The position - The labels - The same code matcher - - - - Sets jump to - Branch instruction - Destination for the jump - [out] The created label - The same code matcher - - - - Inserts some instructions - The instructions - The same code matcher - - - - Inserts an enumeration of instructions - The instructions - The same code matcher - - - - Inserts a branch - The branch opcode - Branch destination - The same code matcher - - - - Inserts some instructions and advances the position - The instructions - The same code matcher - - - - Inserts an enumeration of instructions and advances the position - The instructions - The same code matcher - - - - Inserts a branch and advances the position - The branch opcode - Branch destination - The same code matcher - - - - Removes current instruction - The same code matcher - - - - Removes some instruction fro current position by count - Number of instructions - The same code matcher - - - - Removes the instructions in a range - The start - The end - The same code matcher - - - - Removes the instructions in a offset range - The start offset - The end offset - The same code matcher - - - - Advances the current position - The offset - The same code matcher - - - - Moves the current position to the start - The same code matcher - - - - Moves the current position to the end - The same code matcher - - - - Searches forward with a predicate and advances position - The predicate - The same code matcher - - - - Searches backwards with a predicate and reverses position - The predicate - The same code matcher - - - - Matches forward and advances position - True to set position to end of match, false to set it to the beginning of the match - Some code matches - The same code matcher - - - - Matches backwards and reverses position - True to set position to end of match, false to set it to the beginning of the match - Some code matches - The same code matcher - - - - Repeats a match action until boundaries are met - The match action - An optional action that is executed when no match is found - The same code matcher - - - - Gets a match by its name - The match name - An instruction - - - - Extensions for - - - - Shortcut for testing whether the operand is equal to a non-null value - The - The value - True if the operand has the same type and is equal to the value - - - - Shortcut for code.opcode == opcode && code.OperandIs(operand) - The - The - The operand value - True if the opcode is equal to the given opcode and the operand has the same type and is equal to the given operand - - - - Tests for any form of Ldarg* - The - The (optional) index - True if it matches one of the variations - - - - Tests for Ldarga/Ldarga_S - The - The (optional) index - True if it matches one of the variations - - - - Tests for Starg/Starg_S - The - The (optional) index - True if it matches one of the variations - - - - Tests for any form of Ldloc* - The - The optional local variable - True if it matches one of the variations - - - - Tests for any form of Stloc* - The - The optional local variable - True if it matches one of the variations - - - - Tests if the code instruction branches - The - The label if the instruction is a branch operation or if not - True if the instruction branches - - - - Tests if the code instruction calls the method/constructor - The - The method - True if the instruction calls the method or constructor - - - - Tests if the code instruction loads a constant - The - True if the instruction loads a constant - - - - Tests if the code instruction loads an integer constant - The - The integer constant - True if the instruction loads the constant - - - - Tests if the code instruction loads a floating point constant - The - The floating point constant - True if the instruction loads the constant - - - - Tests if the code instruction loads an enum constant - The - The enum - True if the instruction loads the constant - - - - Tests if the code instruction loads a field - The - The field - Set to true if the address of the field is loaded - True if the instruction loads the field - - - - Tests if the code instruction stores a field - The - The field - True if the instruction stores this field - - - - Adds labels to the code instruction and return it - The - One or several to add - The same code instruction - - - Adds labels to the code instruction and return it - The - An enumeration of - The same code instruction - - - Extracts all labels from the code instruction and returns them - The - A list of - - - Moves all labels from the code instruction to a different one - The to move the labels from - The to move the labels to - The code instruction labels were moved from (now empty) - - - Moves all labels from a different code instruction to the current one - The to move the labels from - The to move the labels to - The code instruction that received the labels - - - Adds ExceptionBlocks to the code instruction and return it - The - One or several to add - The same code instruction - - - Adds ExceptionBlocks to the code instruction and return it - The - An enumeration of - The same code instruction - - - Extracts all ExceptionBlocks from the code instruction and returns them - The - A list of - - - Moves all ExceptionBlocks from the code instruction to a different one - The to move the ExceptionBlocks from - The to move the ExceptionBlocks to - The code instruction blocks were moved from (now empty) - - - Moves all ExceptionBlocks from a different code instruction to the current one - The to move the ExceptionBlocks from - The to move the ExceptionBlocks to - The code instruction that received the blocks - - - General extensions for collections - - - A simple way to execute code for every element in a collection - The inner type of the collection - The collection - The action to execute - - - - A simple way to execute code for elements in a collection matching a condition - The inner type of the collection - The collection - The predicate - The action to execute - - - - A helper to add an item to a collection - The inner type of the collection - The collection - The item to add - The collection containing the item - - Note: this was called 'Add' before but that led to unwanted side effect - See https://github.com/pardeike/Harmony/issues/147 - - - - A helper to add an item to an array - The inner type of the collection - The array - The item to add - The array containing the item - - - - A helper to add items to an array - The inner type of the collection - The array - The items to add - The array containing the items - - - - General extensions for common cases - - - Joins an enumeration with a value converter and a delimiter to a string - The inner type of the enumeration - The enumeration - An optional value converter (from T to string) - An optional delimiter - The values joined into a string - - - - Converts an array of types (for example methods arguments) into a human readable form - The array of types - A human readable description including brackets - - - - A full description of a type - The type - A human readable description - - - - A a full description of a method or a constructor without assembly details but with generics - The method or constructor - A human readable description - - - - A helper converting parameter infos to types - The array of ParameterInfo - The parameter types - - - - A helper to access a value via key from a dictionary - The key type - The value type - The dictionary - The key - The value for the key or the default value (of T) if that key does not exist - - - - A helper to access a value via key from a dictionary with extra casting - The value type - The dictionary - The key - The value for the key or the default value (of T) if that key does not exist or cannot be cast to T - - - - - Extensions for patch sorting - - - - Gets sorted patch methods - The original method - Patches to sort - The sorted patch methods - - - A helper class to retrieve reflection info for non-private methods - - - Given a lambda expression that calls a method, returns the method info - The lambda expression using the method - The MethodInfo for the method in the lambda expression - - - - Given a lambda expression that calls a method, returns the method info - - The lambda expression using the method - The MethodInfo for the method in the lambda expression - - - - Given a lambda expression that calls a method, returns the method info - - - The lambda expression using the method - The MethodInfo for the method in the lambda expression - - - - Given a lambda expression that calls a method, returns the method info - The lambda expression using the method - The MethodInfo for the method in the lambda expression - - - - A file log for debugging - - - Full pathname of the log file - - - The indent character - - - The indent level - - - A buffer - - - Changes indent depth - The value to add to the indent level - - - - Log a string in a buffered way. Use this method only if you are sure that FlushBuffer will be called - or else logging information is incomplete in case of a crash - The string to log - - - - Logs a list of string in a buffered way. Use this method only if you are sure that FlushBuffer will be called - or else logging information is incomplete in case of a crash - The strings to log (they will not be re-indented) - - - - Returns the log buffer and optionally empties it - True to empty the buffer - The buffer. - - - - Replaces the buffer with new lines - The lines to store - - - - Flushes the log buffer to disk (use in combination with LogBuffered) - - - Log a string directly to disk. Slower method that prevents missing information in case of a crash - The string to log. - - - - Resets and deletes the log - - - Logs some bytes as hex values - The pointer to some memory - The length of bytes to log - - - - - Default Harmony logger that writes to a file - - - - - Whether or not to enable writing the log. - - - - - Text writer to write the logs to. If not set, defaults to a file log. - - - - - File path of the log. - - - - - Main logger class that exposes log events. - - - - - A single log event that represents a single log message. - - - - - Log channel of the message. - - - - - The log message. - - - - - Log channel for the messages. - - - - - No channels (or an empty channel). - - - - - Basic information. - - - - - Full IL dumps of the generated dynamic methods. - - - - - Channel for warnings. - - - - - Channel for errors. - - - - - All channels. - - - - - Filter for which channels should be listened to. - If the channel is in the filter, all log messages from that channel get propagated into event. - - - - - Event fired on any incoming message that passes the channel filter. - - - - A helper class for reflection related functions - - - Shortcut for to simplify the use of reflections and make it work for any access level - - - Shortcut for to simplify the use of reflections and make it work for any access level but only within the current type - - - Gets a type by name. Prefers a full name with namespace but falls back to the first type matching the name otherwise - The name of the type, either fully qualified name or just name - A if found, null otherwise - - - Applies a function going up the type hierarchy and stops at the first non null result - Result type of func() - The type to start with - The evaluation function returning T - Returns the first non null result or default(T) when reaching the top level type object - - - Applies a function going into inner types and stops at the first non null result - Generic type parameter - The type to start with - The evaluation function returning T - Returns the first non null result or null with no match - - - Gets the reflection information for a directly declared field - The type where the field is defined - The name of the field - A if field found, otherwise null - - - Gets the reflection information for a field by searching the type and all its super types - The type where the field is defined - The name of the field (case sensitive) - A if field found, otherwise null - - - Gets the reflection information for a field - The type where the field is declared - The zero-based index of the field inside The type definition - A if field found, otherwise null - - - Gets the reflection information for a directly declared property - The type where the property is declared - The name of the property (case sensitive) - A if property found, otherwise null - - - Gets the reflection information for the getter method of a directly declared property - The type where the property is declared - The name of the property (case sensitive) - A if method found, otherwise null - - - Gets the reflection information for the setter method of a directly declared property - The type where the property is declared - The name of the property (case sensitive) - A if method found, otherwise null - - - Gets the reflection information for a property by searching the type and all its super types - The type - The name of the property - A if property found, otherwise null - - - Gets the reflection information for the getter method of a property by searching the type and all its super types - The type - The name of the property - A of the property getter if method found, otherwise null - - - Gets the reflection information for the setter method of a property by searching the type and all its super types - The type - The name - A of the property setter if method found, otherwise null - - - Gets the reflection information for a directly declared method - The type where the method is declared - The name of the method (case sensitive) - Optional parameters to target a specific overload of the method - Optional list of types that define the generic version of the method - A if method found, otherwise null - - - Gets the reflection information for a method by searching the type and all its super types - The type where the method is declared - The name of the method (case sensitive) - Optional parameters to target a specific overload of the method - Optional list of types that define the generic version of the method - A if method found, otherwise null - - - Gets the reflection information for a method by searching the type and all its super types - The target method in form Namespace.Type1.Type2:MethodName of the type where the method is declared - Optional parameters to target a specific overload of the method - Optional list of types that define the generic version of the method - A if method found, otherwise null - - - Gets the names of all method that are declared in a type - The declaring type - A list of method names - - - Gets the names of all method that are declared in the type of the instance - An instance of the type to search in - A list of method names - - - Gets the names of all fields that are declared in a type - The declaring type - A list of field names - - - Gets the names of all fields that are declared in the type of the instance - An instance of the type to search in - A list of field names - - - Gets the names of all properties that are declared in a type - The declaring type - A list of property names - - - Gets the names of all properties that are declared in the type of the instance - An instance of the type to search in - A list of property names - - - - Gets the type of a given member
- * For fields and properties, this is the type of the field/property
- * For methods, this is the return type of the method
- * For event handlers, this is the event handler type -
- A the type of which to get - The type that represents the member -
- - Gets the reflection information for a directly declared constructor - The type where the constructor is declared - Optional parameters to target a specific overload of the constructor - A if found, otherwise null - - - Gets the reflection information for a directly declared constructor - The type where the constructor is declared - Optional parameters to target a specific overload of the constructor - Optional parameters to only consider static constructors - A if found, otherwise null - - - Gets the reflection information for a constructor by searching the type and all its super types - The type where the constructor is declared - Optional parameters to target a specific overload of the method - A if found, otherwise null - - - Gets the reflection information for a constructor by searching the type and all its super types - The type where the constructor is declared - Optional parameters to target a specific overload of the method - Optional parameters to only consider static constructors - A if found, otherwise null - - - Gets reflection information for all declared constructors - The type where the constructors are declared - A list of declared in the type - - - Gets reflection information for all declared constructors - The type where the constructors are declared - Optional parameters to only consider static constructors - A list of declared in the type - - - Gets reflection information for all declared methods - The type where the methods are declared - A list of declared in the type - - - Gets reflection information for all declared properties - The type where the properties are declared - A list of declared in the type - - - Gets reflection information for all declared fields - The type where the fields are declared - A list of declared in the type - - - Gets the return type of a method or constructor - The method or constructor - The return type of the method - - - Given a type, returns the first inner type matching a recursive search by name - The type to start searching at - The name of the inner type (case sensitive) - The inner type if found, otherwise null - - - Given a type, returns the first inner type matching a recursive search with a predicate - The type to start searching at - The predicate to search with - The inner type if found, otherwise null - - - Given a type, returns the first method matching a predicate - The type to start searching at - The predicate to search with - The if found, otherwise null - - - Given a type, returns the first constructor matching a predicate - The type to start searching at - The predicate to search with - The if found, otherwise null - - - Given a type, returns the first property matching a predicate - The type to start searching at - The predicate to search with - The if found, otherwise null - - - Returns an array containing the type of each object in the given array - An array of objects - An array of types or an empty array if parameters is null - - - Creates an array of input parameters for a given method and a given set of potential inputs - The method you are planing to call - The possible input parameters in any order - An object array matching the method signature - - - A read/writable reference to a field - The type the field is defined in - The type of the field - The runtime instance to access the field (leave empty for static fields) - The value of the field (or an assignable object) - - - Creates a field reference - The type the field is defined in - The type of the field - The name of the field - A read and writable field reference - - - Creates a field reference - The type the field is defined in or "object" if type cannot be accessed at compile time - The type of the field - FieldInfo for the field - A readable and writable field reference - - - Creates a field reference for a specific instance - The type the field is defined in - The type of the field - The instance - The name of the field - A readable and writable field reference - - - Creates an instance field reference delegate for a private type - The type of the field - The class/type - The name of the field - A read and writable delegate - - - A readable/writable reference delegate to a static field - The type of the field - An readable/assignable object representing the static field - - - Creates a static field reference - The type the field is defined in or "object" if type cannot be accessed at compile time - The type of the field - The name of the field - An readable/assignable object representing the static field - - - Creates a static field reference - The class the field is defined in or "object" if type cannot be accessed at compile time - The type of the field - The field - An readable/assignable object representing the static field - - - - Creates a static field reference delegate - The type of the field - FieldInfo for the field - A readable and writable field reference delegate - - - Creates a static field reference - The type of the field - The class/type - The name of the field - An readable/assignable object representing the static field - - - Returns who called the current method - The calling method (excluding the current method) - - - Rethrows an exception while preserving its stack trace (throw statement typically clobbers existing stack traces) - The exception to rethrow - - - Checks if the current code is running on Mono runtime - True if we are running under Mono, false otherwise (.NET) - - - Throws a missing member runtime exception - The type that is involved - A list of names - - - Gets default value for a specific type - The type - The default value - - - Creates an (possibly uninitialized) instance of a given type - The type - The new instance - - - Makes a deep copy of any object - The type of the instance that should be created - The original object - A copy of the original object but of type T - - - Makes a deep copy of any object - The type of the instance that should be created - The original object - [out] The copy of the original object - Optional value transformation function (taking a field name and src/dst instances) - The optional path root to start with - - - Makes a deep copy of any object - The original object - The type of the instance that should be created - Optional value transformation function (taking a field name and src/dst instances) - The optional path root to start with - The copy of the original object - - - Tests if a type is a struct - The type - True if the type is a struct - - - Tests if a type is a class - The type - True if the type is a class - - - Tests if a type is a value type - The type - True if the type is a value type - - - Tests if a type is void - The type - True if the type is void - - - Test whether an instance is of a nullable type - Type of instance - An instance to test - True if instance is of nullable type, false if not - - - Test if a class member is declared directly in the type and not in a base type - A member - True if the member is a declared - - - Gets the real implementation of a class member - A member - The member itself if its declared. Otherwise the member that is actually implemented in a base type - - - Tests if a type is an integer type - The type - True if the type represents some integer - - - - Tests if a type is a floating point type - The type - True if the type represents some floating point - - - - Tests if a type is a numerical type - The type - True if the type represents some number - - - - Calculates a combined hash code for an enumeration of objects - The objects - The hash code - - - - A factory to create delegate types - - - - Instance for the delegate type factory - - - Exists for API compatibility with Harmony - - - - - Creates a delegate type for a method - - Type of the return value - Types of the arguments - The new delegate type for the given type info - - - Creates a delegate type for a method - The method - The new delegate type - - - A getter delegate type - Type that getter gets field/property value from - Type of the value that getter gets - The instance get getter uses - An delegate - - - - A setter delegate type - Type that setter sets field/property value for - Type of the value that setter sets - The instance the setter uses - The value the setter uses - An delegate - - - - A constructor delegate type - Type that constructor creates - An delegate - - - - A helper class for fast access to getters and setters - - - Creates an instantiation delegate - Type that constructor creates - The new instantiation delegate - - - - Creates an getter delegate for a property - Type that getter reads property from - Type of the property that gets accessed - The property - The new getter delegate - - - - Creates an getter delegate for a field - Type that getter reads field from - Type of the field that gets accessed - The field - The new getter delegate - - - - Creates an getter delegate for a field (with a list of possible field names) - Type that getter reads field/property from - Type of the field/property that gets accessed - A list of possible field names - The new getter delegate - - - - Creates an setter delegate - Type that setter assigns property value to - Type of the property that gets assigned - The property - The new setter delegate - - - - Creates an setter delegate for a field - Type that setter assigns field value to - Type of the field that gets assigned - The field - The new getter delegate - - - - A delegate to invoke a method - The instance - The method parameters - The method result - - - - A helper class to invoke method with delegates - - - Creates a MethodInvoker that can create a fast invocation handler - - - This option controls how value types passed by reference (e.g. ref int, out my_struct) are handled in the arguments array - passed to the fast invocation handler. - Since the arguments array is an object array, any value types contained within it are actually references to a boxed value object. - Like any other object, there can be other references to such boxed value objects, other than the reference within the arguments array. - For example, - - var val = 5; - var box = (object)val; - var arr = new object[] { box }; - handler(arr); // for a method with parameter signature: ref/out/in int - - - - - If directBoxValueAccess is true, the boxed value object is accessed (and potentially updated) directly when the handler is called, - such that all references to the boxed object reflect the potentially updated value. - In the above example, if the method associated with the handler updates the passed (boxed) value to 10, both box and arr[0] - now reflect the value 10. Note that the original val is not updated, since boxing always copies the value into the new boxed value object. - - - If directBoxValueAccess is false (default), the boxed value object in the arguments array is replaced with a "reboxed" value object, - such that potential updates to the value are reflected only in the arguments array. - In the above example, if the method associated with the handler updates the passed (boxed) value to 10, only arr[0] now reflects the value 10. - - - - - Creates a fast invocation handler from a method and a module - The method to invoke - The module context - The fast invocation handler - - - Creates a fast invocation handler from a method and a module - The method to invoke - The module context - The fast invocation handler - - - - Creates a fast invocation handler from a method and a module - The method to invoke - The fast invocation handler - - - - A reflection helper to read and write private elements - The result type defined by GetValue() - - - - Creates a traverse instance from an existing instance - The original - - - - Gets/Sets the current value - The value to read or write - - - - A reflection helper to read and write private elements - - - Creates a new traverse instance from a class - The class - A traverse instance - - - - Creates a new traverse instance from a class T - The class - A traverse instance - - - - Creates a new traverse instance from an instance - The object - A traverse instance - - - - Creates a new traverse instance from a named type - The type name - A traverse instance - - - - Creates a new and empty traverse instance - A traverse instance - - - - Creates a new traverse instance from a class - The class - A traverse instance - - - - Creates a new traverse instance from an instance - The object - A traverse instance - - - - Gets the current value - The value - - - - Gets the current value - The type of the value - The value - - - - Invokes the current method with arguments and returns the result - The method arguments - The value returned by the method - - - - Invokes the current method with arguments and returns the result - The type of the value - The method arguments - The value returned by the method - - - - Sets a value of the current field or property - The value - The same traverse instance - - - - Gets the type of the current field or property - The type - - - - Moves the current traverse instance to a inner type - The type name - A traverse instance - - - - Moves the current traverse instance to a field - The type name - A traverse instance - - - - Moves the current traverse instance to a field - The type of the field - The type name - A traverse instance - - - - Gets all fields of the current type - A list of field names - - - - Moves the current traverse instance to a property - The type name - Optional property index - A traverse instance - - - - Moves the current traverse instance to a field - The type of the property - The type name - Optional property index - A traverse instance - - - - Gets all properties of the current type - A list of property names - - - - Moves the current traverse instance to a method - The name of the method - The arguments defining the argument types of the method overload - A traverse instance - - - - Moves the current traverse instance to a method - The name of the method - The argument types of the method - The arguments for the method - A traverse instance - - - - Gets all methods of the current type - A list of method names - - - - Checks if the current traverse instance is for a field or a property - True if its a field - - - - Checks if the current traverse instance is for a method - True if its a method - - - - Checks if the current traverse instance is for a type - True if its a type - - - - Checks if the current traverse instance contains any information - True if the traverse contains any information - - - - Iterates over all fields of the current type and executes a traverse action - Original object - The action receiving a traverse for each field - - - - Iterates over all fields of the current type and executes a traverse action - Original object - Target object - The action receiving a traverse for each field traverse pair - - - - Iterates over all fields of the current type and executes a traverse action - Original object - Target object - The action receiving a field dot path and a field pair - - - - Iterates over all properties of the current type and executes a traverse action - Original object - The action receiving a traverse for each property - - - - Iterates over all properties of the current type and executes a traverse action - Original object - Target object - The action receiving a traverse for each property traverse pair - - - - Iterates over all properties of the current type and executes a traverse action - Original object - Target object - The action receiving a property dot path and a property pair - - - - A default field action that copies fields to fields - - - Returns a string that represents the current traverse - A string representation - - - - An abstract wrapper around OpCode and their operands. Used by transpilers - - - The opcode - - - The operand - - - All labels defined on this instruction - - - All exception block boundaries defined on this instruction - - - Creates a new CodeInstruction with a given opcode and optional operand - The code - The operand - - - - Create a full copy (including labels and exception blocks) of a CodeInstruction - The instruction to copy - - - - Clones a CodeInstruction and resets its labels and exception blocks - A lightweight copy of this code instruction - - - - Clones a CodeInstruction, resets labels and exception blocks and sets its opcode - The opcode - A copy of this CodeInstruction with a new opcode - - - - Clones a CodeInstruction, resets labels and exception blocks and sets its operand - The opcode - A copy of this CodeInstruction with a new operand - - - - Returns a string representation of the code instruction - A string representation of the code instruction - - - - Exception block types - - - The beginning of an exception block - - - The beginning of a catch block - - - The beginning of an except filter block - - - The beginning of a fault block - - - The beginning of a finally block - - - The end of an exception block - - - An exception block - - - Block type - - - Catch type - - - Creates an exception block - Block type - Catch type - - - - A collection of commonly used transpilers - - - - Returns an instruction to call the specified delegate. - - The delegate type to emit. - The delegate to emit. - The instruction to - - - A transpiler that replaces all occurrences of a given method with another one - The instructions to act on - Method or constructor to search for - Method or constructor to replace with - Modified instructions - - - - A transpiler that alters instructions that match a predicate by calling an action - The instructions to act on - A predicate selecting the instructions to change - An action to apply to matching instructions - Modified instructions - - - - A transpiler that logs a text at the beginning of the method - The instructions to act on - The log text - Modified instructions - - - - - Indicates that the marked symbol is used implicitly (e.g. via reflection, in external library), - so this symbol will not be reported as unused (as well as by other usage inspections). - - - - - Can be applied to attributes, type parameters, and parameters of a type assignable from . - When applied to an attribute, the decorated attribute behaves the same as . - When applied to a type parameter or to a parameter of type , indicates that the corresponding type - is used implicitly. - - - - - Specify the details of implicitly used symbol when it is marked - with or . - - - - Only entity marked with attribute considered used. - - - Indicates implicit assignment to a member. - - - - Indicates implicit instantiation of a type with fixed constructor signature. - That means any unused constructor parameters won't be reported as such. - - - - Indicates implicit instantiation of a type. - - - - Specify what is considered to be used implicitly when marked - with or . - - - - Members of entity marked with attribute are considered used. - - - Inherited entities are considered used. - - - Entity marked with attribute and all its members considered used. - -
-
diff --git a/Dependencies/Subnautica.stable/FMODUnity.dll b/Dependencies/Subnautica.stable/FMODUnity.dll new file mode 100644 index 00000000..fd195f8a Binary files /dev/null and b/Dependencies/Subnautica.stable/FMODUnity.dll differ diff --git a/Dependencies/Subnautica.stable/Newtonsoft.Json.dll b/Dependencies/Subnautica.stable/Newtonsoft.Json.dll index dec691f5..486a56a5 100644 Binary files a/Dependencies/Subnautica.stable/Newtonsoft.Json.dll and b/Dependencies/Subnautica.stable/Newtonsoft.Json.dll differ diff --git a/Dependencies/Subnautica.stable/QModInstaller.dll b/Dependencies/Subnautica.stable/QModInstaller.dll deleted file mode 100644 index 244755f7..00000000 Binary files a/Dependencies/Subnautica.stable/QModInstaller.dll and /dev/null differ diff --git a/Dependencies/Subnautica.stable/QModInstaller.xml b/Dependencies/Subnautica.stable/QModInstaller.xml deleted file mode 100644 index 1e776bd9..00000000 --- a/Dependencies/Subnautica.stable/QModInstaller.xml +++ /dev/null @@ -1,569 +0,0 @@ - - - - QModInstaller - - - - - All public data about a QMod. - - - - - The ID of the mod - Can only contain alphanumeric characters and underscores: (, , , ) - - - - - The display name of the mod - - - - - The author of the mod - - - - - The game this mod was developed for. - - - - - The dependencies of the mod and their optional minimum required version - - - - - A list of mods, before which, this mod will load - - - - - A list of mods, after which, this mod will load - - - - - The assembly of this mod - Check if before using - - - - - The assembly name of the mod - - - - - The version of the mod. - - - - - Whether or not this mod is enabled - - - - - Whether or not this mod has been loaded - - - - - An set of services provided by QModManager for mods to use. - - - - - Gets a list all mods being tracked by QModManager. - - A read only list of mods containing all of the loaded mods - - - - Returns the mod from the assembly which called this method - - - - - Returns a mod from an - - - - - - Finds a specific mod by its unique value. - - The mod ID. - The instance of the mod if found; otherwise returns null. - - - - Checks whether or not a mod is present based on its unique value. - - The mod ID. - True if the mod is in the collection of mods to load; Otherwise false. - - - - An set of services provided by QModManager for mods to use. - - - - - Finds a specific mod by its unique value. - - The mod ID. - The instance of the mod if found; otherwise returns null. - - - - Finds a specific mod with a that matches the provided one. - - The mod assembly. - The instance of the mod if found; otherwise returns null. - - - - Adds a critical message to the main menu. - Message will stay in the main menu and on the loading screen. - - The message to add. - The size of the text. - The color of the text. - Whether or not to apply formatting tags to the message, or show it as it is. - - - - Identifies the patching class for your QMod. - - - - - - - - - Initializes a new instance of the class. - - - - - Identifies a normal patch method for a QMod. - This method must be public, must take no parameters, and must return . - ALERT: The class that defines this method must have a attribute. - - - - - - Initializes a new instance of the class for normal patching. - - - - - Identifies a post-patch method for a QMod. - This method must be public, must take no parameters, and must return . - ALERT: The class that defines this method must have a attribute. - - - - - - Initializes a new instance of the class. - - - - - Initializes a new instance of the class. - Should only be used for mods that need to load last, after all other mods. Read the documentation for instructions. - - Should only be used for mods that need to load last, after all other mods. Read the documentation for instructions. - - - - Identifies a pre-patch method for a QMod. - This method must be public, must take no parameters, and must return - ALERT: The class that defines this method must have a attribute. - - - - - - Initializes a new instance of the class. - - - - - Initializes a new instance of the class. - Should only be used for mods that need to load first, before all other mods. Read the documentation for instructions. - - Should only be used for mods that need to load first, before all other mods. Read the documentation for instructions. - - - - Minimal legacy support only. - - - - - - Minimal legacy support only. - - - - - Gets a list all mods being tracked by QModManager. - - A read only list of mods containing all of the loaded mods - - - - Returns the mod from the assembly which called this method - - - - - Returns a mod from an - - - - - - Finds a specific mod by its unique value. - - The mod ID. - The instance of the mod if found; otherwise returns null. - - - - Checks whether or not a mod is present based on its unique value. - - The mod ID. - True if the mod is in the collection of mods to load; Otherwise false. - - - - Services offered to mods. - - - - - - Gets the main entry point into the QMod Services. - - - The main. - - - - - Finds the mod by identifier. - - The mod identifier. - - - - - Checks whether or not a mod is present based on its ID. - - The mod ID. - - True if the mod is in the collection of mods to load; Otherwise false. - - - - - Finds the mod by assembly. - - The mod assembly. - - - - - - Gets a list all mods being tracked by QModManager. - - - A read only list of mods containing all of the loaded mods - - - - - Returns the mod from the assembly which called this method - - - - - - - Returns a mod from an - - - - - - - Returns a mod from an ID - - - - - - - Adds a critical message to the main menu. - Message will stay in the main menu and on the loading screen. - - The message to add. - The size of the text. - The color of the text. - Whether or not to apply formatting tags to the message, or show it as it is. - - - - Identifies a required mod and an optional minimum version. - - - - - Gets the required mod's ID. - - - - - Gets a value indicating whether the mod must be at a minimum version for compatibility. - - - - - Gets the minimum version this mod should be at. - If is false, this will return a default value. - - - - - Identifies the Subnautica games. - - - - - No game. - - - - - Subnautica. - - - - - Subnautica: Below Zero. - - - - - Both Subnautica and Below Zero. - - - - - Base class to all attributes that identify QMod patch methods. - - - - - - Initializes a new instance of the class. - - The patch order. - - - - Initializes a new instance of the class. - - The patch order. - The secret pasword. - This modder has not read the documentation and should not be using prepatch/postpatch functions. - - - - Validates the that modder has read the documentation. - - The method. - The mod. - This modder has not read the documentation and should not be using prepatch/postpatch functions. - - - - Game -> game version. - 0 = no minimum version required. - - - - - Searches through all folders in the provided directory and returns an ordered list of mods to load. - Mods that cannot be loaded will have an unsuccessful value. - - The QMods directory - A new, sorted ready to be initialized or skipped. - - - - Enforces the requirements of the mod.json file for legacy mod loading. - - - - - For pre-initialize patch methods - - - - - For normal patch methods - - - - - For post-initialize patch methods - - - - - Searches through all folders in the provided directory and returns an ordered list of mods to load. - Mods that cannot be loaded will have an unsuccessful value. - - The QMods directory - A new, sorted ready to be initialized or skipped. - - - - The dummy which is used to represent QModManager - - - - - Requirements to function within the - - The ID type. - - - - Allows to add critical messages to the main menu. - Messages will stay in the main menu and on loading screen. - - - - Adds an error message to the main menu. - The message to add. - The ID of the caller (or null for "QModManager"). - The size of the text. - The color of the text. - Whether or not to apply formatting tags to the message, or show it as it is. - - - A simple logging class. Can be used for basic logging or to know which logging level is enabled. - - - Possible logging levels. - - - Debugging log level - - - Informational log level - - - Warning log level - - - Error log level - - - Fatal log level - - - Used to know if debug logging is enabled or not. - - - - This function will log given message and/or exception. It can optionally show the message on screen. - You need to provide a message and/or an exception (this function will do nothing if both are set to null). - Warning: You can call this function from any mod but don't call it from QModManager ( would fail). - - The level of the log. - Optional: The message that needs to be logged. - Optional: The exception that needs to be logged. - Optional: Whether to show the message on screen or not. - - - - Defines a service for parsing version strings. - - - - - The default version zero used when no version could be parsed. - - - - - Returns a new based on the provided string value, with all 4 groups populated. - - The version string to parse. - A new with all empty groups populated with 0. - - - - Checks if the provided version is all zeros. - - The version to check. - True if this matches version 0.0.0.0 - - - - A service that handles parsing values into objects. - - - - - The regex used to sanitize incoming version strings. - ^(((\d+)\.?){0,3}\d+)$ - - - - - The default version zero used when no version could be parsed. - - - - - Returns a new based on the provided string value, with all 4 groups populated. - - The version string to parse. This must match . - A new with all empty groups populated with 0. - - "2.8" will be parsed as "2.8.0.0" - - - - - Checks if the provided version is all zeros. - - The version to check. - True if this matches version 0.0.0.0 - - - - Container class for the entry point - - - - - QModManager entry point - - - - diff --git a/Dependencies/Subnautica.stable/Unity.Addressables.dll b/Dependencies/Subnautica.stable/Unity.Addressables.dll new file mode 100644 index 00000000..919bd464 Binary files /dev/null and b/Dependencies/Subnautica.stable/Unity.Addressables.dll differ diff --git a/Dependencies/Subnautica.stable/Unity.ResourceManager.dll b/Dependencies/Subnautica.stable/Unity.ResourceManager.dll new file mode 100644 index 00000000..4c73c5b9 Binary files /dev/null and b/Dependencies/Subnautica.stable/Unity.ResourceManager.dll differ diff --git a/Dependencies/Subnautica.stable/Unity.TextMeshPro.dll b/Dependencies/Subnautica.stable/Unity.TextMeshPro.dll new file mode 100644 index 00000000..29327b25 Binary files /dev/null and b/Dependencies/Subnautica.stable/Unity.TextMeshPro.dll differ diff --git a/Dependencies/Subnautica.stable/UnityEngine.AudioModule.dll b/Dependencies/Subnautica.stable/UnityEngine.AudioModule.dll index e459887e..d063de50 100644 Binary files a/Dependencies/Subnautica.stable/UnityEngine.AudioModule.dll and b/Dependencies/Subnautica.stable/UnityEngine.AudioModule.dll differ diff --git a/Dependencies/Subnautica.stable/UnityEngine.CoreModule.dll b/Dependencies/Subnautica.stable/UnityEngine.CoreModule.dll index 0baea738..a3afb807 100644 Binary files a/Dependencies/Subnautica.stable/UnityEngine.CoreModule.dll and b/Dependencies/Subnautica.stable/UnityEngine.CoreModule.dll differ diff --git a/Dependencies/Subnautica.stable/UnityEngine.ImageConversionModule.dll b/Dependencies/Subnautica.stable/UnityEngine.ImageConversionModule.dll index 8bd6acba..a5048602 100644 Binary files a/Dependencies/Subnautica.stable/UnityEngine.ImageConversionModule.dll and b/Dependencies/Subnautica.stable/UnityEngine.ImageConversionModule.dll differ diff --git a/Dependencies/Subnautica.stable/UnityEngine.PhysicsModule.dll b/Dependencies/Subnautica.stable/UnityEngine.PhysicsModule.dll index 207949f1..243876b7 100644 Binary files a/Dependencies/Subnautica.stable/UnityEngine.PhysicsModule.dll and b/Dependencies/Subnautica.stable/UnityEngine.PhysicsModule.dll differ diff --git a/Dependencies/Subnautica.stable/UnityEngine.TextRenderingModule.dll b/Dependencies/Subnautica.stable/UnityEngine.TextRenderingModule.dll index a0ee03b4..2347e4ad 100644 Binary files a/Dependencies/Subnautica.stable/UnityEngine.TextRenderingModule.dll and b/Dependencies/Subnautica.stable/UnityEngine.TextRenderingModule.dll differ diff --git a/Dependencies/Subnautica.stable/UnityEngine.UI.dll b/Dependencies/Subnautica.stable/UnityEngine.UI.dll index 22c7d060..9d7886e0 100644 Binary files a/Dependencies/Subnautica.stable/UnityEngine.UI.dll and b/Dependencies/Subnautica.stable/UnityEngine.UI.dll differ diff --git a/Dependencies/Subnautica.stable/UnityEngine.UIModule.dll b/Dependencies/Subnautica.stable/UnityEngine.UIModule.dll index 0f24b243..20af0c14 100644 Binary files a/Dependencies/Subnautica.stable/UnityEngine.UIModule.dll and b/Dependencies/Subnautica.stable/UnityEngine.UIModule.dll differ diff --git a/Dependencies/Subnautica.stable/UnityEngine.dll b/Dependencies/Subnautica.stable/UnityEngine.dll index bc73a682..a310eb76 100644 Binary files a/Dependencies/Subnautica.stable/UnityEngine.dll and b/Dependencies/Subnautica.stable/UnityEngine.dll differ diff --git a/Example mod/Example mod.csproj b/Example mod/Example mod.csproj index 27aaf681..8d68f3bc 100644 --- a/Example mod/Example mod.csproj +++ b/Example mod/Example mod.csproj @@ -48,8 +48,8 @@ $(Dependencies)\Assembly-CSharp_publicized.dll False - - $(Dependencies)\QModInstaller.dll + + $(Dependencies)\UnityEngine.dll False @@ -63,8 +63,6 @@ - - PreserveNewest - + \ No newline at end of file diff --git a/Example mod/Mod.cs b/Example mod/Mod.cs index 17611b8e..fd58a1d2 100644 --- a/Example mod/Mod.cs +++ b/Example mod/Mod.cs @@ -1,22 +1,30 @@ -using HarmonyLib; -using QModManager.API.ModLoading; -using SMLHelper.V2.Commands; -using SMLHelper.V2.Handlers; -using SMLHelper.V2.Interfaces; -using SMLHelper.V2.Json; -using SMLHelper.V2.Json.Attributes; -using SMLHelper.V2.Options; -using SMLHelper.V2.Options.Attributes; -using System; -using UnityEngine; -using UnityEngine.UI; -using Logger = QModManager.Utility.Logger; - -namespace SMLHelper.V2.Examples +namespace SMLHelper.V2.Examples { - [QModCore] - public static class ExampleMod + using HarmonyLib; + using SMLHelper.V2.Commands; + using SMLHelper.V2.Handlers; + using SMLHelper.V2.Interfaces; + using SMLHelper.V2.Json; + using SMLHelper.V2.Json.Attributes; + using SMLHelper.V2.Options; + using SMLHelper.V2.Options.Attributes; + using System; + using UnityEngine; + using UnityEngine.UI; + using BepInEx; + using BepInEx.Logging; + + [BepInPlugin(GUID, MODNAME, VERSION)] + public class ExampleMod: BaseUnityPlugin { + private const string + MODNAME = "SMLHelper", + AUTHOR = "The SMLHelper Dev Team", + GUID = "SMLHelperExampleMod", + VERSION = "2.15.0.0"; + + internal static ManualLogSource LogSource { get; private set; } + /// /// A simple SaveDataCache implementation, intended to save the players current position to disk. /// @@ -26,9 +34,10 @@ internal class SaveData : SaveDataCache public Vector3 PlayerPosition { get; set; } } - [QModPatch] - public static void Patch() + public void Awake() { + LogSource = base.Logger; + /// Here, we are setting up a instance of , which will automatically generate an /// options menu using Attributes. The values in this instance will be updated whenever the user changes /// the corresponding option in the menu. @@ -46,9 +55,9 @@ public static void Patch() // We can use polymorphism to convert it back into a SaveData // instance, and access its members, such as PlayerPosition. - Logger.Log(Logger.Level.Info, - $"loaded player position from save slot: {data.PlayerPosition}", - showOnScreen: true); + string msg = $"loaded player position from save slot: {data.PlayerPosition}"; + LogSource.LogInfo(msg); + ErrorMessage.AddMessage(msg); }; // Update the player position before saving it @@ -62,9 +71,9 @@ public static void Patch() saveData.OnFinishedSaving += (object sender, JsonFileEventArgs e) => { SaveData data = e.Instance as SaveData; - Logger.Log(Logger.Level.Info, - $"saved player position to save slot: {data.PlayerPosition}", - showOnScreen: true); + string msg = $"saved player position to save slot: {data.PlayerPosition}"; + LogSource.LogInfo(msg); + ErrorMessage.AddMessage(msg); }; /// Here we are registering a console command by use of a delegate. The delegate will respond to the "delegatecommand" @@ -90,7 +99,7 @@ public static void Patch() /// for an example. ConsoleCommandsHandler.Main.RegisterConsoleCommands(typeof(ExampleMod)); - Logger.Log(Logger.Level.Info, "Patched successfully!"); + LogSource.LogInfo("Patched successfully!"); } private delegate string MyCommand(string myString, int myInt, bool myBool); @@ -250,8 +259,8 @@ public class Config : ConfigFile [Button("My button"), OnGameObjectCreated(nameof(MyGameObjectCreatedEvent))] public void MyButtonClickEvent(ButtonClickedEventArgs e) { - Logger.Log(Logger.Level.Info, "Button was clicked!"); - Logger.Log(Logger.Level.Info, $"{e.Id}"); + ExampleMod.LogSource.LogInfo("Button was clicked!"); + ExampleMod.LogSource.LogInfo($"{e.Id}"); } /// @@ -264,8 +273,8 @@ public void MyButtonClickEvent(ButtonClickedEventArgs e) /// parameter if you do not need the data it contains. private void MyCheckboxToggleEvent(ToggleChangedEventArgs e) { - Logger.Log(Logger.Level.Info, "Checkbox value was changed!"); - Logger.Log(Logger.Level.Info, $"{e.Value}"); + ExampleMod.LogSource.LogInfo("Checkbox value was changed!"); + ExampleMod.LogSource.LogInfo($"{e.Value}"); } /// @@ -283,22 +292,22 @@ private void MyCheckboxToggleEvent(ToggleChangedEventArgs e) /// it contains. private void MyGenericValueChangedEvent(IModOptionEventArgs e) { - Logger.Log(Logger.Level.Info, "Generic value changed!"); - Logger.Log(Logger.Level.Info, $"{e.Id}: {e.GetType()}"); + ExampleMod.LogSource.LogInfo("Generic value changed!"); + ExampleMod.LogSource.LogInfo($"{e.Id}: {e.GetType()}"); switch (e) { case KeybindChangedEventArgs keybindChangedEventArgs: - Logger.Log(Logger.Level.Info, keybindChangedEventArgs.KeyName); + ExampleMod.LogSource.LogInfo(keybindChangedEventArgs.KeyName); break; case ChoiceChangedEventArgs choiceChangedEventArgs: - Logger.Log(Logger.Level.Info, $"{choiceChangedEventArgs.Index}: {choiceChangedEventArgs.Value}"); + ExampleMod.LogSource.LogInfo($"{choiceChangedEventArgs.Index}: {choiceChangedEventArgs.Value}"); break; case SliderChangedEventArgs sliderChangedEventArgs: - Logger.Log(Logger.Level.Info, sliderChangedEventArgs.Value.ToString()); + ExampleMod.LogSource.LogInfo(sliderChangedEventArgs.Value.ToString()); break; case ToggleChangedEventArgs toggleChangedEventArgs: - Logger.Log(Logger.Level.Info, toggleChangedEventArgs.Value.ToString()); + ExampleMod.LogSource.LogInfo(toggleChangedEventArgs.Value.ToString()); break; } } @@ -313,8 +322,8 @@ private void MyGenericValueChangedEvent(IModOptionEventArgs e) /// as a string as well as the newly created . private void MyGameObjectCreatedEvent(GameObjectCreatedEventArgs e) { - Logger.Log(Logger.Level.Info, "GameObject was created"); - Logger.Log(Logger.Level.Info, $"{e.Id}: {e.GameObject}"); + ExampleMod.LogSource.LogInfo("GameObject was created"); + ExampleMod.LogSource.LogInfo($"{e.Id}: {e.GameObject}"); } } } diff --git a/Example mod/mod.json b/Example mod/mod.json deleted file mode 100644 index 4e716067..00000000 --- a/Example mod/mod.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "Id": "SMLHelperExampleMod", - "DisplayName": "Example Mod For SMLHelper", - "Author": "The SMLHelper Dev Team", - "Version": "2.14.1", - "Enable": true, - "AssemblyName": "Example mod.dll", - "VersionDependencies": { - "SMLHelper": "2.14.1" - }, - "Game": "Both", - "NitroxCompat": true -} diff --git a/SMLHelper.Tests/LanguagePatcherTests.cs b/SMLHelper.Tests/LanguagePatcherTests.cs deleted file mode 100644 index 73503c53..00000000 --- a/SMLHelper.Tests/LanguagePatcherTests.cs +++ /dev/null @@ -1,104 +0,0 @@ -namespace SMLHelper.Tests -{ - using NUnit.Framework; - using SMLHelper.V2.Patchers; - using System; - using System.Collections.Generic; - - [TestFixture] - public class LanguagePatcherTests - { - private static readonly IEnumerable Keys = new string[] - { - "Key", - "Tooltip_Key", - }; - - private static readonly IEnumerable CustomValues = new string[] - { - // No special tokens - "CustomValue", - "CustomValue1", - "2Custom:Value1", - "CustomValue%", - // string.format tokens - "CustomValue{0}", - "{0}CustomValue", - "{0}CustomValue{1}", - "{0}Custom{1}Value{2}", - "Custom{0}Value", - // With Unity line breaks - "Custom\\nValue", - "\\nCustomValue", - "CustomValue\\n", - "\\nCustom\\nValue\\n", - // With mix - "Custom:{0}\\n{1}:Value;", - "Custom-Value\\n{0}", - "#1\\nCustom_Value\\n", - "Custom{0}:{1}%Value%", - }; - - [Test, Combinatorial] - public void ExtractOverrideLines_WhenTextIsValid_SingleEntry_KeyIsKnown_Overrides( - [ValueSource(nameof(CustomValues))] string customValue) - { - var originalLines = new Dictionary - { - { "Key", "OriginalValue" } - }; - - string text = "Key:" + customValue; - - Console.WriteLine("TestText"); - Console.WriteLine(text); - int overridesApplied = LanguagePatcher.ExtractOverrideLines("Test1", new[] { text }, originalLines); - - Assert.AreEqual(1, overridesApplied); - Assert.AreEqual(customValue.Replace("\\n", "\n"), LanguagePatcher.GetCustomLine("Key")); - } - - - [Test, Combinatorial] - public void ExtractOverrideLines_WhenTextIsValid_MultipleEntries_KeyIsKnown_Overrides( - [ValueSource(nameof(CustomValues))] string otherCustomValue, - [ValueSource(nameof(Keys))] string secondKey) - { - var originalLines = new Dictionary - { - { "Key1", "OriginalValue1" }, - { secondKey, "OriginalValue2" }, - }; - - string line1 = "Key1:CustomValue1"; - string line2 = secondKey + ":" + otherCustomValue; - Console.WriteLine("TestText"); - Console.WriteLine(line1); - Console.WriteLine(line2); - int overridesApplied = LanguagePatcher.ExtractOverrideLines("Test1", new[] { line1, line2 }, originalLines); - - Assert.AreEqual(2, overridesApplied); - Assert.AreEqual("CustomValue1", LanguagePatcher.GetCustomLine("Key1")); - Assert.AreEqual(otherCustomValue.Replace("\\n", "\n"), LanguagePatcher.GetCustomLine(secondKey)); - } - - [Test, Combinatorial] - public void ExtractOverrideLines_WhenLegacyDelimitersPresent_Overrides( - [ValueSource(nameof(CustomValues))] string customValue) - { - var originalLines = new Dictionary - { - { "Key", "OriginalValue" } - }; - - string text = "Key:{" + customValue + "}"; - - Console.WriteLine("TestText"); - Console.WriteLine(text); - int overridesApplied = LanguagePatcher.ExtractOverrideLines("Test1", new[] { text }, originalLines); - - Assert.AreEqual(1, overridesApplied); - Assert.AreEqual(customValue.Replace("\\n", "\n"), LanguagePatcher.GetCustomLine("Key")); - } - } -} diff --git a/SMLHelper.Tests/PdaItemTests.cs b/SMLHelper.Tests/PdaItemTests.cs deleted file mode 100644 index a6f4cbea..00000000 --- a/SMLHelper.Tests/PdaItemTests.cs +++ /dev/null @@ -1,102 +0,0 @@ -using System.Reflection; - -namespace SMLHelper.Tests.AssestClassTests -{ - using NSubstitute; - using NUnit.Framework; - using SMLHelper.V2.Assets; - using SMLHelper.V2.Crafting; - using SMLHelper.V2.Interfaces; - using UnityEngine; -#if SUBNAUTICA - using Sprite = Atlas.Sprite; -#elif BELOWZERO - using TechData = V2.Crafting.RecipeData; -#endif - - [TestFixture] - internal class PdaItemTests - { - [Test] - public void VirtualMethods_DefaultBeahviors() - { - var pdaItem = new SimpleTestPdaItem(); - - Assert.AreEqual(TechType.None, pdaItem.RequiredForUnlock); - Assert.IsTrue(pdaItem.UnlockedAtStart); - Assert.AreEqual("NotificationBlueprintUnlocked", pdaItem.DiscoverMessageResolved); - } - - [Test] - public void Patch_EventsInvoked() - { - // ARRANGE - const TechType createdTechType = TechType.Accumulator; - - IPrefabHandler mockPrefabHandler = Substitute.For(); - ISpriteHandler mockSpriteHandler = Substitute.For(); - ITechTypeHandlerInternal mockTechTypeHandler = Substitute.For(); - ICraftDataHandler mockCraftDataHandler = Substitute.For(); - IKnownTechHandler mockKnownTechHandler = Substitute.For(); - - mockTechTypeHandler - .AddTechType(Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()) - .Returns(createdTechType); - - var techData = new TechData(); - - var pdaItem = new SimpleTestPdaItem - { - PrefabHandler = mockPrefabHandler, - SpriteHandler = mockSpriteHandler, - TechTypeHandler = mockTechTypeHandler, - CraftDataHandler = mockCraftDataHandler, - KnownTechHandler = mockKnownTechHandler, - TechDataToReturn = techData, - }; - - // ACT - pdaItem.Patch(); - - // ASSERT - mockCraftDataHandler.Received(1).SetTechData(createdTechType, techData); - mockCraftDataHandler.Received(1).AddToGroup(TechGroup.Constructor, TechCategory.Constructor, createdTechType); - mockKnownTechHandler.DidNotReceiveWithAnyArgs(); - mockTechTypeHandler.Received(1).AddTechType(Arg.Any(), "classId", "friendlyName", "description", true); - } - - private class SimpleTestPdaItem : PdaItem - { - public TechData TechDataToReturn { get; set; } - public GameObject GameObjectToReturn { get; set; } - - public SimpleTestPdaItem() - : base("classId", "friendlyName", "description") - { - } - - public SimpleTestPdaItem(string classId, string friendlyName, string description) - : base(classId, friendlyName, description) - { - } - - public override TechGroup GroupForPDA { get; } = TechGroup.Constructor; - public override TechCategory CategoryForPDA { get; } = TechCategory.Constructor; - - public override GameObject GetGameObject() - { - return this.GameObjectToReturn; - } - - protected override TechData GetBlueprintRecipe() - { - return this.TechDataToReturn; - } - - protected override Sprite GetItemSprite() - { - return null; - } - } - } -} diff --git a/SMLHelper.Tests/Properties/AssemblyInfo.cs b/SMLHelper.Tests/Properties/AssemblyInfo.cs deleted file mode 100644 index 9b9f6fa7..00000000 --- a/SMLHelper.Tests/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -[assembly: AssemblyTitle("SMLHelper.Tests")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("SMLHelper.Tests")] -[assembly: AssemblyCopyright("Copyright © 2019")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -[assembly: ComVisible(false)] - -[assembly: Guid("ebc4aaf3-a13b-427e-bf99-3ae23edeb4b8")] - -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/SMLHelper.Tests/SMLHelper.Tests.csproj b/SMLHelper.Tests/SMLHelper.Tests.csproj deleted file mode 100644 index c5798c89..00000000 --- a/SMLHelper.Tests/SMLHelper.Tests.csproj +++ /dev/null @@ -1,110 +0,0 @@ - - - - - - - - - SN.STABLE - AnyCPU - {EBC4AAF3-A13B-427E-BF99-3AE23EDEB4B8} - Library - Properties - SMLHelper.Tests - SMLHelper.Tests - v4.7.2 - 512 - {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - 15.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages - False - UnitTest - - - - - - - - 15.0 - - - bin\SN.STABLE\ - TRACE;DEBUG;SUBNAUTICA;SUBNAUTICA_STABLE - false - full - AnyCPU - prompt - MinimumRecommendedRules.ruleset - true - - - bin\BELOWZERO\ - TRACE;DEBUG;BELOWZERO;BELOWZERO_STABLE - true - pdbonly - AnyCPU - prompt - MinimumRecommendedRules.ruleset - - - - $(Dependencies)\Assembly-CSharp-firstpass_publicized.dll - False - - - $(Dependencies)\Assembly-CSharp_publicized.dll - False - - - ..\packages\Castle.Core.4.4.0\lib\net45\Castle.Core.dll - - - - ..\packages\NSubstitute.4.2.2\lib\net46\NSubstitute.dll - - - ..\packages\NUnit.3.12.0\lib\net45\nunit.framework.dll - - - - - - ..\packages\System.Threading.Tasks.Extensions.4.3.0\lib\portable-net45+win8+wp8+wpa81\System.Threading.Tasks.Extensions.dll - - - $(Dependencies)\UnityEngine.CoreModule.dll - False - - - - - - - - - - - - - - - {418502dd-372d-4ef9-8021-b262552dfede} - SMLHelper - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - - - - \ No newline at end of file diff --git a/SMLHelper.Tests/SelfCheckingDictionaryTests.cs b/SMLHelper.Tests/SelfCheckingDictionaryTests.cs deleted file mode 100644 index 4c605dd6..00000000 --- a/SMLHelper.Tests/SelfCheckingDictionaryTests.cs +++ /dev/null @@ -1,229 +0,0 @@ -namespace SMLHelper.Tests -{ - using NUnit.Framework; - using SMLHelper.V2.Patchers; - - [TestFixture] - internal class SelfCheckingDictionaryTests - { - [Test] - public void Add_WhenUnique_AllAdded() - { - var testDictionary = new SelfCheckingDictionary("Test") - { - { TechType.AcidMushroom, 1 }, - { TechType.AcidMushroomSpore, 2 }, - { TechType.WhiteMushroom, 3 }, - { TechType.WhiteMushroomSpore, 4 }, - { TechType.PinkMushroom, 5 }, - { TechType.PinkMushroomSpore, 6 }, - }; - - Assert.AreEqual(6, testDictionary.Count); - Assert.AreEqual(0, testDictionary.DuplicatesDiscarded.Count); - - Assert.IsTrue(testDictionary.ContainsKey(TechType.AcidMushroom)); - Assert.IsTrue(testDictionary.ContainsKey(TechType.AcidMushroomSpore)); - Assert.IsTrue(testDictionary.ContainsKey(TechType.WhiteMushroom)); - Assert.IsTrue(testDictionary.ContainsKey(TechType.WhiteMushroomSpore)); - Assert.IsTrue(testDictionary.ContainsKey(TechType.PinkMushroom)); - Assert.IsTrue(testDictionary.ContainsKey(TechType.PinkMushroomSpore)); - } - - [Test] - public void Add_WhenUnique_AllAdded_AltComparer() - { - var testDictionary = new SelfCheckingDictionary("Test", TechTypeExtensions.sTechTypeComparer) - { - { TechType.AcidMushroom, 1 }, - { TechType.AcidMushroomSpore, 2 }, - { TechType.WhiteMushroom, 3 }, - { TechType.WhiteMushroomSpore, 4 }, - { TechType.PinkMushroom, 5 }, - { TechType.PinkMushroomSpore, 6 }, - }; - - Assert.AreEqual(6, testDictionary.Count); - Assert.AreEqual(0, testDictionary.DuplicatesDiscarded.Count); - - Assert.IsTrue(testDictionary.ContainsKey(TechType.AcidMushroom)); - Assert.IsTrue(testDictionary.ContainsKey(TechType.AcidMushroomSpore)); - Assert.IsTrue(testDictionary.ContainsKey(TechType.WhiteMushroom)); - Assert.IsTrue(testDictionary.ContainsKey(TechType.WhiteMushroomSpore)); - Assert.IsTrue(testDictionary.ContainsKey(TechType.PinkMushroom)); - Assert.IsTrue(testDictionary.ContainsKey(TechType.PinkMushroomSpore)); - } - - [Test] - public void Add_WhenDupEncountered_AutoRemoved_NotVisible() - { - var testDictionary = new SelfCheckingDictionary("Test") - { - { TechType.AcidMushroom, 1 }, - { TechType.WhiteMushroom, 1 }, - { TechType.AcidMushroom, 2 }, // Dup - { TechType.PinkMushroom, 2 }, - { TechType.AcidMushroom, 3 } // Dup - }; - - Assert.IsFalse(testDictionary.UniqueEntries.ContainsKey(TechType.AcidMushroom)); - Assert.IsTrue(testDictionary.DuplicatesDiscarded.ContainsKey(TechType.AcidMushroom)); - Assert.AreEqual(1, testDictionary.DuplicatesDiscarded.Count); - Assert.AreEqual(3, testDictionary.DuplicatesDiscarded[TechType.AcidMushroom]); // Discarded all three - - Assert.IsTrue(testDictionary.ContainsKey(TechType.WhiteMushroom)); - Assert.IsTrue(testDictionary.ContainsKey(TechType.PinkMushroom)); - - Assert.AreEqual(2, testDictionary.Count); - } - - [Test] - public void Add_WhenDupEncountered_AutoRemoved_NotVisible_AltComparer() - { - var testDictionary = new SelfCheckingDictionary("Test", TechTypeExtensions.sTechTypeComparer) - { - { TechType.AcidMushroom, 1 }, - { TechType.WhiteMushroom, 1 }, - { TechType.AcidMushroom, 2 }, // Dup - { TechType.PinkMushroom, 2 }, - { TechType.AcidMushroom, 3 } // Dup - }; - - Assert.IsFalse(testDictionary.UniqueEntries.ContainsKey(TechType.AcidMushroom)); - Assert.IsTrue(testDictionary.DuplicatesDiscarded.ContainsKey(TechType.AcidMushroom)); - Assert.AreEqual(1, testDictionary.DuplicatesDiscarded.Count); - Assert.AreEqual(3, testDictionary.DuplicatesDiscarded[TechType.AcidMushroom]); // Discarded all three - - Assert.IsTrue(testDictionary.ContainsKey(TechType.WhiteMushroom)); - Assert.IsTrue(testDictionary.ContainsKey(TechType.PinkMushroom)); - - Assert.AreEqual(2, testDictionary.Count); - } - - [Test] - public void Add_StepByStep_DupsRemoved() - { - var testDictionary = new SelfCheckingDictionary("Test"); - - Assert.AreEqual(0, testDictionary.Count); - Assert.AreEqual(0, testDictionary.DuplicatesDiscarded.Count); - - testDictionary.Add(TechType.Accumulator, 0); - Assert.AreEqual(1, testDictionary.Count); - Assert.AreEqual(0, testDictionary.DuplicatesDiscarded.Count); - - testDictionary.Add(TechType.AdvancedWiringKit, 0); - Assert.AreEqual(2, testDictionary.Count); - Assert.AreEqual(0, testDictionary.DuplicatesDiscarded.Count); - - testDictionary.Add(TechType.Accumulator, 0); // Dup - Assert.AreEqual(1, testDictionary.Count); // Count goes down as dup is removed - Assert.AreEqual(1, testDictionary.DuplicatesDiscarded.Count); - Assert.IsTrue(testDictionary.DuplicatesDiscarded.ContainsKey(TechType.Accumulator)); - Assert.IsFalse(testDictionary.UniqueEntries.ContainsKey(TechType.Accumulator)); - Assert.AreEqual(2, testDictionary.DuplicatesDiscarded[TechType.Accumulator]); // Discarded twice - } - - // ---- - - [Test] - public void SetByIndexer_WhenUnique_AllAdded() - { - var testDictionary = new SelfCheckingDictionary("Test") - { - [TechType.AcidMushroom] = 1, - [TechType.AcidMushroomSpore] = 2, - [TechType.WhiteMushroom] = 3, - [TechType.WhiteMushroomSpore] = 4, - [TechType.PinkMushroom] = 5, - [TechType.PinkMushroomSpore] = 6 - }; - - Assert.AreEqual(6, testDictionary.Count); - Assert.AreEqual(0, testDictionary.DuplicatesDiscarded.Count); - - Assert.IsTrue(testDictionary.ContainsKey(TechType.AcidMushroom)); - Assert.IsTrue(testDictionary.ContainsKey(TechType.AcidMushroomSpore)); - Assert.IsTrue(testDictionary.ContainsKey(TechType.WhiteMushroom)); - Assert.IsTrue(testDictionary.ContainsKey(TechType.WhiteMushroomSpore)); - Assert.IsTrue(testDictionary.ContainsKey(TechType.PinkMushroom)); - Assert.IsTrue(testDictionary.ContainsKey(TechType.PinkMushroomSpore)); - } - - [Test] - public void SetByIndexer_WhenUnique_AllAdded_AltComparer() - { - var testDictionary = new SelfCheckingDictionary("Test", TechTypeExtensions.sTechTypeComparer) - { - [TechType.AcidMushroom] = 1, - [TechType.AcidMushroomSpore] = 2, - [TechType.WhiteMushroom] = 3, - [TechType.WhiteMushroomSpore] = 4, - [TechType.PinkMushroom] = 5, - [TechType.PinkMushroomSpore] = 6, - }; - - Assert.AreEqual(6, testDictionary.Count); - Assert.AreEqual(0, testDictionary.DuplicatesDiscarded.Count); - - Assert.IsTrue(testDictionary.ContainsKey(TechType.AcidMushroom)); - Assert.IsTrue(testDictionary.ContainsKey(TechType.AcidMushroomSpore)); - Assert.IsTrue(testDictionary.ContainsKey(TechType.WhiteMushroom)); - Assert.IsTrue(testDictionary.ContainsKey(TechType.WhiteMushroomSpore)); - Assert.IsTrue(testDictionary.ContainsKey(TechType.PinkMushroom)); - Assert.IsTrue(testDictionary.ContainsKey(TechType.PinkMushroomSpore)); - } - - [Test] - public void SetByIndexer_WhenDupEncountered_OriginalOverwritten_NotVisible() - { - const int firstValue = 1; - const int finalValue = 3; - var testDictionary = new SelfCheckingDictionary("Test") - { - [TechType.AcidMushroom] = firstValue, - [TechType.WhiteMushroom] = 1, - [TechType.AcidMushroom] = 2, // Dup - [TechType.PinkMushroom] = 2, - [TechType.AcidMushroom] = finalValue // Dup - }; - - Assert.AreEqual(1, testDictionary.DuplicatesDiscarded.Count); - Assert.AreEqual(2, testDictionary.DuplicatesDiscarded[TechType.AcidMushroom]); // Discarded twice - - Assert.IsTrue(testDictionary.ContainsKey(TechType.AcidMushroom)); - Assert.IsTrue(testDictionary.ContainsKey(TechType.WhiteMushroom)); - Assert.IsTrue(testDictionary.ContainsKey(TechType.PinkMushroom)); - - Assert.AreEqual(finalValue, testDictionary[TechType.AcidMushroom]); - - Assert.AreEqual(3, testDictionary.Count); - } - - [Test] - public void SetByIndexer_WhenDupEncountered_OriginalOverwritten_AltComparer() - { - const int firstValue = 1; - const int finalValue = 3; - var testDictionary = new SelfCheckingDictionary("Test", TechTypeExtensions.sTechTypeComparer) - { - [TechType.AcidMushroom] = firstValue, - [TechType.WhiteMushroom] = 1, - [TechType.AcidMushroom] = 2, // Dup - [TechType.PinkMushroom] = 2, - [TechType.AcidMushroom] = finalValue // Dup - }; - - Assert.AreEqual(1, testDictionary.DuplicatesDiscarded.Count); - Assert.AreEqual(2, testDictionary.DuplicatesDiscarded[TechType.AcidMushroom]); // Discarded twice - - Assert.IsTrue(testDictionary.ContainsKey(TechType.AcidMushroom)); - Assert.IsTrue(testDictionary.ContainsKey(TechType.WhiteMushroom)); - Assert.IsTrue(testDictionary.ContainsKey(TechType.PinkMushroom)); - - Assert.AreEqual(finalValue, testDictionary[TechType.AcidMushroom]); - - Assert.AreEqual(3, testDictionary.Count); - } - } -} diff --git a/SMLHelper.Tests/SpawnableTests.cs b/SMLHelper.Tests/SpawnableTests.cs deleted file mode 100644 index 533b1808..00000000 --- a/SMLHelper.Tests/SpawnableTests.cs +++ /dev/null @@ -1,141 +0,0 @@ -using System.Reflection; - -namespace SMLHelper.Tests.AssestClassTests -{ - using System; - using System.Collections.Generic; - using NSubstitute; - using NUnit.Framework; - using SMLHelper.V2.Assets; - using SMLHelper.V2.Interfaces; - using UnityEngine; -#if SUBNAUTICA - using Sprite = Atlas.Sprite; -#endif - - [TestFixture] - internal class SpawnableTests - { - private List _recordedEvents; - private IPrefabHandler _mockPrefabHandler; - private ISpriteHandler _mockSpriteHandler; - private ITechTypeHandlerInternal _mockTechTypeHandler; - private ICraftDataHandler _craftDataHandler; - private TestSpawnable _spawnable; - - [SetUp] - public void SetupForTests() - { - _recordedEvents = new List(); - _mockPrefabHandler = Substitute.For(); - _mockSpriteHandler = Substitute.For(); - _mockTechTypeHandler = Substitute.For(); - _craftDataHandler = Substitute.For(); - - _spawnable = new TestSpawnable(_recordedEvents) - { - PrefabHandler = _mockPrefabHandler, - SpriteHandler = _mockSpriteHandler, - TechTypeHandler = _mockTechTypeHandler, - CraftDataHandler = _craftDataHandler - }; - } - - [TestCase("")] - [TestCase(null)] - public void Spawnable_Construct_MissingClassId_Throws(string missingClassId) - { - ArgumentException argEx = Assert.Throws(() => - { - var badSpawnable = new TestSpawnable(missingClassId, "", ""); - }); - } - - [Test] - public void Patch_EventsInvokedInCorrectOrder() - { - // ARRANGE - const TechType createdTechType = TechType.Accumulator; - - _mockTechTypeHandler - .AddTechType(Arg.Any(), Arg.Do((c) => _recordedEvents.Add("AddTechType")), Arg.Any(), Arg.Any(), Arg.Any()) - .Returns(createdTechType); - - _mockPrefabHandler.RegisterPrefab(Arg.Do((s) => _recordedEvents.Add("RegisterPrefab"))); - _mockSpriteHandler.RegisterSprite(Arg.Any(), Arg.Do((s) => _recordedEvents.Add("RegisterSprite"))); - - // ACT - _spawnable.Patch(); - - // ASSERT - Assert.AreEqual("OnStartedPatching", _recordedEvents[0]); - Assert.AreEqual("AddTechType", _recordedEvents[1]); - Assert.AreEqual("RegisterPrefab", _recordedEvents[2]); - Assert.AreEqual("RegisterSprite", _recordedEvents[3]); - Assert.AreEqual("OnFinishedPatching", _recordedEvents[4]); - - Assert.AreEqual(createdTechType, _spawnable.TechType); - Assert.IsTrue(_spawnable.GetItemSpriteInvoked); - Assert.IsTrue(_spawnable.IsPatched); - } - - [Test] - public void Patch_WhenSizeDifferent_CallsSetItemSize() - { - // ARRANGE - const TechType createdTechType = TechType.Accumulator; - - _mockTechTypeHandler.AddTechType(Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()) - .Returns(createdTechType); - - var customSize = new Vector2int(2, 2); - _spawnable.DifferentSize = customSize; - - _spawnable.Patch(); - - Assert.AreEqual(createdTechType, _spawnable.TechType); - _craftDataHandler.Received(1).SetItemSize(createdTechType, customSize); - Assert.IsTrue(_spawnable.IsPatched); - } - - private class TestSpawnable : Spawnable - { - public bool GetItemSpriteInvoked { get; private set; } = false; - public Vector2int? DifferentSize { get; set; } - - public TestSpawnable(List recordedEvents) - : base("classId", "friendlyName", "description") - { - OnStartedPatching = () => { recordedEvents.Add("OnStartedPatching"); }; - OnFinishedPatching = () => { recordedEvents.Add("OnFinishedPatching"); }; - } - - public TestSpawnable(string classId, string friendlyName, string description) - : base(classId, friendlyName, description) - { - } - - public override UnityEngine.GameObject GetGameObject() - { - throw new NotImplementedException(); - } - - protected override Sprite GetItemSprite() - { - this.GetItemSpriteInvoked = true; - return null; - } - - public override Vector2int SizeInInventory - { - get - { - if (this.DifferentSize.HasValue) - return this.DifferentSize.Value; - else - return base.SizeInInventory; - } - } - } - } -} diff --git a/SMLHelper.Tests/packages.config b/SMLHelper.Tests/packages.config deleted file mode 100644 index dc8f7fc1..00000000 --- a/SMLHelper.Tests/packages.config +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/SMLHelper.sln b/SMLHelper.sln index 09639a7e..e498b9bd 100644 --- a/SMLHelper.sln +++ b/SMLHelper.sln @@ -3,21 +3,17 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.1.32210.238 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SMLHelper", "SMLHelper\SMLHelper.csproj", "{418502DD-372D-4EF9-8021-B262552DFEDE}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SMLHelper", "SMLHelper\SMLHelper.csproj", "{418502DD-372D-4EF9-8021-B262552DFEDE}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Example mod", "Example mod\Example mod.csproj", "{C8FB0981-77D2-47C7-BBEF-A3A9EBACACBF}" ProjectSection(ProjectDependencies) = postProject {418502DD-372D-4EF9-8021-B262552DFEDE} = {418502DD-372D-4EF9-8021-B262552DFEDE} EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SMLHelper.Tests", "SMLHelper.Tests\SMLHelper.Tests.csproj", "{EBC4AAF3-A13B-427E-BF99-3AE23EDEB4B8}" - ProjectSection(ProjectDependencies) = postProject - {418502DD-372D-4EF9-8021-B262552DFEDE} = {418502DD-372D-4EF9-8021-B262552DFEDE} - EndProjectSection -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{5152F028-6D03-43C0-88C5-986313017D4F}" ProjectSection(SolutionItems) = preProject common.props = common.props + Version.targets = Version.targets EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build scripts", "Build scripts", "{6EF72E95-EA2D-44C1-8FB4-F0FE4865FFC4}" @@ -79,12 +75,6 @@ Global {C8FB0981-77D2-47C7-BBEF-A3A9EBACACBF}.SN.EXP|Any CPU.Build.0 = SN.EXP|Any CPU {C8FB0981-77D2-47C7-BBEF-A3A9EBACACBF}.SN.STABLE|Any CPU.ActiveCfg = SN.STABLE|Any CPU {C8FB0981-77D2-47C7-BBEF-A3A9EBACACBF}.SN.STABLE|Any CPU.Build.0 = SN.STABLE|Any CPU - {EBC4AAF3-A13B-427E-BF99-3AE23EDEB4B8}.BZ.EXP|Any CPU.ActiveCfg = BZ.STABLE|Any CPU - {EBC4AAF3-A13B-427E-BF99-3AE23EDEB4B8}.BZ.STABLE|Any CPU.ActiveCfg = BZ.STABLE|Any CPU - {EBC4AAF3-A13B-427E-BF99-3AE23EDEB4B8}.BZ.STABLE|Any CPU.Build.0 = BZ.STABLE|Any CPU - {EBC4AAF3-A13B-427E-BF99-3AE23EDEB4B8}.SN.EXP|Any CPU.ActiveCfg = SN.STABLE|Any CPU - {EBC4AAF3-A13B-427E-BF99-3AE23EDEB4B8}.SN.STABLE|Any CPU.ActiveCfg = SN.STABLE|Any CPU - {EBC4AAF3-A13B-427E-BF99-3AE23EDEB4B8}.SN.STABLE|Any CPU.Build.0 = SN.STABLE|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/SMLHelper/Assets/Craftable.cs b/SMLHelper/Assets/Craftable.cs index a55a55eb..8d12e98c 100644 --- a/SMLHelper/Assets/Craftable.cs +++ b/SMLHelper/Assets/Craftable.cs @@ -1,6 +1,7 @@ namespace SMLHelper.V2.Assets { using SMLHelper.V2.Interfaces; + using SMLHelper.V2.Utility; /// /// An item that can be crafted into the game world from a fabricator. @@ -45,7 +46,7 @@ private void PatchCraftingData() { if (this.FabricatorType == CraftTree.Type.None) { - Logger.Debug($"Craftable '{this.ClassID}' was not automatically patched into a crafting tree."); + InternalLogger.Debug($"Craftable '{this.ClassID}' was not automatically patched into a crafting tree."); } else { diff --git a/SMLHelper/Assets/CustomFabricator.cs b/SMLHelper/Assets/CustomFabricator.cs index d5935a2a..e3649e66 100644 --- a/SMLHelper/Assets/CustomFabricator.cs +++ b/SMLHelper/Assets/CustomFabricator.cs @@ -1,4 +1,6 @@ -namespace SMLHelper.V2.Assets +using SMLHelper.V2.Utility; + +namespace SMLHelper.V2.Assets { using System; using System.Collections; @@ -6,7 +8,7 @@ using SMLHelper.V2.Crafting; using SMLHelper.V2.Handlers; using UnityEngine; - using Logger = V2.Logger; + using InternalLogger = InternalLogger; #if SUBNAUTICA using Sprite = Atlas.Sprite; @@ -151,22 +153,7 @@ protected CustomFabricator(string classId, string friendlyName, string descripti /// public override GameObject GetGameObject() { -#if SUBNAUTICA_EXP || BELOWZERO return null; -#else - GameObject prefab = this.Model switch - { - Models.Fabricator => GameObject.Instantiate(CraftData.GetPrefabForTechType(TechType.Fabricator)), - Models.Workbench => GameObject.Instantiate(CraftData.GetPrefabForTechType(TechType.Workbench)), -#if SUBNAUTICA - Models.MoonPool => GameObject.Instantiate(Resources.Load("Submarine/Build/CyclopsFabricator")), -#endif - Models.Custom => GetCustomCrafterPreFab(), - _ => null - }; - - return PreProcessPrefab(prefab); -#endif } /// @@ -350,7 +337,7 @@ public void AddTabNode(string tabId, string displayText, Sprite tabSprite, strin /// When this value is null, the craft node will be added to the root of the craft tree. public void AddCraftNode(TechType techType, string parentTabId = null) { - Logger.Debug($"'{techType.AsString()}' will be added to the custom craft tree '{this.ClassID}'"); + InternalLogger.Debug($"'{techType.AsString()}' will be added to the custom craft tree '{this.ClassID}'"); OrderedCraftTreeActions.Add(() => { ModCraftTreeLinkingNode parentTab = CraftTreeLinkingNodes[parentTabId ?? RootNode]; @@ -367,7 +354,7 @@ public void AddCraftNode(TechType techType, string parentTabId = null) /// When this value is null, the craft node will be added to the root of the craft tree. public void AddCraftNode(string moddedTechType, string parentTabId = null) { - Logger.Debug($"'{moddedTechType}' will be added to the custom craft tree '{this.ClassID}'"); + InternalLogger.Debug($"'{moddedTechType}' will be added to the custom craft tree '{this.ClassID}'"); OrderedCraftTreeActions.Add(() => { if (this.TechTypeHandler.TryGetModdedTechType(moddedTechType, out TechType techType)) @@ -377,7 +364,7 @@ public void AddCraftNode(string moddedTechType, string parentTabId = null) } else { - Logger.Info($"Did not find a TechType value for '{moddedTechType}' to add to the custom craft tree '{this.ClassID}'"); + InternalLogger.Info($"Did not find a TechType value for '{moddedTechType}' to add to the custom craft tree '{this.ClassID}'"); } }); } @@ -392,12 +379,12 @@ public void AddCraftNode(string moddedTechType, string parentTabId = null) /// The craft node will be added to the root of the craft tree if both are null. public void AddCraftNode(Craftable item, string parentTabId = null) { - Logger.Debug($"'{item.ClassID}' will be added to the custom craft tree '{this.ClassID}'"); + InternalLogger.Debug($"'{item.ClassID}' will be added to the custom craft tree '{this.ClassID}'"); OrderedCraftTreeActions.Add(() => { if (item.TechType == TechType.None) { - Logger.Info($"'{item.ClassID} had to be patched early to obtain its TechType value for the custom craft tree '{this.ClassID}'"); + InternalLogger.Info($"'{item.ClassID} had to be patched early to obtain its TechType value for the custom craft tree '{this.ClassID}'"); item.Patch(); } diff --git a/SMLHelper/Assets/FishPrefab.cs b/SMLHelper/Assets/FishPrefab.cs index ed2595fe..7f90a3bd 100644 --- a/SMLHelper/Assets/FishPrefab.cs +++ b/SMLHelper/Assets/FishPrefab.cs @@ -47,7 +47,7 @@ public FishPrefab(string classId, string prefabFileName, TechType techType = Tec /// public sealed override GameObject GetGameObject() { - V2.Logger.Debug($"[FishFramework] Initializing fish: {this.ClassID}"); + Utility.InternalLogger.Debug($"[FishFramework] Initializing fish: {this.ClassID}"); GameObject mainObj = modelPrefab; Renderer[] renderers = mainObj.GetComponentsInChildren(); @@ -68,11 +68,7 @@ public sealed override GameObject GetGameObject() forces.handleGravity = true; forces.underwaterDrag = 1f; forces.underwaterGravity = 0; -#if BELOWZERO || SUBNAUTICA_EXP forces.waterDepth = Ocean.GetOceanLevel(); -#else - forces.waterDepth = Ocean.main.GetOceanLevel(); -#endif forces.enabled = false; forces.enabled = true; diff --git a/SMLHelper/Assets/ModPrefabCache.cs b/SMLHelper/Assets/ModPrefabCache.cs index a85cd4ef..764b8682 100644 --- a/SMLHelper/Assets/ModPrefabCache.cs +++ b/SMLHelper/Assets/ModPrefabCache.cs @@ -1,9 +1,11 @@ -namespace SMLHelper.V2.Assets +using SMLHelper.V2.Utility; + +namespace SMLHelper.V2.Assets { using System; using System.Collections.Generic; using UnityEngine; - using Logger = V2.Logger; + using InternalLogger = InternalLogger; /// /// Class that used by to store game objects that used as prefabs. @@ -29,7 +31,7 @@ public void Update() if (Time.time < prefabs[i].Item1 + cleanDelay || Builder.prefab == prefabs[i].Item2) continue; - Logger.Debug($"ModPrefabCache: removing prefab {prefabs[i].Item2}"); + InternalLogger.Debug($"ModPrefabCache: removing prefab {prefabs[i].Item2}"); Destroy(prefabs[i].Item2); prefabs.RemoveAt(i); @@ -85,7 +87,7 @@ private static void AddPrefabInternal(GameObject prefab, bool autoremove) if (autoremove) prefabs.Add(Tuple.Create(Time.time, prefab)); - Logger.Debug($"ModPrefabCache: adding prefab {prefab}"); + InternalLogger.Debug($"ModPrefabCache: adding prefab {prefab}"); } } } diff --git a/SMLHelper/Assets/ModPrefabRequest.cs b/SMLHelper/Assets/ModPrefabRequest.cs index 3cd696d0..9d17994f 100644 --- a/SMLHelper/Assets/ModPrefabRequest.cs +++ b/SMLHelper/Assets/ModPrefabRequest.cs @@ -50,10 +50,8 @@ public bool MoveNext() public void Reset() {} -#if BELOWZERO || SUBNAUTICA_EXP public void Release() { } -#endif } } diff --git a/SMLHelper/Assets/PdaItem.cs b/SMLHelper/Assets/PdaItem.cs index 14995d27..f94b1497 100644 --- a/SMLHelper/Assets/PdaItem.cs +++ b/SMLHelper/Assets/PdaItem.cs @@ -2,6 +2,7 @@ { using Crafting; using SMLHelper.V2.Interfaces; + using SMLHelper.V2.Utility; using System.Collections.Generic; /// @@ -117,7 +118,7 @@ private void PatchTechDataEntry() } else { - Logger.Error($"Failed to add {TechType} to {GroupForPDA}/{CategoryForPDA} as it is not a registered combination."); + InternalLogger.Error($"Failed to add {TechType} to {GroupForPDA}/{CategoryForPDA} as it is not a registered combination."); } } diff --git a/SMLHelper/Assets/Spawnable.cs b/SMLHelper/Assets/Spawnable.cs index 3eca5a1d..8385eb6d 100644 --- a/SMLHelper/Assets/Spawnable.cs +++ b/SMLHelper/Assets/Spawnable.cs @@ -1,4 +1,6 @@ -namespace SMLHelper.V2.Assets +using SMLHelper.V2.Utility; + +namespace SMLHelper.V2.Assets { using Handlers; using Interfaces; @@ -10,7 +12,7 @@ using System.Reflection; using UnityEngine; using UWE; - using Logger = Logger; + using InternalLogger = InternalLogger; #if SUBNAUTICA using Sprite = Atlas.Sprite; #endif @@ -113,7 +115,7 @@ protected Spawnable(string classId, string friendlyName, string description) { if(string.IsNullOrEmpty(classId)) { - Logger.Log($"ClassID for Spawnables must be a non-empty value.", LogLevel.Error); + InternalLogger.Log($"ClassID for Spawnables must be a non-empty value.", LogLevel.Error); throw new ArgumentException($"Error patching Spawnable"); } @@ -222,8 +224,8 @@ internal virtual void PatchTechType() protected virtual Sprite GetItemSprite() { // This is for backwards compatibility with mods that were using the "ModName/Assets" format - string path = this.AssetsFolder != ModFolderLocation - ? IOUtilities.Combine(".", "QMods", this.AssetsFolder.Trim('/'), this.IconFileName) + string path = this.AssetsFolder != ModFolderLocation && !string.IsNullOrWhiteSpace(this.AssetsFolder) + ? IOUtilities.Combine(ModFolderLocation, this.AssetsFolder.Trim('/'), this.IconFileName) : Path.Combine(this.AssetsFolder, this.IconFileName); if(File.Exists(path)) @@ -232,7 +234,7 @@ protected virtual Sprite GetItemSprite() } if(HasSprite) - Logger.Error($"Sprite for '{this.PrefabFileName}'{Environment.NewLine}Did not find an image file at '{path}'"); + InternalLogger.Error($"Sprite for '{this.PrefabFileName}'{Environment.NewLine}Did not find an image file at '{path}'"); return SpriteManager.defaultSprite; } diff --git a/SMLHelper/Assets/SubnauticaModSprite.cs b/SMLHelper/Assets/SubnauticaModSprite.cs index 9287ed27..6865f474 100644 --- a/SMLHelper/Assets/SubnauticaModSprite.cs +++ b/SMLHelper/Assets/SubnauticaModSprite.cs @@ -3,6 +3,7 @@ namespace SMLHelper.V2.Assets { using System; using System.Collections.Generic; + using SMLHelper.V2.Utility; /// /// A class that handles a custom sprite and what item it is associated to. @@ -20,7 +21,7 @@ internal static void Add(SpriteManager.Group group, string name, Atlas.Sprite sp ModSprites.Add(group, new Dictionary(StringComparer.InvariantCultureIgnoreCase)); if(ModSprites[group].ContainsKey(name)) - Logger.Debug($"ModSprite already registered for {group}/{name}. Old sprite will be overwritten."); + InternalLogger.Debug($"ModSprite already registered for {group}/{name}. Old sprite will be overwritten."); ModSprites[group][name] = sprite; } diff --git a/SMLHelper/Commands/ConsoleCommand.cs b/SMLHelper/Commands/ConsoleCommand.cs index 7125c873..7c15061d 100644 --- a/SMLHelper/Commands/ConsoleCommand.cs +++ b/SMLHelper/Commands/ConsoleCommand.cs @@ -1,7 +1,6 @@ namespace SMLHelper.V2.Commands { using HarmonyLib; - using QModManager.API; using System; using System.Collections.Generic; using System.Linq; @@ -20,7 +19,7 @@ internal class ConsoleCommand /// /// The QMod that registered the command. /// - public IQMod QMod { get; } + public string ModName { get; } /// /// The parameters for the command. @@ -53,7 +52,7 @@ public ConsoleCommand(string trigger, MethodInfo targetMethod, bool isDelegate = IsMethodStatic = targetMethod.IsStatic; IsDelegate = isDelegate; Instance = instance; - QMod = QModServices.Main.GetMod(DeclaringType.Assembly); + ModName = DeclaringType.Assembly.GetName().Name; Parameters = targetMethod.GetParameters().Select(param => new Parameter(param)); ParameterTypes = Parameters.Select(param => param.ParameterType).ToArray(); } diff --git a/SMLHelper/FMod/FModMultiSounds.cs b/SMLHelper/FMod/FModMultiSounds.cs index bf28ef83..aa338546 100644 --- a/SMLHelper/FMod/FModMultiSounds.cs +++ b/SMLHelper/FMod/FModMultiSounds.cs @@ -91,7 +91,7 @@ Channel IFModSound.PlaySound() return AudioUtils.PlaySound(_sounds[Index], _bus); } - Logger.Error("MultiSounds must have some sounds."); + InternalLogger.Error("MultiSounds must have some sounds."); return default; } } diff --git a/SMLHelper/Handlers/CoordinatedSpawnsHandler.cs b/SMLHelper/Handlers/CoordinatedSpawnsHandler.cs index 6ac465b2..9bf1edf1 100644 --- a/SMLHelper/Handlers/CoordinatedSpawnsHandler.cs +++ b/SMLHelper/Handlers/CoordinatedSpawnsHandler.cs @@ -1,11 +1,7 @@ using System; using System.Collections.Generic; using UnityEngine; -#if SUBNAUTICA_STABLE -using Oculus.Newtonsoft.Json; -#else using Newtonsoft.Json; -#endif namespace SMLHelper.V2.Handlers { diff --git a/SMLHelper/Handlers/FishHandler.cs b/SMLHelper/Handlers/FishHandler.cs index c58eef31..e3c8a6f8 100644 --- a/SMLHelper/Handlers/FishHandler.cs +++ b/SMLHelper/Handlers/FishHandler.cs @@ -5,6 +5,7 @@ using System.IO; using SMLHelper.V2.Assets; using SMLHelper.V2.Interfaces; + using SMLHelper.V2.Utility; /// /// Class to manage registering of fish into the game @@ -52,7 +53,7 @@ TechType IFishHandler.RegisterFish(Fish fish) PrefabHandler.RegisterPrefab(fishPrefab); - Logger.Debug($"Successfully registered fish: '{fish.displayName}' with Tech Type: '{fish.id}'"); + InternalLogger.Debug($"Successfully registered fish: '{fish.displayName}' with Tech Type: '{fish.id}'"); return type; } diff --git a/SMLHelper/Handlers/KnownTechHandler.cs b/SMLHelper/Handlers/KnownTechHandler.cs index 11cd1134..31fab56e 100644 --- a/SMLHelper/Handlers/KnownTechHandler.cs +++ b/SMLHelper/Handlers/KnownTechHandler.cs @@ -1,10 +1,12 @@ -namespace SMLHelper.V2.Handlers +using SMLHelper.V2.Utility; + +namespace SMLHelper.V2.Handlers { using Interfaces; using Patchers; using System.Collections.Generic; using UnityEngine; - using Logger = V2.Logger; + using InternalLogger = InternalLogger; /// /// A handler class for configuring custom unlocking conditions for item blueprints. @@ -66,7 +68,7 @@ internal void AddAnalysisTech(TechType techTypeToBeAnalysed, IEnumerable compoundTechsF { if (techType == TechType.None) { - Logger.Error("Cannot Add Unlock to TechType.None!"); + InternalLogger.Error("Cannot Add Unlock to TechType.None!"); return; } if (compoundTechsForUnlock.Contains(techType)) { - Logger.Error("Cannot Add Compound Unlock that contains itself!"); + InternalLogger.Error("Cannot Add Compound Unlock that contains itself!"); return; } if (KnownTechPatcher.CompoundTech.TryGetValue(techType, out KnownTech.CompoundTech compoundTech)) { - Logger.Debug($"Compound Unlock already found for {techType.AsString()}, Overwriting."); + InternalLogger.Debug($"Compound Unlock already found for {techType.AsString()}, Overwriting."); compoundTech.dependencies = compoundTechsForUnlock; } else { - Logger.Debug($"Adding Compound Unlock for {techType.AsString()}"); + InternalLogger.Debug($"Adding Compound Unlock for {techType.AsString()}"); KnownTechPatcher.CompoundTech.Add(techType, new KnownTech.CompoundTech() { techType = techType, dependencies = compoundTechsForUnlock }); } } @@ -119,20 +121,20 @@ internal void RemoveAnalysisTechEntry(TechType targetTechType) { if (tech.unlockTechTypes.Contains(targetTechType)) { - Logger.Debug($"Removed {targetTechType.AsString()} from {tech.techType.AsString()} unlocks that was added by another mod!"); + InternalLogger.Debug($"Removed {targetTechType.AsString()} from {tech.techType.AsString()} unlocks that was added by another mod!"); tech.unlockTechTypes.Remove(targetTechType); } } if (KnownTechPatcher.CompoundTech.TryGetValue(targetTechType, out var types)) { - Logger.Debug($"Removed Compound Unlock for {targetTechType.AsString()} that was added by another mod!"); + InternalLogger.Debug($"Removed Compound Unlock for {targetTechType.AsString()} that was added by another mod!"); KnownTechPatcher.CompoundTech.Remove(targetTechType); } if (KnownTechPatcher.UnlockedAtStart.Contains(targetTechType)) { - Logger.Debug($"Removed UnlockedAtStart for {targetTechType.AsString()} that was added by another mod!"); + InternalLogger.Debug($"Removed UnlockedAtStart for {targetTechType.AsString()} that was added by another mod!"); KnownTechPatcher.UnlockedAtStart.Remove(targetTechType); } diff --git a/SMLHelper/Handlers/LootDistributionHandler.cs b/SMLHelper/Handlers/LootDistributionHandler.cs index 362c3ca0..a2b30cd0 100644 --- a/SMLHelper/Handlers/LootDistributionHandler.cs +++ b/SMLHelper/Handlers/LootDistributionHandler.cs @@ -4,6 +4,7 @@ using Interfaces; using Patchers; using SMLHelper.V2.Assets; + using SMLHelper.V2.Utility; using UWE; /// @@ -165,7 +166,7 @@ void ILootDistributionHandler.AddLootDistributionData(ModPrefab prefab, IEnumera void ILootDistributionHandler.AddLootDistributionData(string classId, LootDistributionData.SrcData data) { if (LootDistributionPatcher.CustomSrcData.ContainsKey(classId)) - Logger.Log($"{classId}-{data.prefabPath} already has custom distribution data. Replacing with latest.", LogLevel.Debug); + InternalLogger.Log($"{classId}-{data.prefabPath} already has custom distribution data. Replacing with latest.", LogLevel.Debug); LootDistributionPatcher.CustomSrcData[classId] = data; } diff --git a/SMLHelper/Handlers/PDAEncyclopediaHandler.cs b/SMLHelper/Handlers/PDAEncyclopediaHandler.cs index 5be808b6..5c6a048d 100644 --- a/SMLHelper/Handlers/PDAEncyclopediaHandler.cs +++ b/SMLHelper/Handlers/PDAEncyclopediaHandler.cs @@ -2,6 +2,7 @@ { using Interfaces; using Patchers; + using SMLHelper.V2.Utility; /// /// Handles Encyclopedia. @@ -21,7 +22,7 @@ private PDAEncyclopediaHandler() void IPDAEncyclopediaHandler.AddCustomEntry(PDAEncyclopedia.EntryData entry) { if (PDAEncyclopediaPatcher.CustomEntryData.ContainsKey(entry.key)) - Logger.Log($"{entry.key} already has custom PDAEncyclopedia.EntryData. Replacing with latest.", LogLevel.Debug); + InternalLogger.Log($"{entry.key} already has custom PDAEncyclopedia.EntryData. Replacing with latest.", LogLevel.Debug); PDAEncyclopediaPatcher.CustomEntryData[entry.key] = entry; } diff --git a/SMLHelper/Handlers/PDAHandler.cs b/SMLHelper/Handlers/PDAHandler.cs index 78ed4efe..668ccac5 100644 --- a/SMLHelper/Handlers/PDAHandler.cs +++ b/SMLHelper/Handlers/PDAHandler.cs @@ -2,6 +2,7 @@ { using Interfaces; using Patchers; + using SMLHelper.V2.Utility; /// /// A handler class for various scanner related data. @@ -55,7 +56,7 @@ void IPDAHandler.EditFragmentScanTime(TechType techType, float scanTime) void IPDAHandler.AddCustomScannerEntry(PDAScanner.EntryData entryData) { if (PDAPatcher.CustomEntryData.ContainsKey(entryData.key)) - Logger.Log($"{entryData.key} already has custom PDAScanner.EntryData. Replacing with latest.", LogLevel.Debug); + InternalLogger.Log($"{entryData.key} already has custom PDAScanner.EntryData. Replacing with latest.", LogLevel.Debug); PDAPatcher.CustomEntryData[entryData.key] = entryData; } diff --git a/SMLHelper/Handlers/WorldEntityDatabaseHandler.cs b/SMLHelper/Handlers/WorldEntityDatabaseHandler.cs index 9cba0dca..ed38eeba 100644 --- a/SMLHelper/Handlers/WorldEntityDatabaseHandler.cs +++ b/SMLHelper/Handlers/WorldEntityDatabaseHandler.cs @@ -2,6 +2,7 @@ { using Interfaces; using SMLHelper.V2.Patchers; + using SMLHelper.V2.Utility; using UnityEngine; using UWE; @@ -55,7 +56,7 @@ public static void AddCustomInfo(string classId, TechType techType, Vector3 loca void IWorldEntityDatabaseHandler.AddCustomInfo(string classId, WorldEntityInfo data) { if(WorldEntityDatabasePatcher.CustomWorldEntityInfos.ContainsKey(classId)) - V2.Logger.Log($"{classId}-{data.techType} already has custom WorldEntityInfo. Replacing with latest.", LogLevel.Debug); + Utility.InternalLogger.Log($"{classId}-{data.techType} already has custom WorldEntityInfo. Replacing with latest.", LogLevel.Debug); WorldEntityDatabasePatcher.CustomWorldEntityInfos[classId] = data; } diff --git a/SMLHelper/Initializer.cs b/SMLHelper/Initializer.cs index f7f87dd0..014060de 100644 --- a/SMLHelper/Initializer.cs +++ b/SMLHelper/Initializer.cs @@ -1,54 +1,67 @@ namespace SMLHelper.V2 { using System; + using System.Collections; using System.Reflection; + using BepInEx; using HarmonyLib; using Patchers; using Patchers.EnumPatching; - using QModManager.API.ModLoading; + using SMLHelper.V2.Utility; + using UnityEngine; /// - /// WARNING: This class is for use only by QModManager. + /// WARNING: This class is for use only by Bepinex. /// - [QModCore] - public class Initializer + [BepInPlugin(GUID, MODNAME, VERSION)] + public class Initializer: BaseUnityPlugin { - internal static readonly Harmony harmony = new Harmony("com.ahk1221.smlhelper"); + private const string + MODNAME = "SMLHelper", + GUID = "com.ahk1221.smlhelper", + VERSION = "2.15.0.0"; + + internal static readonly Harmony harmony = new Harmony(GUID); /// - /// WARNING: This method is for use only by QModManager. + /// WARNING: This method is for use only by Bepinex. /// - [QModPrePatch] - [Obsolete("This method is for use only by QModManager.", true)] - public static void PrePatch() + [Obsolete("This method is for use only by Bepinex.", true)] + Initializer() { - Logger.Initialize(); + InternalLogger.Initialize(Logger); #if SUBNAUTICA - Logger.Log($"Loading v{Assembly.GetExecutingAssembly().GetName().Version} for Subnautica", LogLevel.Info); + InternalLogger.Info($"Loading v{VERSION} for Subnautica"); #elif BELOWZERO - Logger.Log($"Loading v{Assembly.GetExecutingAssembly().GetName().Version} for BelowZero", LogLevel.Info); + InternalLogger.Info($"Loading v{VERSION} for BelowZero"); #endif - Logger.Debug("Loading TechType Cache"); + InternalLogger.Debug("Loading TechType Cache"); TechTypePatcher.cacheManager.LoadCache(); - Logger.Debug("Loading CraftTreeType Cache"); + InternalLogger.Debug("Loading CraftTreeType Cache"); CraftTreeTypePatcher.cacheManager.LoadCache(); - Logger.Debug("Loading PingType Cache"); + InternalLogger.Debug("Loading PingType Cache"); PingTypePatcher.cacheManager.LoadCache(); PrefabDatabasePatcher.PrePatch(harmony); + StartCoroutine(InitializePatches()); } - /// - /// WARNING: This method is for use only by QModManager. - /// - [QModPostPatch("E3DC72597463233E62D01BD222AD0C96")] - [Obsolete("This method is for use only by QModManager.", true)] - public static void PostPatch() + + private IEnumerator InitializePatches() { - FishPatcher.Patch(harmony); + Type chainLoader = typeof(BepInEx.Bootstrap.Chainloader); + var _loaded = chainLoader.GetField("_loaded", BindingFlags.NonPublic | BindingFlags.Static); + while(!(bool)_loaded.GetValue(null)) + { + yield return null; + } + + yield return new WaitForSecondsRealtime(2); + + FishPatcher.Patch(harmony); TechTypePatcher.Patch(); CraftTreeTypePatcher.Patch(); PingTypePatcher.Patch(); @@ -82,13 +95,12 @@ public static void PostPatch() EatablePatcher.Patch(harmony); - Logger.Debug("Saving TechType Cache"); + InternalLogger.Debug("Saving TechType Cache"); TechTypePatcher.cacheManager.SaveCache(); - Logger.Debug("Saving CraftTreeType Cache"); + InternalLogger.Debug("Saving CraftTreeType Cache"); CraftTreeTypePatcher.cacheManager.SaveCache(); - Logger.Debug("Saving PingType Cache"); + InternalLogger.Debug("Saving PingType Cache"); PingTypePatcher.cacheManager.SaveCache(); - } } } diff --git a/SMLHelper/Interfaces/IBasicText.cs b/SMLHelper/Interfaces/IBasicText.cs index 8bb5a93f..4e98fac1 100644 --- a/SMLHelper/Interfaces/IBasicText.cs +++ b/SMLHelper/Interfaces/IBasicText.cs @@ -1,9 +1,4 @@ -#if BELOWZERO -using Text = TMPro.TextMeshPro; -using Font = TMPro.TMP_FontAsset; -using FontStyle = TMPro.FontStyles; -#endif - +using TMPro; using UnityEngine; namespace SMLHelper.V2.Interfaces @@ -77,7 +72,7 @@ public interface IBasicText /// Sets the text anchor. /// /// The text anchor to align to - void SetAlign(TextAnchor useAlign); + void SetAlign(TextAlignmentOptions useAlign); /// /// Sets the text color @@ -89,13 +84,13 @@ public interface IBasicText /// Sets the font /// /// The font to render the text as. - void SetFont(Font useFont); + void SetFont(TMP_FontAsset useFont); /// /// Sets the font style. /// /// The text font style to use - void SetFontStyle(FontStyle useStyle); + void SetFontStyle(FontStyles useStyle); /// /// Sets screen display location (position relative to the actual text is determined by the alignment) diff --git a/SMLHelper/Json/ConfigFile.cs b/SMLHelper/Json/ConfigFile.cs index 73785c3d..a54f1869 100644 --- a/SMLHelper/Json/ConfigFile.cs +++ b/SMLHelper/Json/ConfigFile.cs @@ -2,13 +2,8 @@ using System.IO; using System.Reflection; using System.Linq; -#if SUBNAUTICA_STABLE -using Oculus.Newtonsoft.Json; -using Oculus.Newtonsoft.Json.Converters; -#else using Newtonsoft.Json; using Newtonsoft.Json.Converters; -#endif namespace SMLHelper.V2.Json { @@ -61,13 +56,13 @@ public ConfigFile() { JsonFilename = configFile.Filename; JsonPath = Path.Combine( - Path.GetDirectoryName(Assembly.GetCallingAssembly().Location), + Path.Combine(BepInEx.Paths.ConfigPath, Assembly.GetCallingAssembly().GetName().Name), configFile.Subfolder); } else { JsonFilename = "config"; - JsonPath = Path.GetDirectoryName(Assembly.GetCallingAssembly().Location); + JsonPath = Path.Combine(BepInEx.Paths.ConfigPath, Assembly.GetCallingAssembly().GetName().Name); } } @@ -93,7 +88,7 @@ protected ConfigFile(string fileName = "config", string subfolder = null) { JsonFilename = fileName; JsonPath = Path.Combine( - Path.GetDirectoryName(Assembly.GetCallingAssembly().Location), + Path.Combine(BepInEx.Paths.ConfigPath, Assembly.GetCallingAssembly().GetName().Name), string.IsNullOrEmpty(subfolder) ? string.Empty : subfolder); } diff --git a/SMLHelper/Json/Converters/FloatConverter.cs b/SMLHelper/Json/Converters/FloatConverter.cs index a7524170..1115b294 100644 --- a/SMLHelper/Json/Converters/FloatConverter.cs +++ b/SMLHelper/Json/Converters/FloatConverter.cs @@ -2,11 +2,7 @@ { using System; using System.Globalization; -#if SUBNAUTICA_STABLE - using Oculus.Newtonsoft.Json; -#else using Newtonsoft.Json; -#endif /// /// A for rounding floats or doubles to a given number of decimal places, diff --git a/SMLHelper/Json/Converters/KeyCodeConverter.cs b/SMLHelper/Json/Converters/KeyCodeConverter.cs index 32de9174..dd7194e9 100644 --- a/SMLHelper/Json/Converters/KeyCodeConverter.cs +++ b/SMLHelper/Json/Converters/KeyCodeConverter.cs @@ -3,11 +3,7 @@ using System; using SMLHelper.V2.Utility; using UnityEngine; -#if SUBNAUTICA_STABLE - using Oculus.Newtonsoft.Json; -#else using Newtonsoft.Json; -#endif /// /// A for handling s. diff --git a/SMLHelper/Json/Converters/QuaternionConverter.cs b/SMLHelper/Json/Converters/QuaternionConverter.cs index 81e4c3e6..634a10a8 100644 --- a/SMLHelper/Json/Converters/QuaternionConverter.cs +++ b/SMLHelper/Json/Converters/QuaternionConverter.cs @@ -1,10 +1,7 @@ using System; using UnityEngine; -#if SUBNAUTICA_STABLE - using Oculus.Newtonsoft.Json; -#else using Newtonsoft.Json; -#endif + namespace SMLHelper.V2.Json.Converters { /// diff --git a/SMLHelper/Json/Converters/Vector2Converter.cs b/SMLHelper/Json/Converters/Vector2Converter.cs index adf6a09e..855bfd4e 100644 --- a/SMLHelper/Json/Converters/Vector2Converter.cs +++ b/SMLHelper/Json/Converters/Vector2Converter.cs @@ -1,10 +1,7 @@ using System; using UnityEngine; -#if SUBNAUTICA_STABLE -using Oculus.Newtonsoft.Json; -#else using Newtonsoft.Json; -#endif + namespace SMLHelper.V2.Json.Converters { /// diff --git a/SMLHelper/Json/Converters/Vector2IntConverter.cs b/SMLHelper/Json/Converters/Vector2IntConverter.cs index 849813e9..62ce2e62 100644 --- a/SMLHelper/Json/Converters/Vector2IntConverter.cs +++ b/SMLHelper/Json/Converters/Vector2IntConverter.cs @@ -1,10 +1,7 @@ using System; using UnityEngine; -#if SUBNAUTICA_STABLE -using Oculus.Newtonsoft.Json; -#else using Newtonsoft.Json; -#endif + namespace SMLHelper.V2.Json.Converters { /// diff --git a/SMLHelper/Json/Converters/Vector3Converter.cs b/SMLHelper/Json/Converters/Vector3Converter.cs index c68989c8..45a115d1 100644 --- a/SMLHelper/Json/Converters/Vector3Converter.cs +++ b/SMLHelper/Json/Converters/Vector3Converter.cs @@ -1,10 +1,7 @@ using System; using UnityEngine; -#if SUBNAUTICA_STABLE -using Oculus.Newtonsoft.Json; -#else using Newtonsoft.Json; -#endif + namespace SMLHelper.V2.Json.Converters { /// diff --git a/SMLHelper/Json/Converters/Vector3IntConverter.cs b/SMLHelper/Json/Converters/Vector3IntConverter.cs index b052e560..68c92754 100644 --- a/SMLHelper/Json/Converters/Vector3IntConverter.cs +++ b/SMLHelper/Json/Converters/Vector3IntConverter.cs @@ -1,10 +1,7 @@ using System; using UnityEngine; -#if SUBNAUTICA_STABLE -using Oculus.Newtonsoft.Json; -#else using Newtonsoft.Json; -#endif + namespace SMLHelper.V2.Json.Converters { /// diff --git a/SMLHelper/Json/Converters/Vector4Converter.cs b/SMLHelper/Json/Converters/Vector4Converter.cs index 6b747cff..10cbdbe3 100644 --- a/SMLHelper/Json/Converters/Vector4Converter.cs +++ b/SMLHelper/Json/Converters/Vector4Converter.cs @@ -1,10 +1,7 @@ using System; using UnityEngine; -#if SUBNAUTICA_STABLE -using Oculus.Newtonsoft.Json; -#else using Newtonsoft.Json; -#endif + namespace SMLHelper.V2.Json.Converters { /// diff --git a/SMLHelper/Json/ExtensionMethods/JsonExtensions.cs b/SMLHelper/Json/ExtensionMethods/JsonExtensions.cs index b1512724..1b03cadb 100644 --- a/SMLHelper/Json/ExtensionMethods/JsonExtensions.cs +++ b/SMLHelper/Json/ExtensionMethods/JsonExtensions.cs @@ -1,11 +1,7 @@ namespace SMLHelper.V2.Json.ExtensionMethods { using SMLHelper.V2.Utility; -#if SUBNAUTICA_STABLE - using Oculus.Newtonsoft.Json; -#else using Newtonsoft.Json; -#endif /// /// Extension methods for parsing objects as JSON data. diff --git a/SMLHelper/Json/Interfaces/IJsonFile.cs b/SMLHelper/Json/Interfaces/IJsonFile.cs index b3d4fade..917d97e5 100644 --- a/SMLHelper/Json/Interfaces/IJsonFile.cs +++ b/SMLHelper/Json/Interfaces/IJsonFile.cs @@ -1,10 +1,6 @@ namespace SMLHelper.V2.Json.Interfaces { -#if SUBNAUTICA_STABLE - using Oculus.Newtonsoft.Json; -#else using Newtonsoft.Json; -#endif /// /// A simple interface for a JSON file framework. diff --git a/SMLHelper/Json/JsonFile.cs b/SMLHelper/Json/JsonFile.cs index 59da1b13..7a888cb7 100644 --- a/SMLHelper/Json/JsonFile.cs +++ b/SMLHelper/Json/JsonFile.cs @@ -1,12 +1,7 @@ using System; using System.Linq; -#if SUBNAUTICA_STABLE -using Oculus.Newtonsoft.Json; -using Oculus.Newtonsoft.Json.Converters; -#else using Newtonsoft.Json; using Newtonsoft.Json.Converters; -#endif namespace SMLHelper.V2.Json { diff --git a/SMLHelper/Json/SaveDataCache.cs b/SMLHelper/Json/SaveDataCache.cs index 4b2702bf..264860c4 100644 --- a/SMLHelper/Json/SaveDataCache.cs +++ b/SMLHelper/Json/SaveDataCache.cs @@ -1,17 +1,12 @@ -using QModManager.API; -using System; -using System.IO; -using System.Reflection; -#if SUBNAUTICA_STABLE -using Oculus.Newtonsoft.Json; -#else -using Newtonsoft.Json; -#endif - -namespace SMLHelper.V2.Json +namespace SMLHelper.V2.Json { using Attributes; using Interfaces; + using System; + using System.IO; + using System.Reflection; + using Newtonsoft.Json; + using SMLHelper.V2.Utility; /// /// An abstract implementation of intended for use with caching per-save data. @@ -40,7 +35,7 @@ public abstract class SaveDataCache : JsonFile /// public SaveDataCache() { - QModId = QModServices.Main.FindModByAssembly(GetType().Assembly).Id; + QModId = GetType().Assembly.GetName().Name; } /// @@ -56,7 +51,7 @@ public override void Load(bool createFileIfNotExist = true) if (InGame) { base.Load(createFileIfNotExist); - Logger.Log($"[{QModId}] Loaded save data from {JsonFileName}.json"); + InternalLogger.Log($"[{QModId}] Loaded save data from {JsonFileName}.json"); } else { @@ -75,7 +70,7 @@ public override void Save() if (InGame) { base.Save(); - Logger.Log($"[{QModId}] Saved save data to {JsonFileName}.json"); + InternalLogger.Log($"[{QModId}] Saved save data to {JsonFileName}.json"); } else { @@ -98,7 +93,7 @@ public override void LoadWithConverters(bool createFileIfNotExist = true, params if (InGame) { base.LoadWithConverters(createFileIfNotExist, jsonConverters); - Logger.Log($"[{QModId}] Loaded save data from {JsonFileName}.json"); + InternalLogger.Log($"[{QModId}] Loaded save data from {JsonFileName}.json"); } else { @@ -119,7 +114,7 @@ public override void SaveWithConverters(params JsonConverter[] jsonConverters) if (InGame) { base.SaveWithConverters(jsonConverters); - Logger.Log($"[{QModId}] Saved save data to {JsonFileName}.json"); + InternalLogger.Log($"[{QModId}] Saved save data to {JsonFileName}.json"); } else { diff --git a/SMLHelper/Modding Helper/SMLHelper.dll b/SMLHelper/Modding Helper/SMLHelper.dll new file mode 100644 index 00000000..39bd980b Binary files /dev/null and b/SMLHelper/Modding Helper/SMLHelper.dll differ diff --git a/SMLHelper/Modding Helper/SMLHelper.xml b/SMLHelper/Modding Helper/SMLHelper.xml new file mode 100644 index 00000000..e01805a0 --- /dev/null +++ b/SMLHelper/Modding Helper/SMLHelper.xml @@ -0,0 +1,8613 @@ + + + + SMLHelper + + + + + An item that can be built into the game world. + + + + + + + Obsolete. No longer functional. Handle with a customized HandTarget instead. + + + + + Initializes a new , the basic class for any item that can built using the Habitat Builder Tool. + + The main internal identifier for this item. Your item's will be created using this name. + The name displayed in-game for this item whether in the open world or in the inventory. + The description for this item; Typically seen in the PDA, inventory, or crafting screens. + + + + An item that can be crafted into the game world from a fabricator. + + + + + + + Override with the vanilla fabricator that crafts this item. + Leave this as if you are manually adding this item to a custom fabricator. + + + + + Override with the tab node steps to take to get to the tab you want the item's blueprint to appear in. + If not overriden, the item will appear at the craft tree's root. + + + + + Override with a custom crafting time for this item. Normal default crafting time is 1f. + Any value zero or less will be ignored. + + + + + Initializes a new , the basic class for any item that can be crafted at a fabricator. + + The main internal identifier for this item. Your item's will be created using this name. + The name displayed in-game for this item whether in the open world or in the inventory. + The description for this item; Typically seen in the PDA, inventory, or crafting screens. + + + + An asset class inheriting from that streamlines the process of creating a custom fabricator with a custom crafting tree. + + + + + + Defines a list of available models for your . + + + + + The regular fabricator like the one in the life pod. + + + + + The modification station that upgrades your equipment. + + + + + The style of fabricator found in the Moon Pool and the Cyclops sub. + + + + + Use this option only if you want to provide your own custom model for your fabricator. + To use this value, you must override the method. + + + + + Initialized a new based on the asset class. + + The main internal identifier for this item. Your item's will be created using this name. + The name displayed in-game for this item whether in the open world or in the inventory. + The description for this item; Typically seen in the PDA, inventory, or crafting screens. + + + + Override this property to change which model your custom fabricator will use. + By default, this will be the standard as seen in the lifepod. + + + + + Override this property to change the value of . + Defaults to true. + + + + + Override this property to change the value of . + Defaults to true. + + + + + Override this property to change the value of . + Defaults to false. + + + + + Override this property to change the value of . + Defaults to false. + + + + + Override this property to change the value of . + Defaults to true for and false for all others. + + + + + Override this property to change the value of . + Defaults to false for and true for all others. + + + + + Override this property to change the value of . + Defaults to true for and false for all others. + + + + + Override this value tp true along with to apply a simple tint to your custom fabricator for easy customization. + + + + + Override this value to your desired along with to apply a simple tint to your custom fabricator for easy customization. + + + + + The ID value for your custom craft tree. This is set after this method is invoked. + + + + + Gets the root node of the crafting tree. This is set after this method is invoked. + + + + + Override with the category within the group in the PDA blueprints where this item appears. + + + + + Override with the main group in the PDA blueprints where this item appears. + + + + + The in-game . + + + + + + The in-game , async way. + + + + + + Override this method if you want to provide your own prefab and model for your custom fabricator. + + + + + + Override this method if you want to provide your own prefab and model for your custom fabricator. + + + + + + Override this method if you want full control over how your custom craft tree is built up. + To use this method's default behavior, you must use the following methods to build up your crafting tree. + - + - + - + + + + + + Adds a new tab node to the custom crafting tree of this fabricator. + + The internal ID for the tab node. + The in-game text shown for the tab node. + The sprite used for the tab node. + Optional. The parent tab of this tab. + When this value is null, the tab will be added to the root of the craft tree. + + + + Adds a new crafting node to the custom crafting tree of this fabricator. + + The item to craft. + Optional. The parent tab of this craft node. + When this value is null, the craft node will be added to the root of the craft tree. + + + + Safely attempts to add a new crafting node to the custom crafting tree of this fabricator. + If the modded TechType is not found, the craft node will not be added. + + The modded item to craft. + Optional. The parent tab of this craft node. + When this value is null, the craft node will be added to the root of the craft tree. + + + + Safely adds a new crafting node to the custom crafting tree of this fabricator. + If the item has not been patched yet, its method will first be invoked. + + The item to craft from this fabricator. + Optional. The parent tab of this craft node. + When this value is null, the item's property will be checked instead. + The craft node will be added to the root of the craft tree if both are null. + + + + An item that can be crafted and equipped. + + + + + + + Gets the type of equipment slot this item can fit into. + + + The type of the equipment slot compatible with this item. + + + + + Gets the type of equipment slot this item can fit into. + + + The type of the equipment slot compatible with this item. + + + + + Initializes a new instance of the class. + + The main internal identifier for this item. Your item's will be created using this name. + The name displayed in-game for this item whether in the open world or in the inventory. + The description for this item; Typically seen in the PDA, inventory, or crafting screens. + + + + "A wrapper class that uses and to quickly create a custom fish + + + + + The id to use to create the creature. This should be unique + + + + + The display name for your fish. This is shown in the inventory, and can be whatever you want + + + + + The short description of your fish in the inventory + + + + + The file name of your fish's sprite in the inventory. You can leave this null if your fish isn't pickupable. The file is relative + from the QMods folder, e.g. "MinecraftFish/Assets/cod.png" + + + + + The model to use to create the creature. This would ideally only have renderer/collider components attached, but will still work if it has behaviours + + + + + Determines whether your creature can be picked up by the player + + + + + Determines whether the creature moves on land or in water. Default true, which is in water. Land creature AI does not work ATM. + + + + + The speed at which your creature will swim + + + + + The interval (in seconds) between when your fish will find a new position to swim to + + + + + The area in which your creature will look for a random position when swimming. This should be larger for larger creatures + + + + + Class used by CustomFish for constructing a prefab based on the values provided by the user. + You can use this yourself if you want, but you will need to manually provide a TechType + + + + + The model to use to create the creature. This would ideally only have renderer/collider components attached, but will still work if it has behaviours + + + + + Determines whether your creature can be picked up + + + + + Determines whether your creature walks or swims. Only works for swimming at the moment, land will probably be fixed at a later time + + + + + The speed at which your creature moves + + + + + The area in which your creature's AI will look for a new spot to move to + + + + + The interval in seconds between when your creature finds a new spot to move to + + + + + Creates a new with the given values + + + + + + + + Gets the prefab game object + + + + + The abstract class to inherit when you want to add new PreFabs into the game. + + + + + The class identifier used for the component whenever applicable. + + + + + Name of the prefab file. + + + + + The of the corresponding item. + Used for , and components whenever applicable. + + + + + Initializes a new instance of the class. + + The class identifier used for the component whenever applicable. + Name of the prefab file. + The techtype of the corresponding item. + Used for the and components whenever applicable. + Can also be set later in the constructor if it is not yet provided. + + + + Caches the prefab, then sets its TechType and ClassID to a default set of values applicable to most mods.
+ FOR ADVANCED MODDING ONLY. Do not override unless you know exactly what you are doing. +
+ +
+ + + Gets the prefab game object. Set up your prefab components here. + The and ClassID are already handled. + + The game object to be instantiated into a new in-game entity. + + + + Gets the prefab game object asynchronously. Set up your prefab components here. + The and ClassID are already handled. + + The game object to be instantiated into a new in-game entity. + + + + Class that used by to store game objects that used as prefabs. + Also it can be used by mods directly, e.g. in to store prefab before returning. + Game objects in cache are inactive and will not be on scene. + + + + Add prefab to cache + Prefab to add. + + Is prefab needed to be removed from cache after use. + Prefabs without autoremove flag can be safely deleted by + + + + Add prefab copy to cache (instatiated copy will not run 'Awake') + Prefab to copy and add. + + Is prefab copy needed to be removed from cache after use. + Prefabs without autoremove flag can be safely deleted by + + Prefab copy + + + + A item that appears in the PDA blueprints. + + + + + + Override to set the that must first be scanned or picked up to unlock the blueprint for this item. + + + + + Override to set multiple s that must first be scanned or picked up to unlock the blueprint for this item. + + + + + Override to add a scanner entry to the TechType if it does not have one. + WARNING. You can overwrite an existing entry with this. Use with Caution as this can break recipe unlocks of the original! + Default is . + + + + + Override to set the number of that must be scanned to unlock; + If not overriden, Default value is . + + + + + Override to set the speed that the fragments are scanned; + If not overriden, Default value is . + + + + + Override to allow fragments to be scanned for materials after the relavent TechType is already Unlocked. + Default is . + + + + + Override to add a into the PDA's Encyclopedia for this object. + WARNING. You can overwrite an existing entry with this. Use with Caution! + Default is . + + + + + Override with the main group in the PDA blueprints where this item appears. + + + + + Override with the category within the group in the PDA blueprints where this item appears. + + + + + Override this property to assign whether or not the should be unlocked at the start, defaulted to == + + + + + Message which should be shown when the item is unlocked. + If not overridden, the message will default to Subnautica's (language key ""). + + + + + Initializes a new , the basic class for any item that appears among your PDA blueprints. + + The main internal identifier for this item. Your item's will be created using this name. + The name displayed in-game for this item whether in the open world or in the inventory. + The description for this item; Typically seen in the PDA, inventory, or crafting screens. + + + + This provides the instance used to designate how this item is crafted or constructed. + + + + + An item that can be spawned into the game. + + + + + + A simple delegate type that takes no parameters and returns void. + + + + + Override with the folder where your mod's icons and other assets are stored. + By default, this will point to the same folder where your mod DLL is. + + "MyModAssembly/Assets" + + + + Override with the file name for this item's icon. + If not overriden, this defaults to "[this item's ClassID].png". + + "MyClassID.png" + + + + The in-game name of this spawnable item. + + + + + The description text when viewing this spawnable item from the inventory or crafting UI. + + + + + Returns true if this spawnable item has already been patched; Otherwise false. + This will become true after the method has finished running. + + + + + Returns the size that this entity will occupy inside the player inventory.
+ By default this will be 1x1. Override to change the size. +
+
+ + + A lightweight class used to specify the position of a Coordinated Spawn and optionally set its rotation. + + + + + + + A lightweight class used to specify the position of a Coordinated Spawn and optionally set its rotation. + + + + + + + + + + + + + Returns the list of s that specify the prefab's Coordinated Spawns.
+ By default this will be null. +
+
+ + + Returns the List of BiomeData that handles what Biomes this prefab will spawn, how probable it is to spawn there and how many per spawn. + By default this will be null. Override to change this. + + + + + Returns the of this object if it has one. + By default this will be null. Override to change this. + + + + + Gets a value indicating whether if we should be looking for a Sprite when NOT overriding . + + + + + Initializes a new , the basic class needed for any item that can be spawned into the Subnautica game world. + + The main internal identifier for this item. Your item's will be created using this name. + The name displayed in-game for this item whether in the open world or in the inventory. + The description for this item; Typically seen in the PDA, inventory, or crafting screens. + + + + This event triggers before the core patching methods begins. + You can attach simple methods to this event if you want to run code before the any of the core patching methods begin. + + + + + The main patching methods are executed here. + This event should only be used by the SMLHelper QuickStart classes. + + + + + This event triggers after the core patching methods begins. + You can attach simple methods to this event if you want to run code after the core patching methods have finished. + + + + + Starts all patching code in SMLHelper. + If is true then this method is skipped to avoid duplicate patching. + + + + + + + Determines thee to be used for this spawnable's icon. + Default behavior will look for a PNG file named inside . + + Returns the that will be used in the call. + + + + A class that handles a custom sprite and what item it is associated to. + + + + + The tech type of a specific item associated with this sprite. + Can be if this sprite is for used on a group. + + + + + The actual sprite used in-game when this sprite is references. + + + + + The group that this sprite belongs to. + Can be if this sprite is for used on an item. + + + + + The internal identifier of this sprite when it isn't associated to an item. + + + + + Creates a new ModSprite to be used with a specific TechType. + Created with an Atlas Sprite. + + The techtype paired to this sprite. + The sprite to be added. + + + + Creates a new ModSprite to be used with a specific group and internal ID. + Created with an Atlas Sprite. + + The sprite group. + The sprite internal identifier. + The sprite to be added. + + + + Creates a new ModSprite to be used with a specific group and internal ID. + Created with an Atlas Sprite. + + The sprite group. + The techtype paired to this sprite. + The sprite to be added. + + + + Creates a new ModSprite to be used with a specific group and internal ID. + Created with a UnityEngine Sprite. + + The sprite group this sprite will be added to. + The sprite internal identifier. + The sprite to be added. + + + + Creates a new ModSprite to be used with a specific TechType. + Created with a UnityEngine Sprite. + + The techtype paired to this sprite. + The sprite to be added. + + + + Represents a console command. + + + + + The string that triggers the command. + + + + + The QMod that registered the command. + + + + + The parameters for the command. + + + + + The types of the parameters. + + + + + Creates an instance of . + + The string that triggers the command. + The method targeted by the command. + Whether or not the method is a delegate. + The instance the method belongs to. + + + + Determines whether the targeted method is valid in terms of whether it is static or delegate. + + + + + + Determines whether the target methods parameters are valid. + + + + + + Returns a list of all invalid parameters. + + + + + + Attempts to parse input parameters into appropriate types as defined in the target method. + + The parameters as input by the user. + The parameters that have been successfully parsed. + Whether or not all parameters were succesfully parsed. + + + + Invokes the command with the given parameters. + + The command parameters. + The string returned from the command. + + + + Attribute used to signify the decorated method should be called in response to a console command. + + Decorated method must be both and . + + + The command can take parameters and will respect optional parameters as outlined in the method's signature.
+ Supported parameter types: , , , , + .
+ + If the method has a return type, it will be printed to both the screen and the log. +
+ + + + +
+ + + The unique, case-insensitive command that when entered, will call the decorated method. + + + + + Signifies the decorated method should be called when the given is entered + in the dev console. + + Decorated method must be both and . + + + The command can take parameters and will respect optional parameters as outlined in the method's signature.
+ Supported parameter types: , , , , + .
+ + If the method has a return type, it will be printed to both the screen and the log. +
+ The unique, case-insensitive command that when entered into the dev console will call the + decorated method. + + + + +
+ + + A crafting node of a CraftTree. This is the last node on a tree; The one that actually crafts something. + + + + + + Abstract class that provides methods for adding new nodes into the crafting tree. + + + + + + The child nodes linked bellow this node. + + + + + Creates a new tab node for the crafting tree and links it to the calling node. + + The name/ID of this node. + The hover text to display in-game. + The custom sprite to display on this tab node. + A new tab node linked to the root node and ready to use. + + + + Creates a new tab node for the crafting tree and links it to the calling node. + + The name/ID of this node. + The hover text to display in-game. + The custom sprite to display on this tab node. + A new tab node linked to the root node and ready to use. + + + + Creates a new tab node for the crafting tree and links it to the calling node. + + The name/ID of this node. + A new tab node linked to the root node and ready to use. + + + + Gets the tab from the calling node. + + The name id of the tab to get. + + + + + Gets the crafting node from the calling node. + + The TechType whose node to get. + + + + + Gets the node associated with the ID specified. Used if you don't know whether node is a tab or a craft node. + + + + + + + Creates a new crafting node for the crafting tree and links it to the calling node. + + The TechType to be crafted. + + + + Creates a collection of new crafting nodes for the crafting tree and links it to the calling node. + + The TechTypes to be crafted. + + + + Creates a collection of new crafting nodes for the crafting tree and links it to the calling node. + + The TechTypes to be crafted. + + + + Creates a new crafting node for a modded item and links it to the calling node. + If the modded item isn't present for the player, this call is safely ignored. + + The internal name of the custom TechType to be crafted. + + If the player doesn't have the mod for this TechType installed, then nothing will happen. + + + + + Basic data structure of a crafting tree node. + + + + + The action this node takes in the crafting tree. + + + + + The tech type ID associated to this node. + For item nodes, it is the item ID to be crafted. + For root and tab nodes, this is always . + + + + + The name ID for this tab node. + + + + + The the in-game representation of this node. + + + + + Removes the calling node from parent. + + + + + The root node of a CraftTree. The whole tree starts here. + Build up your custom crafting tree from this root node using the AddCraftingNode and AddTabNode methods.
+ This tree will be automatically patched into the game. No further calls into required. + For more advanced usage, you can replace the default value of with your own custom function. +
+ +
+ + + Dynamically creates the CraftTree object for this crafting tree. + The CraftNode objects were created and linked as the classes of the ModCraftTreeFamily were created and linked. + + + + + Populates a new ModCraftTreeRoot from a CraftNode tree. + + The tree to create the ModCraftTreeRoot from. + + + + + The craft tree creation function.
+ Default implementaion returns a new instantiated with and the root . + You can replace this function with your own to have more control of the crafting tree when it is being created. +
+
+ + + Gets the tab node at the specified path from the root. + + + The steps to the target tab. + These must match the id value of the CraftNode in the crafting tree you're targeting. + Do not include "root" in this path. + + If the specified tab node is found, returns that ; Otherwise, returns null. + + + + Gets the node at the specified path from the root. + + + The steps to the target tab. + These must match the id value of the CraftNode in the crafting tree you're targeting. + Do not include "root" in this path. + + If the specified tab node is found, returns that ; Otherwise, returns null. + + + + A tab node of a CraftTree. Tab nodes help organize crafting nodes by grouping them into categories. + + + + + + A class that fully describes a recipe for a identified item. + + + + + + Gets or sets the how many copies of the item are created when crafting this recipe. + + + The quantity of the item this recipe yields. + + + + + Gets the number of different ingredients for this recipe. + + + The number of ingredients for this recipe. + + + + + Gets the number of items linked to this recipe. + + + The number of linked items. + + + + + The list of ingredients required for this recipe. + + + + + The items that will also be created when this recipe is crafted. + + + + + Initializes a new instance of the class a custom recipe. + + + + + Initializes a new instance of the class for a custom recipe with a list of ingridients. + + The ingredients. + + + + Initializes a new instance of the class for a custom recipe with a collection of ingridients. + + The ingredients. + + + + Gets the ingredient at the specified index. + + The index. + The at the requested the index if the index is value; Otherwise returns null. + + + + Gets the linked item at the specified index. + + The index. + The at the requested the index if the index is value; Otherwise returns null. + + + + A class for representing a required ingredient in a recipe. + + + + + + + Gets or sets the item ID. + + + The item ID. + + + + + Gets or sets the number of this item required for the recipe. + + + The amount of this item needed for the recipe. + + + + + Initializes a new instance of the class. + + The item ID. + The number of instances of this item required for the recipe. + + + + This class is used to register FMOD events with multiple sounds in one event. + + + + + Makes the sounds play in a randomized order. when false, sounds will play subsequently. + + + + + Constructs a new instance of . Used to register FMOD events with multiple sounds in one event. + + The sounds to register for this object. Please ensure that none of the sounds are on or modes. + path to play these sounds under. + Makes the sounds play in a randomized order. when false, sounds will play subsequently. + + + + Constructs a new instance of . Used to register FMOD events with multiple sounds in one event. + + The clips to register for this object. + The mode to set the clips to. Cannot be MODE.LOOP_NORMAL or MODE.LOOP_BIDI. + path to play these sounds under. + Makes the sounds play in a randomized order. when false, sounds will play subsequently. + + + + Constructs a new instance of . Used to register FMOD events with multiple sounds in one event. + + The sound paths to register for this object. Paths must be relative to the base game folder. + The mode to set the clips to. Cannot be MODE.LOOP_NORMAL or MODE.LOOP_BIDI. + path to play these sounds under. + Makes the sounds play in a randomized order. when false, sounds will play subsequently. + + + + This interface is used to integrate with . + + + + + Defines how to play sound in this object. + + The channel the sound was played on + + + + A simple location where every SMLHelper handler class can be accessed. + + + + + A handler with common methods for updating BioReactor values. + + + + + A handler class for adding and editing crafted items. + + + + + A handler class for creating and editing of crafting trees. + + + + + A handler class that offers simple ways to tap into functionality of the in game menu. + + + + + Class to manage registering of fish into the game + + + + + A handler class for registering your custom middle click actions for items + + + + + A handler class for configuring custom unlocking conditions for item blueprints. + + + + + A handler for adding language lines. + + + + + A handler class for registering your custom in-game mod options. + + + + + A handler class for various scanner related data. + + + + + A handler class for adding custom sprites into the game. + + + + + A handler class for everything related to creating new TechTypes. + + + + + A handler class for adding and editing resource spawns. + + + + + A handler for adding custom entries to the world entity database. + + + + + A handler for adding custom entries to the PDA Encyclopedia. + + + + + A handler for registering Unity prefabs associated to a . + + + + + a handler for common uses to the Survival component + + + + + A handler to making coordinated Vector3 spawns ingame. + + + + + A handler class for adding custom TechGroups into the game. + + + + + A handler class for adding custom TechCategories into the game. + + + + + A handler class for registering your custom console commands. + + + + + A handler related to PingTypes + + + + + A handler for everything related to creating new BackgroundTypes. + + + + + A handler related to Custom Sounds + + + + + A handler for adding custom EquipmentTypes into the game. + + + + + A handler for stuff related to the PDALog class. + + + + + A handler for editing values for eatable classes + + + + + A handler for everything related to creating new BackgroundTypes. + + + + + Main entry point for all calls to this handler. + + + + + adds a new into the game. + + the name of the BackgroundType, should not contain special characters. + The sprite for this BackgroundType. + The new that's created. + + + + Safely looks for a modded Background Type from another mod in the SMLHelper BackgroundTypeCache and outputs its value when found. + + The string used to define the BackgroundType + The BackgroundType enum value of the modded. Defaults to when the item was not found. + if the item was found; otherwise . + + + + Safely looks for a modded Background Type from another mod in the SMLHelper BackgroundTypeCache. + + The string used to define the BackgroundType. + if the item was found; otherwise . + + + + adds a new into the game. + + the name of the BackgroundType, should not contain special characters. + The sprite for this BackgroundType. + The new that's created. + + + + + Safely looks for a modded Background Type from another mod in the SMLHelper BackgroundTypeCache and outputs its value when found. + + The string used to define the BackgroundType + The BackgroundType enum value of the modded. Defaults to when the item was not found. + if the item was found; otherwise . + + + + Safely looks for a modded Background Type from another mod in the SMLHelper BackgroundTypeCache. + + The string used to define the BackgroundType. + if the item was found; otherwise . + + + + A handler with common methods for updating BioReactor values. + + + + + Main entry point for all calls to this handler. + + + + + Allows you to specify the quantity of energy that a TechType will produce with bio reactors. + + The TechType that you want to use with bioreactors. + The quantity of energy that will be produced by this TechType. + + + + + Allows you to specify the quantity of energy that a TechType will produce with bio reactors. + + The TechType that you want to use with bioreactors. + The quantity of energy that will be produced by this TechType. + + + + + A handler class for registering your custom console commands. + + + + + Main entry point for all calls to this handler. + + + + + a Handler that handles and registers Coordinated ( spawns). + + + + + Main entry point for all calls to this handler. + + + + + Registers Multiple Coordinated spawns for one single passed TechType + + The TechType to spawn + the coordinates the should spawn to + + + + Registers a Coordinated Spawn + + the SpawnInfo to spawn + + + + registers Many Coordinated Spawns. + + The SpawnInfos to spawn. + + + + Registers Multiple Coordinated spawns with rotations for one single passed TechType + + The TechType to spawn + the coordinates(Key) and the rotations(Value) the should spawn to + + + + Registers a Coordinated Spawn + + the SpawnInfo to spawn + + + + registers Many Coordinated Spawns. + + The SpawnInfo to spawn. + + + + Registers Multiple Coordinated spawns for one single passed TechType + + The TechType to spawn + the coordinates the should spawn to + + + + Registers Multiple Coordinated spawns with rotations for one single passed TechType + + The TechType to spawn + the coordinates(Key) and the rotations(Value) the should spawn to + + + + A basic struct that provides enough info for the System to function. + + + + + Initializes a new . + + TechType to spawn. + Position to spawn into. + + + + Initializes a new . + + ClassID to spawn. + Position to spawn into. + + + + Initializes a new . + + TechType to spawn. + Position to spawn into. + Rotation to spawn at. + + + + Initializes a new . + + ClassID to spawn. + Position to spawn into. + Rotation to spawn at. + + + + Initializes a new . + + TechType to spawn. + Position to spawn into. + Rotation to spawn at. + + + + Initializes a new . + + ClassID to spawn. + Position to spawn into. + Rotation to spawn at. + + + + Indicates whether this instance and a specified object are equal. + + + It is worth noting that we use Unity's and + operator comparisons for comparing the and properties of each instance, + to allow for an approximate comparison of these values. + + The object to compare with the current instance. + if is a and represents the same + value as this instance; otherwise, . + + + + + A custom hash code algorithm that takes into account the values of each property of the instance, + and attempts to reduce diagonal collisions. + + A 32-bit signed integer that is the hash code for this instance. + + + + Indicates whether the current is equal to another. + + + It is worth noting that we use Unity's and + operator comparisons for comparing the and properties of each instance, + to allow for an approximate comparison of these values. + + The other . + if the current is equal to the parameter; + otherwise . + + + + Indicates whether two instances are equal. + + The first instance to compare. + The second instance to compare. + if the instances are equal; otherwise, . + + + + + + Indicates whether two instances are not equal. + + The first instance to compare. + The second instance to compare. + if the instances are not equal; otherwise, . + + + + + + A handler class for adding and editing crafted items. + + + A handler class for adding and editing crafted items. + + + + + Main entry point for all calls to this handler. + + + + + Allows you to edit EquipmentTypes for TechTypes. + Can be used for existing TechTypes too. + + The TechType whose EqiupmentType you want to edit. + The EquipmentType for that TechType. + + + + Allows you to edit QuickSlotType for TechTypes. Can be used for existing TechTypes too. + Careful: This has to be called after and . + + The TechType whose QuickSlotType you want to edit. + The QuickSlotType for that TechType. + + + + Allows you to edit harvest output, i.e. what TechType you get when you "harvest" a TechType. + Can be used for existing TechTypes too. + + The TechType whose harvest output you want to edit. + The harvest output for that TechType. + + + + Allows you to edit how TechTypes are harvested. + Can be used for existing TechTypes too. + + The TechType whose HarvestType you want to edit. + The HarvestType for that TechType. + + + + Allows you to edit how much additional slices/seeds are given upon last knife hit. + Can be used for existing TechTypes too. + + The TechType whose final cut bonus you want to edit. + The number of additional slices/seeds you'll receive on last cut. + + + + Allows you to edit item sizes for TechTypes. + Can be used for existing TechTypes too. + + The TechType whose item size you want to edit. + The item size for that TechType. + + + + Allows you to edit item sizes for TechTypes. + Can be used for existing TechTypes too. + + The TechType whose item size you want to edit. + The width of the item + The height of the item + + + + Allows you to edit crafting times for TechTypes. + Can be used for existing TechTypes too. + + The TechType whose crafting time you want to edit. + The crafting time, in seconds, for that TechType. + + + + Allows you to edit the cooked creature list, i.e. associate the unedible TechType to the cooked TechType. + Can be used for existing TechTypes too. + + The TechType whose cooked creature counterpart to edit. + The cooked creature counterpart for that TechType. + + + + Allows you to edit inventory background colors for TechTypes. + + The TechType whose BackgroundType you want to edit. + The background color for that TechType. + + + + + Allows you to add items to the buildable list. + + The TechType which you want to add to the buildable list. + + + + Allows you to add items to the game's internal grouping system. + Required if you want to make buildable items show up in the Habitat Builder. + + The TechGroup you want to add your TechType to. + The TechCategory (in the TechGroup) you want to add your TechType to. + The TechType you want to add. + + + + Allows you to add items to the game's internal grouping system. + Required if you want to make buildable items show up in the Habitat Builder. + + The TechGroup you want to add your TechType to. + The TechCategory (in the TechGroup) you want to add your TechType to. + The TechType you want to add. + Added TechType will be added after this TechType, for sorting purposes. + + + + Allows you to remove an existing TechType from the game's internal group system. + + The TechGroup in which the TechType is located. + The TechCategory in which the TechType is located. + The TechType which you want to remove. + + + + Allows you to add items to the game's internal grouping system. + Required if you want to make buildable items show up in the Habitat Builder or show in the Blueprints Tab of the PDA. + + The TechGroup you want to add your TechType to. + The TechCategory (in the TechGroup) you want to add your TechType to. + The TechType you want to add. + + + + Allows you to add items to the game's internal grouping system. + Required if you want to make buildable items show up in the Habitat Builder or show in the Blueprints Tab of the PDA. + + The TechGroup you want to add your TechType to. + The TechCategory (in the TechGroup) you want to add your TechType to. + The TechType you want to add. + Added TechType will be added after this TechType, for sorting purposes. + + + + Allows you to remove an existing TechType from the game's internal group system. + + The TechGroup in which the TechType is located. + The TechCategory in which the TechType is located. + The TechType which you want to remove. + + + + Allows you to edit recipes, i.e. TechData for TechTypes. + Can be used for existing TechTypes too. + + The TechType whose TechData you want to edit. + The TechData for that TechType. + + + + + Allows you to edit recipes, i.e. TechData for TechTypes. + Can be used for existing TechTypes too. + + The TechType whose TechData you want to edit. + The TechData for that TechType. + + + + + Safely accesses the crafting data from a modded item. + WARNING: This method is highly dependent on mod load order. + Make sure your mod is loading after the mod whose TechData you are trying to access. + + The TechType whose TechData you want to access. + The ITechData from the modded item if it exists; Otherwise, returns null. + + + + Safely accesses the crafting data from any item. + WARNING: This method is highly dependent on mod load order. + Make sure your mod is loading after the mod whose TechData you are trying to access. + + The TechType whose TechData you want to access. + Returns TechData if it exists; Otherwise, returns null. + + + + Sets the eating sound for the provided TechType. + + The item being consumed during . + + The sound path. + + Value values are + - "event:/player/drink" + - "event:/player/drink_stillsuit" + - "event:/player/use_first_aid" + - "event:/player/eat" (default) + + + + + + Allows you to edit recipes, i.e. TechData for TechTypes. + Can be used for existing TechTypes too. + + The TechType whose TechData you want to edit. + The TechData for that TechType. + + + + + Allows you to edit recipes, i.e. TechData for TechTypes. + Can be used for existing TechTypes too. + + The TechType whose TechData you want to edit. + The TechData for that TechType. + + + + + Allows you to edit EquipmentTypes for TechTypes. + Can be used for existing TechTypes too. + + The TechType whose EqiupmentType you want to edit. + The EquipmentType for that TechType. + + + + Allows you to edit QuickSlotType for TechTypes. Can be used for existing TechTypes too. + Careful: This has to be called after and . + + The TechType whose QuickSlotType you want to edit. + The QuickSlotType for that TechType. + + + + Allows you to edit harvest output, i.e. what TechType you get when you "harvest" a TechType. + Can be used for existing TechTypes too. + + The TechType whose harvest output you want to edit. + The harvest output for that TechType. + + + + Allows you to edit how TechTypes are harvested. + Can be used for existing TechTypes too. + + The TechType whose HarvestType you want to edit. + The HarvestType for that TechType. + + + + Allows you to edit how much additional slices/seeds are given upon last knife hit. + Can be used for existing TechTypes too. + + The TechType whose final cut bonus you want to edit. + The number of additional slices/seeds you'll receive on last cut. + + + + Allows you to edit item sizes for TechTypes. + Can be used for existing TechTypes too. + + The TechType whose item size you want to edit. + The item size for that TechType. + + + + Allows you to edit item sizes for TechTypes. + Can be used for existing TechTypes too. + + The TechType whose item size you want to edit. + The width of the item + The height of the item + + + + Allows you to edit crafting times for TechTypes. + Can be used for existing TechTypes too. + + The TechType whose crafting time you want to edit. + The crafting time, in seconds, for that TechType. + + + + Allows you to edit the cooked creature list, i.e. associate the unedible TechType to the cooked TechType. + Can be used for existing TechTypes too. + + The TechType whose cooked creature counterpart to edit. + The cooked creature counterpart for that TechType. + + + + Allows you to edit inventory background colors for TechTypes. + + The TechType whose BackgroundType you want to edit. + The background color for that TechType. + + + + + Allows you to add items to the buildable list. + + The TechType which you want to add to the buildable list. + + + + Safely accesses the crafting data from a modded item. + WARNING: This method is highly dependent on mod load order. + Make sure your mod is loading after the mod whose TechData you are trying to access. + + The TechType whose TechData you want to access. + The ITechData from the modded item if it exists; Otherwise, returns null. + + + + Safely accesses the crafting data from any item. + WARNING: This method is highly dependent on mod load order. + Make sure your mod is loading after the mod whose TechData you are trying to access. + + The TechType whose TechData you want to access. + Returns TechData if it exists; Otherwise, returns null. + + + + Sets the eating sound for the provided TechType. + + The item being consumed during . + + The sound path. + + Value values are + - "event:/player/drink" + - "event:/player/drink_stillsuit" + - "event:/player/use_first_aid" + - "event:/player/eat" (default) + + + + + + A handler class for creating and editing of crafting trees. + + + + + Main entry point for all calls to this handler. + + + + + Your first method call to start a new custom crafting tree.
+ Creating a new CraftTree only makes sense if you're going to use it in a new type of . +
+ The name for the new enum. + The new enum instance for your custom craft tree type. + + Returns the root node for your custom craft tree, as a new instance.
+ Build up your custom crafting tree from this root node.
+ This tree will be automatically patched into the game. No further calls into required. + For more advanced usage, you can replace the default value of with your own custom function. +
+ + + + +
+ + + Safely looks for a modded CraftTree Type from another mod in the SMLHelper CraftTreeTypeCache. + + The string used to define the modded item's new techtype. + + True if the craft tree was found; Otherwise false. + + + There's no guarantee in which order SMLHelper dependent mods are loaded, + so if two mods are added at the same time, it may take a second game load for both to be visible to each other. + + + + + Adds a new crafting node to the root of the specified crafting tree, at the provided tab location. + + The target craft tree to edit. + The item to craft. + + The steps to the target tab. + These must match the id value of the CraftNode in the crafting tree you're targeting. + Do not include "root" in this path. + + + + + Adds a new crafting node to the root of the specified crafting tree + + The target craft tree to edit. + The item to craft. + + + + Adds a new tab node to the root of the specified crafting tree. + + The target craft tree to edit. + The ID of the tab node. Must be unique! + The display name of the tab, which will show up when you hover your mouse on the tab. + The sprite of the tab. + + + + Adds a new tab node to the root of the specified crafting tree. + + The target craft tree to edit. + The ID of the tab node. Must be unique! + The display name of the tab, which will show up when you hover your mouse on the tab. + The sprite of the tab. + + + + Adds a new tab node to the root of the specified crafting tree, at the specified tab location. + + The target craft tree to edit. + The ID of the tab node. Must be unique! + The display name of the tab, which will show up when you hover your mouse on the tab. + The sprite of the tab. + + The steps to the target tab. + These must match the id value of the CraftNode in the crafting tree you're targeting. + Do not include "root" in this path. + + + + + Adds a new tab node to the root of the specified crafting tree, at the specified tab location. + + The target craft tree to edit. + The ID of the tab node. Must be unique! + The display name of the tab, which will show up when you hover your mouse on the tab. + The sprite of the tab. + + The steps to the target tab. + These must match the id value of the CraftNode in the crafting tree you're targeting. + Do not include "root" in this path. + + + + + Removes a node at the specified node location. Can be used to remove either tabs or craft nodes. + If a tab node is selected, all child nodes to it will also be removed. + + The target craft tree to edit. + + The steps to the target node. + These must match the id value of the CraftNode in the crafting tree you're targeting. + This means matching the id of the crafted item or the id of the tab name. + Do not include "root" in this path. + + + + + Your first method call to start a new custom crafting tree.
+ Creating a new CraftTree only makes sense if you're going to use it in a new type of . +
+ The name for the new enum. + The new enum instance for your custom craft tree type. + + Returns the root node for your custom craft tree, as a new instance.
+ Build up your custom crafting tree from this root node.
+ This tree will be automatically patched into the game. No further calls into required. + For more advanced usage, you can replace the default value of with your own custom function. +
+ + + + +
+ + + Safely looks for a modded CraftTree Type from another mod in the SMLHelper CraftTreeTypeCache. + + The string used to define the modded item's new techtype. + + True if the craft tree was found; Otherwise false. + + + There's no guarantee in which order SMLHelper dependent mods are loaded, + so if two mods are added at the same time, it may take a second game load for both to be visible to each other. + + + + + Adds a new crafting node to the root of the specified crafting tree, at the provided tab location. + + The target craft tree to edit. + The item to craft. + + The steps to the target tab. + These must match the id value of the CraftNode in the crafting tree you're targeting. + Do not include "root" in this path. + + + + + Adds a new crafting node to the root of the specified crafting tree + + The target craft tree to edit. + The item to craft. + + + + Adds a new tab node to the root of the specified crafting tree. + + The target craft tree to edit. + The ID of the tab node. Must be unique! + The display name of the tab, which will show up when you hover your mouse on the tab. + The sprite of the tab. + + + + Adds a new tab node to the root of the specified crafting tree. + + The target craft tree to edit. + The ID of the tab node. Must be unique! + The display name of the tab, which will show up when you hover your mouse on the tab. + The sprite of the tab. + + + + Adds a new tab node to the root of the specified crafting tree, at the specified tab location. + + The target craft tree to edit. + The ID of the tab node. Must be unique! + The display name of the tab, which will show up when you hover your mouse on the tab. + The sprite of the tab. + + The steps to the target tab. + These must match the id value of the CraftNode in the crafting tree you're targeting. + Do not include "root" in this path. + + + + + Adds a new tab node to the root of the specified crafting tree, at the specified tab location. + + The target craft tree to edit. + The ID of the tab node. Must be unique! + The display name of the tab, which will show up when you hover your mouse on the tab. + The sprite of the tab. + + The steps to the target tab. + These must match the id value of the CraftNode in the crafting tree you're targeting. + Do not include "root" in this path. + + + + + Removes a node at the specified node location. Can be used to remove either tabs or craft nodes. + If a tab node is selected, all child nodes to it will also be removed. + + The target craft tree to edit. + + The steps to the target node. + These must match the id value of the CraftNode in the crafting tree you're targeting. + This means matching the id of the crafted item or the id of the tab name. + Do not include "root" in this path. + + + + + A handler class for adding and overriding Sounds. + + + + + Main entry point for all calls to this handler. + + + + + Register a Custom sound by file path. Some vanilla game sounds can be overridden by matching the id to the . + + The Id of your custom sound which is used when checking which sounds to play. + The file path on disk of the sound file to load + The sound channel to get the volume to play the sound at. defaults to + the loaded + + + + Register a Custom sound by file path. Some vanilla game sounds can be overridden by matching the id to the . + + The Id of your custom sound which is used when checking which sounds to play. + The file path on disk of the sound file to load. + The bus path to play the sound on. + the loaded + + + + Register a Custom sound by file path. Some vanilla game sounds can be overridden by matching the id to the . + + The Id of your custom sound which is used when checking which sounds to play. + The file path on disk of the sound file to load. + The bus to play the sound on. + the loaded + + + + Register a custom sound by an instance. Some vanilla game sounds can be overridden by matching the id to the . + + The Id of your custom sound which is used when checking which sounds to play. + The AudioClip to register. + The sound channel to get the volume to play the sound at. defaults to + the registered. + + + + Register a custom sound by an instance. Some vanilla game sounds can be overridden by matching the id to the . + + The Id of your custom sound which is used when checking which sounds to play. + The AudioClip to register. + The bus path to play the sound on. + the loaded + + + + Register a custom sound by an instance. Some vanilla game sounds can be overridden by matching the id to the . + + The Id of your custom sound which is used when checking which sounds to play. + The AudioClip to register. + The bus to play the sound on. + the loaded + + + + Registers a Custom sound by an instance. IFModSound instances have custom logic for playing sounds. + + The Id of your custom sound which is used when checking which sounds to play. + The sound IFModSound object to register. + + + + Register a Custom sound that has been loaded using AudioUtils. Some vanilla game sounds can be overridden by matching the id to the . + + The Id of your custom sound which is used when checking which sounds to play. + The pre loaded sound + The sound channel to get the volume to play the sound at. + + + + Register a Custom sound that has been loaded using AudioUtils. Some vanilla game sounds can be overridden by matching the id to the . + + The Id of your custom sound which is used when checking which sounds to play. + The pre loaded sound + The bus path to play the sound on. + + + + Register a Custom sound that has been loaded using AudioUtils. Some vanilla game sounds can be overridden by matching the id to the . + + The Id of your custom sound which is used when checking which sounds to play. + The pre loaded sound + The bus to play the sound on. + + + + Try to find and play a custom that has been registered. + + The Id of the custom sound + + + + Try to get a registered custom . + + The Id of the custom sound + Outputs the if found and null if not found. + true or false depending on if the id was found + + + + Try to get a playing custom sound channel for an emitter + + The emitter's ID, can be retrieved by calling object.GetInstanceID(). + Outputs the . + True if found, otherwise false. + + + + Register a Custom sound by file path. Some vanilla game sounds can be overridden by matching the id to the . + + The Id of your custom sound which is used when checking which sounds to play. + The file path on disk of the sound file to load + The sound channel to get the volume to play the sound at. defaults to + the loaded + + + + Register a Custom sound by file path. Some vanilla game sounds can be overridden by matching the id to the . + + The Id of your custom sound which is used when checking which sounds to play. + The file path on disk of the sound file to load. + The bus path to play the sound on. + the loaded + + + + Register a Custom sound by file path. Some vanilla game sounds can be overridden by matching the id to the . + + The Id of your custom sound which is used when checking which sounds to play. + The file path on disk of the sound file to load. + The bus to play the sound on. + the loaded + + + + Register a custom sound by an instance. Some vanilla game sounds can be overridden by matching the id to the . + + The Id of your custom sound which is used when checking which sounds to play. + The AudioClip to register. + The sound channel to get the volume to play the sound at. defaults to + the registered. + + + + Register a custom sound by an instance. Some vanilla game sounds can be overridden by matching the id to the . + + The Id of your custom sound which is used when checking which sounds to play. + The AudioClip to register. + The bus path to play the sound on. + the loaded + + + + Registers a Custom sound by an instance. IFModSound instances have custom logic for playing sounds. + + The Id of your custom sound which is used when checking which sounds to play. + The sound IFModSound object to register. + + + + Register a custom sound by an instance. Some vanilla game sounds can be overridden by matching the id to the . + + The Id of your custom sound which is used when checking which sounds to play. + The AudioClip to register. + The bus to play the sound on. + the loaded + + + + Register a Custom sound that has been loaded using AudioUtils. Some vanilla game sounds can be overridden by matching the id to the . + + The Id of your custom sound which is used when checking which sounds to play. + The pre loaded sound + The sound channel to get the volume to play the sound at. + + + + Register a Custom sound that has been loaded using AudioUtils. Some vanilla game sounds can be overridden by matching the id to the . + + The Id of your custom sound which is used when checking which sounds to play. + The pre loaded sound + The bus path to play the sound on. + + + + Register a Custom sound that has been loaded using AudioUtils. Some vanilla game sounds can be overridden by matching the id to the . + + The Id of your custom sound which is used when checking which sounds to play. + The pre loaded sound + The bus to play the sound on. + + + + Try to find and play a custom that has been registered. + + The Id of the custom sound + + + + Try to get a registered custom . + + The Id of the custom sound + Outputs the if found and null if not found. + true or false depending on if the id was found + + + + Try to get a playing custom sound channel for an emitter + + The emitter's ID, can be retrieved by calling object.GetInstanceID(). + Outputs the . + True if found, otherwise false. + + + + A handler for editing values for eatable classes + + + + + Main entry point for all calls to this handler. + + + + + Use this to change the values of a specific TechType. + + The TechType of the item you want to change. + The food value you want to change it to. + The water value you want to change it to. + Whether or not the item decomposes over time + + + + A handler class for everything related to creating new Equipments. + + + + + Main entry point for all calls to this handler. + + + + + Adds a new into the game. + + The name of the Equipment. Should not contain special characters. + + The new that is created. + + + + + Safely looks for a modded group from another mod in the SMLHelper EquipmentCache. + + The string used to define the techgroup. + + True if the item was found; Otherwise false. + + + + + Safely looks for a modded item from another mod in the SMLHelper EquipmentCache and outputs its value when found. + + The string used to define the techgroup. + The Equipment enum value of the modded. Defaults to when the item was not found. + + True if the item was found; Otherwise false. + + + + + Class to manage registering of fish into the game + + + + + Main entry point for all calls to this handler. + + + + + A list of all the custom fish that have so far been registered into the game. This includes ones from mods that may have been loaded earlier. + It is mainly used by CustomFishPatcher to spawn fish in + + + + + Registers a CustomFish object into the game + + The CustomFish that you are registering + The TechType created using the info from your CustomFish object + + + + Registers a CustomFish object into the game + + The CustomFish that you are registering + The TechType created using the info from your CustomFish object + + + + A handler class that offers simple ways to tap into functionality of the in game menu. + + + + + Main entry point for all calls to this handler. + + + + + Registers a simple method to invoke whenever the player saves the game via the in game menu. + + The method to invoke. + + + + Registers a simple method to invoke whenever the player loads a saved game via the in game menu. + + The method to invoke. + + + + Registers a simple method to invoke whenever the player quits the game via the in game menu. + + The method to invoke. + + + + Removes a method previously added through so it is no longer invoked when saving the game. + If you plan on using this, do not register an anonymous method. + + The method invoked. + + + + Removes a method previously added through so it is no longer invoked when loading the game. + If you plan on using this, do not register an anonymous method. + + The method invoked. + + + + Removes a method previously added through so it is no longer invoked when quitting the game. + If you plan on using this, do not register an anonymous method. + + The method invoked. + + + + Registers a simple method to invoke the first time the player saves the game via the in game menu. + + The method to invoke. This action will not be invoked a second time. + + + + Registers a simple method to invoke the first time the player loads a saved game via the in game menu. + + The method to invoke. This action will not be invoked a second time. + + + + Registers a simple method to invoke the first time the player quits the game via the in game menu. + + The method to invoke. This action will not be invoked a second time. + + + + Registers a simple method to invoke whenever the player saves the game via the in game menu. + + The method to invoke. + + + + Registers a simple method to invoke whenever the player quits the game via the in game menu. + + The method to invoke. + + + + Removes a method previously added through so it is no longer invoked when saving the game. + If you plan on using this, do not register an anonymous method. + + The method invoked. + + + + Removes a method previously added through so it is no longer invoked when quiting the game. + If you plan on using this, do not register an anonymous method. + + The method invoked. + + + + Registers a simple method to invoke the first time the player saves the game via the in game menu. + + The method to invoke. This action will not be invoked a second time. + + + + Registers a simple method to invoke the first time the player quits the game via the in game menu. + + The method to invoke. This action will not be invoked a second time. + + + + A handler class for registering your custom middle click actions for items + + + + + Main entry point for all calls to this handler. + + + + + Registers a custom left click action for a + + The to which the left click action will be assigned + The method which will be called when a matching with the specified was left-clicked + The secondary tooltip which will appear in the description of the item + The condition which must return for the action to be called when the item is clickedIf ommited, the action will always be called + + + + Registers a custom middle click action for a + + The which the middle click action will be assigned + The method which will be called when a matching with the specified was middle-clicked + The secondary tooltip which will appear in the description of the item + The condition which must return for the action to be called when the item is clickedIf ommited, the action will always be called + + + + Registers a custom left click action for a + + The to which the left click action will be assigned + The method which will be called when a matching with the specified was left-clicked + The secondary tooltip which will appear in the description of the item + The condition which must return for the action to be called when the item is clickedIf ommited, the action will always be called + + + + Registers a custom middle click action for a + + The which the middle click action will be assigned + The method which will be called when a matching with the specified was middle-clicked + The secondary tooltip which will appear in the description of the item + The condition which must return for the action to be called when the item is clickedIf ommited, the action will always be called + + + + A handler class for configuring custom unlocking conditions for item blueprints. + + + + + Main entry point for all calls to this handler. + + + + + Allows you to unlock a TechType on game start. + + + + + + Allows you to unlock a TechType on game start. + + + + + + Allows you to define which TechTypes are unlocked when a certain TechType is unlocked, i.e., "analysed". + If there is already an exisitng AnalysisTech entry for a TechType, all the TechTypes in "techTypesToUnlock" will be + added to the existing AnalysisTech entry unlocks. + + This TechType is the criteria for all of the "unlock TechTypes"; when this TechType is unlocked, so are all the ones in that list + The TechTypes that will be unlocked when "techTypeToSet" is unlocked. + The message that shows up on the right when the blueprint is unlocked. + The sound that plays when you unlock the blueprint. + The sprite that shows up when you unlock the blueprint. + + + + Allows you to set up a custom Compound Unlock requiring multiple techtypes to be unlocked before 1 is. + ***Note: This will not remove any original unlock and if you need to do so you should use or + + + + + + + Allows you to remove unlock entries for a from specific entries. + + Target to remove the unlocks for. + List of to remove the targetTechType from. + + + + Allows you to remove all unlock entries from a to be able to disable or change it to a new unlock. + ***Note: This is patch time specific so the LAST mod to call this on a techtype will be the only one to control what unlocks said type after its use.*** + + Target to remove the unlocks for. + + + + Allows you to define which TechTypes are unlocked when a certain TechType is unlocked, i.e., "analysed". + If there is already an exisitng AnalysisTech entry for a TechType, all the TechTypes in "techTypesToUnlock" will be + added to the existing AnalysisTech entry unlocks. + + This TechType is the criteria for all of the "unlock TechTypes"; when this TechType is unlocked, so are all the ones in that list + The TechTypes that will be unlocked when "techTypeToSet" is unlocked. + + + + Allows you to define which TechTypes are unlocked when a certain TechType is unlocked, i.e., "analysed". + If there is already an exisitng AnalysisTech entry for a TechType, all the TechTypes in "techTypesToUnlock" will be + added to the existing AnalysisTech entry unlocks. + + This TechType is the criteria for all of the "unlock TechTypes"; when this TechType is unlocked, so are all the ones in that list + The TechTypes that will be unlocked when "techTypeToSet" is unlocked. + The message that shows up on the right when the blueprint is unlocked. + + + + Allows you to define which TechTypes are unlocked when a certain TechType is unlocked, i.e., "analysed". + If there is already an exisitng AnalysisTech entry for a TechType, all the TechTypes in "techTypesToUnlock" will be + added to the existing AnalysisTech entry unlocks. + + This TechType is the criteria for all of the "unlock TechTypes"; when this TechType is unlocked, so are all the ones in that list + The TechTypes that will be unlocked when "techTypeToSet" is unlocked. + The sound that plays when you unlock the blueprint. + + + + Allows you to define which TechTypes are unlocked when a certain TechType is unlocked, i.e., "analysed". + If there is already an exisitng AnalysisTech entry for a TechType, all the TechTypes in "techTypesToUnlock" will be + added to the existing AnalysisTech entry unlocks. + + This TechType is the criteria for all of the "unlock TechTypes"; when this TechType is unlocked, so are all the ones in that list + The TechTypes that will be unlocked when "techTypeToSet" is unlocked. + The sprite that shows up when you unlock the blueprint. + + + + Allows you to define which TechTypes are unlocked when a certain TechType is unlocked, i.e., "analysed". + If there is already an exisitng AnalysisTech entry for a TechType, all the TechTypes in "techTypesToUnlock" will be + added to the existing AnalysisTech entry unlocks. + + This TechType is the criteria for all of the "unlock TechTypes"; when this TechType is unlocked, so are all the ones in that list + The TechTypes that will be unlocked when "techTypeToSet" is unlocked. + The message that shows up on the right when the blueprint is unlocked. + The sound that plays when you unlock the blueprint. + + + + Allows you to define which TechTypes are unlocked when a certain TechType is unlocked, i.e., "analysed". + If there is already an exisitng AnalysisTech entry for a TechType, all the TechTypes in "techTypesToUnlock" will be + added to the existing AnalysisTech entry unlocks. + + This TechType is the criteria for all of the "unlock TechTypes"; when this TechType is unlocked, so are all the ones in that list + The TechTypes that will be unlocked when "techTypeToSet" is unlocked. + The message that shows up on the right when the blueprint is unlocked. + The sprite that shows up when you unlock the blueprint. + + + + Allows you to define which TechTypes are unlocked when a certain TechType is unlocked, i.e., "analysed". + If there is already an exisitng AnalysisTech entry for a TechType, all the TechTypes in "techTypesToUnlock" will be + added to the existing AnalysisTech entry unlocks. + + This TechType is the criteria for all of the "unlock TechTypes"; when this TechType is unlocked, so are all the ones in that list + The TechTypes that will be unlocked when "techTypeToSet" is unlocked. + The sound that plays when you unlock the blueprint. + The sprite that shows up when you unlock the blueprint. + + + + Allows you to set up a custom Compound Unlock requiring multiple techtypes to be unlocked before 1 is. + ***Note: This will not remove any original unlock and if you need to do so you should use or + + + + + + + Allows you to remove unlock entries for a from specific entries. + + Target to remove the unlocks for. + List of to remove the targetTechType from. + + + + Allows you to remove all unlock entries from a to be able to disable or change it to a new unlock. + ***Note: This is patch time specific so the LAST mod to call this on a techtype will be the only one to control what unlocks said type after its use.*** + + Target to remove the unlocks for. + + + + A handler for adding custom language lines. + + + + + Main entry point for all calls to this handler. + + + + + Allows you to define a language entry into the game. + + The ID of the entry, this is what is used to get the actual text. + The actual text related to the entry. + + + + Allows you to set the display name of a specific . + + The whose display name that is to be changed. + The new display name for the chosen . + + + + Allows you to set the tooltip of a specific . + + The whose tooltip that is to be changed. + The new tooltip for the chosen . + + + + Allows you to define a language entry into the game. + + The ID of the entry, this is what is used to get the actual text. + The actual text related to the entry. + + + + Allows you to set the display name of a specific . + + The whose display name that is to be changed. + The new display name for the chosen . + + + + Allows you to set the tooltip of a specific . + + The whose tooltip that is to be changed. + The new tooltip for the chosen . + + + + A handler that manages Loot Distribution. + + + + + Main entry point for all calls to this handler. + + + + + Adds in a custom entry into the Loot Distribution of the game. + + + + + + + Adds in a custom entry into the Loot Distribution of the game. + You must also add the into the using . + + The that contains data related to the spawning of a prefab, also contains the path to the prefab. + The classId of the prefab. + The WorldEntityInfo of the prefab. For more information on how to set this up, see . + + + + Adds in a custom entry into the Loot Distribution of the game. + You must also add the into the using . + + The classId of the prefab. + The prefab path of the prefab. + The dictating how the prefab should spawn in the world. + + + + Adds in a custom entry into the Loot Distribution of the game. + You must also add the into the using . + + The classId of the prefab. + The prefab path of the prefab. + The dictating how the prefab should spawn in the world. + The WorldEntityInfo of the prefab. For more information on how to set this up, see . + + + + Adds in a custom entry into the Loot Distribution of the game. + You must also add the into the using . + + The custom prefab which you want to spawn naturally in the game. + The dictating how the prefab should spawn in the world. + The WorldEntityInfo of the prefab. For more information on how to set this up, see . + + + + Edits Loot Distribution Data for existing/original class IDs. + + + + + Edits Loot Distribution data for existing prefabs, for e.g. original game prefabs. + + The ClassID of the prefab. If unsure, use CraftData.GetClassIdForTechType. + The list of that contains information about how/when it should spawn in biomes. + + + + Adds in a custom entry into the Loot Distribution of the game. + You must also add the into the using . + + The that contains data related to the spawning of a prefab, also contains the path to the prefab. + The classId of the prefab. + The WorldEntityInfo of the prefab. For more information on how to set this up, see . + + + + Adds in a custom entry into the Loot Distribution of the game. + You must also add the into the using . + + The classId of the prefab. + The prefab path of the prefab. + The dictating how the prefab should spawn in the world. + + + + Adds in a custom entry into the Loot Distribution of the game. + + The classId of the prefab. + The prefab path of the prefab. + The dictating how the prefab should spawn in the world. + The WorldEntityInfo of the prefab. For more information on how to set this up, see . + + + + Adds in a custom entry into the Loot Distribution of the game. + + The custom prefab which you want to spawn naturally in the game. + The dictating how the prefab should spawn in the world. + The WorldEntityInfo of the prefab. For more information on how to set this up, see . + + + + Edits Loot Distribution data for existing prefabs, for e.g. original game prefabs. + + The ClassID of the prefab. If unsure, use CraftData.GetClassIdForTechType. + The list of that contains information about how/when it should spawn in biomes. + + + + A handler class for registering your custom in-game mod options. + + + + + Main entry point for all calls to this handler. + + + + + Registers your mod options to the in-game menu. + + The mod options. Create a new child class inheriting from this one + and add your options to it. + + + + + Registers your mod options to the in-game menu. + + The mod options. Create a new child class inheriting from this one + and add your options to it. + + + + + Generates an options menu based on the attributes and members declared in the + and registers it to the in-game menu. + + A class derived from to generate the options menu from. + An instance of the : with values loaded + from the config file on disk. + + + + Generates an options menu based on the attributes and members declared in the + and registers it to the in-game menu. + + A class derived from to generate the options menu from. + An instance of the : with values loaded + from the config file on disk. + + + + Handles Encyclopedia. + + + + + Main entry point for all calls to this handler. + + + + + Adds custom entry. + + The entry. + + + + A handler class for various scanner related data. + + + + + Main entry point for all calls to this handler. + + + + + Edits how many fragments must be scanned before unlocking the techtype's blueprint. + + Can be either techtype of the fragment or the crafted item. + The number of fragments to scan. + + + + Edits the time it takes to finish scanning a fragment. + + Can be either techtype of the fragment or the crafted item. + The relative time spent on scanning. Default value is 1. + + + + Adds in a custom . ***Cannot be used to Change the values of a techtype that has data already!*** + + The of the entry. Must be populated when passed in. + + + + Edits how many fragments must be scanned before unlocking the techtype's blueprint. + + Can be either techtype of the fragment or the crafted item. + The number of fragments to scan. + + + + Edits the time it takes to finish scanning a fragment. + + Can be either techtype of the fragment or the crafted item. + The relative time spent on scanning. Default value is 1. + + + + Adds in a custom . + + The of the entry. Must be populated when passed in. + + + + Adds in a custom . + + The scanned object's . In case of fragments, the fragment is the key. + The when unlocked when scanned. In case of fragments, this is the actual that unlocks when all fragments are scanned. + Whether the is a fragment or not. + The total amount of objects of that need to be scanned to unlock the and . + The amount of time it takes to finish one scan. In seconds. + Whether the object should be destroyed after the scan is finished. + The key to the encyclopedia entry. + + + + A handler for stuff related to the PDALog class. + + + + + Main entry point for all calls to this handler. + + + + + Adds a custom log entry. + + The key to refer to this entry. + The subtitles language key for this entry. + The icon that will be used in the Log tab for this entry. if null It will use the default log entry icon. + The sound that will be played once this entry is triggered or played in the Log tab.
+ If null the Play button in the Log tab will disappear and a sound wont play when this entry is triggered. +
+ + + Adds a custom log entry. + + The key to refer to this entry. + The subtitles language key for this entry. + The icon that will be used in the Log tab for this entry. if null It will use the default log entry icon. + The sound that will be played once this entry is triggered or played in the Log tab.
+ If null the Play button in the Log tab will disappear and a sound wont play when this entry is triggered. +
+ + + A handler related to PingTypes + + + + + Main entry point for all calls to this handler. + + + + + Registers a ping type for use when creating a beacon + + The name of the new ping type + The sprite that is associated with the ping + The newly registered PingType + + + + Safely looks for a modded ping type in the SMLHelper PingTypeCache and outputs its value when found. + + The string used to define the modded PingType + The PingType enum value. Defaults to when the PingType was not found. + True if the PingType was found; Otherwise false + + + + Registers a ping type for use when creating a beacon + + The name of the new ping type + The sprite that is associated with the ping + The newly registered PingType + + + + Safely looks for a modded ping type in the SMLHelper PingTypeCache and outputs its value when found. + + The string used to define the modded PingType + The PingType enum value. Defaults to when the PingType was not found. + True if the PingType was found; Otherwise false + + + + A handler for registering Unity prefabs associated to a . + + + + + Main entry point for all calls to this handler. + + + + + Registers a ModPrefab into the game. + + The mod prefab to register. Create a child class inheriting off this one and configure as needed. + + + + + Registers a ModPrefab into the game. + + The mod prefab to register. Create a child class inheriting off this one and configure as needed. + + + + + A handler class for registering your . + + + + + Main entry point for all calls to this handler. + + + + + A handler class for adding custom sprites into the game. + + + + + Main entry point for all calls to this handler. + + + + + Registers a new sprite to the game. + + The techtype paired to this sprite. + The sprite to be added. + + + + Registers a new sprite to the game. + + The sprite group. + The sprite internal identifier. + The sprite to be added. + + + + Registers a new sprite to the game. + + The sprite group this sprite will be added to. + The sprite internal identifier. + The sprite to be added. + + + + Registers a new sprite to the game. + + The techtype paired to this sprite. + The sprite to be added. + + + + Registers a new sprite to the game. + + The techtype paired to this sprite. + The file path to image to be converted into a sprite. + + + + + Registers a new sprite to the game. + + The techtype paired to this sprite. + The file path to image to be converted into a sprite. + The texture format. By default, this uses . + https://docs.unity3d.com/ScriptReference/TextureFormat.BC7.html + Don't change this unless you really know what you're doing. + + + + + Registers a new sprite to the game. + + The sprite group. + The sprite internal identifier. + The file path to image. + + + + + Registers a new sprite to the game. + + The sprite group. + The sprite internal identifier. + The file path to image. + The texture format. By default, this uses . + https://docs.unity3d.com/ScriptReference/TextureFormat.BC7.html + Don't change this unless you really know what you're doing. + + + + + Registers a new sprite to the game. + + The techtype paired to this sprite. + The sprite to be added. + + + + Registers a new sprite to the game. + + The sprite group. + The sprite internal identifier. + The sprite to be added. + + + + Registers a new sprite to the game. + + The sprite group this sprite will be added to. + The sprite internal identifier. + The sprite to be added. + + + + Registers a new sprite to the game. + + The techtype paired to this sprite. + The sprite to be added. + + + + Registers a new sprite to the game. + + The techtype paired to this sprite. + The file path to image to be converted into a sprite. + + + + + Registers a new sprite to the game. + + The techtype paired to this sprite. + The file path to image to be converted into a sprite. + The texture format. By default, this uses . + https://docs.unity3d.com/ScriptReference/TextureFormat.BC7.html + Don't change this unless you really know what you're doing. + + + + + Registers a new sprite to the game. + + The sprite group. + The sprite internal identifier. + The file path to image. + + + + + Registers a new sprite to the game. + + The sprite group. + The sprite internal identifier. + The file path to image. + The texture format. By default, this uses . + https://docs.unity3d.com/ScriptReference/TextureFormat.BC7.html + Don't change this unless you really know what you're doing. + + + + + a common handler for uses specified to the Survival component + + + + + Main entry point for all calls to this handler. + + + + + makes the item gives oxygen on use. + + the TechType that you want to make it give oxygen on use + the oxygen amount the item gives + set it to if the item is edible and has the component attached to it. + defaults to + + + + + makes the item Heal the player on consume. + + the TechType that you want it to heal back + amount to heal the player + set it to if the item is edible and has the component attached to it. + defaults to + + + + + makes the item gives oxygen on use. + + the TechType that you want to make it give oxygen on use + the oxygen amount the item gives + set it to if the item is edible and has the component attached to it. + defaults to + + + + + makes the item Heal the player on consume. + + the TechType that you want it to heal back + amount to heal the player + set it to if the item is edible and has the component attached to it. + defaults to + + + + + A handler class for everything related to creating new TechCategories. + + + + + + Main entry point for all calls to this handler. + + + + + Adds a new into the game. + + The name of the TechCategory. Should not contain special characters. + The display name of the TechCategory. Can be anything. + + The new that is created. + + + + + Safely looks for a modded category from another mod in the SMLHelper TechCategoryCache. + + The string used to define the techcategory. + + True if the item was found; Otherwise false. + + + + + Safely looks for a modded category from another mod in the SMLHelper TechCategoryCache and outputs its value when found. + + The string used to define the techcategory. + The TechCategory enum value of the modded. Defaults to when the item was not found. + + True if the item was found; Otherwise false. + + + + + Registers the TechCategory to a TechGroup in CraftData.groups. + + The tech group. + The tech category. + + + + + A handler class for everything related to creating new TechGroups. + + + + + Main entry point for all calls to this handler. + + + + + Adds a new into the game. + + The name of the TechGroup. Should not contain special characters. + The display name of the TechGroup. Can be anything. + + The new that is created. + + + + + Safely looks for a modded group from another mod in the SMLHelper TechGroupCache. + + The string used to define the techgroup. + + True if the item was found; Otherwise false. + + + + + Safely looks for a modded item from another mod in the SMLHelper TechGroupCache and outputs its value when found. + + The string used to define the techgroup. + The TechGroup enum value of the modded. Defaults to when the item was not found. + + True if the item was found; Otherwise false. + + + + + A handler class for everything related to creating new TechTypes. + + + + + Main entry point for all calls to this handler. + + + + + Adds a new into the game. This new will be unlocked at the start of a game. + + The assembly this TechType is getting added by. + The internal name of the TechType. Should not contain special characters + The display name of the TechType. Can be anything. + The tooltip, displayed when hovered in an inventory. Can be anything. + The new that is created. + + + + Adds a new into the game. + + The assembly this TechType is getting added by. + The internal name of the TechType. Should not contain special characters + The display name of the TechType. Can be anything. + The tooltip, displayed when hovered in an inventory. Can be anything. + Whether this TechType should be unlocked on game start, or not. By default, . + The new that is created. + + + + Adds a new into the game. This new will be unlocked at the start of a game. + + The internal name of the TechType. Should not contain special characters. + The display name of the TechType. Can be anything. + The tooltip, displayed when hovered in an inventory. Can be anything. + The new that is created. + + + + Adds a new into the game. + + The internal name of the TechType. Should not contain special characters. + The display name of the TechType. Can be anything. + The tooltip, displayed when hovered in an inventory. Can be anything. + Whether this TechType should be unlocked on game start, or not. By default, . + The new that is created. + + + + Adds a new into the game, with a sprite. This new techtype will be unlocked at the start of a the game. + + The internal name of the TechType. Should not contain special characters. + The display name of the TechType. Can be anything. + The tooltip, displayed when hovered in an inventory. Can be anything. + The sprite that will related to this TechType. + The new that is created. + + + + Adds a new into the game, with a sprite. + + The internal name of the TechType. Should not contain special characters. + The display name of the TechType. Can be anything. + The tooltip, displayed when hovered in an inventory. Can be anything. + The sprite that will related to this TechType. + Whether this TechType should be unlocked on game start, or not. By default, . + The new that is created. + + + + Adds a new into the game, with a sprite. This new techtype will be unlocked at the start of a the game. + + The internal name of the TechType. Should not contain special characters. + The display name of the TechType. Can be anything. + The tooltip, displayed when hovered in an inventory. Can be anything. + The sprite that will related to this TechType. + The new that is created. + + + + Adds a new into the game, with a sprite. + + The internal name of the TechType. Should not contain special characters. + The display name of the TechType. Can be anything. + The tooltip, displayed when hovered in an inventory. Can be anything. + The sprite that will related to this TechType. + Whether this TechType should be unlocked on game start, or not. By default, . + The new that is created. + + + + Safely looks for a modded item from another mod in the SMLHelper TechTypeCache and outputs its value when found. + + The string used to define the modded item's new techtype. + The TechType enum value of the modded. Defaults to when the item was not found. + + if the item was found; Otherwise . + + + There's no guarantee in which order SMLHelper dependent mods are loaded, + so if two mods are added at the same time, it may take a second game load for both to be visible to each other. + + + + + Safely looks for a modded item from another mod in the SMLHelper TechTypeCache. + + The string used to define the modded item's new . + + True if the item was found; Otherwise . + + + There's no guarantee in which order SMLHelper dependent mods are loaded, + so if two mods are added at the same time, it may take a second game load for both to be visible to each other. + + + + + Adds a new into the game. + + The internal name of the TechType. Should not contain special characters. + The display name of the TechType. Can be anything. + The tooltip, displayed when hovered in an inventory. Can be anything. + Whether this TechType should be unlocked on game start, or not. By default, . + The new that is created. + + + + Adds a new into the game. This new techtype will be unlocked at the start of a the game. + + The internal name of the TechType. Should not contain special characters. + The display name of the TechType. Can be anything. + The tooltip, displayed when hovered in an inventory. Can be anything. + The new that is created. + + + + Adds a new into the game, with a sprite. + + The internal name of the TechType. Should not contain special characters. + The display name of the TechType. Can be anything. + The tooltip, displayed when hovered in an inventory. Can be anything. + The sprite that will related to this TechType. + Whether this TechType should be unlocked on game start, or not. By default, true. + The new that is created. + + + + Adds a new into the game, with a sprite. This new techtype will be unlocked at the start of a the game. + + The internal name of the TechType. Should not contain special characters. + The display name of the TechType. Can be anything. + The tooltip, displayed when hovered in an inventory. Can be anything. + The sprite that will related to this TechType. + The new that is created. + + + + Adds a new into the game, with a sprite. + + The internal name of the TechType. Should not contain special characters. + The display name of the TechType. Can be anything. + The tooltip, displayed when hovered in an inventory. Can be anything. + The sprite that will related to this TechType. + Whether this TechType should be unlocked on game start, or not. By default, true. + The new that is created. + + + + Adds a new into the game, with a sprite. This new techtype will be unlocked at the start of a the game. + + The internal name of the TechType. Should not contain special characters. + The display name of the TechType. Can be anything. + The tooltip, displayed when hovered in an inventory. Can be anything. + The sprite that will related to this TechType. + The new that is created. + + + + Safely looks for a modded item from another mod in the SMLHelper TechTypeCache and outputs its value when found. + + The string used to define the modded item's new techtype. + The TechType enum value of the modded. Defaults to when the item was not found. + + True if the item was found; Otherwise false. + + + There's no guarantee in which order SMLHelper dependent mods are loaded, + so if two mods are added at the same time, it may take a second game load for both to be visible to each other. + + + + + Safely looks for a modded item from another mod in the SMLHelper TechTypeCache. + + The string used to define the modded item's new techtype. + + True if the item was found; Otherwise false. + + + There's no guarantee in which order SMLHelper dependent mods are loaded, + so if two mods are added at the same time, it may take a second game load for both to be visible to each other. + + + + + A handler for the WorldEntityDatabase of the game. + + + + + Main entry point for all calls to this handler. + + + + + Adds in a custom to the of the game. + It contains information about the entity, like its , its , etc. + + The classID of the entity whose data you are adding in. + The data. Data is stored in the fields of the class, so they must be populated when passed in. + + + + Adds in a custom to the of the game. + It contains information about the entity, like its , its , etc. + + The classId of the entity. + The of the entity. + Whether the prefab's Z-axis should be facing up, when spawned. + The of the entity. + The of the entity. Dictates which "slots" are suitable for this entity to spawn in. For e.g., most in-crate fragments have a slot type. + The scale that the entity's local scale is set to when spawned. + + + + WARNING: This class is for use only by QModManager. + + + + + WARNING: This method is for use only by QModManager. + + + + + WARNING: This method is for use only by QModManager. + + + + + A handler interface for everything related to creating new BackgroundTypes. + + + + + adds a new into the game. + + the name of the BackgroundType, should not contain special characters. + The sprite for this BackgroundType. + The new that's created. + + + + Safely looks for a modded Background Type from another mod in the SMLHelper BackgroundTypeCache and outputs its value when found. + + The string used to define the BackgroundType + The BackgroundType enum value of the modded. Defaults to when the item was not found. + if the item was found; otherwise . + + + + Safely looks for a modded Background Type from another mod in the SMLHelper BackgroundTypeCache. + + The string used to define the BackgroundType. + if the item was found; otherwise . + + + + + Places a simple text object on the screen and keeps it there until either hidden (or a designated fade-to-black timer has passed). + By default uses the same font/size/color as the "Press Any Button To Begin" message at the beginning of the game, and appears + centered about 1/3 down the screen, but all parameters can be reconfigured. + + + The idea of the defaults is that new modders don't have to bootstrap a bunch of irritating Unity stuff -- don't have to understand + what a "Material" is or how to make one, don't have to know to initialize a font, or even a color. Can just start adding text and + then can always custom and configure on further revision. + + + + SIMPLE USAGE EXAMPLE: + BasicText message = new BasicText(); + message.ShowMessage("This Message Will Fade In 10 Seconds", 10); + + COMPLEX USAGE EXAMPLE: + BasicText message = new BasicText(TextAnchor.UpperLeft); // Note many other properties could also be set as constructor parameters + message.setColor(Color.red); // Set Color + message.setSize(20); // Set Font Size + message.setLoc(200, 400); // Set x/y position (0,0 is center of screen) + message.setFontStyle(FontStyle.Bold); // Bold + message.ShowMessage("This message stays on screen until hidden"); // Display message; if fadeout seconds not specified, it just keeps showing + ... // other things happen, time goes by + message.Hide(); // Hides the message + + + + + Resets to using "cloned" font style of Subnautica default + + + + + Resets to using "cloned" color of Subnautica default. + + + + + Resets to using "cloned" font of Subnautica default. + + + + + Resets to using "cloned" font style of Subnautica default. + + + + + Resets to using "cloned" size of Subnautica default. + + + + + Returns our current text. + + + + + + Hides our text item if it is displaying. + + + + + Sets the text anchor. + + The text anchor to align to + + + + Sets the text color + + The text color to use + + + + Sets the font + + The font to render the text as. + + + + Sets the font style. + + The text font style to use + + + + Sets screen display location (position relative to the actual text is determined by the alignment) + + The x coordinate to set + The y coordinate to set + + + + Sets the font size. + + The text size to use + + + + Shows our text item, with no schedule fade (i.e. indefinitely) + + The text to display + + + + Shows our text item, fading after a specified number of seconds (or stays on indefinitely if 0 seconds) + + The text to display + The duration to hold before fading + + + + A handler with common methods for updating BioReactor values. + + + + + Allows you to specify the quantity of energy that a TechType will produce with bio reactors. + + The TechType that you want to use with bioreactors. + The quantity of energy that will be produced by this TechType. + + + + + A handler class for registering your custom console commands. + + + + + Registers your custom console command by targeting a method. + + + Target method must be . + + The command can take parameters and will respect optional parameters as outlined in the method's signature.
+ Supported parameter types: , , , , + .
+ + If the method has a return type, it will be printed to both the screen and the log. +
+ The case-insensitive command to register. + The declaring type that holds the method to call when the command is entered. + The name of the method to call within the declaring type when the command is entered. + Method must be . + The parameter types the method receives, for targeting overloads. + + + +
+ + + Registers your custom console command by passing a . + + + Supported parameter types: , , , , + . + + If the delegate has a return type, it will be printed to both the screen and the log. + + The delegate type. + The case-insensitive command to register. + The callback to handle the command. + + + + + + + Registers methods decorated with the + within the as console commands. + + + Target methods must be . + + Commands can take parameters and will respect optional parameters as outlined in the method's signature.
+ Supported parameter types: , , , , + .
+ + If a decorated method has a return type, it will be printed to both the screen and the log. +
+ + + +
+ + + a Handler interface that handles and registers Coordinated ( spawns). + + + + + Registers a Coordinated Spawn + + the SpawnInfo to spawn + + + + registers Many Coordinated Spawns. + + The SpawnInfos to spawn. + + + + Registers Multiple Coordinated spawns for one single passed TechType + + The TechType to spawn + the coordinates the should spawn to + + + + Registers Multiple Coordinated spawns with rotations for one single passed TechType + + The TechType to spawn + the coordinates(Key) and the rotations(Value) the should spawn to + + + + A handler class for adding and editing crafted and some non-crafted items. + + + + + Allows you to edit EquipmentTypes for TechTypes. + Can be used for existing TechTypes too. + + The TechType whose EqiupmentType you want to edit. + The EquipmentType for that TechType. + + + + Allows you to edit QuickSlotType for TechTypes. Can be used for existing TechTypes too. + Careful: This has to be called after and . + + The TechType whose QuickSlotType you want to edit. + The QuickSlotType for that TechType. + + + + Allows you to edit harvest output, i.e. what TechType you get when you "harvest" a TechType. + Can be used for existing TechTypes too. + + The TechType whose harvest output you want to edit. + The harvest output for that TechType. + + + + Allows you to edit how TechTypes are harvested. + Can be used for existing TechTypes too. + + The TechType whose HarvestType you want to edit. + The HarvestType for that TechType. + + + + Allows you to edit how much additional slices/seeds are given upon last knife hit. + Can be used for existing TechTypes too. + + The TechType whose final cut bonus you want to edit. + The number of additional slices/seeds you'll receive on last cut. + + + + Allows you to edit item sizes for TechTypes. + Can be used for existing TechTypes too. + + The TechType whose item size you want to edit. + The item size for that TechType. + + + + Allows you to edit item sizes for TechTypes. + Can be used for existing TechTypes too. + + The TechType whose item size you want to edit. + The width of the item + The height of the item + + + + Allows you to edit crafting times for TechTypes. + Can be used for existing TechTypes too. + + The TechType whose crafting time you want to edit. + The crafting time, in seconds, for that TechType. + + + + Allows you to edit the cooked creature list, i.e. associate the unedible TechType to the cooked TechType. + Can be used for existing TechTypes too. + + The TechType whose cooked creature counterpart to edit. + The cooked creature counterpart for that TechType. + + + + Allows you to edit inventory background colors for TechTypes. + + The TechType whose BackgroundType you want to edit. + The background color for that TechType. + + + + + Allows you to add items to the buildable list. + + The TechType which you want to add to the buildable list. + + + + Allows you to add items to the game's internal grouping system. + Required if you want to make buildable items show up in the Habitat Builder. + + The TechGroup you want to add your TechType to. + The TechCategory (in the TechGroup) you want to add your TechType to. + The TechType you want to add. + + + + Allows you to add items to the game's internal grouping system. + Required if you want to make buildable items show up in the Habitat Builder. + + The TechGroup you want to add your TechType to. + The TechCategory (in the TechGroup) you want to add your TechType to. + The TechType you want to add. + Added TechType will be added after this TechType, for sorting purposes. + + + + Allows you to remove an existing TechType from the game's internal group system. + + The TechGroup in which the TechType is located. + The TechCategory in which the TechType is located. + The TechType which you want to remove. + + + + Allows you to edit recipes, i.e. TechData for TechTypes. + Can be used for existing TechTypes too. + + The TechType whose TechData you want to edit. + The TechData for that TechType. + + + + + Allows you to edit recipes, i.e. TechData for TechTypes. + Can be used for existing TechTypes too. + + The TechType whose TechData you want to edit. + The TechData for that TechType. + + + + + Safely accesses the crafting data from a modded item. + WARNING: This method is highly dependent on mod load order. + Make sure your mod is loading after the mod whose TechData you are trying to access. + + The TechType whose TechData you want to access. + The ITechData from the modded item if it exists; Otherwise, returns null. + + + + Safely accesses the crafting data from any item. + WARNING: This method is highly dependent on mod load order. + Make sure your mod is loading after the mod whose TechData you are trying to access. + + The TechType whose TechData you want to access. + Returns TechData if it exists; Otherwise, returns null. + + + + Sets the eating sound for the provided TechType. + + The item being consumed during . + + The sound path. + + Value values are + - "event:/player/drink" + - "event:/player/drink_stillsuit" + - "event:/player/use_first_aid" + - "event:/player/eat" (default) + + + + + + A handler class for creating and editing of crafting trees. + + + + + Your first method call to start a new custom crafting tree.
+ Creating a new CraftTree only makes sense if you're going to use it in a new type of . +
+ The name for the new enum. + The new enum instance for your custom craft tree type. + + Returns the root node for your custom craft tree, as a new instance.
+ Build up your custom crafting tree from this root node.
+ This tree will be automatically patched into the game. No further calls into required. + For more advanced usage, you can replace the default value of with your own custom function. +
+ + + + +
+ + + Safely looks for a modded CraftTree Type from another mod in the SMLHelper CraftTreeTypeCache. + + The string used to define the modded item's new techtype. + + True if the craft tree was found; Otherwise false. + + + There's no guarantee in which order SMLHelper dependent mods are loaded, + so if two mods are added at the same time, it may take a second game load for both to be visible to each other. + + + + + Adds a new crafting node to the root of the specified crafting tree, at the provided tab location. + + The target craft tree to edit. + The item to craft. + + The steps to the target tab. + These must match the id value of the CraftNode in the crafting tree you're targeting. + Do not include "root" in this path. + + + + + Adds a new crafting node to the root of the specified crafting tree + + The target craft tree to edit. + The item to craft. + + + + Adds a new tab node to the root of the specified crafting tree. + + The target craft tree to edit. + The ID of the tab node. Must be unique! + The display name of the tab, which will show up when you hover your mouse on the tab. + The sprite of the tab. + + + + Adds a new tab node to the root of the specified crafting tree. + + The target craft tree to edit. + The ID of the tab node. Must be unique! + The display name of the tab, which will show up when you hover your mouse on the tab. + The sprite of the tab. + + + + Adds a new tab node to the root of the specified crafting tree, at the specified tab location. + + The target craft tree to edit. + The ID of the tab node. Must be unique! + The display name of the tab, which will show up when you hover your mouse on the tab. + The sprite of the tab. + + The steps to the target tab. + These must match the id value of the CraftNode in the crafting tree you're targeting. + Do not include "root" in this path. + + + + + Adds a new tab node to the root of the specified crafting tree, at the specified tab location. + + The target craft tree to edit. + The ID of the tab node. Must be unique! + The display name of the tab, which will show up when you hover your mouse on the tab. + The sprite of the tab. + + The steps to the target tab. + These must match the id value of the CraftNode in the crafting tree you're targeting. + Do not include "root" in this path. + + + + + Removes a node at the specified node location. Can be used to remove either tabs or craft nodes. + If a tab node is selected, all child nodes to it will also be removed. + + The target craft tree to edit. + + The steps to the target node. + These must match the id value of the CraftNode in the crafting tree you're targeting. + This means matching the id of the crafted item or the id of the tab name. + Do not include "root" in this path. + + + + + A handler class for adding and overriding Sounds. + + + + + Register a Custom sound by file path. Some vanilla game sounds can be overridden by matching the id to the . + + The Id of your custom sound which is used when checking which sounds to play. + The file path on disk of the sound file to load + The sound channel to get the volume to play the sound at. defaults to + the loaded + + + + Register a Custom sound by file path. Some vanilla game sounds can be overridden by matching the id to the . + + The Id of your custom sound which is used when checking which sounds to play. + The file path on disk of the sound file to load. + The bus path to play the sound on. + the loaded + + + + Register a Custom sound by file path. Some vanilla game sounds can be overridden by matching the id to the . + + The Id of your custom sound which is used when checking which sounds to play. + The file path on disk of the sound file to load. + The bus to play the sound on. + the loaded + + + + Register a custom sound by an instance. Some vanilla game sounds can be overridden by matching the id to the . + + The Id of your custom sound which is used when checking which sounds to play. + The AudioClip to register. + The sound channel to get the volume to play the sound at. defaults to + the registered. + + + + Register a custom sound by an instance. Some vanilla game sounds can be overridden by matching the id to the . + + The Id of your custom sound which is used when checking which sounds to play. + The AudioClip to register. + The bus path to play the sound on. + the loaded + + + + Register a custom sound by an instance. Some vanilla game sounds can be overridden by matching the id to the . + + The Id of your custom sound which is used when checking which sounds to play. + The AudioClip to register. + The bus to play the sound on. + the loaded + + + + Registers a Custom sound by an instance. IFModSound instances have custom logic for playing sounds. + + The Id of your custom sound which is used when checking which sounds to play. + The sound IFModSound object to register. + + + + Register a Custom sound that has been loaded using AudioUtils. Some vanilla game sounds can be overridden by matching the id to the . + + The Id of your custom sound which is used when checking which sounds to play. + The pre loaded sound + The sound channel to get the volume to play the sound at. + + + + Register a Custom sound that has been loaded using AudioUtils. Some vanilla game sounds can be overridden by matching the id to the . + + The Id of your custom sound which is used when checking which sounds to play. + The pre loaded sound + The bus path to play the sound on. + + + + Register a Custom sound that has been loaded using AudioUtils. Some vanilla game sounds can be overridden by matching the id to the . + + The Id of your custom sound which is used when checking which sounds to play. + The pre loaded sound + The bus to play the sound on. + + + + Try to find and play a custom that has been registered. + + The Id of the custom sound + + + + Try to get a registered custom . + + The Id of the custom sound + Outputs the if found and null if not found. + true or false depending on if the id was found + + + + Try to get a playing custom sound channel for an emitter + + The emitter's ID, can be retrieved by calling object.GetInstanceID(). + Outputs the . + True if found, otherwise false. + + + + A handler with common methods for changing edible items values. + + + + + Allows you to change the water/food values of a specific item. + + The TechType of the item you wish to edit. + The food value you want the item to have. + The water value you want the item to have. + Whether or not the item decomposes over time, losing food and water values in the process. + + + + A handler related to EquipmentTypes + + + + + Registers an equipment type for use when creating a equipment + + The name of the new equipment type + The newly registered EquipmentType + + + + Safely looks for a modded equipment type in the SMLHelper EquipmentTypeCache and outputs its value when found. + + The string used to define the modded EquipmentType + The EquipmentType enum value. Defaults to when the EquipmentType was not found. + True if the EquipmentType was found; Otherwise false + + + + Checks for the existence of an added EquipmentType in the SMLHelper EquipmentTypeCache and outputs the result of the check + + The string used to define the modded EquipmentType + True if the EquipmentType was found; Otherwise false + + + + Interface for + Can be used for dependency injection + + + + + Registers a CustomFish object into the game + + The CustomFish that you are registering + The TechType created using the info from your CustomFish object + + + + A handler class that offers simple ways to tap into functionality of the in game menu. + + + + + Registers a simple method to invoke whenever the player saves the game via the in game menu. + + The method to invoke. + + + + Registers a simple method to invoke whenever the player loads a saved game via the in game menu. + + The method to invoke. + + + + Registers a simple method to invoke whenever the player quits the game via the in game menu. + + The method to invoke. + + + + Removes a method previously added through so it is no longer invoked when saving the game. + If you plan on using this, do not register an anonymous method. + + The method invoked. + + + + Removes a method previously added through so it is no longer invoked when loading the game. + If you plan on using this, do not register an anonymous method. + + The method invoked. + + + + Removes a method previously added through so it is no longer invoked when quiting the game. + If you plan on using this, do not register an anonymous method. + + The method invoked. + + + + Registers a simple method to invoke the first time the player saves the game via the in game menu. + + The method to invoke. This action will not be invoked a second time. + + + + Registers a simple method to invoke the first time the player loads a saved game via the in game menu. + + The method to invoke. This action will not be invoked a second time. + + + + Registers a simple method to invoke the first time the player quits the game via the in game menu. + + The method to invoke. This action will not be invoked a second time. + + + + A handler class for registering your custom middle click actions for items + + + + + Registers a custom left click action for a + + The to which the left click action will be assigned + The method which will be called when a matching with the specified was left-clicked + The secondary tooltip which will appear in the description of the item + The condition which must return for the action to be called when the item is clickedIf ommited, the action will always be called + + + + Registers a custom middle click action for a + + The which the middle click action will be assigned + The method which will be called when a matching with the specified was middle-clicked + The secondary tooltip which will appear in the description of the item + The condition which must return for the action to be called when the item is clickedIf ommited, the action will always be called + + + + A handler class for configuring custom unlocking conditions for item blueprints. + + + + + Allows you to unlock a TechType on game start. + + + + + + Allows you to define which TechTypes are unlocked when a certain TechType is unlocked, i.e., "analysed". + If there is already an exisitng AnalysisTech entry for a TechType, all the TechTypes in "techTypesToUnlock" will be + added to the existing AnalysisTech entry unlocks. + + This TechType is the criteria for all of the "unlock TechTypes"; when this TechType is unlocked, so are all the ones in that list + The TechTypes that will be unlocked when "techTypeToSet" is unlocked. + + + + Allows you to define which TechTypes are unlocked when a certain TechType is unlocked, i.e., "analysed". + If there is already an exisitng AnalysisTech entry for a TechType, all the TechTypes in "techTypesToUnlock" will be + added to the existing AnalysisTech entry unlocks. + + This TechType is the criteria for all of the "unlock TechTypes"; when this TechType is unlocked, so are all the ones in that list + The TechTypes that will be unlocked when "techTypeToSet" is unlocked. + The message that shows up on the right when the blueprint is unlocked. + + + + Allows you to define which TechTypes are unlocked when a certain TechType is unlocked, i.e., "analysed". + If there is already an exisitng AnalysisTech entry for a TechType, all the TechTypes in "techTypesToUnlock" will be + added to the existing AnalysisTech entry unlocks. + + This TechType is the criteria for all of the "unlock TechTypes"; when this TechType is unlocked, so are all the ones in that list + The TechTypes that will be unlocked when "techTypeToSet" is unlocked. + The sound that plays when you unlock the blueprint. + + + + Allows you to define which TechTypes are unlocked when a certain TechType is unlocked, i.e., "analysed". + If there is already an exisitng AnalysisTech entry for a TechType, all the TechTypes in "techTypesToUnlock" will be + added to the existing AnalysisTech entry unlocks. + + This TechType is the criteria for all of the "unlock TechTypes"; when this TechType is unlocked, so are all the ones in that list + The TechTypes that will be unlocked when "techTypeToSet" is unlocked. + The sprite that shows up when you unlock the blueprint. + + + + Allows you to define which TechTypes are unlocked when a certain TechType is unlocked, i.e., "analysed". + If there is already an exisitng AnalysisTech entry for a TechType, all the TechTypes in "techTypesToUnlock" will be + added to the existing AnalysisTech entry unlocks. + + This TechType is the criteria for all of the "unlock TechTypes"; when this TechType is unlocked, so are all the ones in that list + The TechTypes that will be unlocked when "techTypeToSet" is unlocked. + The message that shows up on the right when the blueprint is unlocked. + The sound that plays when you unlock the blueprint. + + + + Allows you to define which TechTypes are unlocked when a certain TechType is unlocked, i.e., "analysed". + If there is already an exisitng AnalysisTech entry for a TechType, all the TechTypes in "techTypesToUnlock" will be + added to the existing AnalysisTech entry unlocks. + + This TechType is the criteria for all of the "unlock TechTypes"; when this TechType is unlocked, so are all the ones in that list + The TechTypes that will be unlocked when "techTypeToSet" is unlocked. + The message that shows up on the right when the blueprint is unlocked. + The sprite that shows up when you unlock the blueprint. + + + + Allows you to set up a custom Compound Unlock requiring multiple techtypes to be unlocked before 1 is. + ***Note: This will not remove any original unlock and if you need to do so you should use or + + + + + + + Allows you to remove unlock entries for a from specific entries. + + Target to remove the unlocks for. + List of to remove the targetTechType from. + + + + Allows you to remove all unlock entries from a to be able to disable or change it to a new unlock. + ***Note: This is patch time specific so the LAST mod to call this on a techtype will be the only one to control what unlocks said type after its use.*** + + Target to remove the unlocks for. + + + + Allows you to define which TechTypes are unlocked when a certain TechType is unlocked, i.e., "analysed". + If there is already an exisitng AnalysisTech entry for a TechType, all the TechTypes in "techTypesToUnlock" will be + added to the existing AnalysisTech entry unlocks. + + This TechType is the criteria for all of the "unlock TechTypes"; when this TechType is unlocked, so are all the ones in that list + The TechTypes that will be unlocked when "techTypeToSet" is unlocked. + The sound that plays when you unlock the blueprint. + The sprite that shows up when you unlock the blueprint. + + + + A handler for adding custom language lines. + + + + + Allows you to define a language entry into the game. + + The ID of the entry, this is what is used to get the actual text. + The actual text related to the entry. + + + + Allows you to set the display name of a specific . + + The whose display name that is to be changed. + The new display name for the chosen . + + + + Allows you to set the tooltip of a specific . + + The whose tooltip that is to be changed. + The new tooltip for the chosen . + + + + A handler that manages Loot Distribution (spawning of fragments, fish, etc). + + + + + Adds in a custom entry into the Loot Distribution of the game. + + + + + + + Adds in a custom entry into the Loot Distribution of the game. + You must also add the into the using . + + The that contains data related to the spawning of a prefab, also contains the path to the prefab. + The classId of the prefab. + The WorldEntityInfo of the prefab. For more information on how to set this up, see . + + + + Adds in a custom entry into the Loot Distribution of the game. + You must also add the into the using . + + The classId of the prefab. + The prefab path of the prefab. + The dictating how the prefab should spawn in the world. + + + + Adds in a custom entry into the Loot Distribution of the game. + You must also add the into the using . + + The classId of the prefab. + The prefab path of the prefab. + The dictating how the prefab should spawn in the world. + The WorldEntityInfo of the prefab. For more information on how to set this up, see . + + + + Adds in a custom entry into the Loot Distribution of the game. + You must also add the into the using . + + The custom prefab which you want to spawn naturally in the game. + The dictating how the prefab should spawn in the world. + The WorldEntityInfo of the prefab. For more information on how to set this up, see . + + + + Edits Loot Distribution Data for existing/original class IDs. + + + + + Edits Loot Distribution data for existing prefabs, for e.g. original game prefabs. + + The ClassID of the prefab. If unsure, use CraftData.GetClassIdForTechType. + The list of that contains information about how/when it should spawn in biomes. + + + + Defines properties for derivatives to implement for the purpose of holding + metadata about fields and their generation. + + + + + The label to use when displaying the field in the mod's options menu. + + + + + The Id to be used for the field in the mod's option menu. If none is specified, one will be automatically generated when + your is registered to the . This means it will + change every time the game is launched, but is guaranteed to be unique. If you would like to specify an Id to use for + internal comparisons, you can do so here. + + + + + The order in which to display fields in the mod's option menu, in ascending order. If none is specified, the order will be + automatically set. + + + + + An optional tooltip to display for the field. + + + + + An optional id to be parsed with for the label, allowing for custom language-based strings + via the API. + + + + + + + Interface for event arguments for a . + + + + + The ID of the this event corresponds to. + + + + + Defines properties for derivatives to implement for the purpose + of holding metadata about events. + + + + + The name of the method to invoke. + + + + + A handler class for registering your custom in-game mod options. + + + + + Registers your mod options to the in-game menu. + + The mod options. Create a new child class inheriting from this one + and add your options to it. + + + + + Generates an options menu based on the attributes and members declared in the + and registers it to the in-game menu. + + A class derived from to generate the options menu from. + An instance of the : with values loaded + from the config file on disk. + + + + Handles Encyclopedia. + + + + + Adds custom entry. + + + + + + A handler class for various scanner related data. + + + + + Edits how many fragments must be scanned before unlocking the techtype's blueprint. + + Can be either techtype of the fragment or the crafted item. + The number of fragments to scan. + + + + Edits the time it takes to finish scanning a fragment. + + Can be either techtype of the fragment or the crafted item. + The relative time spent on scanning. Default value is 1. + + + + Adds custom scanner entry. + + + + + + A handler for stuff related to the PDALog class. + + + + + Adds a custom log entry. + + The key to refer to this entry. + The subtitles language key for this entry. + The icon that will be used in the Log tab for this entry. if null It will use the default log entry icon. + The sound that will be played once this entry is triggered or played in the Log tab.
+ If null the Play button in the Log tab will disappear and a sound wont play when this entry is triggered. +
+ + + A handler related to PingTypes + + + + + Registers a ping type for use when creating a beacon + + The name of the new ping type + The sprite that is associated with the ping + The newly registered PingType + + + + Safely looks for a modded ping type in the SMLHelper PingTypeCache and outputs its value when found. + + The string used to define the modded PingType + The PingType enum value. Defaults to when the PingType was not found. + True if the PingType was found; Otherwise false + + + + A handler for registering Unity prefabs associated to a . + + + + + Registers a ModPrefab into the game. + + The mod prefab to register. Create a child class inheriting off this one and configure as needed. + + + + + A handler class for registering your . + + + + + Registers your to be automatically loaded and saved whenever the game is. + + A class derived from to hold your save data. + An instance of the : with values loaded + from the json file on disk whenever a save slot is loaded. + + + + A handler class for adding custom sprites into the game. + + + + + Registers a new sprite to the game. + + The techtype paired to this sprite. + The sprite to be added. + + + + Registers a new sprite to the game. + + The sprite group. + The sprite internal identifier. + The sprite to be added. + + + + Registers a new sprite to the game. + + The sprite group this sprite will be added to. + The sprite internal identifier. + The sprite to be added. + + + + Registers a new sprite to the game. + + The techtype paired to this sprite. + The sprite to be added. + + + + Registers a new sprite to the game. + + The techtype paired to this sprite. + The file path to image to be converted into a sprite. + The texture format. By default, this uses . + https://docs.unity3d.com/ScriptReference/TextureFormat.BC7.html + Don't change this unless you really know what you're doing. + + + + + Registers a new sprite to the game. + + The techtype paired to this sprite. + The file path to image to be converted into a sprite. + + + + + Registers a new sprite to the game. + + The sprite group. + The sprite internal identifier. + The file path to image. + The texture format. By default, this uses . + https://docs.unity3d.com/ScriptReference/TextureFormat.BC7.html + Don't change this unless you really know what you're doing. + + + + + Registers a new sprite to the game. + + The sprite group. + The sprite internal identifier. + The file path to image. + + + + + a handler for common uses to the Survival component + + + + + makes the item gives oxygen on use. + + the TechType that you want to make it give oxygen on use + the oxygen amount the item gives + set it to if the item is edible and has the component attached to it. + defaults to + + + + + makes the item Heal the player on consume. + + the TechType that you want it to heal back + amount to heal the player + set it to if the item is edible and has the component attached to it. + defaults to + + + + + A handler class for everything related to creating new TechCategorys. + + + + + Adds a new into the game. + + The name of the TechCategory. Should not contain special characters. + The display name of the TechCategory. Can be anything. + The new that is created. + + + + Safely looks for a modded item from another mod in the SMLHelper TechCategoryCache and outputs its value when found. + + The string used to define the techcategory. + The TechCategory enum value of the modded. Defaults to when the item was not found. + + True if the item was found; Otherwise false. + + + + + Safely looks for a modded item from another mod in the SMLHelper TechCategoryCache. + + The string used to define the techcategory. + + True if the item was found; Otherwise false. + + + + + Registers the TechCategory to a TechGroup. + + The tech group. + The tech category. + + + + + A handler class for everything related to creating new TechGroups. + + + + + Adds a new into the game. + + The name of the TechGroup. Should not contain special characters. + The display name of the TechGroup. Can be anything. + The new that is created. + + + + Safely looks for a modded item from another mod in the SMLHelper TechGroupCache and outputs its value when found. + + The string used to define the techgroup. + The TechGroup enum value of the modded. Defaults to when the item was not found. + + True if the item was found; Otherwise false. + + + + + Safely looks for a modded item from another mod in the SMLHelper TechGroupCache. + + The string used to define the techgroup. + + True if the item was found; Otherwise false. + + + + + A handler class for everything related to creating new TechTypes. + + + + + Adds a new into the game. This new techtype will be unlocked at the start of a the game. + + The internal name of the TechType. Should not contain special characters. + The display name of the TechType. Can be anything. + The tooltip, displayed when hovered in an inventory. Can be anything. + The new that is created. + + + + Adds a new into the game. + + The internal name of the TechType. Should not contain special characters. + The display name of the TechType. Can be anything. + The tooltip, displayed when hovered in an inventory. Can be anything. + Whether this TechType should be unlocked on game start, or not. By default, true. + The new that is created. + + + + Adds a new into the game, with a sprite. This new techtype will be unlocked at the start of a the game. + + The internal name of the TechType. Should not contain special characters. + The display name of the TechType. Can be anything. + The tooltip, displayed when hovered in an inventory. Can be anything. + The sprite that will related to this TechType. + The new that is created. + + + + Adds a new into the game, with a sprite. + + The internal name of the TechType. Should not contain special characters. + The display name of the TechType. Can be anything. + The tooltip, displayed when hovered in an inventory. Can be anything. + The sprite that will related to this TechType. + Whether this TechType should be unlocked on game start, or not. By default, true. + The new that is created. + + + + Adds a new into the game, with a sprite. This new techtype will be unlocked at the start of a the game. + + The internal name of the TechType. Should not contain special characters. + The display name of the TechType. Can be anything. + The tooltip, displayed when hovered in an inventory. Can be anything. + The sprite that will related to this TechType. + The new that is created. + + + + Adds a new into the game, with a sprite. + + The internal name of the TechType. Should not contain special characters. + The display name of the TechType. Can be anything. + The tooltip, displayed when hovered in an inventory. Can be anything. + The sprite that will related to this TechType. + Whether this TechType should be unlocked on game start, or not. By default, true. + The new that is created. + + + + Safely looks for a modded item from another mod in the SMLHelper TechTypeCache and outputs its value when found. + + The string used to define the modded item's new techtype. + The TechType enum value of the modded. Defaults to when the item was not found. + + True if the item was found; Otherwise false. + + + There's no guarantee in which order SMLHelper dependent mods are loaded, + so if two mods are added at the same time, it may take a second game load for both to be visible to each other. + + + + + Safely looks for a modded item from another mod in the SMLHelper TechTypeCache. + + The string used to define the modded item's new techtype. + + True if the item was found; Otherwise false. + + + There's no guarantee in which order SMLHelper dependent mods are loaded, + so if two mods are added at the same time, it may take a second game load for both to be visible to each other. + + + + + Handles WorldEntityDatabase. + + + + + Adds custom World Entity data to WorldEntityDatabase. + + + + + + + A utility class that offers additional info about instances. + + + + + + Using the cached container info, determines whether the specified container has room for an item of the specified size. + + The container to check. + The item width. + The item height. + + true if there is room for the item in the container,; otherwise, false. + + + + + Using the cached container info, determines whether the specified container has room for an item of the specified size. + + The container to check. + Size of the item. + + true if there is room for the item in the container,; otherwise, false. + + + + + Determines whether the specified container is empty. + + The items container to check. + + true if the specified container is empty; otherwise, false. + + + + + Determines whether the specified container is full. + + The items container to check. + + true if the specified container is full; otherwise, false. + + + + + Get the totals number of 1x1 slots in the container, as calculated by the container's width and height. + + The container. + The total number of slots in the container. + + + + Get the inernal label for the storage container. + + The container. + The label used and displayed in-game for the container. + + + + Gets the set of techtypes allowed in this container. This set can be altered. + If the set is null or empty, then all items can be added. + + The container to check. + The collection of techtypes allowed in the container. + + + + Utilities for audio and sound + + + + + Creates a instance from a path. Can be stored and later used with + + The path of the sound. Relative to the base game folder. + + The instance + + + + Creates a instance from an . Can be stored and later used with + + the AudioClip to make a Sound instance of. + + The instance. + + + + Creates an FMOD collection from an collection. + + AudioClips to create from. + The mode to set the sound to + A collection of FMOD Sounds. + + + + Converts a sound paths collection to an FMOD collection. + + Sound paths to create from. Relative to the base game folder + The mode to set the sound to + A collection of FMOD Sounds. + + + + Plays a from an . + + The AudioClip of the sound. + + The channel on which the sound was created. + + + + Plays a from an . Has overload for controlling volume. + + The AudioClip of the sound. + + Which volume control to adjust sound levels by. How loud sound is. + The channel on which the sound was created + + + + Plays a globally from a path. Must be a .wav file + + The path of the sound. Relative to the base game folder. + + The channel on which the sound was created + + + + Plays a globally from a path. Must be a .wav file. Has overload for controlling volume + + The path of the sound. Relative to the base game folder. + + Which volume control to adjust sound levels by. How loud sound is. + The channel on which the sound was created + + + + Plays a globally + + The sound which should be played + The channel on which the sound was created + + + + Plays a globally at specified volume + + The sound which should be played + Which volume control to adjust sound levels by. How loud sound is. + The channel on which the sound was created + + + + Plays a on the specified . + + The sound which should be played. + The bus to play the sound on. + The channel on which the sound was created. + + + + A list of the relevant FMOD bus paths the game uses. + + + + + Used for underwater creature SFXs. Tied to the master volume. + + + + + Used for surface creature SFXs that dont get muted when at the surface of the ocean. Tied to the master volume. + + + + + Used for PDA voices. Tied to the voice volume. + + + + + Used for encyclopedia VOs. Tied to the voice volume. + + + + + Used for main music. Tied to the music volume. + + + + + Used for environmental music. Tied to the music volume. + + + + + Used for underwater ambience SFXs. Tied to the ambient volume. + + + + + Used for ambience SFXs that dont get muted when at the surface of the ocean. Tied to the ambient volume. + + + + + Used for player and hand-held tools SFXs. Tied to the master volume. + + + + + + Places a simple text object on the screen and keeps it there until either hidden (or a designated fade-to-black timer has passed). + By default uses the same font/size/color as the "Press Any Button To Begin" message at the beginning of the game, and appears + centered about 1/3 down the screen, but all parameters can be reconfigured. + + + The idea of the defaults is that new modders don't have to bootstrap a bunch of irritating Unity stuff -- don't have to understand + what a "Material" is or how to make one, don't have to know to initialize a font, or even a color. Can just start adding text and + then can always custom and configure on further revision. + + + + SIMPLE USAGE EXAMPLE: + BasicText message = new BasicText(); + message.ShowMessage("This Message Will Fade In 10 Seconds", 10); + + COMPLEX USAGE EXAMPLE: + BasicText message = new BasicText(TextAnchor.UpperLeft); // Note many other properties could also be set as constructor parameters + message.setColor(Color.red); // Set Color + message.setSize(20); // Set Font Size + message.setLoc(200, 400); // Set x/y position (0,0 is center of screen) + message.setFontStyle(FontStyle.Bold); // Bold + message.ShowMessage("This message stays on screen until hidden"); // Display message; if fadeout seconds not specified, it just keeps showing + ... // other things happen, time goes by + message.Hide(); // Hides the message + + + + + Creates a new instances of with all default options. + + + + + Creates a new instances of at the specified origin point. + + The x coordinate to set + The y coordinate to set + + + + Creates a new instances of at a specified . + + The text anchor to align to + + + + Creates a new instances of with a specified . + + The text color to use + + + + Creates a new instances of with a specified size. + + The text size to uset + + + + Creates a new instances of with a specified size and . + + The text size to use + The text color to use + + + + Creates a new instances of with a specified size and . + + The text size to use + The text anchor to align to + + + + Creates a new instances of with a specified size, , and . + + The text size to use + The text color to use + The text anchor to align to + + + + Creates a new instances of with a specified origin point, size, , and . + + The x coordinate to set + The y coordinate to set + The text size to use + The text color to use + The text anchor to align to + + + + Creates a new instances of with a specified origin point, size, and . + + The x coordinate to set + The y coordinate to set + The text size to use + The text color to use + + + + Creates a new instances of with a specified origin point and size. + + The x coordinate to set + The y coordinate to set + The text size to use + + + + Shows our text item, with no schedule fade (i.e. indefinitely) + + The text to display + + + + Shows our text item, fading after a specified number of seconds (or stays on indefinitely if 0 seconds) + + The text to display + The duration to hold before fading + + + + Hides our text item if it is displaying. + + + + + Returns our current text. + + + + + + Sets screen display location (position relative to the actual text is determined by the alignment) + + The x coordinate to set + The y coordinate to set + + + + Sets the text color + + The text color to use + + + + Resets to using "cloned" color of Subnautica default. + + + + + Sets the font size. + + The text size to use + + + + Resets to using "cloned" size of Subnautica default. + + + + + Sets the font + + The font to render the text as. + + + + Resets to using "cloned" font of Subnautica default. + + + + + Sets the font style. + + The text font style to use + + + + Resets to using "cloned" font style of Subnautica default. + + + + + Sets the text anchor. + + The text anchor to align to + + + + Resets to using "cloned" font style of Subnautica default + + + + + Computes proper transform position based on alignment and size of text. + + + + + Sets up all of our objects/components, when we are ready to actually display text for the first time. + + + + + This class is tasked with checking external txt files for banned IDs that are not to be isssued when patching in new enum entries. + + + + + Gets the banned ids, reported by the external files, for the specified enum. + + Name of the enum. + Any previously known banned IDs for this enum can be combined into the final list. + An of banned indexes not to be issued for new entries of the specified enum. + + + + Gets the banned ids, reported by the external files, for the specified enum. + + Name of the enum. + An of banned indexes not to be issued for new entries of the specified enum. + + + + A collection of image loading utility methods that can create Unity objects from image files at runtime. + + + + + Creates a new from an image file. + + The path to the image file. + + The texture format. By default, this uses . + https://docs.unity3d.com/ScriptReference/TextureFormat.BC7.html + Don't change this unless you really know what you're doing. + + Will return a new instance if the file exists; Otherwise returns null. + + Ripped from: https://github.com/RandyKnapp/SubnauticaModSystem/blob/master/SubnauticaModSystem/Common/Utility/ImageUtils.cs + + + + + Creates a new from an image file. + + The path to the image file. + + The texture format. By default, this uses .
+ https://docs.unity3d.com/ScriptReference/TextureFormat.BC7.html
+ Don't change this unless you really know what you're doing. + + Will return a new instance if the file exists; Otherwise returns null. +
+ + + Creates a new from an image file. + + The 2D texture to convert into a sprite. + + Will return a new instance using the provided texture. + + + + + Utilities for files and paths + + + + + Works like , but can have more than 2 paths + + + + + + + + + A utility class that offers additional info about instances. + + + + + + Main entry point for all calls to this handler. + + + + + Using the cached container info, determines whether the specified container has room for an item of the specified size. + + The container to check. + The item width. + The item height. + + true if there is room for the item in the container,; otherwise, false. + + + + + Using the cached container info, determines whether the specified container has room for an item of the specified size. + + The container to check. + Size of the item. + + true if there is room for the item in the container,; otherwise, false. + + + + + Determines whether the specified container is empty. + + The items container to check. + + true if the specified container is empty; otherwise, false. + + + + + Determines whether the specified container is full. + + The items container to check. + + true if the specified container is full; otherwise, false. + + + + + The totals number of 1x1 slots in the container, as calculated by the container's width and height. + + The container. + + + + + Get the inernal label for the storage container. + + The container. + + The label used and displayed in-game for the container. + + + + + Gets the set of techtypes allowed in container. This set can be altered. + If the set is null or empty, then all items can be added. + + The container to check. + + The collection of techtypes allowed in the container. + + + + + Using the cached container info, determines whether the specified container has room for an item of the specified size. + + The container to check. + The item width. + The item height. + + true if there is room for the item in the container,; otherwise, false. + + + + + Using the cached container info, determines whether the specified container has room for an item of the specified size. + + The container to check. + Size of the item. + + true if there is room for the item in the container,; otherwise, false. + + + + + Determines whether the specified container is empty. + + The items container to check. + + true if the specified container is empty; otherwise, false. + + + + + Determines whether the specified container is full. + + The items container to check. + + true if the specified container is full; otherwise, false. + + + + + The totals number of 1x1 slots in the container, as calculated by the container's width and height. + + The container. + + + + + Get the inernal label for the storage container. + + The container. + + The label used and displayed in-game for the container. + + + + + Gets the set of techtypes allowed in this container. This set can be altered. + If the set is null or empty, then all items can be added. + + The container to check. + + The collection of techtypes allowed in the container. + + + + + A collection of utilities for interacting with JSON files. + + + + + Create an instance of , populated with data from the JSON file at the given + . + + The type of object to initialise and populate with JSON data. + The path on disk at which the JSON file can be found. + Whether a new JSON file should be created with default values if it does not + already exist. + An array of s to be used for deserialization. + The instance populated with data from the JSON file at + , or default values if it cannot be found or an error is encountered while parsing the + file. + + + + + + Loads data from the JSON file at into the . + + The type of to populate with JSON data. + The instance to popular with JSON data. + The path on disk at which the JSON file can be found. + Whether a new JSON file should be created with default values if it does not + already exist. + An array of s to be used for deserialization. + + + + + + Saves the parsed as JSON data to the JSON file at , + creating it if it does not exist. + + The type of to parse into JSON data. + The instance to parse into JSON data. + The path on disk at which to store the JSON file. + An array of s to be used for serialization. + + + + + + A collection of related utility methods. + + + + + Turn a into a + + + + + + + Turn a into a + + + + + + + Check this is the first frame a key has been pressed + + + True during the first frame a key has been pressed, otherwise false + + + + + + Check this is the first frame a key has been pressed. + + + True during the first frame a key has been pressed, otherwise false + + + + + Check a key is currently held down + + + True every frame a key is held down, otherwise false + + + + + + Check a key is currently held down + + + True every frame a key is held down, otherwise false + + + + + Check how long a key has been held down + + + + + + + + + Check how long a key has been held down + + + + + + + + Check this is the frame a key has been released + + + True during the first frame a key has been released, otherwise false + + + + + + Check this is the first frame a key has been released + + + True during the first frame a key has been released, otherwise false + + + + + Gets the analog value for a following the same logic as + + + + 1f while a key is being held, otherwise 0f + + + + + + Gets the analog value for a key by value, following the same logic as + + + + 1f while a key is being held, otherwise 0f + + + + + A collection of utility methods that simplify calls into for quick custom save data. + + + + + Get a value using + + + + + + + + Set a value using + + + + + + + Get a value using + + + + + + + + Set a value using + + + + + + + Get a value using + + + + + + Get a value using + + + + + + + Set a value using + + + + + + + Get a value using + + + + + + + Get a value using + + + + + + + + Set a value using + + + + + + + Get a value using + + + + + + + Get a value using + + + + + + + + Set a value using + + + + + + + Get a value using + + + + + + + Get a value using + + + + + + + + Set a value using + + + + + + + Get a value using + + + + + + + Get a value using + + + + + + + + Set a value using + + + + + + + Get a value using + + + + + + + Get a value using + + + + + + + + Set a value using + + + + + + + A small collection of prefab related utilities. + + + + + Adds and configures the following components on the gameobject passed by reference: + - + - + - + - + - + + + + + + + Will attempt to return . + If the component is not found, it will be added through . + + A type of Unity . + The gameobject that should have the component. + The existing component attached to the gameobject or a newly created and attached one. + + + + An extension method class for simplifying reflection calls for improved readability. + + + + + Gets the value of the requested private field, using reflection, from the instance object. + + The instance class type. + The instance. + Name of the private field. + The additional binding flags you wish to set. + and are already included. + + The value of the requested field as an . + + + + + Sets the value of the requested private field, using reflection, on the instance object. + + The instance class type. + The instance. + Name of the private field. + The value to set. + The additional binding flags you wish to set. + and are already included. + + + + Gets the value of the requested private static field, using reflection, from the static object. + + The static class type. + Name of the field. + The additional binding flags you wish to set. + and are already included. + + The value of the requested static field as an . + + + + + Gets the value of the requested private static field, using reflection, from the instance object. + + The static class type. + The instance. + Name of the field. + The additional binding flags you wish to set. + and are already included. + + The value of the requested static field as an . + + + + + Sets the value of the requested private static field, using reflection, on the static object. + + The static class type. + Name of the field. + The value to set. + The additional binding flags you wish to set. + and are already included. + + + + Sets the value of the requested private static field, using reflection, on the instance object. + + The static class type. + The instance. + Name of the field. + The value to set. + The additional binding flags you wish to set. + and are already included. + + + + Gets the of a private instance method, using refelction, from the specified class. + + The instance object type. + Name of the method. + The additional binding flags you wish to set. + and are already included. + + The of the requested private method. + + + + + Gets the of a private instance method, using refelction, from the instance object. + + The instance object type. + The instance. + Name of the method. + The additional binding flags you wish to set. + and are already included. + + The of the requested private method. + + + + + Gets the of a private static method, using refelction, from the specified class. + + The object type. + Name of the method. + The additional binding flags you wish to set. + and are already included. + + The of the requested private method. + + + + + Gets the of a private static method, using refelction, from the instance object. + + The object type. + The instance. + Name of the method. + The additional binding flags you wish to set. + and are already included. + + The of the requested private method. + + + + + Does a deep copy of all field values from the original instance onto the copied instance. + + The class type of both objects. + The original instance. + The instance receiving the copied values. + The additional binding flags you wish to set. + is already included. + + + + A small collection of save data related utilities. + + + + + Returns the path to the current save slot's directory. + + + + + The a list the different volume controls in the game + + + + Master volume control + + + Music volume control + + + Voice volume control + + + Ambient volume control + + + + Extension methods to provide static calls for into methods. + + + + + Using the cached container info, determines whether the specified container has room for an item of the specified size. + + The container to check. + The item width. + The item height. + + true if there is room for the item in the container,; otherwise, false. + + + + + Using the cached container info, determines whether the specified container has room for an item of the specified size. + + The container to check. + Size of the item. + + true if there is room for the item in the container,; otherwise, false. + + + + + Determines whether the specified container is empty. + + The items container to check. + + true if the specified container is empty; otherwise, false. + + + + + Determines whether the specified container is full. + + The items container to check. + + true if the specified container is full; otherwise, false. + + + + + The totals number of 1x1 slots in the container, as calculated by the container's width and height. + + The container. + + + + + Get the inernal label for the storage container. + + The container. + + The label used and displayed in-game for the container. + + + + + Gets the set of techtypes allowed in this container. This set can be altered. + If the set is null or empty, then all items can be added. + + The container to check. + + The collection of techtypes allowed in the container. + + + + + Attribute used to specify a file name for use with a . + + + + + The filename. + + + + + Used to specify the file name for a . + + + + + + A simple implementation of for use with config files. + + + + + The file path at which the JSON file is accessible for reading and writing. + + + + + The s that should always be used when reading/writing JSON data. + + + + + + Creates a new instance of , parsing the filename and subfolder from a + if declared, or with default values otherwise. + + + + + Creates a new instance of . + + The name of the , "config" by default. + Optional subfolder for the . + + + using SMLHelper.V2.Options; + using UnityEngine; + + public class MyConfig : ConfigFile + { + public KeyCode ActivationKey { get; set; } = KeyCode.Escape; + public MyConfig() : base("options", "Config Files") { } + // The config file will be stored at the path "QMods\YourModName\Config Files\options.json" + } + + + + + + An event that is invoked whenever the is about to load data from disk. + + + + + An event that is invoked whenever the has finished loading data from disk. + + + + + An event that is invoked whenever the is about to save data to disk. + + + + + An event that is invoked whenever the has finished saving data to disk. + + + + + Loads the JSON properties from the file on disk into the . + + Whether a new JSON file should be created with default values if it does not + already exist. + + + + + + Saves the current fields and properties of the as JSON properties to the file on disk. + + + + + + + Loads the JSON properties from the file on disk into the . + + Whether a new JSON file should be created with default values if it does not + already exist. + Optional s to be used for serialization. + The will always be used, regardless of whether you pass them. + + + + + + Saves the current fields and properties of the as JSON properties to the file on disk. + + Optional s to be used for deserialization. + The will always be used, regardless of whether you pass them. + + + + + + Attribute used to specify the filename and subfolder for a . + + + When used alongside the constructor, this attribute is ignored. + + + + using SMLHelper.V2.Json; + + [ConfigFile("options", "configs")] + public class Config : ConfigFile + { + public float MyFloatValue; + } + + + + + + The filename to use for the . + + + + + The subfolder within the mod's folder for the . + + + + + Used to specify the filename for the . + + + When used alongside the constructor, this attribute is ignored. + + The filename to use for the . + + + + Contains basic information for a event. + + + + + The instance of the this event pertains to. + + + + + Instantiates a new . + + The instance the event pertains to. + + + + A for rounding floats or doubles to a given number of decimal places, + trimming trailing 0s. + + + + + Creates a new . + + The number of decimal places to round to, where -1 disables rounding. + The rounding mode to use when rounding. + + + + + Creates a new . + + The number of decimal places to round to, where -1 disables rounding. + + + + Creates a new . + + The rounding mode to use when rounding. + + + + Creates a new . + + + + + The method for writing the data to the . + + + + + + + + The method for reading the or data from the . + + + + + + + + + + The method for determining whether the current can be processed byt this + + + + + + + + A for handling s. + + + + + The method for writing the data to the . + + + + + + + + The method for reading the data from the . + + + + + + + + + + The method for determining whether the current can be processed by this + . + + + + + + + A Quaternion json converter that simplifies the Vector3 to only x,y,z serialization. + + + + + A method that determines when this converter should process. + + the current object type + + + + + A method that tells Newtonsoft how to Serialize the current object. + + + + + + + + A method that tells Newtonsoft how to Deserialize and read the current object. + + + + + + + + + + A Vector2 json converter that simplifies the Vector2 to only x,y serialization. + + + + + A method that determines when this converter should process. + + the current object type + + + + + A method that tells Newtonsoft how to Serialize the current object. + + + + + + + + A method that tells Newtonsoft how to Deserialize and read the current object. + + + + + + + + + + A Vector2Int json converter that simplifies the Vector2Int to only x,y serialization. + + + + + A method that determines when this converter should process. + + the current object type + + + + + A method that tells Newtonsoft how to Serialize the current object. + + + + + + + + A method that tells Newtonsoft how to Deserialize and read the current object. + + + + + + + + + + A Vector3 json converter that simplifies the Vector3 to only x,y,z serialization. + + + + + A method that determines when this converter should process. + + the current object type + + + + + A method that tells Newtonsoft how to Serialize the current object. + + + + + + + + A method that tells Newtonsoft how to Deserialize and read the current object. + + + + + + + + + + A Vector3Int json converter that simplifies the Vector3Int to only x,y,z serialization. + + + + + A method that determines when this converter should process. + + the current object type + + + + + A method that tells Newtonsoft how to Serialize the current object. + + + + + + + + A method that tells Newtonsoft how to Deserialize and read the current object. + + + + + + + + + + A Vector4 json converter that simplifies the Vector4 to only x,y,z,w serialization. + + + + + A method that determines when this converter should process. + + the current object type + + + + + A method that tells Newtonsoft how to Serialize the current object. + + + + + + + + A method that tells Newtonsoft how to Deserialize and read the current object. + + + + + + + + + + Extension methods for parsing objects as JSON data. + + + + + Loads the JSON properties from a file on disk into the . + + The type of the . + The object instance to load the properties into. + The file path to the JSON file to parse. + Whether a new JSON file should be created with default values if it does not + already exist. + The s to be used for deserialization. + + + + + Saves the fields and properties of the as JSON properties to the file on disk. + + The type of the . + The object instance to save the fields and properties from. + The file path at which to save the JSON file. + The s to be used for serialization. + + + + A simple interface for a JSON file framework. + + + + + The file path at which the JSON file is accessible for reading and writing. + + + + + The s that should always be used when reading/writing JSON data. + + + + + A method for loading the JSON properties from disk. + + Whether a new JSON file should be created with default values if it does not + already exist. + + + + + + A method for saving the JSON properties to disk. + + + + + + + A method for loading the JSON properties from disk. + + Whether a new JSON file should be created with default values if it does not + already exist. + Optional s to be used for + deserialization. + + + + + + A method for saving the JSON properties to disk. + + Optional s to be used for serialization. + + + + + + A simple abstract implementation of . + + + + + The file path at which the JSON file is accessible for reading and writing. + + + + + The s that should always be used when reading/writing JSON data. + + + + + + An event that is invoked whenever the is about to load data from disk. + + + + + An event that is invoked whenever the has finished loading data from disk. + + + + + An event that is invoked whenever the is about to save data to disk. + + + + + An event that is invoked whenever the has finished saving data to disk. + + + + + Loads the JSON properties from the file on disk into the . + + Whether a new JSON file should be created with default values if it does not + already exist. + + + + + + Saves the current fields and properties of the as JSON properties to the file on disk. + + + + + + + Loads the JSON properties from the file on disk into the . + + Whether a new JSON file should be created with default values if it does not + already exist. + Optional s to be used for serialization. + The will always be used, regardless of whether you pass them. + + + + + + Saves the current fields and properties of the as JSON properties to the file on disk. + + Optional s to be used for deserialization. + The will always be used, regardless of whether you pass them. + + + + + + Contains basic information for a event. + + + + + The instance of the this event pertains to. + + + + + Instantiates a new . + + The instance the event pertains to. + + + + An abstract implementation of intended for use with caching per-save data. + + + + + The file path at which the JSON file is accessible for reading and writing. + + + + + Creates a new instance of , parsing the file name from + if declared, or with default values otherwise. + + + + + Loads the JSON properties from the file on disk into the . + + Whether a new JSON file should be created with default values if it does not + already exist. + + + Thrown when the player is not in-game. + + + + Saves the current fields and properties of the as JSON properties to the file on disk. + + + + Thrown when the player is not in-game. + + + + Loads the JSON properties from the file on disk into the . + + Whether a new JSON file should be created with default values if it does not + already exist. + Optional s to be used for serialization. + The will always be used, regardless of whether you pass them. + + + Thrown when the player is not in-game. + + + + Saves the current fields and properties of the as JSON properties to the file on disk. + + Optional s to be used for deserialization. + The will always be used, regardless of whether you pass them. + + + Thrown when the player is not in-game. + + + This component is obsolete + + + + Attribute used to signify the decorated method should be represented in the mod's options menu + as a . + When the button is clicked, the given method will run. + + + + using SMLHelper.V2.Json; + using SMLHelper.V2.Options; + using QModManager.Utility; + + [Menu("My Options Menu")] + public class Config : ConfigFile + { + [Button("My Cool Button")] + public static void MyCoolButton(object sender, ButtonClickedEventArgs e) + { + Logger.Log(Logger.Level.Info, "Button was clicked!"); + Logger.Log(Logger.Level.Info, e.Id.ToString()); + } + } + + + + + + + + + + Signifies the decorated method should be represented in the mod's options menu as a + and sets its label. + + The label for the button. If none is set, the name of the method will be used. + + + + Signifies the decorated method should be represented in the mod's options menu as a . + + + + + Attribute used to signify the decorated member should be represented in the mod's options menu as a + . Works for either index-based, -based, or + -based members. + + + choices can also be parsed from their values by merely omitting the . + + + + using SMLHelper.V2.Json; + using SMLHelper.V2.Options; + + public enum CustomChoice { One, Two, Three } + + [Menu("My Options Menu")] + public class Config : ConfigFile + { + [Choice("My index-based choice", "One", "Two", "Three")] + public int MyIndexBasedChoice; + + [Choice] + public CustomChoice MyEnumBasedChoice; + } + + + + + + + + + The list of options that will be displayed. + + + + + Attribute used to signify the decorated member should be represented in the mod's options menu as a + . Works for either index-based, -based, or + -based members. + + + choices can also be parsed from their values by merely omitting the . + + The label for the choice. If none is set, the name of the member will be used. + The list of options for the user to choose from. + + + + Attribute used to signify the decorated member should be represented in the mod's options menu as a + . Works for either index-based, -based, or + -based members. + + + choices can also be parsed from their values by merely omitting the . + + The list of options for the user to choose from. + + + + Attribute used to signify the decorated member should be represented in the mod's options menu as a + . Works for either index-based, -based, or + -based members. + + + + + The relating to this menu. + + + + + A dictionary of , indexed by . + + + + + Process metadata for members of . + + + + + Checks whether a given is declared in any subclass of . + + The to check. + Whether the given is declared in any subclass of . + + + + Checks whether a given should be ignored when generating the options menu, based on whether + the member has a declared , or the 's + property. + + The to check. + Whether the given member should be ignored when generating the options menu. + + + + Processes the given field or property and hands off to + to generate a + and add it to the dictionary. + + The of the member. + The of the member. + The underlying of the member. + + + + Processes the given method and hands off to + to generate a and add it to the dictionary. + + The of the method. + + + + Generates a based on the member and its attributes, then adds it to the + dictionary. + + The type of the to generate for this member. + The of the member. + The of the member. + The underlying of the member. + + + + Gets the metadata of every defined for a member. + + + The type of attribute defined on the member to gather metadata for. + + The member to gather attribute metadata for. + + + + + Invokes the method for a given and passes parameters when the button is clicked. + + The sender of the original button click event. + The for the click event. + + + + Sets the value in the , optionally saving the to disk if the + flag is set, before passing off to + + to invoke any methods specified with an . + + The sender of the original choice changed event. + The for the choice changed event. + + + + Sets the value in the , optionally saving the to disk if the + flag is set, before passing off to + + to invoke any methods specified with an . + + The sender of the original keybind changed event. + The for the keybind changed event. + + + + Sets the value in the , optionally saving the to disk if the + flag is set, before passing off to + + to invoke any methods specified with an . + + The sender of the original slider changed event. + The for the slider changed event. + + + + Sets the value in the , optionally saving the to disk if the + flag is set, before passing off to + + to invoke any methods specified with an . + + The sender of the original toggle changed event. + The for the toggle changed event. + + + + Generates tooltips as required for each , before + invoking any relevant method(s) specified with (s) and passes + parameters when a is created in the options menu. + + + + + + + Invokes the relevant method(s) specified with the (s) + and passes parameters when a value is changed when loaded from disk. + + The metadata for the mod option. + The sender of the event. + + + + Invokes the relevant method(s) specified with (s) + and passes parameters when a value is changed. + + The type of the event args. + The metadata for the mod option. + The sender of the event. + The event args from the OnChange event. + + + + Invoke the relevant method specified by a + and passes relevant parameters. + + The type of the event args. + The metadata for the method. + The sender of the event. + The event args from the event. + + + + Attribute used to signify the given property, field or method should be ignored when generating your mod options menu. + + + By default, all members are ignored unless either they are decorated with a derivative, + or the property is set to . + + + + using SMLHelper.V2.Json; + using SMLHelper.V2.Options; + + [Menu("My Options Menu")] + public class Config : ConfigFile + { + [Button("My Cool Button)] + public static void MyCoolButton(object sender, ButtonClickedEventArgs e) + { + Logger.Log(Logger.Level.Info, "Button was clicked!"); + Logger.Log(Logger.Level.Info, e.Id.ToString()); + } + + [IgnoreMember] + public int FieldNotDisplayedInMenu; + } + + + + + + + + + + + Attribute used to signify the decorated should be represented in the mod's + option menu as a . + + + + using SMLHelper.V2.Json; + using SMLHelper.V2.Options; + using UnityEngine; + + [Menu("My Options Menu")] + public class Config : ConfigFile + { + [Keybind("My Keybind")] + public KeyCode MyKeybind; + } + + + + + + + + Signifies the decorated should be represented in the mod's option menu + as a . + + The label for the keybind. If none is set, the name of the member will be used. + + + + Signifies the decorated should be represented in the mod's option menu + as a . + + + + + Uses the stored metadata to get the current value of the member. + + The type of the value. + The config to get the value from. + The value. + + + + Uses the stored metadata to get the current value of the member. + + The config to get the value from. + The value. + + + + Uses the stored metadata to set the current value of the member. + + The type of the value. + The config the set the value in. + The value. + + + + Stores the of each parameter of a method to the + array. + + of the method to parse. + + + + Use the stored metadata to invoke the method. + + The config in which the method. + An array of arguments to pass to the method. + + + + Attribute used to signify a menu should be automatically generated from a + , as well as specifying options for handling the + and menu. + + + + using SMLHelper.V2.Interfaces; + using SMLHelper.V2.Json; + using SMLHelper.V2.Options; + using QModManager.Utility; + using UnityEngine; + + [Menu("SMLHelper Example Mod")] + public class Config : ConfigFile + { + [Choice("My index-based choice", "Choice 1", "Choice 2", "Choice 3", Tooltip = "A simple tooltip")] + [OnChange(nameof(MyGenericValueChangedEvent))] + public int ChoiceIndex; + + [Choice("My enum-based choice"), OnChange(nameof(MyGenericValueChangedEvent))] + public CustomChoice ChoiceEnum; + + [Keybind("My keybind"), OnChange(nameof(MyGenericValueChangedEvent))] + public KeyCode KeybindKey; + + [Slider("My slider", 0, 50, DefaultValue = 25, Format = "{0:F2}"), OnChange(nameof(MyGenericValueChangedEvent))] + public float SliderValue; + + [Toggle("My checkbox"), OnChange(nameof(MyCheckboxToggleEvent)), OnChange(nameof(MyGenericValueChangedEvent))] + public bool ToggleValue; + + [Button("My button")] + public void MyButtonClickEvent(ButtonClickedEventArgs e) + { + Logger.Log(Logger.Level.Info, "Button was clicked!"); + Logger.Log(Logger.Level.Info, $"{e.Id}"); + } + + public void MyCheckboxToggleEvent(ToggleChangedEventArgs e) + { + Logger.Log(Logger.Level.Info, "Checkbox value was changed!"); + Logger.Log(Logger.Level.Info, $"{e.Value}"); + } + + private void MyGenericValueChangedEvent(IModOptionEventArgs e) + { + Logger.Log(Logger.Level.Info, "Generic value changed!"); + Logger.Log(Logger.Level.Info, $"{e.Id}: {e.GetType()}"); + + switch (e) + { + case KeybindChangedEventArgs keybindChangedEventArgs: + Logger.Log(Logger.Level.Info, keybindChangedEventArgs.KeyName); + break; + case ChoiceChangedEventArgs choiceChangedEventArgs: + Logger.Log(Logger.Level.Info, choiceChangedEventArgs.Value); + break; + case SliderChangedEventArgs sliderChangedEventArgs: + Logger.Log(Logger.Level.Info, sliderChangedEventArgs.Value.ToString()); + break; + case ToggleChangedEventArgs toggleChangedEventArgs: + Logger.Log(Logger.Level.Info, toggleChangedEventArgs.Value.ToString()); + break; + } + } + } + + + + + + + + + + + + + + + Specifies after which events the config file should be saved to disk automatically. + + + This enumeration has a that allows a bitwise combination of its member values. + + + + + Never automatically save. + + + + + Save whenever any value is changed. + + + + + Save when the player saves the game. + + + + + Save when the player quits the game. + + + + + Specifies after which events the config file should be loaded from disk automatically. + + + This enumeration has a that allows a bitwise combination of its member values. + + + + + Never automatically load. + + + + + Load when the menu is registered to SMLHelper via . + + + In normal usage, this option is equivalent to loading when the game is launched. + + + + + Load when the menu is opened by the player. + + + Useful for allowing players to edit their config files manually without restarting the game for their changes to take effect. + + + + + Specifies which members of the will be parsed and added to the menu. + + + + + Only members decorated with a derivative such as + , etc. will be processed. + + + + + All members will be processed, and where they are not decorated, a default attribute + will be generated for them. + + + + + The display name for the generated options menu. + + + + + The events after which the config file will be saved to disk automatically. + Defaults to . + + + + + + + The events after which the config file will be loaded from disk automatically. + Defaults to . + + + + + + + How members of the will be processed. + Defaults to , so that only decorated members will be processed. + + + + + + Signifies a menu should be automatically generated from a . + + The display name for the generated options menu. + + + + Abstract base attribute used to signify the decorated public member should generate a + in a mod's options menu. + + + + + The label to use when displaying the field in the mod's options menu. If is set, this + will be ignored. + + + + + The Id to be used for the field in the mod's option menu. If none is specified, one will be automatically generated when + your is registered to the . This means it will + change every time the game is launched, but is guaranteed to be unique. If you would like to specify an Id to use for + internal comparisons, you can do so here. + + + + + The order in which to display fields in the mod's option menu, in ascending order. If none is specified, the order will be + automatically set. + + + + + An optional tooltip to display for the field. If is set, this will be ignored. + + + + + An optional id to be parsed with for the label, allowing for custom language-based strings + via the API. If this is set, it will take precedence. + + + + + + + An optional id to be parsed with for the tooltip, allowing for custom lanaguage-based strings + via the API. If this is set, it will take precedence. + + + + + Signifies the decorated member should be represented in the mod's options menu as a + with an optional label. + + The label to display. If none is set, the name of the member will be used. If + is set, this will be ignored. + + + + Abstract base attribute used to signify a method to call whenever the derivative event is invoked for the decorated member. + + + The method must be a member of the same class. + + + + + The name of the method to invoke. + + + + + Signifies a method to call whenever the derivative event is invoked for the decorated member. + + + The method must be a member of the same class. + + The name of the method within the same class to invoke. + + + + Attribute used to signify a method to call whenever the decorated member's value changes. + + + The method must be a member of the same class. Can be specified mutliple times to call multiple methods. + + The specified method can take the following parameters in any order:
+ - sender: The sender of the event
+ - eventArgs: The generalized event arguments of the event
+ - choiceChangedEventArgs: Only when the member corresponds to a +
+ - keybindChangedEventArgs: Only when the member correspends to a +
+ - sliderChangedEventArgs: Only when the member corresponds to a +
+ - toggleChangedEventArgs: Only when the member corresponds to a + +
+
+ + + using SMLHelper.V2.Interfaces; + using SMLHelper.V2.Json; + using SMLHelper.V2.Options; + using QModManager.Utility; + using UnityEngine; + + [Menu("SMLHelper Example Mod")] + public class Config : ConfigFile + { + [Toggle("My checkbox"), OnChange(nameof(MyCheckboxToggleEvent)), OnChange(nameof(MyGenericValueChangedEvent))] + public bool ToggleValue; + + public void MyCheckboxToggleEvent(ToggleChangedEventArgs e) + { + Logger.Log(Logger.Level.Info, "Checkbox value was changed!"); + Logger.Log(Logger.Level.Info, $"{e.Value}"); + } + + private void MyGenericValueChangedEvent(IModOptionEventArgs e) + { + Logger.Log(Logger.Level.Info, "Generic value changed!"); + Logger.Log(Logger.Level.Info, $"{e.Id}: {e.GetType()}"); + + switch (e) + { + case KeybindChangedEventArgs keybindChangedEventArgs: + Logger.Log(Logger.Level.Info, keybindChangedEventArgs.KeyName); + break; + case ChoiceChangedEventArgs choiceChangedEventArgs: + Logger.Log(Logger.Level.Info, choiceChangedEventArgs.Value); + break; + case SliderChangedEventArgs sliderChangedEventArgs: + Logger.Log(Logger.Level.Info, sliderChangedEventArgs.Value.ToString()); + break; + case ToggleChangedEventArgs toggleChangedEventArgs: + Logger.Log(Logger.Level.Info, toggleChangedEventArgs.Value.ToString()); + break; + } + } + + + + + + + + + + + + +
+ + + Signifies a method to call whenever the decorated member's value changes. + + + The method must be a member of the same class. + + The name of the method within the same class to invoke. + + + + Attribute used to signify a method to call whenever the for the + corresponding to the decorated member is created. + + + The method must be a member of the same class. Can be specified multiple times to call multiple methods. + + The specified method can optionally take the following parameters in any order:
+ - sender: The sender of the event
+ - eventArgs: The generalized event arguments of the event
+ - gameObjectCreatedEventArgs: The + for the event +
+
+ + + using SMLHelper.V2.Json; + using SMLHelper.V2.Options; + using QModManager.Utility; + using UnityEngine; + + [Menu("SMLHelper Example Mod")] + public class Config : ConfigFile + { + [Toggle("My checkbox"), OnGameObjectCreated(nameof(MyGameObjectCreatedEvent))] + public bool ToggleValue; + + private void MyGameObjectCreatedEvent(GameObjectCreatedEventArgs e) + { + Logger.Log(Logger.Level.Info, "GameObject was created"); + Logger.Log(Logger.Level.Info, $"{e.Id}: {e.GameObject}"); + } + } + + + + + + + + +
+ + + Signifies a method to call whenever the for the + corresponding to the decorated member is created. + + + The method must be a member of the same class. + + The name of the method within the same class to invoke. + + + + An internal derivative of for use in auto-generating a menu based on attributes + declared in a . + + The type of the class derived from to use for + loading to/saving from disk. + + + + Instantiates a new , generating s by parsing the fields, + properties and methods declared in the class. + + + + + Adds options to the menu based on the . + + + + + Adds a to the menu. + + + + + + + Adds a to the menu. + + + + The metadata of the corresponding member. + The defined or generated of the member. + + + + Adds a to the menu. + + + + The metadata of the corresponding member. + + + + Adds a to the menu. + + + + The metadata of the corresponding member. + The defined or generated of the member. + + + + Adds a to the menu. + + + + The metadata of the corresponding member. + + + + Attribute used to signify the specified , or should be represented + in the mod's option menu as a . + + + + using SMLHelper.V2.Json; + using SMLHelper.V2.Options; + + [Menu("My Options Menu")] + public class Config : ConfigFile + { + [Slider("My Slider", 0, 50, DefaultValue = 25, Format = "{0:F2}")] + public float MySlider; + } + + + + + + + + The minimum value of the slider. + + + + + The maximum value of the slider. + + + + + The default value of the slider. + + + + + The format to use when displaying the value, e.g. "{0:F2}" or "{0:F0} %" + + + + + The step to apply to the slider (ie. round to nearest) + + + + + Signifies the specified , or should be represented in the mod's + options menu as a . + + The label for the slider. If none is set, the name of the method will be used. + The minimum value of the slider. + The maximum value of the slider. + + + + Signifies the specified , or should be represented in the mod's + options menu as a . + + The minimum value of the slider. + The maximum value of the slider. + + + + Signifies the specified , or should be represented in the mod's + options menu as a . + + The label for the slider. If none is set, the name of the method will be used. + + + + Signifies the specified , or should be represented in the mod's + options menu as a . + + + + + Attribute used to signify the decorated should be represented in the mod's + option menu as a . + + + + using SMLHelper.V2.Json; + using SMLHelper.V2.Options; + + [Menu("My Options Menu")] + public class Config : ConfigFile + { + [Toggle("My Toggle")] + public bool MyToggle; + } + + + + + + + + Signifies the decorated should be represented in the mod's option menu + as a . + + The label for the toggle. + + + + Signifies the decorated should be represented in the mod's option menu + as a . + + + + + Contains all the information about a button click event. + + + + + The ID of the that was clicked. + + + + + Constructs a new . + + The ID of the that was clicked. + + + + Abstract class that provides the framework for your mod's in-game configuration options. + + + + + The event that is called whenever a button is clicked. Subscribe to this in the constructor. + + + + + Notifies button click to all subscribed event handlers. + + The internal ID for the button option. + + + + Adds a new to this instance. + + The internal ID for the button option. + The display text to use in the in-game menu. + + + + The event that is called whenever a choice is changed. Subscribe to this in the constructor. + + + + + Notifies a choice change to all subscribed event handlers. + + + + + + + Notifies a choice change to all subscribed event handlers. + + + + + + + + Adds a new to this instance. + + The internal ID for the choice option. + The display text to use in the in-game menu. + The collection of available values. + The starting value. + + + + Adds a new to this instance. + + The internal ID for the choice option. + The display text to use in the in-game menu. + The collection of available values. + The starting value. + + + + Adds a new to this instance. + + The internal ID for the choice option. + The display text to use in the in-game menu. + The collection of available values. + The starting value. + + + + Adds a new to this instance. + + The internal ID for the choice option. + The display text to use in the in-game menu. + The collection of available values. + The starting value. + + + + Adds a new to this instance, automatically using the values of an enum + + The enum which will be used to populate the options + The internal ID for the choice option. + The display text to use in the in-game menu. + The starting value + + + + The event that is called whenever a keybind is changed. Subscribe to this in the constructor. + + + + + Notifies a keybind change to all subscribed event handlers. + + + + + + + Adds a new to this instance. + + The internal ID for the toggle option. + The display text to use in the in-game menu. + The device name. + The starting keybind value. + + + + Adds a new to this instance. + + The internal ID for the toggle option. + The display text to use in the in-game menu. + The device name. + The starting keybind value. + + + + The name of this set of configuration options. + + + + + Obtains the s that belong to this instance. Can be null. + + + + + Creates a new instance of . + + The name that will display above this section of options in the in-game menu. + + + + Builds up the configuration the options. + This method should be composed of calls into the following methods: + | | | . + Make sure you have subscribed to the events in the constructor to handle what happens when the value is changed: + | | | . + + + + The event that is called whenever a game object created for the option + + + + The event that is called whenever a slider is changed. Subscribe to this in the constructor. + + + + + Notifies a slider change to all subsribed event handlers. + + + + + + + Adds a new to this instance. + + The internal ID for the slider option. + The display text to use in the in-game menu. + The minimum value for the range. + The maximum value for the range. + The starting value. + + + + Adds a new to this instance. + + The internal ID for the slider option. + The display text to use in the in-game menu. + The minimum value for the range. + The maximum value for the range. + The starting value. + The default value for the slider. If this is null then 'value' used as default. + format for value, e.g. "{0:F2}" or "{0:F0} %" + (more on this here) + + + + Adds a new to this instance. + + The internal ID for the slider option. + The display text to use in the in-game menu. + The minimum value for the range. + The maximum value for the range. + The starting value. + The default value for the slider. If this is null then 'value' used as default. + format for value, e.g. "{0:F2}" or "{0:F0} %" + (more on this here) + Step for the slider, ie. round to nearest X + + + + The event that is called whenever a toggle is changed. Subscribe to this in the constructor. + + + + + Notifies a toggle change to all subscribed event handlers. + + + + + + + Adds a new to this instance. + + The internal ID for the toggle option. + The display text to use in the in-game menu. + The starting value. + + + + A mod option class for handling a button that can be clicked. + + + + + Instantiates a new for handling a button that can be clicked. + + The internal ID of this option. + The display text to show on the in-game menus. + + + + Contains all the information about a choice changed event. + + + + + The ID of the that was changed. + + + + + The new index for the . + + + + + The value of the as a string. + + + + + Constructs a new . + + The ID of the that was changed. + The new index for the . + + + + Constructs a new . + + The ID of the that was changed. + The new index for the . + The value of the as a string. + + + + A mod option class for handling an option that can select one item from a list of values. + + + + + The array of readable string options to choose between in the . + + + + + The currently selected index among the options array. + + + + + Instantiates a new for handling an option that can select one item from a list of values. + + The internal ID of this option. + The display text to show on the in-game menus. + The collection of available values. + The starting value. + + + + Contains all the information about a keybind changed event. + + + + + The ID of the that was changed. + + + + + The new value for the . + + + + + The new value for the parsed as a + + + + + Constructs a new . + + The ID of the that was changed. + The new value for the . + + + + A mod option class for handling an option that is a keybind. + + + + + The currently selected for the . + + + + + The currently select input source device for the . + + + + + Instantiates a new for handling an option that is a keybind. + + The internal ID of this option. + The display text to show on the in-game menus. + The device name. + The starting keybind value. + + + Contains all the information about a created game object event + + + The ID of the for which game object was created + + + New game object for the + + + Constructs a new + The ID of the for which game object was created + New game object for the + + + + The common abstract class to all mod options. + + + + + The internal ID that identifies this option. + + + + + The display text to be shown for this option in the in-game menus. + + + + UI GameObject for this option + + + Parent for this option + + + + Base constructor for all mod options. + + The display text to show on the in-game menus. + The internal ID if this option. + + + + Contains all the information about a slider changed event. + + + + + The ID of the that was changed. + + + + + The new value for the . + + + + + The new value for the parsed as an + + + + + Constructs a new . + + The ID of the that was changed. + The new value for the . + + + + A mod option class for handling an option that can have any floating point value between a minimum and maximum. + + + + + The minimum value of the . + + + + + The maximum value of the . + + + + + The current value of the . + + + + + The default value of the . + Showed on the slider by small gray circle. Slider's handle will snap to the default value near it. + + + + + The step value of the . + Defaults to 0f for compatibility with older mods. + + + + Format for value field () + + + + Instantiates a new for handling an option that can have any floating point value between a minimum and maximum. + + The internal ID of this option. + The display text to show on the in-game menus. + The minimum value for the range. + The maximum value for the range. + The starting value. + The default value for the slider. If this is null then 'value' used as default. + Format for value field () + Step for the slider ie. round to nearest X + + + + Component for customizing slider's value behaviour. + If you need more complex behaviour than just custom value format then you can inherit this component + and add it to "Slider" game object in OnGameObjectCreated event (see for details on adding component) + You can override value converters and , + in that case internal range for slider will be changed to [0.0f : 1.0f] and you can control displayed value with these converters + (also this value will be passed to event) + + + + The value label of the + + + The slider controlling this + + + + The minimum value of the . + In case of custom value converters it can be not equal to internal minimum value for slider + + + + + The maximum value of the . + In case of custom value converters it can be not equal to internal maximum value for slider + + + + Custom value format property. Set it right after adding component to game object for proper behaviour + + + Custom value format + + + Step for the slider + + + + Width for value text field. Used by to adjust label width. + It is calculated in , but you can override this property. + + + + Override this if you need to initialize custom value converters + + + Converts internal slider value [0.0f : 1.0f] to displayed value + + + Converts displayed value to internal slider value [0.0f : 1.0f] + + + Component initialization. If you overriding this, make sure that you calling base.Awake() + + + .Start() + + + + Method for calculating necessary label's width. Creates temporary label and compares widths of min and max values, + then sets to the wider. Be aware that in case of using custom converters some intermediate value may be wider than min/max values. + + + + Called when user changes slider value + + + + Updates label's text with formatted and converted slider's value. + Override this if you need even more control on slider's value behaviour. + + + + + Contains all the information about a toggle changed event. + + + + + The ID of the that was changed. + + + + + The new value for the . + + + + + Constructs a new . + + The ID of the that was changed. + The new value for the . + + + + A mod option class for handling an option that can be either ON or OFF. + + + + + The current value of the . + + + + + Instantiates a new for handling an option that can be either ON or OFF. + + The internal ID of this option. + The display text to show on the in-game menus. + The starting value. + + + + Adds a custom console command from a target method/delegate. + + The command string that a user should enter. + The targeted method. + Whether the method is a delegate. + The instance the method belongs to. + + + + Searches the given for methods decorated with the and + passes them on to . + + The type within which to search. + + + + Harmony patch on the to intercept user submissions. + + The submitted value. + Original result of the method, used to determine whether or not the string will be added to the + . + Whether or not to let the original method run. + + + + Attempts to handle a user command. + + The command input. + Whether we have handled the command. Will return if the command is in our list of + watched commands, whether or not the parameters were valid. + + + + Logs the message after stripping XML tags (colors), but announces to the user with XML tags intact. + + The message. + Log level. + + + + A constant value to represent a custom middle click item action + + + + + A constant value to represent a custom left click item action + + + + + This dictionary strtucture automatically checks for duplicate keys as they are being added to the collection. + Duplicate entires are logged and removed from the final collection. + + + + + + + Maintains a collection of the keys that have encountered duplicates and how many of them were discarded. + + + + + Maintains the final collection of only unique keys. + + + + + Gets a key value pair from the collection or sets a key value pair into the collection. + When setting, if a key already exists, the previous entry will be discarded. + + The unique key. + The value corresponding to the key. + + + + Add a new entry the collection. + If a duplicate key is found, all entries with that key will be excluded from the final collection. + + The unique key. + The value. + + + + Add a new entry the collection. + If a duplicate key is found, all entries with that key will be excluded from the final collection. + + The key value pair. + + + + Informs the user that all entries for the specified key have been discarded. + + The no longer unique key. + + + + Informs the user that the previous entry for the specified key has been discarded. + + The no longer unique key. + +
+
diff --git a/SMLHelper/MonoBehaviours/EntitySpawner.cs b/SMLHelper/MonoBehaviours/EntitySpawner.cs index c7494957..960d9e09 100644 --- a/SMLHelper/MonoBehaviours/EntitySpawner.cs +++ b/SMLHelper/MonoBehaviours/EntitySpawner.cs @@ -1,3 +1,5 @@ +using SMLHelper.V2.Utility; + namespace SMLHelper.V2.MonoBehaviours { using System.Collections; @@ -5,7 +7,7 @@ namespace SMLHelper.V2.MonoBehaviours using Patchers; using UnityEngine; using UWE; - using Logger = Logger; + using InternalLogger = InternalLogger; internal class EntitySpawner : MonoBehaviour { @@ -31,7 +33,7 @@ IEnumerator SpawnAsync() if (prefab == null) { - Logger.Error($"no prefab found for {stringToLog}; process for Coordinated Spawn canceled."); + InternalLogger.Error($"no prefab found for {stringToLog}; process for Coordinated Spawn canceled."); Destroy(gameObject); } diff --git a/SMLHelper/MonoBehaviours/Fixer.cs b/SMLHelper/MonoBehaviours/Fixer.cs index c2837082..f477668c 100644 --- a/SMLHelper/MonoBehaviours/Fixer.cs +++ b/SMLHelper/MonoBehaviours/Fixer.cs @@ -7,6 +7,6 @@ namespace SMLHelper.V2.MonoBehaviours [Obsolete("Use SMLHelper.V2.Assets.ModPrefabCache instead", true)] public class Fixer : MonoBehaviour { - private void Awake() => V2.Logger.Warn("Fixer component is obsolete."); + private void Awake() => Utility.InternalLogger.Warn("Fixer component is obsolete."); } } diff --git a/SMLHelper/Options/Attributes/ButtonAttribute.cs b/SMLHelper/Options/Attributes/ButtonAttribute.cs index 53e247b6..5385b13f 100644 --- a/SMLHelper/Options/Attributes/ButtonAttribute.cs +++ b/SMLHelper/Options/Attributes/ButtonAttribute.cs @@ -2,7 +2,7 @@ { using Json; using System; - using QModManager.Utility; + using SMLHelper.V2.Utility; /// /// Attribute used to signify the decorated method should be represented in the mod's options menu @@ -29,7 +29,7 @@ /// /// /// - /// + /// /// [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] public sealed class ButtonAttribute : ModOptionAttribute diff --git a/SMLHelper/Options/Attributes/ConfigFileMetadata.cs b/SMLHelper/Options/Attributes/ConfigFileMetadata.cs index 1cce354f..c9f439ca 100644 --- a/SMLHelper/Options/Attributes/ConfigFileMetadata.cs +++ b/SMLHelper/Options/Attributes/ConfigFileMetadata.cs @@ -1,8 +1,9 @@ -namespace SMLHelper.V2.Options.Attributes +using SMLHelper.V2.Utility; + +namespace SMLHelper.V2.Options.Attributes { using Interfaces; using Json; - using QModManager.API; using System; using System.Collections; using System.Collections.Generic; @@ -10,17 +11,9 @@ using System.Linq; using System.Reflection; using UnityEngine; - using Logger = Logger; -#if SUBNAUTICA - using Text = UnityEngine.UI.Text; -#elif BELOWZERO - using Text = TMPro.TextMeshProUGUI; -#endif -#if SUBNAUTICA_STABLE - using Oculus.Newtonsoft.Json; -#else + using InternalLogger = InternalLogger; using Newtonsoft.Json; -#endif + using TMPro; internal class ConfigFileMetadata where T : ConfigFile, new() { @@ -28,7 +21,7 @@ public bool Registered { get; set; } = false; - public IQMod QMod { get; } = QModServices.Main.GetMod(Assembly.GetAssembly(typeof(T))); + public string ModName { get; } = Assembly.GetAssembly(typeof(T)).GetName().Name; /// /// The relating to this menu. @@ -47,18 +40,18 @@ public void ProcessMetadata() { Stopwatch stopwatch = new Stopwatch(); - if (Logger.EnableDebugging) + if (InternalLogger.EnableDebugging) stopwatch.Start(); - MenuAttribute = typeof(T).GetCustomAttribute(true) ?? new MenuAttribute(QMod.DisplayName); + MenuAttribute = typeof(T).GetCustomAttribute(true) ?? new MenuAttribute(ModName); ModOptionAttributesMetadata = new Dictionary>(); processMetadata(); - if (Logger.EnableDebugging) + if (InternalLogger.EnableDebugging) { stopwatch.Stop(); - Logger.Debug($"[{QMod.DisplayName}] [{typeof(T).Name}] OptionsMenuBuilder metadata parsed in {stopwatch.ElapsedMilliseconds}ms."); + InternalLogger.Debug($"[{ModName}] [{typeof(T).Name}] OptionsMenuBuilder metadata parsed in {stopwatch.ElapsedMilliseconds}ms."); } } @@ -86,7 +79,7 @@ private void processMetadata() processMethod(method); } - Logger.Debug($"[{QMod.DisplayName}] [{typeof(T).Name}] Found {ModOptionAttributesMetadata.Count()} options to add to the menu."); + InternalLogger.Debug($"[{ModName}] [{typeof(T).Name}] Found {ModOptionAttributesMetadata.Count()} options to add to the menu."); } /// @@ -227,7 +220,7 @@ private void addModOptionMetadata(MemberInfo memberInfo, MemberType } catch (Exception ex) { - Logger.Error($"[OptionsMenuBuilder] {ex.Message}"); + InternalLogger.Error($"[OptionsMenuBuilder] {ex.Message}"); } } @@ -486,7 +479,7 @@ public void HandleGameObjectCreated(object sender, GameObjectCreatedEventArgs e) // Create a tooltip if specified if (tooltip is not null) { - e.GameObject.GetComponentInChildren().gameObject.AddComponent().Tooltip = tooltip; + e.GameObject.GetComponentInChildren().gameObject.AddComponent().Tooltip = tooltip; } if (modOptionMetadata.OnGameObjectCreatedMetadata == null) @@ -613,7 +606,7 @@ private void InvokeEvent(MemberInfoMetadata memberInfoMetadata, obje if (!memberInfoMetadata.MethodValid) { // Method not found, log error and skip. - Logger.Error($"[OptionsMenuBuilder] Could not find the specified method: {typeof(T)}.{memberInfoMetadata.Name}"); + InternalLogger.Error($"[OptionsMenuBuilder] Could not find the specified method: {typeof(T)}.{memberInfoMetadata.Name}"); return; } diff --git a/SMLHelper/Options/Attributes/MemberInfoMetadata.cs b/SMLHelper/Options/Attributes/MemberInfoMetadata.cs index 23e18c62..2a0b64bd 100644 --- a/SMLHelper/Options/Attributes/MemberInfoMetadata.cs +++ b/SMLHelper/Options/Attributes/MemberInfoMetadata.cs @@ -2,6 +2,7 @@ { using HarmonyLib; using Json; + using SMLHelper.V2.Utility; using System; using System.Linq; using System.Reflection; @@ -82,7 +83,7 @@ public void ParseMethodParameterTypes(MethodInfo methodInfo = null) if (methodInfo == null) { // Method not found, log error and skip. - Logger.Error($"[OptionsMenuBuilder] Could not find the specified method: {typeof(T)}.{Name}"); + InternalLogger.Error($"[OptionsMenuBuilder] Could not find the specified method: {typeof(T)}.{Name}"); return; } } @@ -104,7 +105,7 @@ public void InvokeMethod(T config, params object[] arguments) if (!MethodValid) { // Method not found, log error and skip. - Logger.Error($"[OptionsMenuBuilder] Could not find the specified method: {typeof(T)}.{Name}"); + InternalLogger.Error($"[OptionsMenuBuilder] Could not find the specified method: {typeof(T)}.{Name}"); return; } diff --git a/SMLHelper/Options/Attributes/MenuAttribute.cs b/SMLHelper/Options/Attributes/MenuAttribute.cs index aa5c12a1..579b7ffa 100644 --- a/SMLHelper/Options/Attributes/MenuAttribute.cs +++ b/SMLHelper/Options/Attributes/MenuAttribute.cs @@ -2,7 +2,7 @@ { using Json; using System; - using QModManager.Utility; + using SMLHelper.V2.Utility; /// /// Attribute used to signify a menu should be automatically generated from a @@ -81,7 +81,7 @@ /// /// /// - /// + /// [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] public sealed class MenuAttribute : Attribute { diff --git a/SMLHelper/Options/Attributes/OnChangeAttribute.cs b/SMLHelper/Options/Attributes/OnChangeAttribute.cs index ae0fa9da..6a988c79 100644 --- a/SMLHelper/Options/Attributes/OnChangeAttribute.cs +++ b/SMLHelper/Options/Attributes/OnChangeAttribute.cs @@ -2,7 +2,7 @@ { using Interfaces; using Json; - using QModManager.Utility; + using SMLHelper.V2.Utility; using System; /// @@ -76,7 +76,7 @@ /// /// /// - /// + /// [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = true)] public sealed class OnChangeAttribute : ModOptionEventAttribute { diff --git a/SMLHelper/Options/Attributes/OnGameObjectCreatedAttribute.cs b/SMLHelper/Options/Attributes/OnGameObjectCreatedAttribute.cs index 134d1dee..b3e9589f 100644 --- a/SMLHelper/Options/Attributes/OnGameObjectCreatedAttribute.cs +++ b/SMLHelper/Options/Attributes/OnGameObjectCreatedAttribute.cs @@ -2,7 +2,7 @@ { using Interfaces; using System; - using QModManager.Utility; + using SMLHelper.V2.Utility; /// /// Attribute used to signify a method to call whenever the for the @@ -44,7 +44,7 @@ /// /// /// - /// + /// [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Method, AllowMultiple = true)] public sealed class OnGameObjectCreatedAttribute : ModOptionEventAttribute { diff --git a/SMLHelper/Options/Attributes/OptionsMenuBuilder.cs b/SMLHelper/Options/Attributes/OptionsMenuBuilder.cs index ad40faf8..609a247d 100644 --- a/SMLHelper/Options/Attributes/OptionsMenuBuilder.cs +++ b/SMLHelper/Options/Attributes/OptionsMenuBuilder.cs @@ -1,4 +1,6 @@ -namespace SMLHelper.V2.Options.Attributes +using SMLHelper.V2.Utility; + +namespace SMLHelper.V2.Options.Attributes { using Json; using System; @@ -6,7 +8,7 @@ using System.Collections.Generic; using System.Linq; using UnityEngine; - using Logger = Logger; + using InternalLogger = InternalLogger; /// /// An internal derivative of for use in auto-generating a menu based on attributes @@ -115,9 +117,9 @@ public override void BuildModOptions() if (Language.main.TryGet(modOptionMetadata.ModOptionAttribute.LabelLanguageId, out string languageLabel)) label = languageLabel; - Logger.Debug($"[{ConfigFileMetadata.QMod.DisplayName}] [{typeof(T).Name}] {modOptionMetadata.MemberInfoMetadata.Name}: " + + InternalLogger.Debug($"[{ConfigFileMetadata.ModName}] [{typeof(T).Name}] {modOptionMetadata.MemberInfoMetadata.Name}: " + $"{modOptionMetadata.ModOptionAttribute.GetType().Name}"); - Logger.Debug($"[{ConfigFileMetadata.QMod.DisplayName}] [{typeof(T).Name}] Label: {label}"); + InternalLogger.Debug($"[{ConfigFileMetadata.ModName}] [{typeof(T).Name}] Label: {label}"); switch (modOptionMetadata.ModOptionAttribute) diff --git a/SMLHelper/Options/KeybindModOption.cs b/SMLHelper/Options/KeybindModOption.cs index c58a33a6..2c8532f5 100644 --- a/SMLHelper/Options/KeybindModOption.cs +++ b/SMLHelper/Options/KeybindModOption.cs @@ -6,11 +6,7 @@ using SMLHelper.V2.Utility; using UnityEngine; using UnityEngine.Events; -#if SUBNAUTICA - using Text = UnityEngine.UI.Text; -#elif BELOWZERO - using Text = TMPro.TextMeshProUGUI; -#endif + using TMPro; /// /// Contains all the information about a keybind changed event. @@ -120,7 +116,7 @@ internal override void AddToPanel(uGUI_TabbedControlsPanel panel, int tabIndex) OptionGameObject = panel.AddItem(tabIndex, panel.bindingOptionPrefab); // Update text - Text text = OptionGameObject.GetComponentInChildren(); + TextMeshProUGUI text = OptionGameObject.GetComponentInChildren(); if (text != null) { OptionGameObject.GetComponentInChildren().translationKey = Label; @@ -139,11 +135,6 @@ internal override void AddToPanel(uGUI_TabbedControlsPanel panel, int tabIndex) // Update bindings binding.device = Device; binding.value = KeyCodeUtils.KeyCodeToString(Key); -#if SUBNAUTICA - binding.onValueChanged.RemoveAllListeners(); - var callback = new UnityAction((KeyCode key) => parentOptions.OnKeybindChange(Id, key)); - binding.onValueChanged.AddListener(new UnityAction((string s) => callback?.Invoke(KeyCodeUtils.StringToKeyCode(s)))); -#elif BELOWZERO binding.gameObject.EnsureComponent(); binding.bindingSet = GameInput.BindingSet.Primary; binding.bindCallback = new Action((_, _1, _2, s) => @@ -152,15 +143,11 @@ internal override void AddToPanel(uGUI_TabbedControlsPanel panel, int tabIndex) parentOptions.OnKeybindChange(Id, KeyCodeUtils.StringToKeyCode(s)); binding.RefreshValue(); }); -#endif base.AddToPanel(panel, tabIndex); } -#if BELOWZERO internal class ModBindingTag: MonoBehaviour { }; -#endif - private class BindingOptionAdjust: ModOptionAdjust { diff --git a/SMLHelper/Options/ModOptionTooltip.cs b/SMLHelper/Options/ModOptionTooltip.cs index a113927b..a80cdc80 100644 --- a/SMLHelper/Options/ModOptionTooltip.cs +++ b/SMLHelper/Options/ModOptionTooltip.cs @@ -10,15 +10,11 @@ internal class ModOptionTooltip : MonoBehaviour, ITooltip void Awake() => Destroy(GetComponent()); -#if BELOWZERO public bool showTooltipOnDrag => true; public void GetTooltip(TooltipData tooltip) { tooltip.prefix.Append(Tooltip); } -#else - public void GetTooltip(out string tooltipText, List _) => tooltipText = Tooltip; -#endif } } diff --git a/SMLHelper/Options/ModOptions.cs b/SMLHelper/Options/ModOptions.cs index 6934906f..34837f82 100644 --- a/SMLHelper/Options/ModOptions.cs +++ b/SMLHelper/Options/ModOptions.cs @@ -5,7 +5,7 @@ using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; - using QModManager.API; + using SMLHelper.V2.Utility; /// /// Abstract class that provides the framework for your mod's in-game configuration options. @@ -114,13 +114,13 @@ internal void SetParent(ModOptions parent) if (parentOptions == null) parentOptions = parent; else - V2.Logger.Log($"ModOption.SetParent: parent already setted for {Id}", LogLevel.Warn); + V2.Utility.InternalLogger.Log($"ModOption.SetParent: parent already setted for {Id}", LogLevel.Warn); } // adds UI GameObject to panel and updates OptionGameObject internal virtual void AddToPanel(uGUI_TabbedControlsPanel panel, int tabIndex) { - if (isNeedAdjusting && AdjusterComponent != null) + if (AdjusterComponent != null) OptionGameObject.AddComponent(AdjusterComponent); parentOptions.OnGameObjectCreated(Id, OptionGameObject); @@ -137,9 +137,6 @@ internal ModOption(string label, string id) Id = id; } - // if ModsOptionsAdjusted mod is active, we don't add adjuster components - internal static readonly bool isNeedAdjusting = (QModServices.Main.FindModById("ModsOptionsAdjusted")?.Enable != true); - // type of component derived from ModOptionAdjust (for using in base.AddToPanel) internal abstract Type AdjusterComponent { get; } @@ -166,7 +163,7 @@ protected void SetCaptionGameObject(string gameObjectPath, float minWidth = 0f) if (!caption) { - V2.Logger.Log($"ModOptionAdjust: caption gameobject '{gameObjectPath}' not found", LogLevel.Warn); + V2.Utility.InternalLogger.Log($"ModOptionAdjust: caption gameobject '{gameObjectPath}' not found", LogLevel.Warn); return; } diff --git a/SMLHelper/Options/SliderModOption.cs b/SMLHelper/Options/SliderModOption.cs index f18c6b3b..19480485 100644 --- a/SMLHelper/Options/SliderModOption.cs +++ b/SMLHelper/Options/SliderModOption.cs @@ -7,11 +7,8 @@ using UnityEngine; using UnityEngine.UI; using UnityEngine.Events; -#if SUBNAUTICA - using Text = UnityEngine.UI.Text; -#elif BELOWZERO - using Text = TMPro.TextMeshProUGUI; -#endif + using TMPro; + using SMLHelper.V2.Utility; /// /// Contains all the information about a slider changed event. @@ -147,52 +144,22 @@ public class ModSliderOption : ModOption private SliderValue sliderValue = null; -#if !BELOWZERO - private float previousValue; -#endif internal override void AddToPanel(uGUI_TabbedControlsPanel panel, int tabIndex) { -#if BELOWZERO UnityAction callback = new UnityAction((value) => parentOptions.OnSliderChange(Id, sliderValue?.ConvertToDisplayValue(value) ?? value)); -#else - UnityAction callback = new UnityAction((value) => - { - value = sliderValue?.ConvertToDisplayValue(value) ?? value; - if (value != previousValue) - { - previousValue = value; - parentOptions.OnSliderChange(Id, value); - } - }); -#endif -#if SUBNAUTICA - panel.AddSliderOption(tabIndex, Label, Value, MinValue, MaxValue, DefaultValue, callback); -#elif BELOWZERO panel.AddSliderOption(tabIndex, Label, Value, MinValue, MaxValue, DefaultValue, Step, callback, SliderLabelMode.Default, "0.0"); -#endif // AddSliderOption for some reason doesn't return created GameObject, so we need this little hack Transform options = panel.tabs[tabIndex].container.transform; OptionGameObject = options.GetChild(options.childCount - 1).gameObject; // last added game object -#if BELOWZERO // if we using custom value format, we need to replace vanilla uGUI_SliderWithLabel with our component if (ValueFormat != null) OptionGameObject.transform.Find("Slider").gameObject.AddComponent().ValueFormat = ValueFormat; // fixing tooltip for slider - OptionGameObject.transform.Find("Slider/Caption").GetComponent().raycastTarget = true; -#else - // if we using custom value format or step, we need to replace vanilla uGUI_SliderWithLabel with our component - if (ValueFormat != null || Step >= Mathf.Epsilon) - { - var sliderValue = OptionGameObject.transform.Find("Slider").gameObject.AddComponent(); - sliderValue.Step = Step; - if (ValueFormat != null) - sliderValue.ValueFormat = ValueFormat; - } -#endif + OptionGameObject.transform.Find("Slider/Caption").GetComponent().raycastTarget = true; base.AddToPanel(panel, tabIndex); @@ -231,7 +198,7 @@ internal ModSliderOption(string id, string label, float minValue, float maxValue public class SliderValue : MonoBehaviour { /// The value label of the - protected Text label; + protected TextMeshProUGUI label; /// The slider controlling this protected Slider slider; @@ -308,7 +275,7 @@ bool _isOverrided(string methodName) Destroy(sliderLabel); } else - V2.Logger.Log("uGUI_SliderWithLabel not found", LogLevel.Error); + V2.Utility.InternalLogger.Log("uGUI_SliderWithLabel not found", LogLevel.Error); if (GetComponent() is uGUI_SnappingSlider snappingSlider) { @@ -327,7 +294,7 @@ bool _isOverrided(string methodName) } } else - V2.Logger.Log("uGUI_SnappingSlider not found", LogLevel.Error); + V2.Utility.InternalLogger.Log("uGUI_SnappingSlider not found", LogLevel.Error); slider.onValueChanged.AddListener(new UnityAction(OnValueChanged)); UpdateLabel(); @@ -347,12 +314,12 @@ protected virtual IEnumerator UpdateValueWidth() tempLabel.AddComponent().horizontalFit = ContentSizeFitter.FitMode.PreferredSize; // we'll add formatted min value to the label and skip one frame for updating ContentSizeFitter - tempLabel.GetComponent().text = string.Format(valueFormat, minValue); + tempLabel.GetComponent().text = string.Format(valueFormat, minValue); yield return null; float widthForMin = tempLabel.GetComponent().rect.width; // same for max value - tempLabel.GetComponent().text = string.Format(valueFormat, maxValue); + tempLabel.GetComponent().text = string.Format(valueFormat, maxValue); yield return null; float widthForMax = tempLabel.GetComponent().rect.width; @@ -376,11 +343,7 @@ protected virtual void UpdateLabel() private class SliderOptionAdjust : ModOptionAdjust { -#if SUBNAUTICA - private const string sliderBackground = "Slider/Background"; -#elif BELOWZERO private const string sliderBackground = "Slider/Slider/Background"; -#endif private const float spacing_MainMenu = 30f; private const float spacing_GameMenu = 10f; private const float valueSpacing = 15f; // used in game menu diff --git a/SMLHelper/Options/Utility/Validator.cs b/SMLHelper/Options/Utility/Validator.cs index ede44c04..3ebac0c3 100644 --- a/SMLHelper/Options/Utility/Validator.cs +++ b/SMLHelper/Options/Utility/Validator.cs @@ -1,6 +1,7 @@ namespace SMLHelper.V2.Options.Utility { using System.Text.RegularExpressions; + using SMLHelper.V2.Utility; internal static class Validator { @@ -8,17 +9,17 @@ internal static bool ValidateChoiceOrDropdownOption(string id, string label, str { if (!ValidateID(id, out string result)) { - Logger.Log($"There was an error while trying to add choice option with id: {id}. {result}", LogLevel.Error); + InternalLogger.Log($"There was an error while trying to add choice option with id: {id}. {result}", LogLevel.Error); return false; } if (!ValidateLabel(label, out result)) { - Logger.Log($"There was an error while trying to add choice option with id: {id}. {result}", LogLevel.Error); + InternalLogger.Log($"There was an error while trying to add choice option with id: {id}. {result}", LogLevel.Error); return false; } if (!ValidateArray(options, index, out result)) { - Logger.Log($"There was an error while trying to add choice option with id: {id}. {result}", LogLevel.Error); + InternalLogger.Log($"There was an error while trying to add choice option with id: {id}. {result}", LogLevel.Error); return false; } return true; diff --git a/SMLHelper/Patchers/BioReactorPatcher.cs b/SMLHelper/Patchers/BioReactorPatcher.cs index 2aecd025..842f4057 100644 --- a/SMLHelper/Patchers/BioReactorPatcher.cs +++ b/SMLHelper/Patchers/BioReactorPatcher.cs @@ -1,6 +1,7 @@ namespace SMLHelper.V2.Patchers { using System.Collections.Generic; + using SMLHelper.V2.Utility; internal class BioReactorPatcher { @@ -12,7 +13,7 @@ internal static void Patch() // See README.md for details. PatchUtils.PatchDictionary(BaseBioReactor.charge, CustomBioreactorCharges); - Logger.Log("BaseBioReactorPatcher is done.", LogLevel.Debug); + InternalLogger.Log("BaseBioReactorPatcher is done.", LogLevel.Debug); } } } diff --git a/SMLHelper/Patchers/ConsoleCommandsPatcher.cs b/SMLHelper/Patchers/ConsoleCommandsPatcher.cs index 0c974942..1331be36 100644 --- a/SMLHelper/Patchers/ConsoleCommandsPatcher.cs +++ b/SMLHelper/Patchers/ConsoleCommandsPatcher.cs @@ -1,15 +1,17 @@ -namespace SMLHelper.V2.Patchers +using SMLHelper.V2.Utility; + +namespace SMLHelper.V2.Patchers { using Commands; using System; using System.Collections.Generic; using HarmonyLib; - using QModManager.API; using System.Reflection; using System.Linq; using System.Text.RegularExpressions; using UnityEngine; - using Logger = Logger; + using InternalLogger = InternalLogger; + using SMLHelper.V2.Utility; internal static class ConsoleCommandsPatcher { @@ -25,7 +27,7 @@ internal static class ConsoleCommandsPatcher public static void Patch(Harmony harmony) { harmony.PatchAll(typeof(ConsoleCommandsPatcher)); - Logger.Debug("ConsoleCommandsPatcher is done."); + InternalLogger.Debug("ConsoleCommandsPatcher is done."); } /// @@ -43,8 +45,8 @@ public static void AddCustomCommand(string command, MethodInfo targetMethod, boo if (ConsoleCommands.TryGetValue(consoleCommand.Trigger, out ConsoleCommand alreadyDefinedCommand)) { string error = $"Could not register custom command {GetColoredString(consoleCommand)} for mod " + - $"{GetColoredString(consoleCommand.QMod)}\n" + - $"{GetColoredString(alreadyDefinedCommand.QMod, ModConflictColor)} already registered this command!"; + $"{GetColoredString(consoleCommand.ModName, ModOriginColor)}\n" + + $"{GetColoredString(alreadyDefinedCommand.ModName, ModConflictColor)} already registered this command!"; LogAndAnnounce(error, LogLevel.Error); @@ -55,7 +57,7 @@ public static void AddCustomCommand(string command, MethodInfo targetMethod, boo if (!consoleCommand.HasValidInvoke()) { string error = $"Could not register custom command {GetColoredString(consoleCommand)} for mod " + - $"{GetColoredString(consoleCommand.QMod)}\n" + + $"{GetColoredString(consoleCommand.ModName, ModOriginColor)}\n" + "Target method must be static."; LogAndAnnounce(error, LogLevel.Error); @@ -67,7 +69,7 @@ public static void AddCustomCommand(string command, MethodInfo targetMethod, boo if (!consoleCommand.HasValidParameterTypes()) { string error = $"Could not register custom command {GetColoredString(consoleCommand)} for mod " + - $"{GetColoredString(consoleCommand.QMod)}\n" + + $"{GetColoredString(consoleCommand.ModName, ModOriginColor)}\n" + "The following parameters have unsupported types:\n" + consoleCommand.GetInvalidParameters().Select(param => GetColoredString(param)).Join(delimiter: "\n") + "Supported parameter types:\n" + @@ -128,7 +130,7 @@ private static bool HandleCommand(string input) if (string.IsNullOrWhiteSpace(input)) return false; - Logger.Debug($"Attempting to handle console command: {input}"); + InternalLogger.Debug($"Attempting to handle console command: {input}"); input = input.Trim(); string[] components = input.Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries); @@ -137,7 +139,7 @@ private static bool HandleCommand(string input) if (!ConsoleCommands.TryGetValue(trigger, out ConsoleCommand command)) { - Logger.Debug($"No command listener registered for [{trigger}]."); + InternalLogger.Debug($"No command listener registered for [{trigger}]."); return false; } @@ -178,19 +180,19 @@ private static bool HandleCommand(string input) // Print a message detailing all received parameters. if (parameters.Any()) - Logger.Announce($"Received parameters: {parameters.Join()}", LogLevel.Error, true); + InternalLogger.Announce($"Received parameters: {parameters.Join()}", LogLevel.Error, true); return true; // We've handled the command insofar as we've handled and reported the user error to them. } - Logger.Debug($"Handing command [{trigger}] to [{command.QMod.DisplayName}]..."); + InternalLogger.Debug($"Handing command [{trigger}] to [{command.ModName}]..."); string result = command.Invoke(parsedParameters); // Invoke the command with the parameters parsed from user input. if (!string.IsNullOrEmpty(result)) // If the command has a return, print it. - LogAndAnnounce($"{GetColoredString($"[{command.QMod.DisplayName}]", ModOriginColor)} {result}", LogLevel.Info); + LogAndAnnounce($"{GetColoredString($"[{command.ModName}]", ModOriginColor)} {result}", LogLevel.Info); - Logger.Debug($"Command [{trigger}] handled successfully by [{command.QMod.DisplayName}]."); + InternalLogger.Debug($"Command [{trigger}] handled successfully by [{command.ModName}]."); return true; } @@ -202,18 +204,8 @@ private static bool HandleCommand(string input) /// Log level. private static void LogAndAnnounce(string message, LogLevel level) { - Logger.Announce(message); - Logger.Log(message.StripXML(), level); - } - - private static string GetColoredString(IQMod mod) - { - return GetColoredString(mod, ModOriginColor); - } - - private static string GetColoredString(IQMod mod, Color color) - { - return GetColoredString(mod.DisplayName, color); + InternalLogger.Announce(message); + InternalLogger.Log(message.StripXML(), level); } private static string GetColoredString(ConsoleCommand command) diff --git a/SMLHelper/Patchers/CraftDataPatcher.cs b/SMLHelper/Patchers/CraftDataPatcher.cs index 76861dd0..4027542e 100644 --- a/SMLHelper/Patchers/CraftDataPatcher.cs +++ b/SMLHelper/Patchers/CraftDataPatcher.cs @@ -5,6 +5,7 @@ using Assets; using HarmonyLib; using SMLHelper.V2.Patchers.EnumPatching; + using SMLHelper.V2.Utility; internal partial class CraftDataPatcher { @@ -21,19 +22,19 @@ internal static void AddToCustomGroup(TechGroup group, TechCategory category, Te if (!CraftData.groups.TryGetValue(group, out Dictionary> techGroup)) { // Should never happen, but doesn't hurt to add it. - Logger.Log("Invalid TechGroup!", LogLevel.Error); + InternalLogger.Log("Invalid TechGroup!", LogLevel.Error); return; } if (!techGroup.TryGetValue(category, out List techCategory)) { - Logger.Log($"{group} does not contain {category} as a registered group. Please ensure to register your TechCategory to the TechGroup using the TechCategoryHandler before using the combination.", LogLevel.Error); + InternalLogger.Log($"{group} does not contain {category} as a registered group. Please ensure to register your TechCategory to the TechGroup using the TechCategoryHandler before using the combination.", LogLevel.Error); return; } if(techCategory.Contains(techType)) { - Logger.Log($"\"{techType.AsString():G}\" Already exists at \"{group:G}->{category:G}\", Skipping Duplicate Entry", LogLevel.Debug); + InternalLogger.Log($"\"{techType.AsString():G}\" Already exists at \"{group:G}->{category:G}\", Skipping Duplicate Entry", LogLevel.Debug); return; } @@ -42,13 +43,13 @@ internal static void AddToCustomGroup(TechGroup group, TechCategory category, Te if (index == -1) // Not found { techCategory.Add(techType); - Logger.Log($"Added \"{techType.AsString():G}\" to groups under \"{group:G}->{category:G}\"", LogLevel.Debug); + InternalLogger.Log($"Added \"{techType.AsString():G}\" to groups under \"{group:G}->{category:G}\"", LogLevel.Debug); } else { techCategory.Insert(index + 1, techType); - Logger.Log($"Added \"{techType.AsString():G}\" to groups under \"{group:G}->{category:G}\" after \"{after.AsString():G}\"", LogLevel.Debug); + InternalLogger.Log($"Added \"{techType.AsString():G}\" to groups under \"{group:G}->{category:G}\" after \"{after.AsString():G}\"", LogLevel.Debug); } } @@ -64,7 +65,7 @@ internal static void RemoveFromCustomGroup(TechGroup group, TechCategory categor return; techCategory.Remove(techType); - Logger.Log($"Successfully Removed \"{techType.AsString():G}\" from groups under \"{group:G}->{category:G}\"", LogLevel.Debug); + InternalLogger.Log($"Successfully Removed \"{techType.AsString():G}\" from groups under \"{group:G}->{category:G}\"", LogLevel.Debug); } #endregion @@ -81,7 +82,7 @@ internal static void Patch(Harmony harmony) harmony.Patch(AccessTools.Method(typeof(CraftData), nameof(CraftData.PreparePrefabIDCache)), postfix: new HarmonyMethod(AccessTools.Method(typeof(CraftDataPatcher), nameof(CraftDataPrefabIDCachePostfix)))); - Logger.Log("CraftDataPatcher is done.", LogLevel.Debug); + InternalLogger.Log("CraftDataPatcher is done.", LogLevel.Debug); } private static void CraftDataPrefabIDCachePostfix() diff --git a/SMLHelper/Patchers/CraftDataPatcher_BelowZero.cs b/SMLHelper/Patchers/CraftDataPatcher_BelowZero.cs index beafdee1..e52b05ae 100644 --- a/SMLHelper/Patchers/CraftDataPatcher_BelowZero.cs +++ b/SMLHelper/Patchers/CraftDataPatcher_BelowZero.cs @@ -5,6 +5,7 @@ namespace SMLHelper.V2.Patchers using System.Collections.Generic; using System.Text; using HarmonyLib; + using SMLHelper.V2.Utility; internal partial class CraftDataPatcher { @@ -65,13 +66,13 @@ private static void AddCustomTechDataToOriginalDictionary() if (added.Count > 0) { - Logger.Log($"Added {added.Count} new entries to the TechData.entries dictionary.", LogLevel.Info); + InternalLogger.Log($"Added {added.Count} new entries to the TechData.entries dictionary.", LogLevel.Info); LogEntries("Added the following TechTypes", added); } if (updated.Count > 0) { - Logger.Log($"Updated {updated.Count} existing entries to the TechData.entries dictionary.", LogLevel.Info); + InternalLogger.Log($"Updated {updated.Count} existing entries to the TechData.entries dictionary.", LogLevel.Info); LogEntries("Updated the following TechTypes", updated); } } @@ -84,7 +85,7 @@ private static void LogEntries(string log, List updated) builder.AppendLine($"{updated[i]}"); } - Logger.Log($"{log}:{Environment.NewLine}{builder}", LogLevel.Debug); + InternalLogger.Log($"{log}:{Environment.NewLine}{builder}", LogLevel.Debug); } } } diff --git a/SMLHelper/Patchers/CraftDataPatcher_Subnautica.cs b/SMLHelper/Patchers/CraftDataPatcher_Subnautica.cs index 3654441e..db4e8d64 100644 --- a/SMLHelper/Patchers/CraftDataPatcher_Subnautica.cs +++ b/SMLHelper/Patchers/CraftDataPatcher_Subnautica.cs @@ -2,7 +2,9 @@ namespace SMLHelper.V2.Patchers { using HarmonyLib; + using SMLHelper.V2.Utility; using System.Collections.Generic; + using static RootMotion.FinalIK.InteractionTrigger.Range; internal partial class CraftDataPatcher { @@ -98,17 +100,13 @@ private static void GetUseEatSoundPrefix(TechType techType) { DictionaryPrefix(techType, CustomEatingSounds, CraftData.useEatSound); } - [PatchUtils.Prefix] - [HarmonyPatch(typeof(CraftData), nameof(CraftData.IsInvUseable))] - private static bool IsInvUseablePrefix(TechType techType, ref bool __result) + + [PatchUtils.Postfix] + [HarmonyPatch(typeof(Inventory), nameof(Inventory.GetAllItemActions))] + private static void GetAllItemActionsPostfix(InventoryItem item, ref ItemAction __result) { - if (SurvivalPatcher.InventoryUseables.Contains(techType)) - { - __result = true; - return false; - } - __result = false; - return true; + if (item != null && item.item != null && SurvivalPatcher.InventoryUseables.Contains(item.item.GetTechType())) + __result |= ItemAction.Use; } private static void DictionaryPrefix(TechType techType, IDictionary smlCollection, IDictionary craftDataCollection) @@ -190,7 +188,7 @@ private static void PatchCustomTechData() ITechData smlTechData = CustomTechData[techType]; bool sameData = false; - if (techExists) + if (techExists && smlTechData != null) { sameData = smlTechData.craftAmount == techData.craftAmount && @@ -228,12 +226,12 @@ private static void PatchCustomTechData() var techDataInstance = new CraftData.TechData { _techType = techType, - _craftAmount = smlTechData.craftAmount + _craftAmount = smlTechData?.craftAmount ?? 0 }; var ingredientsList = new CraftData.Ingredients(); - if (smlTechData.ingredientCount > 0) + if (smlTechData?.ingredientCount > 0) { for (int i = 0; i < smlTechData.ingredientCount; i++) { @@ -245,7 +243,7 @@ private static void PatchCustomTechData() techDataInstance._ingredients = ingredientsList; } - if (smlTechData.linkedItemCount > 0) + if (smlTechData?.linkedItemCount > 0) { var linkedItems = new List(); for (int l = 0; l < smlTechData.linkedItemCount; l++) @@ -258,7 +256,7 @@ private static void PatchCustomTechData() if (techExists) { CraftData.techData.Remove(techType); - Logger.Log($"{techType} TechType already existed in the CraftData.techData dictionary. Original value was replaced.", LogLevel.Warn); + InternalLogger.Log($"{techType} TechType already existed in the CraftData.techData dictionary. Original value was replaced.", LogLevel.Warn); replaced++; } else @@ -270,10 +268,10 @@ private static void PatchCustomTechData() } if (added > 0) - Logger.Log($"Added {added} new entries to the CraftData.techData dictionary.", LogLevel.Info); + InternalLogger.Log($"Added {added} new entries to the CraftData.techData dictionary.", LogLevel.Debug); if (replaced > 0) - Logger.Log($"Replaced {replaced} existing entries to the CraftData.techData dictionary.", LogLevel.Info); + InternalLogger.Log($"Replaced {replaced} existing entries to the CraftData.techData dictionary.", LogLevel.Debug); } diff --git a/SMLHelper/Patchers/CraftTreePatcher.cs b/SMLHelper/Patchers/CraftTreePatcher.cs index a53dc6aa..3b244c25 100644 --- a/SMLHelper/Patchers/CraftTreePatcher.cs +++ b/SMLHelper/Patchers/CraftTreePatcher.cs @@ -4,6 +4,7 @@ using System.Reflection; using Crafting; using HarmonyLib; + using SMLHelper.V2.Utility; internal class CraftTreePatcher { @@ -22,7 +23,7 @@ internal static void Patch(Harmony harmony) { PatchUtils.PatchClass(harmony); - Logger.Log($"CraftTreePatcher is done.", LogLevel.Debug); + InternalLogger.Log($"CraftTreePatcher is done.", LogLevel.Debug); } [PatchUtils.Prefix] @@ -132,7 +133,7 @@ private static void AddCustomTabs(ref CraftNode nodes, List customTabs, for (int i = 0; i < tab.Path.Length; i++) { string currentPath = tab.Path[i]; - Logger.Log("Tab Current Path: " + currentPath + " Tab: " + tab.Name + " Crafter: " + tab.Scheme.ToString(), LogLevel.Debug); + InternalLogger.Log("Tab Current Path: " + currentPath + " Tab: " + tab.Name + " Crafter: " + tab.Scheme.ToString(), LogLevel.Debug); TreeNode node = currentNode[currentPath]; @@ -198,7 +199,7 @@ private static void RemoveNodes(ref CraftNode nodes, List nodesToRemove, C if (nodeToRemove.Path == null || nodeToRemove.Path.Length == 0) { - Logger.Warn($"An empty path in {nameof(RemoveNodes)} for '{scheme}' was skipped"); + InternalLogger.Warn($"An empty path in {nameof(RemoveNodes)} for '{scheme}' was skipped"); continue; } @@ -224,7 +225,7 @@ private static void RemoveNodes(ref CraftNode nodes, List nodesToRemove, C { if (currentNode.parent == null) { - Logger.Warn($"Skipped removing craft tree node in {nameof(RemoveNodes)} for '{scheme}'. Could not identify the parent node."); + InternalLogger.Warn($"Skipped removing craft tree node in {nameof(RemoveNodes)} for '{scheme}'. Could not identify the parent node."); } else { diff --git a/SMLHelper/Patchers/CustomSoundPatcher.cs b/SMLHelper/Patchers/CustomSoundPatcher.cs index 16b4ba7f..8eb26ff8 100644 --- a/SMLHelper/Patchers/CustomSoundPatcher.cs +++ b/SMLHelper/Patchers/CustomSoundPatcher.cs @@ -1,4 +1,5 @@ using SMLHelper.V2.FMod.Interfaces; +using SMLHelper.V2.Utility; namespace SMLHelper.V2.Patchers { @@ -9,8 +10,8 @@ namespace SMLHelper.V2.Patchers using FMOD.Studio; using Utility; using UnityEngine; - using Logger = Logger; - + using InternalLogger = InternalLogger; + internal class CustomSoundPatcher { internal static readonly SelfCheckingDictionary CustomSounds = new("CustomSounds"); @@ -24,7 +25,7 @@ internal class CustomSoundPatcher internal static void Patch(Harmony harmony) { harmony.PatchAll(typeof(CustomSoundPatcher)); - Logger.Debug("CustomSoundPatcher is done."); + InternalLogger.Debug("CustomSoundPatcher is done."); } [HarmonyPatch(typeof(PDASounds), nameof(PDASounds.Deinitialize))] @@ -35,7 +36,7 @@ public static void PDASounds_Deinitialize_Postfix() PlayedChannels.Clear(); } -#if SUBNAUTICA +#if SUBNAUTICA [HarmonyPatch(typeof(FMODUWE), nameof(FMODUWE.PlayOneShotImpl))] [HarmonyPrefix] @@ -96,11 +97,7 @@ public static bool SoundQueue_Play_Prefix(SoundQueue __instance, string sound, s if (!string.IsNullOrEmpty(subtitles)) { - Subtitles main = Subtitles.main; - if (main) - { - main.Add(subtitles); - } + Subtitles.Add(subtitles); } return false; } @@ -125,11 +122,7 @@ public static bool SoundQueue_Update_Prefix(SoundQueue __instance) if (!SoundQueue.GetIsStartingOrPlaying(__instance.eventInstance)) return true; ATTRIBUTES_3D attributes = Player.main.transform.To3DAttributes(); -#if SUBNAUTICA_STABLE - channel.set3DAttributes(ref attributes.position, ref attributes.velocity, ref attributes.forward); -#elif SUBNAUTICA_EXP channel.set3DAttributes(ref attributes.position, ref attributes.velocity); -#endif channel.getPosition(out var position, TIMEUNIT.MS); __instance._position = (int)position; @@ -609,24 +602,16 @@ public static bool FMOD_CustomLoopingEmitter_OnPlay_Prefix(FMOD_CustomLoopingEmi } #endif - private static void SetChannel3DAttributes(Channel channel, Transform transform) + private static void SetChannel3DAttributes(Channel channel, Transform transform) { var attributes = transform.To3DAttributes(); -#if SUBNAUTICA_STABLE - channel.set3DAttributes(ref attributes.position, ref attributes.velocity, ref attributes.forward); -#else channel.set3DAttributes(ref attributes.position, ref attributes.velocity); -#endif } private static void SetChannel3DAttributes(Channel channel, Vector3 position) { var attributes = position.To3DAttributes(); -#if SUBNAUTICA_STABLE - channel.set3DAttributes(ref attributes.position, ref attributes.velocity, ref attributes.forward); -#else channel.set3DAttributes(ref attributes.position, ref attributes.velocity); -#endif } } } \ No newline at end of file diff --git a/SMLHelper/Patchers/EatablePatcher.cs b/SMLHelper/Patchers/EatablePatcher.cs index 70c5a140..be9ab9a5 100644 --- a/SMLHelper/Patchers/EatablePatcher.cs +++ b/SMLHelper/Patchers/EatablePatcher.cs @@ -1,6 +1,7 @@ namespace SMLHelper.V2.Patchers { using HarmonyLib; + using SMLHelper.V2.Utility; using System.Collections.Generic; using static Handlers.EatableHandler; @@ -13,7 +14,7 @@ public static void Patch(Harmony harmony) harmony.Patch(AccessTools.Method(typeof(Eatable), nameof(Eatable.Awake)), new HarmonyMethod(typeof(EatablePatcher), nameof(AwakePrefix))); - Logger.Debug("EatablePatcher is done."); + InternalLogger.Debug("EatablePatcher is done."); } private static void AwakePrefix(Eatable __instance) { diff --git a/SMLHelper/Patchers/EnumPatching/BackgroundTypePatcher.cs b/SMLHelper/Patchers/EnumPatching/BackgroundTypePatcher.cs index fb9bf83a..5760459e 100644 --- a/SMLHelper/Patchers/EnumPatching/BackgroundTypePatcher.cs +++ b/SMLHelper/Patchers/EnumPatching/BackgroundTypePatcher.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using Handlers; + using SMLHelper.V2.Utility; using Utility; internal class BackgroundTypePatcher @@ -28,9 +29,9 @@ internal static CraftData.BackgroundType AddBackgroundType(string name) CraftData.BackgroundType backgroundType = (CraftData.BackgroundType)cache.Index; if(cacheManager.Add(backgroundType, cache.Index, cache.Name)) - Logger.Log($"Successfully added Backgroundtype: '{name}' to Index: '{cache.Index}'", LogLevel.Debug); + InternalLogger.Log($"Successfully added Backgroundtype: '{name}' to Index: '{cache.Index}'", LogLevel.Debug); else - Logger.Log($"Failed adding Backgroundtype: '{name}' to Index: '{cache.Index}', Already Existed!", LogLevel.Warn); + InternalLogger.Log($"Failed adding Backgroundtype: '{name}' to Index: '{cache.Index}', Already Existed!", LogLevel.Warn); return backgroundType; } @@ -63,7 +64,7 @@ private static List PreRegisteredBackgroundTypes() bannedIndices.Add(realEnumValue); } - Logger.Log($"Finished known BackgroundType exclusion. {bannedIndices.Count} IDs were added in ban list.", LogLevel.Info); + InternalLogger.Log($"Finished known BackgroundType exclusion. {bannedIndices.Count} IDs were added in ban list.", LogLevel.Info); return bannedIndices; } @@ -72,9 +73,9 @@ internal static void Patch() { IngameMenuHandler.Main.RegisterOneTimeUseOnSaveEvent(() => cacheManager.SaveCache()); - Logger.Log($"Added {cacheManager.ModdedKeysCount} BackgroundTypes succesfully into the game.", LogLevel.Info); + InternalLogger.Log($"Added {cacheManager.ModdedKeysCount} BackgroundTypes succesfully into the game.", LogLevel.Info); - Logger.Log("BackgroundTypePatcher is done.", LogLevel.Debug); + InternalLogger.Log("BackgroundTypePatcher is done.", LogLevel.Debug); } } } diff --git a/SMLHelper/Patchers/EnumPatching/CraftTreeTypePatcher.cs b/SMLHelper/Patchers/EnumPatching/CraftTreeTypePatcher.cs index 04c867dc..25e1a20e 100644 --- a/SMLHelper/Patchers/EnumPatching/CraftTreeTypePatcher.cs +++ b/SMLHelper/Patchers/EnumPatching/CraftTreeTypePatcher.cs @@ -2,6 +2,7 @@ { using Crafting; using SMLHelper.V2.Handlers; + using SMLHelper.V2.Utility; using System; using System.Collections.Generic; using Utility; @@ -29,9 +30,9 @@ internal static ModCraftTreeRoot CreateCustomCraftTreeAndType(string name, out C craftTreeType = (CraftTree.Type)cache.Index; if(cacheManager.Add(craftTreeType, cache.Index, cache.Name)) - Logger.Log($"Successfully added CraftTree Type: '{name}' to Index: '{cache.Index}'", LogLevel.Debug); + InternalLogger.Log($"Successfully added CraftTree Type: '{name}' to Index: '{cache.Index}'", LogLevel.Debug); else - Logger.Log($"Failed adding CraftTree Type: '{name}' to Index: '{cache.Index}', Already Existed!", LogLevel.Warn); + InternalLogger.Log($"Failed adding CraftTree Type: '{name}' to Index: '{cache.Index}', Already Existed!", LogLevel.Warn); if(!CraftTreePatcher.CustomTrees.TryGetValue(craftTreeType, out var customTreeRoot)) customTreeRoot = new ModCraftTreeRoot(craftTreeType, name); @@ -69,7 +70,7 @@ private static List PreRegisteredCraftTreeTypes() bannedIndices.Add(realEnumValue); } - Logger.Log($"Finished known CraftTreeType exclusion. {bannedIndices.Count} IDs were added in ban list.", LogLevel.Info); + InternalLogger.Log($"Finished known CraftTreeType exclusion. {bannedIndices.Count} IDs were added in ban list.", LogLevel.Info); return bannedIndices; } @@ -78,8 +79,8 @@ internal static void Patch() { IngameMenuHandler.Main.RegisterOneTimeUseOnSaveEvent(() => cacheManager.SaveCache()); - Logger.Log($"Added {cacheManager.ModdedKeysCount} CraftTreeTypes succesfully into the game."); - Logger.Log("CraftTreeTypePatcher is done.", LogLevel.Debug); + InternalLogger.Log($"Added {cacheManager.ModdedKeysCount} CraftTreeTypes succesfully into the game."); + InternalLogger.Log("CraftTreeTypePatcher is done.", LogLevel.Debug); } } } diff --git a/SMLHelper/Patchers/EnumPatching/EnumPatcher.cs b/SMLHelper/Patchers/EnumPatching/EnumPatcher.cs index d88cfd95..76aed00b 100644 --- a/SMLHelper/Patchers/EnumPatching/EnumPatcher.cs +++ b/SMLHelper/Patchers/EnumPatching/EnumPatcher.cs @@ -11,7 +11,7 @@ internal static void Patch(Harmony harmony) { PatchUtils.PatchClass(harmony); - Logger.Log("EnumPatcher is done.", LogLevel.Debug); + InternalLogger.Log("EnumPatcher is done.", LogLevel.Debug); } [PatchUtils.Postfix] diff --git a/SMLHelper/Patchers/EnumPatching/EquipmentTypePatcher.cs b/SMLHelper/Patchers/EnumPatching/EquipmentTypePatcher.cs index f7737be4..cf20ebb8 100644 --- a/SMLHelper/Patchers/EnumPatching/EquipmentTypePatcher.cs +++ b/SMLHelper/Patchers/EnumPatching/EquipmentTypePatcher.cs @@ -28,7 +28,7 @@ private static List PreRegisteredEquipmentTypes() preRegistered.Add(typeCode); } } - Logger.Log($"Finished known EquipmentType exclusion. {preRegistered.Count} IDs were added in ban list."); + InternalLogger.Log($"Finished known EquipmentType exclusion. {preRegistered.Count} IDs were added in ban list."); return preRegistered; } @@ -41,17 +41,17 @@ internal static EquipmentType AddEquipmentType(string name) }; var equipmentType = (EquipmentType) cache.Index; if(cacheManager.Add(equipmentType, cache.Index, cache.Name)) - Logger.Log($"Successfully added EquipmentType: '{name}' to Index: '{cache.Index}'", LogLevel.Debug); + InternalLogger.Log($"Successfully added EquipmentType: '{name}' to Index: '{cache.Index}'", LogLevel.Debug); else - Logger.Log($"Failed adding EquipmentType: '{name}' to Index: '{cache.Index}', Already Existed!", LogLevel.Warn); + InternalLogger.Log($"Failed adding EquipmentType: '{name}' to Index: '{cache.Index}', Already Existed!", LogLevel.Warn); return equipmentType; } internal static void Patch() { IngameMenuHandler.Main.RegisterOneTimeUseOnSaveEvent(() => cacheManager.SaveCache()); - Logger.Log($"Added {cacheManager.ModdedKeysCount} EquipmentTypes succesfully into the game."); - Logger.Log("EquipmentTypePatcher is done.", LogLevel.Debug); + InternalLogger.Log($"Added {cacheManager.ModdedKeysCount} EquipmentTypes succesfully into the game."); + InternalLogger.Log("EquipmentTypePatcher is done.", LogLevel.Debug); } } } diff --git a/SMLHelper/Patchers/EnumPatching/PingTypePatcher.cs b/SMLHelper/Patchers/EnumPatching/PingTypePatcher.cs index 20e3db91..8206914c 100644 --- a/SMLHelper/Patchers/EnumPatching/PingTypePatcher.cs +++ b/SMLHelper/Patchers/EnumPatching/PingTypePatcher.cs @@ -34,7 +34,7 @@ private static List PreRegisteredPingTypes() } } - Logger.Log($"Finished known PingType exclusion. {preRegistered.Count} IDs were added in ban list."); + InternalLogger.Log($"Finished known PingType exclusion. {preRegistered.Count} IDs were added in ban list."); return preRegistered; } @@ -57,11 +57,11 @@ internal static PingType AddPingType(string name, Sprite sprite) if (PingManager.sCachedPingTypeTranslationStrings.valueToString.ContainsKey(pingType) == false) PingManager.sCachedPingTypeTranslationStrings.valueToString.Add(pingType, name); - Logger.Log($"Successfully added PingType: '{name}' to Index: '{cache.Index}'", LogLevel.Debug); + InternalLogger.Log($"Successfully added PingType: '{name}' to Index: '{cache.Index}'", LogLevel.Debug); } else { - Logger.Log($"Failed adding PingType: '{name}' to Index: '{cache.Index}', Already Existed!", LogLevel.Warn); + InternalLogger.Log($"Failed adding PingType: '{name}' to Index: '{cache.Index}', Already Existed!", LogLevel.Warn); } return pingType; } @@ -70,9 +70,9 @@ internal static void Patch() { IngameMenuHandler.Main.RegisterOneTimeUseOnSaveEvent(() => cacheManager.SaveCache()); - Logger.Log($"Added {cacheManager.ModdedKeysCount} PingTypes succesfully into the game."); + InternalLogger.Log($"Added {cacheManager.ModdedKeysCount} PingTypes succesfully into the game."); - Logger.Log("PingTypePatcher is done.", LogLevel.Debug); + InternalLogger.Log("PingTypePatcher is done.", LogLevel.Debug); } } } diff --git a/SMLHelper/Patchers/EnumPatching/TechCategoryPatcher.cs b/SMLHelper/Patchers/EnumPatching/TechCategoryPatcher.cs index 6e5757f7..4ebd86eb 100644 --- a/SMLHelper/Patchers/EnumPatching/TechCategoryPatcher.cs +++ b/SMLHelper/Patchers/EnumPatching/TechCategoryPatcher.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using SMLHelper.V2.Handlers; + using SMLHelper.V2.Utility; using Utility; internal class TechCategoryPatcher @@ -28,9 +29,9 @@ internal static TechCategory AddTechCategory(string name) TechCategory TechCategory = (TechCategory)cache.Index; if(cacheManager.Add(TechCategory, cache.Index, cache.Name)) - Logger.Log($"Successfully added TechCategory: '{name}' to Index: '{cache.Index}'", LogLevel.Debug); + InternalLogger.Log($"Successfully added TechCategory: '{name}' to Index: '{cache.Index}'", LogLevel.Debug); else - Logger.Log($"Failed adding TechCategory: '{name}' to Index: '{cache.Index}', Already Existed!", LogLevel.Warn); + InternalLogger.Log($"Failed adding TechCategory: '{name}' to Index: '{cache.Index}', Already Existed!", LogLevel.Warn); return TechCategory; @@ -64,7 +65,7 @@ private static List PreRegisteredTechCategoryTypes() bannedIndices.Add(realEnumValue); } - Logger.Log($"Finished known TechCategory exclusion. {bannedIndices.Count} IDs were added in ban list.", LogLevel.Info); + InternalLogger.Log($"Finished known TechCategory exclusion. {bannedIndices.Count} IDs were added in ban list.", LogLevel.Info); return bannedIndices; } @@ -73,8 +74,8 @@ internal static void Patch() { IngameMenuHandler.Main.RegisterOneTimeUseOnSaveEvent(() => cacheManager.SaveCache()); - Logger.Log($"Added {cacheManager.ModdedKeysCount} TechCategorys succesfully into the game."); - Logger.Log("TechCategoryPatcher is done.", LogLevel.Debug); + InternalLogger.Log($"Added {cacheManager.ModdedKeysCount} TechCategorys succesfully into the game."); + InternalLogger.Log("TechCategoryPatcher is done.", LogLevel.Debug); } } } diff --git a/SMLHelper/Patchers/EnumPatching/TechGroupPatcher.cs b/SMLHelper/Patchers/EnumPatching/TechGroupPatcher.cs index fe22468a..fbf2ec52 100644 --- a/SMLHelper/Patchers/EnumPatching/TechGroupPatcher.cs +++ b/SMLHelper/Patchers/EnumPatching/TechGroupPatcher.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using HarmonyLib; using SMLHelper.V2.Handlers; + using SMLHelper.V2.Utility; using Utility; internal class TechGroupPatcher @@ -37,11 +38,11 @@ internal static TechGroup AddTechGroup(string name) if (!CraftData.groups.ContainsKey(techGroup)) CraftData.groups[techGroup] = new Dictionary>(); - Logger.Log($"Successfully added TechGroup: '{name}' to Index: '{cache.Index}'", LogLevel.Debug); + InternalLogger.Log($"Successfully added TechGroup: '{name}' to Index: '{cache.Index}'", LogLevel.Debug); } else { - Logger.Log($"Failed adding TechGroup: '{name}' to Index: '{cache.Index}', Already Existed!", LogLevel.Warn); + InternalLogger.Log($"Failed adding TechGroup: '{name}' to Index: '{cache.Index}', Already Existed!", LogLevel.Warn); } @@ -76,7 +77,7 @@ private static List PreRegisteredTechGroupTypes() bannedIndices.Add(realEnumValue); } - Logger.Log($"Finished known TechGroup exclusion. {bannedIndices.Count} IDs were added in ban list.", LogLevel.Info); + InternalLogger.Log($"Finished known TechGroup exclusion. {bannedIndices.Count} IDs were added in ban list.", LogLevel.Info); return bannedIndices; } @@ -85,8 +86,8 @@ internal static void Patch() { IngameMenuHandler.Main.RegisterOneTimeUseOnSaveEvent(() => cacheManager.SaveCache()); - Logger.Log($"Added {cacheManager.ModdedKeysCount} TechGroups succesfully into the game."); - Logger.Log("TechGroupPatcher is done.", LogLevel.Debug); + InternalLogger.Log($"Added {cacheManager.ModdedKeysCount} TechGroups succesfully into the game."); + InternalLogger.Log("TechGroupPatcher is done.", LogLevel.Debug); } } } diff --git a/SMLHelper/Patchers/EnumPatching/TechTypePatcher.cs b/SMLHelper/Patchers/EnumPatching/TechTypePatcher.cs index cad54903..ffbdd4d7 100644 --- a/SMLHelper/Patchers/EnumPatching/TechTypePatcher.cs +++ b/SMLHelper/Patchers/EnumPatching/TechTypePatcher.cs @@ -2,6 +2,7 @@ { using System.Collections.Generic; using SMLHelper.V2.Handlers; + using SMLHelper.V2.Utility; using Utility; internal class TechTypePatcher @@ -44,11 +45,11 @@ internal static TechType AddTechType(string name) TechTypeExtensions.techTypeKeys[techType] = intKey; TechTypeExtensions.keyTechTypes[intKey] = techType; - Logger.Log($"Successfully added Tech Type: '{name}' to Index: '{cache.Index}'", LogLevel.Debug); + InternalLogger.Log($"Successfully added Tech Type: '{name}' to Index: '{cache.Index}'", LogLevel.Debug); } else { - Logger.Log($"Failed adding Tech Type: '{name}' to Index: '{cache.Index}', Already Existed!", LogLevel.Warn); + InternalLogger.Log($"Failed adding Tech Type: '{name}' to Index: '{cache.Index}', Already Existed!", LogLevel.Warn); } return techType; @@ -79,7 +80,7 @@ private static List PreRegisteredTechTypes() } if (bannedIndices.Count > 0) - Logger.Log($"Finished known TechTypes exclusion. {bannedIndices.Count} IDs were added in ban list.", LogLevel.Debug); + InternalLogger.Log($"Finished known TechTypes exclusion. {bannedIndices.Count} IDs were added in ban list.", LogLevel.Debug); return bannedIndices; } @@ -88,9 +89,9 @@ internal static void Patch() { IngameMenuHandler.Main.RegisterOneTimeUseOnSaveEvent(() => cacheManager.SaveCache()); - Logger.Log($"Added {cacheManager.ModdedKeysCount} TechTypes succesfully into the game.", LogLevel.Info); + InternalLogger.Log($"Added {cacheManager.ModdedKeysCount} TechTypes succesfully into the game.", LogLevel.Info); - Logger.Log("TechTypePatcher is done.", LogLevel.Debug); + InternalLogger.Log("TechTypePatcher is done.", LogLevel.Debug); } } } diff --git a/SMLHelper/Patchers/FishPatcher.cs b/SMLHelper/Patchers/FishPatcher.cs index eb31adef..917a5bc9 100644 --- a/SMLHelper/Patchers/FishPatcher.cs +++ b/SMLHelper/Patchers/FishPatcher.cs @@ -1,4 +1,6 @@ -namespace SMLHelper.V2.Patchers +using SMLHelper.V2.Utility; + +namespace SMLHelper.V2.Patchers { using System; using System.Collections; @@ -7,7 +9,7 @@ using SMLHelper.V2.Handlers; using UnityEngine; using UWE; - using Logger = V2.Logger; + using InternalLogger = InternalLogger; using Random = UnityEngine.Random; internal static class FishPatcher @@ -22,7 +24,7 @@ public static void Patch(Harmony harmony) harmony.Patch(AccessTools.Method(typeof(Creature), nameof(Creature.Start)), postfix: new HarmonyMethod(typeof(FishPatcher), nameof(FishPatcher.CreatureStart_Postfix))); - Logger.Debug("CustomFishPatcher is done."); + InternalLogger.Debug("CustomFishPatcher is done."); } private static void CreatureStart_Postfix(Creature __instance) diff --git a/SMLHelper/Patchers/IngameMenuPatcher.cs b/SMLHelper/Patchers/IngameMenuPatcher.cs index 8fd7d70c..81f19626 100644 --- a/SMLHelper/Patchers/IngameMenuPatcher.cs +++ b/SMLHelper/Patchers/IngameMenuPatcher.cs @@ -19,7 +19,7 @@ public static void Patch(Harmony harmony) { harmony.Patch(AccessTools.Method(typeof(IngameMenu), nameof(IngameMenu.CaptureSaveScreenshot)), postfix: new HarmonyMethod(AccessTools.Method(typeof(IngameMenuPatcher), nameof(InvokeSaveEvents)))); - harmony.Patch(AccessTools.Method(typeof(uGUI_SceneLoading), nameof(uGUI_SceneLoading.BeginAsyncSceneLoad)), + harmony.Patch(AccessTools.Method(typeof(MainSceneLoading), nameof(MainSceneLoading.Launch)), postfix: new HarmonyMethod(AccessTools.Method(typeof(IngameMenuPatcher), nameof(InvokeLoadEvents)))); harmony.Patch(AccessTools.Method(typeof(IngameMenu), nameof(IngameMenu.QuitGameAsync)), postfix: new HarmonyMethod(AccessTools.Method(typeof(IngameMenuPatcher), nameof(InvokeQuitEvents)))); @@ -52,19 +52,21 @@ internal static void InvokeSaveEvents() } } - internal static void InvokeLoadEvents(string sceneName) + internal static IEnumerator InvokeLoadEvents(IEnumerator enumerator) { - if (sceneName == "Main") + while (enumerator.MoveNext()) { - OnLoadEvents?.Invoke(); + yield return enumerator.Current; + } - if (oneTimeUseOnLoadEvents.Count > 0) - { - foreach (Action action in oneTimeUseOnLoadEvents) - action.Invoke(); + OnLoadEvents?.Invoke(); + + if (oneTimeUseOnLoadEvents.Count > 0) + { + foreach (Action action in oneTimeUseOnLoadEvents) + action.Invoke(); - oneTimeUseOnLoadEvents.Clear(); - } + oneTimeUseOnLoadEvents.Clear(); } } diff --git a/SMLHelper/Patchers/ItemActionPatcher.cs b/SMLHelper/Patchers/ItemActionPatcher.cs index ed9973d6..0a87b9d8 100644 --- a/SMLHelper/Patchers/ItemActionPatcher.cs +++ b/SMLHelper/Patchers/ItemActionPatcher.cs @@ -1,6 +1,7 @@ namespace SMLHelper.V2.Patchers { using HarmonyLib; + using SMLHelper.V2.Utility; using System; using System.Collections.Generic; using System.Text; @@ -59,13 +60,13 @@ internal static void Patch(Harmony harmony) postfix: new HarmonyMethod(AccessTools.Method(typeof(ItemActionPatcher), nameof(ItemActionPatcher.ItemActions_Postfix)))); if (MiddleClickActions.Count > 0 && LeftClickActions.Count > 0) - Logger.Log($"Added {LeftClickActions.Count} left click actions and {MiddleClickActions.Count} middle click actions."); + InternalLogger.Log($"Added {LeftClickActions.Count} left click actions and {MiddleClickActions.Count} middle click actions."); else if (LeftClickActions.Count > 0) - Logger.Log($"Added {LeftClickActions.Count} left click actions."); + InternalLogger.Log($"Added {LeftClickActions.Count} left click actions."); else if (MiddleClickActions.Count > 0) - Logger.Log($"Added {MiddleClickActions.Count} middle click actions."); + InternalLogger.Log($"Added {MiddleClickActions.Count} middle click actions."); - Logger.Log("ItemActionPatcher is done.", LogLevel.Debug); + InternalLogger.Log("ItemActionPatcher is done.", LogLevel.Debug); } internal static bool OnPointerClick_Prefix(InventoryItem item, int button) diff --git a/SMLHelper/Patchers/ItemsContainerPatcher.cs b/SMLHelper/Patchers/ItemsContainerPatcher.cs index 33b05b46..bc008630 100644 --- a/SMLHelper/Patchers/ItemsContainerPatcher.cs +++ b/SMLHelper/Patchers/ItemsContainerPatcher.cs @@ -21,7 +21,7 @@ internal static void Patch(Harmony harmony) harmony.Patch(AccessTools.Method(typeof(ItemsContainer), nameof(ItemsContainer.NotifyResize)), postfix: new HarmonyMethod(AccessTools.Method(typeof(ItemsContainerPatcher), nameof(ItemsContainerPatcher.NotifyChangeItem_Postfix)))); - Logger.Log($"ItemsContainerPatcher is done.", LogLevel.Debug); + InternalLogger.Log($"ItemsContainerPatcher is done.", LogLevel.Debug); } private static bool HasRoomFor_XY_Prefix(ItemsContainer __instance, int width, int height, ref bool __result, ref Vector2int __state) diff --git a/SMLHelper/Patchers/KnownTechPatcher.cs b/SMLHelper/Patchers/KnownTechPatcher.cs index 2ed2d2db..00133c81 100644 --- a/SMLHelper/Patchers/KnownTechPatcher.cs +++ b/SMLHelper/Patchers/KnownTechPatcher.cs @@ -86,25 +86,20 @@ internal static void InitializePostfix() analysisTech.Add(tech); } - List compoundTech = KnownTech.compoundTech; - IEnumerable compoundTechToAdd = CompoundTech.Values.Where(a => !compoundTech.Any(a2 => a.techType == a2.techType)); - - foreach (KnownTech.CompoundTech tech in compoundTech) - { - foreach (KnownTech.CompoundTech customTech in CompoundTech.Values) - { - tech.dependencies = customTech.dependencies; - } - } - - foreach (KnownTech.CompoundTech tech in compoundTechToAdd) + foreach (KnownTech.CompoundTech customTech in CompoundTech.Values) { - if (tech == null) + if (customTech == null) // Safety check continue; - if (!KnownTech.Contains(tech.techType)) - compoundTech.Add(tech); + // Only add the new compound tech if it isn't unlocked yet + if (!KnownTech.Contains(customTech.techType)) + compoundTech.Add(customTech); + + // If a compound tech already exists, set the dependencies correctly. + var foundTech = compoundTech.Find(tech => tech.techType == customTech.techType); + if (foundTech != null) + foundTech.dependencies = customTech.dependencies; } } } diff --git a/SMLHelper/Patchers/LanguagePatcher.cs b/SMLHelper/Patchers/LanguagePatcher.cs index 4a43e4e1..6ffddd8b 100644 --- a/SMLHelper/Patchers/LanguagePatcher.cs +++ b/SMLHelper/Patchers/LanguagePatcher.cs @@ -6,10 +6,11 @@ using System.Reflection; using System.Text; using HarmonyLib; + using SMLHelper.V2.Utility; internal class LanguagePatcher { - private static readonly string LanguageDir = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Language"); + private static readonly string LanguageDir = Path.Combine(Path.Combine(BepInEx.Paths.ConfigPath, Assembly.GetExecutingAssembly().GetName().Name), "Language"); private static readonly string LanguageOrigDir = Path.Combine(LanguageDir, "Originals"); private static readonly string LanguageOverDir = Path.Combine(LanguageDir, "Overrides"); private const char KeyValueSeparator = ':'; @@ -56,7 +57,7 @@ internal static void Patch(Harmony harmony) harmony.Patch(AccessTools.Method(typeof(Language), nameof(Language.TryGet)), prefix: repatchCheckMethod); harmony.Patch(AccessTools.Method(typeof(Language), nameof(Language.Contains)), prefix: repatchCheckMethod); - Logger.Log("LanguagePatcher is done.", LogLevel.Debug); + InternalLogger.Log("LanguagePatcher is done.", LogLevel.Debug); } private static void WriteOriginalCustomLines() @@ -73,15 +74,15 @@ private static void WriteOriginalCustomLines() if (!FileNeedsRewrite(modKey)) continue; // File is identical to captured lines. No need to rewrite it. - Logger.Log($"Writing original language lines file for {modKey}", LogLevel.Debug); + InternalLogger.Log($"Writing original language lines file for {modKey}", LogLevel.Debug); if (WriteOriginalLinesFile(modKey)) filesWritten++; else - Logger.Log($"Error writing language lines file for {modKey}", LogLevel.Warn); + InternalLogger.Log($"Error writing language lines file for {modKey}", LogLevel.Warn); } if (filesWritten > 0) - Logger.Log($"Updated {filesWritten} of {originalCustomLines.Count} original language files.", LogLevel.Debug); + InternalLogger.Log($"Updated {filesWritten} of {originalCustomLines.Count} original language files.", LogLevel.Debug); } private static bool WriteOriginalLinesFile(string modKey) @@ -116,7 +117,7 @@ private static void ReadOverrideCustomLines() string[] files = Directory.GetFiles(LanguageOverDir); - Logger.Log($"{files.Length} language override files found.", LogLevel.Debug); + InternalLogger.Log($"{files.Length} language override files found.", LogLevel.Debug); if (files.Length == 0) return; @@ -134,7 +135,7 @@ private static void ReadOverrideCustomLines() int overridesApplied = ExtractOverrideLines(modName, languageLines, originalLines); - Logger.Log($"Applied {overridesApplied} language overrides to mod {modName}.", LogLevel.Info); + InternalLogger.Log($"Applied {overridesApplied} language overrides to mod {modName}.", LogLevel.Info); } } @@ -153,13 +154,13 @@ internal static int ExtractOverrideLines(string modName, string[] languageLines, if (split.Length != SplitCount) { - Logger.Log($"Line '{lineIndex}' in language override file for '{modName}' was incorrectly formatted.", LogLevel.Warn); + InternalLogger.Log($"Line '{lineIndex}' in language override file for '{modName}' was incorrectly formatted.", LogLevel.Warn); continue; // Not correctly formatted } if (!originalLines.ContainsKey(key)) { - Logger.Log($"Key '{key}' on line '{lineIndex}' in language override file for '{modName}' did not match an original key.", LogLevel.Warn); + InternalLogger.Log($"Key '{key}' on line '{lineIndex}' in language override file for '{modName}' did not match an original key.", LogLevel.Warn); continue; // Skip keys we don't recognize. } diff --git a/SMLHelper/Patchers/LargeWorldStreamerPatcher.cs b/SMLHelper/Patchers/LargeWorldStreamerPatcher.cs index 69b9b781..cb209548 100644 --- a/SMLHelper/Patchers/LargeWorldStreamerPatcher.cs +++ b/SMLHelper/Patchers/LargeWorldStreamerPatcher.cs @@ -1,8 +1,10 @@ +using SMLHelper.V2.Utility; + namespace SMLHelper.V2.Patchers { using System; using System.Linq; - using Logger = Logger; + using InternalLogger = InternalLogger; using Json.Converters; using System.Collections.Generic; using System.IO; @@ -10,11 +12,7 @@ namespace SMLHelper.V2.Patchers using Handlers; using MonoBehaviours; using UnityEngine; -#if SUBNAUTICA_STABLE - using Oculus.Newtonsoft.Json; -#else using Newtonsoft.Json; -#endif internal class LargeWorldStreamerPatcher { @@ -39,7 +37,7 @@ private static void InitializePostfix() var file = Path.Combine(SaveLoadManager.GetTemporarySavePath(), "CoordinatedSpawnsInitialized.smlhelper"); if (File.Exists(file)) { - Logger.Debug("Coordinated Spawns already been spawned in the current save. Loading Data"); + InternalLogger.Debug("Coordinated Spawns already been spawned in the current save. Loading Data"); using var reader = new StreamReader(file); try @@ -52,7 +50,7 @@ private static void InitializePostfix() } catch (Exception ex) { - Logger.Error($"Failed to load Saved spawn data from {file}\nSkipping static spawning until fixed!\n{ex}"); + InternalLogger.Error($"Failed to load Saved spawn data from {file}\nSkipping static spawning until fixed!\n{ex}"); reader.Close(); return; } @@ -65,7 +63,7 @@ private static void InitializePostfix() } InitializeSpawners(); - Logger.Debug("Coordinated Spawns have been initialized in the current save."); + InternalLogger.Debug("Coordinated Spawns have been initialized in the current save."); } private static void SaveData() @@ -81,7 +79,7 @@ private static void SaveData() } catch (Exception ex) { - Logger.Error($"Failed to save spawn data to {file}\n{ex}"); + InternalLogger.Error($"Failed to save spawn data to {file}\n{ex}"); writer.Close(); } } diff --git a/SMLHelper/Patchers/LootDistributionPatcher.cs b/SMLHelper/Patchers/LootDistributionPatcher.cs index f9f648bb..0aadd55f 100644 --- a/SMLHelper/Patchers/LootDistributionPatcher.cs +++ b/SMLHelper/Patchers/LootDistributionPatcher.cs @@ -1,8 +1,11 @@ -namespace SMLHelper.V2.Patchers +using SMLHelper.V2.Utility; + +namespace SMLHelper.V2.Patchers { using System.Collections.Generic; using HarmonyLib; - using Logger = V2.Logger; + using SMLHelper.V2.Utility; + using InternalLogger = InternalLogger; internal class LootDistributionPatcher { @@ -13,7 +16,7 @@ internal static void Patch(Harmony harmony) harmony.Patch(AccessTools.Method(typeof(LootDistributionData), nameof(LootDistributionData.Initialize)), postfix: new HarmonyMethod(AccessTools.Method(typeof(LootDistributionPatcher), nameof(LootDistributionPatcher.InitializePostfix)))); - Logger.Log("LootDistributionPatcher is done.", LogLevel.Debug); + InternalLogger.Log("LootDistributionPatcher is done.", LogLevel.Debug); } private static void InitializePostfix(LootDistributionData __instance) diff --git a/SMLHelper/Patchers/OptionsPanelPatcher.cs b/SMLHelper/Patchers/OptionsPanelPatcher.cs index 2b9349c0..916365ae 100644 --- a/SMLHelper/Patchers/OptionsPanelPatcher.cs +++ b/SMLHelper/Patchers/OptionsPanelPatcher.cs @@ -10,20 +10,10 @@ using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; - using QModManager.API; - -#if SUBNAUTICA_STABLE - using Oculus.Newtonsoft.Json; -#else using Newtonsoft.Json; -#endif - -#if SUBNAUTICA - using Text = UnityEngine.UI.Text; -#elif BELOWZERO - using Text = TMPro.TextMeshProUGUI; using static SMLHelper.V2.Options.ModKeybindOption; -#endif + using TMPro; + using SMLHelper.V2.Utility; internal class OptionsPanelPatcher { @@ -35,11 +25,7 @@ internal static void Patch(Harmony harmony) { PatchUtils.PatchClass(harmony); PatchUtils.PatchClass(harmony, typeof(ScrollPosKeeper)); - - if (QModServices.Main.FindModById("ModsOptionsAdjusted")?.Enable == true) - V2.Logger.Log("ModOptionsAdjuster is not inited (ModsOptionsAdjusted mod is active)", LogLevel.Warn); - else - PatchUtils.PatchClass(harmony, typeof(ModOptionsHeadingsToggle)); + PatchUtils.PatchClass(harmony, typeof(ModOptionsHeadingsToggle)); } @@ -52,7 +38,6 @@ internal static void AddTab_Postfix(string label, int __result) modsTabIndex = __result; } -#if BELOWZERO [PatchUtils.Prefix] [HarmonyPatch(typeof(uGUI_Binding), nameof(uGUI_Binding.RefreshValue))] internal static bool RefreshValue_Prefix(uGUI_Binding __instance) @@ -64,7 +49,6 @@ internal static bool RefreshValue_Prefix(uGUI_Binding __instance) __instance.UpdateState(); return false; } -#endif [PatchUtils.Postfix] [HarmonyPatch(typeof(uGUI_OptionsPanel), nameof(uGUI_OptionsPanel.AddTabs))] @@ -78,7 +62,7 @@ internal static void AddTabs_Postfix(uGUI_OptionsPanel __instance) for (int i = 0; i < optionsPanel.tabsContainer.childCount; i++) { // Check if they are named "Mods" - var text = optionsPanel.tabsContainer.GetChild(i).GetComponentInChildren(true); + var text = optionsPanel.tabsContainer.GetChild(i).GetComponentInChildren(true); if (text != null && text.text == "Mods") { @@ -96,7 +80,7 @@ internal static void AddTabs_Postfix(uGUI_OptionsPanel __instance) // Maybe this could be split into its own file to handle smlhelper options, or maybe it could be removed alltogether optionsPanel.AddHeading(modsTab, "SMLHelper"); - optionsPanel.AddToggleOption(modsTab, "Enable debug logs", V2.Logger.EnableDebugging, V2.Logger.SetDebugging); + optionsPanel.AddToggleOption(modsTab, "Enable debug logs", Utility.InternalLogger.EnableDebugging, Utility.InternalLogger.SetDebugging); optionsPanel.AddChoiceOption(modsTab, "Extra item info", new string[] { "Mod name (default)", @@ -108,40 +92,6 @@ internal static void AddTabs_Postfix(uGUI_OptionsPanel __instance) modOptions.Values.ForEach(options => options.AddOptionsToPanel(optionsPanel, modsTab)); } -#if SUBNAUTICA_STABLE - // fix for slider, check for zero divider added (in that case just return value unchanged) - // it happens when slider is in pre-awake state, so any given value snaps to default value - [PatchUtils.Transpiler] - [HarmonyPatch(typeof(uGUI_SnappingSlider), nameof(uGUI_SnappingSlider.SnapValue))] - internal static IEnumerable SnapValue_Fix(IEnumerable cins) - { - var list = new List(cins); - - int indexLabel = list.FindIndex(cin => cin.opcode == OpCodes.Starg_S && cin.operand.Equals((byte)1)) + 1; - if (indexLabel == 0 || list[indexLabel].labels.Count == 0) - { - V2.Logger.Log("SnapValue_Fix: indexLabel not found", LogLevel.Warn); - return cins; - } - - int indexToInject = list.FindIndex(cin => cin.opcode == OpCodes.Stloc_1) + 1; - if (indexToInject == 0) - { - V2.Logger.Log("SnapValue_Fix: indexToInject not found", LogLevel.Warn); - return cins; - } - - list.InsertRange(indexToInject, new List - { - new CodeInstruction(OpCodes.Ldloc_1), - new CodeInstruction(OpCodes.Ldc_R4, 0f), - new CodeInstruction(OpCodes.Beq, list[indexLabel].labels[0]) - }); - - return list; - } -#endif - // Class for collapsing/expanding options in 'Mods' tab // Options can be collapsed/expanded by clicking on mod's title or arrow button private static class ModOptionsHeadingsToggle @@ -152,7 +102,7 @@ private enum HeadingState { Collapsed, Expanded }; private static class StoredHeadingStates { - private static readonly string configPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "headings_states.json"); + private static readonly string configPath = Path.Combine(Path.Combine(BepInEx.Paths.ConfigPath, Assembly.GetExecutingAssembly().GetName().Name), "headings_states.json"); private class StatesConfig { @@ -225,7 +175,7 @@ private void Init() if (childOptions != null) return; - headingName = transform.Find("Caption")?.GetComponent()?.text ?? ""; + headingName = transform.Find("Caption")?.GetComponent()?.text ?? ""; childOptions = new List(); diff --git a/SMLHelper/Patchers/PDAEncyclopediaPatcher.cs b/SMLHelper/Patchers/PDAEncyclopediaPatcher.cs index 10b109a4..9279dae5 100644 --- a/SMLHelper/Patchers/PDAEncyclopediaPatcher.cs +++ b/SMLHelper/Patchers/PDAEncyclopediaPatcher.cs @@ -24,12 +24,12 @@ private static void InitializePostfix() if (!mapping.ContainsKey(customEntry.Key)) { mapping.Add(customEntry.Key, customEntry.Value); - Logger.Debug($"Adding PDAEncyclopedia EntryData for Key Value: {customEntry.Key}."); + InternalLogger.Debug($"Adding PDAEncyclopedia EntryData for Key Value: {customEntry.Key}."); } else { mapping[customEntry.Key] = customEntry.Value; - Logger.Debug($"PDAEncyclopedia already Contains EntryData for Key Value: {customEntry.Key}, Overwriting Original."); + InternalLogger.Debug($"PDAEncyclopedia already Contains EntryData for Key Value: {customEntry.Key}, Overwriting Original."); } } } diff --git a/SMLHelper/Patchers/PdaPatcher.cs b/SMLHelper/Patchers/PdaPatcher.cs index dffef972..8f991a9e 100644 --- a/SMLHelper/Patchers/PdaPatcher.cs +++ b/SMLHelper/Patchers/PdaPatcher.cs @@ -19,7 +19,7 @@ internal static void Patch(Harmony harmony) harmony.Patch(AccessTools.Method(typeof(PDAScanner), nameof(PDAScanner.Initialize)), postfix: new HarmonyMethod(AccessTools.Method(typeof(PDAPatcher), nameof(PDAPatcher.InitializePostfix)))); - Logger.Log($"PDAPatcher is done.", LogLevel.Debug); + InternalLogger.Log($"PDAPatcher is done.", LogLevel.Debug); } private static void InitializePostfix() @@ -44,12 +44,12 @@ private static void InitializePostfix() if (!mapping.ContainsKey(customEntry.Key)) { PDAScanner.mapping.Add(customEntry.Key, customEntry.Value); - Logger.Debug($"Adding PDAScanner EntryData for TechType: {customEntry.Key.AsString()}"); + InternalLogger.Debug($"Adding PDAScanner EntryData for TechType: {customEntry.Key.AsString()}"); } else { mapping[customEntry.Key] = customEntry.Value; - Logger.Debug($"PDAScanner already Contains EntryData for TechType: {customEntry.Key.AsString()}, Overwriting Original."); + InternalLogger.Debug($"PDAScanner already Contains EntryData for TechType: {customEntry.Key.AsString()}, Overwriting Original."); } } @@ -66,7 +66,7 @@ private static void InitializePostfix() } else { - Logger.Log($"Warning: TechType {fragmentEntry.Key} not known in PDAScanner.EntryData", LogLevel.Warn); + InternalLogger.Log($"Warning: TechType {fragmentEntry.Key} not known in PDAScanner.EntryData", LogLevel.Warn); } } @@ -83,7 +83,7 @@ private static void InitializePostfix() } else { - Logger.Log($"Warning: TechType {fragmentEntry.Key} not known in PDAScanner.EntryData", LogLevel.Warn); + InternalLogger.Log($"Warning: TechType {fragmentEntry.Key} not known in PDAScanner.EntryData", LogLevel.Warn); } } } diff --git a/SMLHelper/Patchers/PrefabDatabasePatcher.cs b/SMLHelper/Patchers/PrefabDatabasePatcher.cs index ae60d2f0..0a640ebd 100644 --- a/SMLHelper/Patchers/PrefabDatabasePatcher.cs +++ b/SMLHelper/Patchers/PrefabDatabasePatcher.cs @@ -1,4 +1,6 @@ -namespace SMLHelper.V2.Patchers +using SMLHelper.V2.Utility; + +namespace SMLHelper.V2.Patchers { using System; using System.Reflection; @@ -10,7 +12,11 @@ using HarmonyLib; using UnityEngine; using UWE; - using Logger = V2.Logger; + using InternalLogger = InternalLogger; + using SMLHelper.V2.Utility; + using static SMLHelper.V2.PatchUtils; + using static TechStringCache; + using UnityEngine.ResourceManagement.AsyncOperations; internal static class PrefabDatabasePatcher { @@ -42,7 +48,6 @@ internal static bool TryGetPrefabFilename_Prefix(string classId, ref string file return false; } -#if !SUBNAUTICA_STABLE [PatchUtils.Prefix] [HarmonyPatch(typeof(DeferredSpawner.AddressablesTask), nameof(DeferredSpawner.AddressablesTask.SpawnAsync))] internal static bool DeferredSpawner_AddressablesTask_Spawn_Prefix(DeferredSpawner.AddressablesTask __instance, ref IEnumerator __result) @@ -69,20 +74,6 @@ internal static IEnumerator SpawnAsyncReplacement(DeferredSpawner.AddressablesTa task.HandleLateCancelledSpawn(); yield break; } -#endif - -#if SUBNAUTICA_STABLE - [PatchUtils.Prefix] // SUBNAUTICA_EXP TODO: remove for SN after async update - [HarmonyPatch(typeof(PrefabDatabase), "GetPrefabForFilename")] // method can be absent - internal static bool GetPrefabForFilename_Prefix(string filename, ref GameObject __result) - { - if (!ModPrefab.TryGetFromFileName(filename, out ModPrefab prefab)) - return true; - - __result = prefab.GetGameObjectInternal(); - return false; - } -#endif private static IPrefabRequest GetModPrefabAsync(string classId) { @@ -97,7 +88,7 @@ private static IPrefabRequest GetModPrefabAsync(string classId) } catch (Exception e) { - Logger.Debug($"Caught exception while calling GetGameObject for {classId}, trying GetGameObjectAsync now. {Environment.NewLine}{e}"); + InternalLogger.Debug($"Caught exception while calling GetGameObject for {classId}, trying GetGameObjectAsync now. {Environment.NewLine}{e}"); } return new ModPrefabRequest(prefab); @@ -111,6 +102,29 @@ internal static bool GetPrefabAsync_Prefix(ref IPrefabRequest __result, string c return __result == null; } + [PatchUtils.Prefix] + [HarmonyPatch(typeof(AddressablesUtility), nameof(AddressablesUtility.InstantiateAsync), new Type[] + { + typeof(string), typeof(IOut), typeof(Transform), typeof(Vector3), typeof(Quaternion), typeof(bool) + })] + internal static bool InstantiateAsync_Prefix(ref IEnumerator __result,string key, IOut result, Transform parent, Vector3 position, Quaternion rotation, bool awake) + { + if(!ModPrefab.TryGetFromFileName(key, out var prefab)) + return true; + + __result = InstantiateAsync(prefab, result, parent, position, rotation, awake); + return false; + } + + internal static IEnumerator InstantiateAsync(ModPrefab modPrefab, IOut result, Transform parent, Vector3 position, Quaternion rotation, bool awake) + { + TaskResult task = new TaskResult(); + yield return modPrefab.GetGameObjectAsync(task); + + var prefab = task.Get(); + result.Set(GameObject.Instantiate(prefab, parent, position, rotation, awake)); + yield break; + } // transpiler for ProtobufSerializer.DeserializeObjectsAsync private static IEnumerable DeserializeObjectsAsync_Transpiler(IEnumerable cins) @@ -145,21 +159,20 @@ internal static void PrePatch(Harmony harmony) { PatchUtils.PatchClass(harmony); -#if !SUBNAUTICA_STABLE // patching iterator method ProtobufSerializer.DeserializeObjectsAsync MethodInfo DeserializeObjectsAsync = typeof(ProtobufSerializer).GetMethod( nameof(ProtobufSerializer.DeserializeObjectsAsync), BindingFlags.NonPublic | BindingFlags.Instance); harmony.Patch(PatchUtils.GetIteratorMethod(DeserializeObjectsAsync), transpiler: new HarmonyMethod(AccessTools.Method(typeof(PrefabDatabasePatcher), nameof(DeserializeObjectsAsync_Transpiler)))); -#endif - Logger.Log("PrefabDatabasePatcher is done.", LogLevel.Debug); + + InternalLogger.Log("PrefabDatabasePatcher is done.", LogLevel.Debug); } internal static void PostPatch(Harmony harmony) { PatchUtils.PatchClass(harmony, typeof(PostPatches)); - Logger.Log("PrefabDatabasePostPatcher is done.", LogLevel.Debug); + InternalLogger.Log("PrefabDatabasePostPatcher is done.", LogLevel.Debug); } } } diff --git a/SMLHelper/Patchers/SpritePatcher.cs b/SMLHelper/Patchers/SpritePatcher.cs index 3e0d01eb..e77c6433 100644 --- a/SMLHelper/Patchers/SpritePatcher.cs +++ b/SMLHelper/Patchers/SpritePatcher.cs @@ -1,4 +1,6 @@ -namespace SMLHelper.V2.Patchers +using SMLHelper.V2.Utility; + +namespace SMLHelper.V2.Patchers { using System; using System.Collections; @@ -9,7 +11,7 @@ using HarmonyLib; using UnityEngine; using UWE; - using Logger = Logger; + using InternalLogger = InternalLogger; #if SUBNAUTICA using Sprite = Atlas.Sprite; #elif BELOWZERO @@ -64,17 +66,17 @@ private static void PatchSprites() { if (spriteAtlas.ContainsKey(sprite.Key)) { - Logger.Debug($"Overwriting Sprite {sprite.Key} in {nameof(SpriteManager.Group)}.{moddedSpriteGroup.Key}"); + InternalLogger.Debug($"Overwriting Sprite {sprite.Key} in {nameof(SpriteManager.Group)}.{moddedSpriteGroup.Key}"); spriteAtlas[sprite.Key] = sprite.Value; } else { - Logger.Debug($"Adding Sprite {sprite.Key} to {nameof(SpriteManager.Group)}.{moddedSpriteGroup.Key}"); + InternalLogger.Debug($"Adding Sprite {sprite.Key} to {nameof(SpriteManager.Group)}.{moddedSpriteGroup.Key}"); spriteAtlas.Add(sprite.Key, sprite.Value); } } } - Logger.Debug("SpritePatcher is done."); + InternalLogger.Debug("SpritePatcher is done."); } private static bool PatchBackgrounds(CraftData.BackgroundType backgroundType, ref Sprite __result) @@ -91,7 +93,7 @@ private static Dictionary GetSpriteAtlas(SpriteManager.Group gro { if (!SpriteManager.mapping.TryGetValue(groupKey, out string atlasName)) { - Logger.Error($"SpritePatcher was unable to find a sprite mapping for {nameof(SpriteManager.Group)}.{groupKey}"); + InternalLogger.Error($"SpritePatcher was unable to find a sprite mapping for {nameof(SpriteManager.Group)}.{groupKey}"); return null; } #if SUBNAUTICA @@ -102,7 +104,7 @@ private static Dictionary GetSpriteAtlas(SpriteManager.Group gro if (SpriteManager.atlases.TryGetValue(atlasName, out var spriteGroup)) return spriteGroup; #endif - Logger.Error($"SpritePatcher was unable to find a sprite atlas for {nameof(SpriteManager.Group)}.{groupKey}"); + InternalLogger.Error($"SpritePatcher was unable to find a sprite atlas for {nameof(SpriteManager.Group)}.{groupKey}"); return null; } } diff --git a/SMLHelper/Patchers/SurvivalPatcher.cs b/SMLHelper/Patchers/SurvivalPatcher.cs index 546ae020..a2ca6971 100644 --- a/SMLHelper/Patchers/SurvivalPatcher.cs +++ b/SMLHelper/Patchers/SurvivalPatcher.cs @@ -1,10 +1,13 @@ +using SMLHelper.V2.Utility; + namespace SMLHelper.V2.Patchers { using System; using System.Collections.Generic; using HarmonyLib; + using SMLHelper.V2.Utility; using UnityEngine; - using Logger = Logger; + using InternalLogger = InternalLogger; internal class SurvivalPatcher { @@ -19,7 +22,7 @@ internal static void Patch(Harmony harmony) harmony.Patch(AccessTools.Method(typeof(Survival), nameof(Survival.Eat)), postfix: new HarmonyMethod(typeof(SurvivalPatcher), nameof(SurvivalPostfix))); - Logger.Log($"SurvivalPatcher is done.", LogLevel.Debug); + InternalLogger.Log($"SurvivalPatcher is done.", LogLevel.Debug); } private static void SurvivalPostfix(GameObject useObj, ref bool __result) { diff --git a/SMLHelper/Patchers/TooltipPatcher.cs b/SMLHelper/Patchers/TooltipPatcher.cs index af12147a..997996b7 100644 --- a/SMLHelper/Patchers/TooltipPatcher.cs +++ b/SMLHelper/Patchers/TooltipPatcher.cs @@ -1,7 +1,6 @@ namespace SMLHelper.V2.Patchers { using HarmonyLib; - using QModManager.API; using SMLHelper.V2.Handlers; using SMLHelper.V2.Patchers.EnumPatching; using System.IO; @@ -9,6 +8,7 @@ using System.Text; using System.Linq; using System.Collections.Generic; + using SMLHelper.V2.Utility; internal class TooltipPatcher { @@ -21,11 +21,7 @@ internal static void Patch(Harmony harmony) MethodInfo buildTech = AccessTools.Method(typeof(TooltipFactory), nameof(TooltipFactory.BuildTech)); MethodInfo itemCommons = AccessTools.Method(typeof(TooltipFactory), nameof(TooltipFactory.ItemCommons)); -#if BELOWZERO MethodInfo recipe = AccessTools.Method(typeof(TooltipFactory), nameof(TooltipFactory.CraftRecipe)); -#else - MethodInfo recipe = AccessTools.Method(typeof(TooltipFactory), nameof(TooltipFactory.Recipe)); -#endif HarmonyMethod customTooltip = new HarmonyMethod(AccessTools.Method(typeof(TooltipPatcher), nameof(TooltipPatcher.CustomTooltip))); HarmonyMethod techTypePostfix = new HarmonyMethod(AccessTools.Method(typeof(TooltipPatcher), nameof(TooltipPatcher.TechTypePostfix))); @@ -33,7 +29,7 @@ internal static void Patch(Harmony harmony) harmony.Patch(recipe, postfix: techTypePostfix); harmony.Patch(buildTech, postfix: techTypePostfix); - Logger.Log("TooltipPatcher is done.", LogLevel.Debug); + InternalLogger.Log("TooltipPatcher is done.", LogLevel.Debug); } internal static void CustomTooltip(StringBuilder sb, TechType techType) @@ -74,17 +70,7 @@ internal static void WriteModNameFromTechType(StringBuilder sb, TechType type) if (TechTypeHandler.TechTypesAddedBy.TryGetValue(type, out Assembly assembly)) { - string modName = null; - - foreach (IQMod mod in QModServices.Main.GetAllMods()) - { - if (mod == null || mod.LoadedAssembly == null) continue; - if (mod.LoadedAssembly == assembly) - { - modName = mod.DisplayName; - break; - } - } + string modName = assembly.GetName().Name; if (string.IsNullOrEmpty(modName)) { @@ -130,7 +116,7 @@ internal enum ExtraItemInfo internal static void SetExtraItemInfo(ExtraItemInfo value) { - string configPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "ExtraItemInfo.txt"); + string configPath = Path.Combine(Path.Combine(BepInEx.Paths.ConfigPath, Assembly.GetExecutingAssembly().GetName().Name), "ExtraItemInfo.txt"); string text; switch (value) @@ -159,7 +145,7 @@ internal static void Initialize() if (Initialized) return; Initialized = true; - string configPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "ExtraItemInfo.txt"); + string configPath = Path.Combine(Path.Combine(BepInEx.Paths.ConfigPath, Assembly.GetExecutingAssembly().GetName().Name), "ExtraItemInfo.txt"); if (!File.Exists(configPath)) { @@ -175,43 +161,32 @@ internal static void Initialize() { case "Mod name (default)": ExtraItemInfoOption = ExtraItemInfo.ModName; - Logger.Log($"Extra item info set to: {fileContents}", LogLevel.Info); + InternalLogger.Log($"Extra item info set to: {fileContents}", LogLevel.Info); break; case "Mod name and item ID": ExtraItemInfoOption = ExtraItemInfo.ModNameAndItemID; - Logger.Log($"Extra item info set to: {fileContents}", LogLevel.Info); + InternalLogger.Log($"Extra item info set to: {fileContents}", LogLevel.Info); break; case "Nothing": ExtraItemInfoOption = ExtraItemInfo.Nothing; - Logger.Log($"Extra item info set to: {fileContents}", LogLevel.Info); + InternalLogger.Log($"Extra item info set to: {fileContents}", LogLevel.Info); break; default: File.WriteAllText(configPath, "Mod name (default)"); ExtraItemInfoOption = ExtraItemInfo.ModName; - Logger.Log("Error reading ExtraItemInfo.txt configuration file. Defaulted to mod name.", LogLevel.Warn); + InternalLogger.Log("Error reading ExtraItemInfo.txt configuration file. Defaulted to mod name.", LogLevel.Warn); break; } } -#endregion - -#region Patches + #endregion + #region Patches -#if SUBNAUTICA - internal static void TechTypePostfix(TechType techType, ref string tooltipText) - { - StringBuilder stringBuilder = new StringBuilder(tooltipText); - - CustomTooltip(stringBuilder, techType); - tooltipText = stringBuilder.ToString(); - } -#elif BELOWZERO internal static void TechTypePostfix(TechType techType, TooltipData data) { CustomTooltip(data.prefix, techType); } -#endif #endregion } } diff --git a/SMLHelper/SMLHelper.csproj b/SMLHelper/SMLHelper.csproj index b949a24d..ebcc2a66 100644 --- a/SMLHelper/SMLHelper.csproj +++ b/SMLHelper/SMLHelper.csproj @@ -57,8 +57,12 @@ $(Dependencies)\Newtonsoft.Json.dll False - - $(Dependencies)\QModInstaller.dll + + $(Dependencies)\Unity.Addressables.dll + False + + + $(Dependencies)\Unity.ResourceManager.dll False @@ -93,21 +97,22 @@ $(Dependencies)\UnityEngine.UIModule.dll False - + $(Dependencies)\Unity.TextMeshPro.dll False - + $(Dependencies)\FMODUnity.dll False - - - - + + $(Dependencies)\Unity.ResourceManager.dll + False + + \ No newline at end of file diff --git a/SMLHelper/ThunderstoreMetadata/BZ.EXP/manifest.json b/SMLHelper/ThunderstoreMetadata/BZ.EXP/manifest.json index 8a6ba169..4e3c0baa 100644 --- a/SMLHelper/ThunderstoreMetadata/BZ.EXP/manifest.json +++ b/SMLHelper/ThunderstoreMetadata/BZ.EXP/manifest.json @@ -1,7 +1,7 @@ { "name": "SMLHelper_BZ_Experimental", - "version_number": "2.14.1", + "version_number": "2.15.0000", "website_url": "https://github.com/SubnauticaModding/SMLHelper/wiki", "description": "SMLHelper is a modding library that helps making mods easier by helping with adding new items, changing items, adding models, sprites, etc.", - "dependencies": [ "Subnautica_Modding-QModManager_BZ_Experimental-4.4.2" ] + "dependencies": [ "Subnautica_Modding-BepInExPack-5.4.2101" ] } \ No newline at end of file diff --git a/SMLHelper/ThunderstoreMetadata/BZ.STABLE/manifest.json b/SMLHelper/ThunderstoreMetadata/BZ.STABLE/manifest.json index 8a4a98db..d0349492 100644 --- a/SMLHelper/ThunderstoreMetadata/BZ.STABLE/manifest.json +++ b/SMLHelper/ThunderstoreMetadata/BZ.STABLE/manifest.json @@ -1,7 +1,7 @@ { "name": "SMLHelper_BZ", - "version_number": "2.14.1", + "version_number": "2.15.0000", "website_url": "https://github.com/SubnauticaModding/SMLHelper/wiki", "description": "SMLHelper is a modding library that helps making mods easier by helping with adding new items, changing items, adding models, sprites, etc.", - "dependencies": [ "Subnautica_Modding-QModManager_BZ-4.4.2" ] + "dependencies": [ "Subnautica_Modding-BepInExPack-5.4.2101" ] } \ No newline at end of file diff --git a/SMLHelper/ThunderstoreMetadata/SN.EXP/manifest.json b/SMLHelper/ThunderstoreMetadata/SN.EXP/manifest.json index 56113f4c..d764c81b 100644 --- a/SMLHelper/ThunderstoreMetadata/SN.EXP/manifest.json +++ b/SMLHelper/ThunderstoreMetadata/SN.EXP/manifest.json @@ -1,7 +1,7 @@ { - "name": "SMLHelper_Experimental", - "version_number": "2.14.1", - "website_url": "https://github.com/SubnauticaModding/SMLHelper/wiki", - "description": "SMLHelper is a modding library that helps making mods easier by helping with adding new items, changing items, adding models, sprites, etc.", - "dependencies": [ "Subnautica_Modding-QModManager_Experimental-4.4.2" ] + "name": "SMLHelper_Experimental", + "version_number": "2.15.0000", + "website_url": "https://github.com/SubnauticaModding/SMLHelper/wiki", + "description": "SMLHelper is a modding library that helps making mods easier by helping with adding new items, changing items, adding models, sprites, etc.", + "dependencies": [ "Subnautica_Modding-BepInExPack-5.4.2101" ] } \ No newline at end of file diff --git a/SMLHelper/ThunderstoreMetadata/SN.STABLE/manifest.json b/SMLHelper/ThunderstoreMetadata/SN.STABLE/manifest.json index a4605cc2..daf2aab7 100644 --- a/SMLHelper/ThunderstoreMetadata/SN.STABLE/manifest.json +++ b/SMLHelper/ThunderstoreMetadata/SN.STABLE/manifest.json @@ -1,7 +1,7 @@ { "name": "SMLHelper", - "version_number": "2.14.1", + "version_number": "2.15.0000", "website_url": "https://github.com/SubnauticaModding/SMLHelper/wiki", "description": "SMLHelper is a modding library that helps making mods easier by helping with adding new items, changing items, adding models, sprites, etc.", - "dependencies": [ "Subnautica_Modding-QModManager-4.4.0" ] + "dependencies": [ "Subnautica_Modding-BepInExPack-5.4.2101" ] } \ No newline at end of file diff --git a/SMLHelper/Utility/AudioUtils.cs b/SMLHelper/Utility/AudioUtils.cs index 1c6ebc84..47ba6fb8 100644 --- a/SMLHelper/Utility/AudioUtils.cs +++ b/SMLHelper/Utility/AudioUtils.cs @@ -15,11 +15,8 @@ namespace SMLHelper.V2.Utility /// public static partial class AudioUtils { -#if SUBNAUTICA_STABLE - private static System FMOD_System => RuntimeManager.LowlevelSystem; -#else private static System FMOD_System => RuntimeManager.CoreSystem; -#endif + /// /// Creates a instance from a path. Can be stored and later used with /// diff --git a/SMLHelper/Utility/BasicText.cs b/SMLHelper/Utility/BasicText.cs index a8e64266..04c185f3 100644 --- a/SMLHelper/Utility/BasicText.cs +++ b/SMLHelper/Utility/BasicText.cs @@ -1,12 +1,7 @@ using UnityEngine; using UnityEngine.UI; using SMLHelper.V2.Interfaces; - -#if BELOWZERO -using Text = TMPro.TextMeshProUGUI; -using Font = TMPro.TMP_FontAsset; -using FontStyle = TMPro.FontStyles; -#endif +using TMPro; namespace SMLHelper.V2.Utility { @@ -67,7 +62,7 @@ public BasicText(int set_x, int set_y) : this() /// Creates a new instances of at a specified . /// /// The text anchor to align to - public BasicText(TextAnchor useAlign) : this() + public BasicText(TextAlignmentOptions useAlign) : this() { CloneAlign = false; Align = useAlign; @@ -111,7 +106,7 @@ public BasicText(int useSize, Color useColor) : this() /// /// The text size to use /// The text anchor to align to - public BasicText(int useSize, TextAnchor useAlign) : this() + public BasicText(int useSize, TextAlignmentOptions useAlign) : this() { CloneAlign = false; Align = useAlign; @@ -125,7 +120,7 @@ public BasicText(int useSize, TextAnchor useAlign) : this() /// The text size to use /// The text color to use /// The text anchor to align to - public BasicText(int useSize, Color useColor, TextAnchor useAlign) : this() + public BasicText(int useSize, Color useColor, TextAlignmentOptions useAlign) : this() { CloneAlign = false; Align = useAlign; @@ -143,7 +138,7 @@ public BasicText(int useSize, Color useColor, TextAnchor useAlign) : this() /// The text size to use /// The text color to use /// The text anchor to align to - public BasicText(int set_x, int set_y, int useSize, Color useColor, TextAnchor useAlign) : this() + public BasicText(int set_x, int set_y, int useSize, Color useColor, TextAlignmentOptions useAlign) : this() { X = set_x; Y = set_y; @@ -317,7 +312,7 @@ public void ClearSize() /// Sets the font /// /// The font to render the text as. - public void SetFont(Font useFont) + public void SetFont(TMP_FontAsset useFont) { CloneFont = false; Font = useFont; @@ -345,7 +340,7 @@ public void ClearFont() /// Sets the font style. /// /// The text font style to use - public void SetFontStyle(FontStyle useStyle) + public void SetFontStyle(FontStyles useStyle) { CloneStyle = false; Style = useStyle; @@ -372,17 +367,13 @@ public void ClearFontStyle() /// Sets the text anchor. /// /// The text anchor to align to - public void SetAlign(TextAnchor useAlign) + public void SetAlign(TextAlignmentOptions useAlign) { CloneAlign = false; Align = useAlign; if (TextObject != null) { -#if SUBNAUTICA TextText.alignment = Align; -#elif BELOWZERO - TextText.alignment = Convert(Align); -#endif DoAlignment(); } } @@ -417,15 +408,15 @@ private void DoAlignment() switch (Align) { - case TextAnchor.UpperLeft: - case TextAnchor.MiddleLeft: - case TextAnchor.LowerLeft: + case TextAlignmentOptions.TopLeft: + case TextAlignmentOptions.Left: + case TextAlignmentOptions.BottomLeft: displayX = X + width / 2; break; - case TextAnchor.UpperRight: - case TextAnchor.MiddleRight: - case TextAnchor.LowerRight: + case TextAlignmentOptions.TopRight: + case TextAlignmentOptions.Right: + case TextAlignmentOptions.BottomRight: displayX = X - width / 2; break; @@ -436,15 +427,15 @@ private void DoAlignment() switch (Align) { - case TextAnchor.UpperLeft: - case TextAnchor.UpperCenter: - case TextAnchor.UpperRight: + case TextAlignmentOptions.TopLeft: + case TextAlignmentOptions.Top: + case TextAlignmentOptions.TopRight: displayY = Y - height / 2; break; - case TextAnchor.LowerLeft: - case TextAnchor.LowerCenter: - case TextAnchor.LowerRight: + case TextAlignmentOptions.BottomLeft: + case TextAlignmentOptions.Bottom: + case TextAlignmentOptions.BottomRight: displayY = Y + height / 2; break; @@ -464,7 +455,7 @@ private void InitializeText() // Make our own text object TextObject = new GameObject("BasicText" + (++index)); TextFade = TextObject.EnsureComponent(); // The uGUI's helpful automatic fade component - TextText = TextFade?.text ?? TextObject.EnsureComponent(); // The text itself + TextText = TextFade?.text ?? TextObject.EnsureComponent(); // The text itself // This makes the text box fit the text (rather than the other way around) TextFitter = TextObject.EnsureComponent(); @@ -475,11 +466,7 @@ private void InitializeText() TextText.font = CloneFont ? uGUI.main.intro.mainText.text.font : Font; TextText.fontSize = CloneSize ? uGUI.main.intro.mainText.text.fontSize : Size; TextText.fontStyle = CloneStyle ? uGUI.main.intro.mainText.text.fontStyle : Style; -#if SUBNAUTICA TextText.alignment = CloneAlign ? uGUI.main.intro.mainText.text.alignment : Align; -#elif BELOWZERO - TextText.alignment = CloneAlign ? uGUI.main.intro.mainText.text.alignment : Convert(Align); -#endif TextText.color = CloneColor ? uGUI.main.intro.mainText.text.color : Color; TextText.material = CloneMaterial ? uGUI.main.intro.mainText.text.material : Material; @@ -499,46 +486,18 @@ private void InitializeText() internal bool CloneFont { get; set; } // True if we're cloning Subnautica's "Press Any Button To Begin" font internal bool CloneStyle { get; set; } // True if we're cloning Subnautica's "Press Any Button To Begin" font style internal bool CloneMaterial { get; set; } // True if we're cloning Subnautica's "Press Any Button To Begin" material - internal TextAnchor Align { get; set; } // text alignment + internal TextAlignmentOptions Align { get; set; } // text alignment internal Color Color { get; set; } // text color internal int Size { get; set; } // text size - internal Font Font { get; set; } // text font - internal FontStyle Style { get; set; } // text font style + internal TMP_FontAsset Font { get; set; } // text font + internal FontStyles Style { get; set; } // text font style internal Material Material { get; set; } // text material internal GameObject TextObject { get; set; } = null; // Our game object internal uGUI_TextFade TextFade { get; set; } = null; // Our text fader - internal Text TextText { get; set; } = null; // Our text object + internal TextMeshProUGUI TextText { get; set; } = null; // Our text object internal ContentSizeFitter TextFitter { get; set; } = null; // Our content size fitter internal static int index = 0; // For giving unique names to the game objects -#if BELOWZERO - private static TMPro.TextAlignmentOptions Convert(TextAnchor textAnchor) - { - switch (textAnchor) - { - case TextAnchor.UpperLeft: - return TMPro.TextAlignmentOptions.TopLeft; - case TextAnchor.UpperCenter: - return TMPro.TextAlignmentOptions.Top; - case TextAnchor.UpperRight: - return TMPro.TextAlignmentOptions.TopRight; - case TextAnchor.MiddleLeft: - return TMPro.TextAlignmentOptions.MidlineLeft; - case TextAnchor.MiddleCenter: - return TMPro.TextAlignmentOptions.Midline; - case TextAnchor.MiddleRight: - return TMPro.TextAlignmentOptions.MidlineRight; - case TextAnchor.LowerLeft: - return TMPro.TextAlignmentOptions.BottomLeft; - case TextAnchor.LowerCenter: - return TMPro.TextAlignmentOptions.Bottom; - case TextAnchor.LowerRight: - return TMPro.TextAlignmentOptions.BottomRight; - default: // Fallback case should never happen - return TMPro.TextAlignmentOptions.Center; - } - } -#endif } } diff --git a/SMLHelper/Utility/EnumCacheManager.cs b/SMLHelper/Utility/EnumCacheManager.cs index b4c7970c..7c72a577 100644 --- a/SMLHelper/Utility/EnumCacheManager.cs +++ b/SMLHelper/Utility/EnumCacheManager.cs @@ -27,6 +27,8 @@ internal class EnumCacheManager where T : Enum { private class DoubleKeyDictionary : IEnumerable> { + private readonly Type _underlyingType = Enum.GetUnderlyingType(typeof(T)); + private readonly SortedDictionary MapIntString = new SortedDictionary(); private readonly SortedDictionary MapEnumString = new SortedDictionary(); @@ -53,7 +55,8 @@ public bool TryGetValue(string name, out int backingValue) public void Add(int backingValue, string name) { - Add((T) (object) backingValue, backingValue, name); + var enumValue = (T)Convert.ChangeType(backingValue, _underlyingType); + Add(enumValue, backingValue, name); } public void Add(T enumValue, int backingValue, string name) @@ -69,7 +72,8 @@ public void Add(T enumValue, int backingValue, string name) public void Remove(int backingValue, string name) { - Remove((T) (object) backingValue, backingValue, name); + var enumValue = (T)Convert.ChangeType(backingValue, _underlyingType); + Remove(enumValue, backingValue, name); } public void Remove(T enumValue, int backingValue, string name) @@ -174,7 +178,7 @@ internal EnumCacheManager(string enumTypeName, int startingIndex, IEnumerable loadParsedEnt } catch (Exception exception) { - Logger.Error($"Caught exception while reading {savePathDir}{Environment.NewLine}{exception}"); + InternalLogger.Error($"Caught exception while reading {savePathDir}{Environment.NewLine}{exception}"); } } @@ -256,7 +260,7 @@ internal void SaveCache() } catch (Exception exception) { - Logger.Error($"Caught exception while saving cache!{Environment.NewLine}{exception}"); + InternalLogger.Error($"Caught exception while saving cache!{Environment.NewLine}{exception}"); } } diff --git a/SMLHelper/Utility/ExtBannedIdManager.cs b/SMLHelper/Utility/ExtBannedIdManager.cs index 6ac07567..939c5e75 100644 --- a/SMLHelper/Utility/ExtBannedIdManager.cs +++ b/SMLHelper/Utility/ExtBannedIdManager.cs @@ -15,7 +15,7 @@ internal static class ExtBannedIdManager private static readonly Dictionary> BannedIdDictionary = new Dictionary>(); - private static readonly string BannedIdDirectory = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "RestrictedIDs"); + private static readonly string BannedIdDirectory = Path.Combine(Path.Combine(BepInEx.Paths.ConfigPath, Assembly.GetExecutingAssembly().GetName().Name), "RestrictedIDs"); /// /// Gets the banned ids, reported by the external files, for the specified enum. @@ -110,7 +110,7 @@ private static void LoadFromFiles() foreach (string bannedIdType in BannedIdDictionary.Keys) { - Logger.Log($"{BannedIdDictionary[bannedIdType].Count} retricted IDs were registered for {bannedIdType}.", LogLevel.Info); + InternalLogger.Log($"{BannedIdDictionary[bannedIdType].Count} retricted IDs were registered for {bannedIdType}.", LogLevel.Info); } IsInitialized = true; @@ -121,11 +121,11 @@ private static void CreateBannedIdDirectory() try { Directory.CreateDirectory(BannedIdDirectory); - Logger.Log("RetrictedIDs folder was not found. Folder created.", LogLevel.Debug); + InternalLogger.Log("RetrictedIDs folder was not found. Folder created.", LogLevel.Debug); } catch (Exception ex) { - Logger.Log($"RetrictedIDs folder was not found. Failed to create folder.{Environment.NewLine}" + + InternalLogger.Log($"RetrictedIDs folder was not found. Failed to create folder.{Environment.NewLine}" + $" Exception: {ex}", LogLevel.Error); } @@ -133,7 +133,7 @@ private static void CreateBannedIdDirectory() private static void LogBadEntry(string filePath, string line) { - Logger.Log($"Badly formatted entry for Retricted IDs{Environment.NewLine}" + + InternalLogger.Log($"Badly formatted entry for Retricted IDs{Environment.NewLine}" + $" File: '{filePath}{Environment.NewLine}'" + $" Line: '{line}'{Environment.NewLine}" + $" This entry has been skipped.", LogLevel.Warn); diff --git a/SMLHelper/Utility/ImageUtils.cs b/SMLHelper/Utility/ImageUtils.cs index ecef894f..14e58e6d 100644 --- a/SMLHelper/Utility/ImageUtils.cs +++ b/SMLHelper/Utility/ImageUtils.cs @@ -2,7 +2,7 @@ { using System.IO; using UnityEngine; - using Logger = V2.Logger; + using Logger = InternalLogger; #if SUBNAUTICA using Sprite = Atlas.Sprite; #endif diff --git a/SMLHelper/Logger.cs b/SMLHelper/Utility/InternalLogger.cs similarity index 67% rename from SMLHelper/Logger.cs rename to SMLHelper/Utility/InternalLogger.cs index b81819c0..5d2d5a6c 100644 --- a/SMLHelper/Logger.cs +++ b/SMLHelper/Utility/InternalLogger.cs @@ -1,8 +1,9 @@ -namespace SMLHelper.V2 +namespace SMLHelper.V2.Utility { using System; using System.IO; using System.Reflection; + using BepInEx.Logging; internal enum LogLevel { @@ -12,25 +13,27 @@ internal enum LogLevel Error = 3, } - internal static class Logger + internal static class InternalLogger { internal static bool Initialized = false; + private static ManualLogSource logSource; internal static bool EnableDebugging { get; private set; } internal static void SetDebugging(bool value) { - string configPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "EnableDebugLogs.txt"); + string configPath = Path.Combine(Path.Combine(BepInEx.Paths.ConfigPath, Assembly.GetExecutingAssembly().GetName().Name), "EnableDebugLogs.txt"); File.WriteAllText(configPath, value.ToString()); EnableDebugging = value; } - internal static void Initialize() + internal static void Initialize(ManualLogSource logger) { if (Initialized) return; + logSource = logger; Initialized = true; - string configPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "EnableDebugLogs.txt"); + string configPath = Path.Combine(Path.Combine(BepInEx.Paths.ConfigPath, Assembly.GetExecutingAssembly().GetName().Name), "EnableDebugLogs.txt"); if (!File.Exists(configPath)) { @@ -56,7 +59,7 @@ internal static void Initialize() Log("Error reading EnableDebugLogs.txt configuration file. Defaulted to false", LogLevel.Warn); } } - + internal static void Debug(string text) => Log(text, LogLevel.Debug); internal static void Info(string text) => Log(text, LogLevel.Info); internal static void Warn(string text) => Log(text, LogLevel.Warn); @@ -69,27 +72,40 @@ internal static void Initialize() internal static void Log(string text, LogLevel level = LogLevel.Info) { - Initialize(); + if(!Initialized) + { + if(level >= LogLevel.Info || EnableDebugging) + Console.WriteLine($"[SMLHelper/{level}] {text}"); + return; + } - if (level >= LogLevel.Info || EnableDebugging) - Console.WriteLine($"[SMLHelper/{level}] {text}"); + switch(level) + { + case LogLevel.Debug when EnableDebugging: + logSource.LogDebug(text); + break; + case LogLevel.Info: + logSource.LogInfo(text); + break; + case LogLevel.Warn: + logSource.LogWarning(text); + break; + case LogLevel.Error: + logSource.LogError(text); + break; + } } internal static void Log(string text, LogLevel level = LogLevel.Info, params object[] args) { - Initialize(); - - if (args != null && args.Length > 0) + if(args != null && args.Length > 0) text = string.Format(text, args); - if (level >= LogLevel.Info || EnableDebugging) - Console.WriteLine($"[SMLHelper/{level}] {text}"); + Log(text, level); } internal static void Announce(string text, LogLevel level = LogLevel.Info, bool logToFile = false) { - Initialize(); - ErrorMessage.AddMessage(text); if (logToFile) @@ -98,8 +114,6 @@ internal static void Announce(string text, LogLevel level = LogLevel.Info, bool internal static void Announce(string text, LogLevel level = LogLevel.Info, bool logToFile = false, params object[] args) { - Initialize(); - ErrorMessage.AddMessage(string.Format(text, args)); if (logToFile) diff --git a/SMLHelper/Utility/JsonUtils.cs b/SMLHelper/Utility/JsonUtils.cs index 9d7ba5f5..000e29ae 100644 --- a/SMLHelper/Utility/JsonUtils.cs +++ b/SMLHelper/Utility/JsonUtils.cs @@ -6,11 +6,7 @@ using System.Text; using System.Threading; using System.Reflection; -#if SUBNAUTICA_STABLE - using Oculus.Newtonsoft.Json; -#else using Newtonsoft.Json; -#endif /// /// A collection of utilities for interacting with JSON files. @@ -20,7 +16,7 @@ public static class JsonUtils private static string GetDefaultPath(Assembly assembly) where T : class { return Path.Combine( - Path.GetDirectoryName(assembly.Location), + Path.Combine(BepInEx.Paths.ConfigPath, assembly.GetName().Name), $"{GetName()}.json" ); } @@ -71,9 +67,9 @@ public static T Load(string path = null, bool createFileIfNotExist = true, } catch (Exception ex) { - Logger.Announce($"Could not parse JSON file, loading default values: {path}", LogLevel.Warn, true); - Logger.Error(ex.Message); - Logger.Error(ex.StackTrace); + InternalLogger.Announce($"Could not parse JSON file, loading default values: {path}", LogLevel.Warn, true); + InternalLogger.Error(ex.Message); + InternalLogger.Error(ex.StackTrace); return new T(); } } @@ -125,9 +121,9 @@ public static void Load(T jsonObject, string path = null, bool createFileIfNo } catch (Exception ex) { - Logger.Announce($"Could not parse JSON file, instance values unchanged: {path}", LogLevel.Warn, true); - Logger.Error(ex.Message); - Logger.Error(ex.StackTrace); + InternalLogger.Announce($"Could not parse JSON file, instance values unchanged: {path}", LogLevel.Warn, true); + InternalLogger.Error(ex.Message); + InternalLogger.Error(ex.StackTrace); } } else if (createFileIfNotExist) diff --git a/SMLHelper/Utility/KeyCodeUtils.cs b/SMLHelper/Utility/KeyCodeUtils.cs index ff45e88e..a1c168f2 100644 --- a/SMLHelper/Utility/KeyCodeUtils.cs +++ b/SMLHelper/Utility/KeyCodeUtils.cs @@ -130,7 +130,7 @@ public static KeyCode StringToKeyCode(string s) } catch (Exception) { - V2.Logger.Log($"Failed to parse {s} as a valid KeyCode!", LogLevel.Error); + InternalLogger.Log($"Failed to parse {s} as a valid KeyCode!", LogLevel.Error); return 0; } } diff --git a/SMLHelper/Utility/SelfCheckingDictionary.cs b/SMLHelper/Utility/SelfCheckingDictionary.cs index 842dcf2f..da88bea4 100644 --- a/SMLHelper/Utility/SelfCheckingDictionary.cs +++ b/SMLHelper/Utility/SelfCheckingDictionary.cs @@ -3,6 +3,7 @@ using System; using System.Collections; using System.Collections.Generic; + using SMLHelper.V2.Utility; /// /// This dictionary strtucture automatically checks for duplicate keys as they are being added to the collection. @@ -145,7 +146,7 @@ public void CopyTo(KeyValuePair[] array, int arrayIndex) private void DupFoundAllDiscardedLog(K key) { string keyLogString = ToLogString(key); - Logger.Warn($"{CollectionName} already exists for '{keyLogString}'.{Environment.NewLine}" + + InternalLogger.Warn($"{CollectionName} already exists for '{keyLogString}'.{Environment.NewLine}" + $"All entries will be removed so conflict can be noted and resolved.{Environment.NewLine}" + $"So far we have discarded or overwritten {DuplicatesDiscarded[key]} entries for '{keyLogString}'."); } @@ -157,7 +158,7 @@ private void DupFoundAllDiscardedLog(K key) private void DupFoundLastDiscardedLog(K key) { string keyLogString = ToLogString(key); - Logger.Warn($"{CollectionName} already exists for '{keyLogString}'.{Environment.NewLine}" + + InternalLogger.Warn($"{CollectionName} already exists for '{keyLogString}'.{Environment.NewLine}" + $"Original value has been overwritten by later entry.{Environment.NewLine}" + $"So far we have discarded or overwritten {DuplicatesDiscarded[key]} entries for '{keyLogString}'."); } diff --git a/SMLHelper/mod_BelowZero.json b/SMLHelper/mod_BelowZero.json deleted file mode 100644 index 9094c33e..00000000 --- a/SMLHelper/mod_BelowZero.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "Id": "SMLHelper", - "DisplayName": "SMLHelper", - "Author": "The SMLHelper Dev Team", - "Version": "2.14.1", - "Enable": true, - "Game": "BelowZero", - "AssemblyName": "SMLHelper.dll", - "VersionChecker": { "LatestVersionURL": "https://raw.githubusercontent.com/SubnauticaModding/SMLHelper/master/SMLHelper/mod_BelowZero.json" } -} diff --git a/SMLHelper/mod_Subnautica.json b/SMLHelper/mod_Subnautica.json deleted file mode 100644 index 58160946..00000000 --- a/SMLHelper/mod_Subnautica.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "Id": "SMLHelper", - "DisplayName": "SMLHelper", - "Author": "The SMLHelper Dev Team", - "Version": "2.14.1", - "Enable": true, - "Game": "Subnautica", - "AssemblyName": "SMLHelper.dll", - "VersionChecker": { "LatestVersionURL": "https://raw.githubusercontent.com/SubnauticaModding/SMLHelper/master/SMLHelper/mod_Subnautica.json" }, - "NitroxCompat": true -} diff --git a/Scripts/SMLHelper-post-build.ps1 b/Scripts/SMLHelper-post-build.ps1 index 0b19acd8..ae3b6c23 100644 --- a/Scripts/SMLHelper-post-build.ps1 +++ b/Scripts/SMLHelper-post-build.ps1 @@ -50,15 +50,6 @@ function Zip } } } -# Copy correct mod.json to target dir -$modJsonSuffix = switch ($ConfigurationName.ToUpper()) -{ - {($_ -like "SN*")} { "Subnautica" } - {($_ -like "BZ*")} { "BelowZero" } - default { "Subnautica" } -} -$modJsonFilename = "mod_$($modJsonSuffix).json" -Copy-Item $([System.IO.Path]::Combine($ProjectDir, $modJsonFilename)) -Destination $([System.IO.Path]::Combine($TargetDir, "mod.json")) $buildPath = switch ($ConfigurationName.ToUpper()) { @@ -67,28 +58,30 @@ $buildPath = switch ($ConfigurationName.ToUpper()) default { "Modding Helper" } } -$qmodsDir = [System.IO.Path]::Combine($TargetDir, "QMods") -$buildDir = [System.IO.Path]::Combine($qmodsDir, $buildPath) +$pluginsDir = [System.IO.Path]::Combine($ProjectDir, "bin", $ConfigurationName, "plugins") -# Remove build dir and create fresh -if (Test-Path $buildDir) +# Remove prep dir and create fresh +if (Test-Path $pluginsDir) { - $null = Remove-Item -Path $buildDir -Force -Recurse + $null = Remove-Item -Path $pluginsDir -Force -Recurse } +$null = New-Item -Path $pluginsDir -ItemType "directory" + +$buildDir = [System.IO.Path]::Combine($pluginsDir, $buildPath) $null = New-Item -Path $buildDir -ItemType "directory" # Copy core mod files to build dir -foreach ($file in "mod.json", "SMLHelper.xml", "SMLHelper.dll") +foreach ($file in "SMLHelper.xml", "SMLHelper.dll") { Copy-Item $([System.IO.Path]::Combine($TargetDir, $file)) -Destination $buildDir } # Zip the standard QMod build $buildZipPath = [System.IO.Path]::Combine($TargetDir, "SMLHelper_$($ConfigurationName).zip") -$null = Zip -Path $buildDir -DestinationPath $buildZipPath -Fresh +$null = Zip -Path $pluginsDir -DestinationPath $buildZipPath -Fresh # Zip the Thunderstore build $thunderstoreMetadataPath = [System.IO.Path]::Combine($ProjectDir, "ThunderstoreMetadata", $ConfigurationName, "*") $thunderstoreZipPath = [System.IO.Path]::Combine($TargetDir, "SMLHelper_$($ConfigurationName)_Thunderstore.zip") -$null = Zip -Path $qmodsDir -DestinationPath $thunderstoreZipPath -Fresh +$null = Zip -Path $pluginsDir -DestinationPath $thunderstoreZipPath -Fresh $null = Zip -Path $thunderstoreMetadataPath -DestinationPath $thunderstoreZipPath \ No newline at end of file diff --git a/Version.targets b/Version.targets index abc9878b..2b68597f 100644 --- a/Version.targets +++ b/Version.targets @@ -2,6 +2,6 @@ - 2.14.1 + 2.15.0 \ No newline at end of file diff --git a/nuget.config b/nuget.config new file mode 100644 index 00000000..1864ded5 --- /dev/null +++ b/nuget.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file