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