diff --git a/build/0Harmony.dll b/build/0Harmony.dll
index 72ca2b61..1564f1c5 100644
Binary files a/build/0Harmony.dll and b/build/0Harmony.dll differ
diff --git a/build/0Harmony.xml b/build/0Harmony.xml
deleted file mode 100644
index f1b9b4cf..00000000
--- a/build/0Harmony.xml
+++ /dev/null
@@ -1,3693 +0,0 @@
-
-
-
- 0Harmony
-
-
-
- A factory to create delegate types
-
-
- Default constructor
-
-
- 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 fast invocation handler from a method
- The method to invoke
- Controls if boxed value object is accessed/updated directly
- The
-
-
- The directBoxValueAccess 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.
-
-
-
-
- A low level memory helper
-
-
-
- Mark method for no inlining (currently only works on Mono)
- The method/constructor to change
-
-
-
- Detours a method
- The original method/constructor
- The replacement method/constructor
- An error string
-
-
-
- Writes a jump to memory
- The memory address
- Jump destination
- An error string
-
-
-
- Gets the start of a method in memory
- The method/constructor
- [out] Details of the exception
- The method start address
-
-
-
- special parameter names that can be used in prefix and postfix methods
-
-
- Patch function helpers
-
-
- Sorts patch methods by their priority rules
- The original method
- Patches to sort
- Use debug mode
- The sorted patch methods
-
-
-
- Creates new replacement method with the latest patches and detours the original method
- The original method
- Information describing the patches
- The newly created replacement method
-
-
-
- Creates a patch sorter
- Array of patches that will be sorted
- Use debugging
-
-
- 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
-
-
- 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
-
-
- This targets the MoveNext method of the enumerator result
-
-
- 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 (directly from IL)
-
-
- Use the original as it is right now including previous patches but excluding future ones
-
-
- Specifies the type of method call dispatching mechanics
-
-
-
- Call the method using dynamic dispatching if method is virtual (including overriden)
-
-
- This is the built-in form of late binding (a.k.a. dynamic binding) and is the default dispatching mechanic in C#.
- This directly corresponds with the instruction.
-
-
- For virtual (including overriden) methods, the instance type's most-derived/overriden implementation of the method is called.
- For non-virtual (including static) methods, same behavior as : the exact specified method implementation is called.
-
-
- Note: This is not a fully dynamic dispatch, since non-virtual (including static) methods are still called non-virtually.
- A fully dynamic dispatch in C# involves using
- the dynamic type
- (actually a fully dynamic binding, since even the name and overload resolution happens at runtime), which does not support.
-
-
-
-
- Call the method using static dispatching, regardless of whether method is virtual (including overriden) or non-virtual (including static)
-
-
- a.k.a. non-virtual dispatching, early binding, or static binding.
- This directly corresponds with the instruction.
-
-
- For both virtual (including overriden) and non-virtual (including static) methods, the exact specified method implementation is called, without virtual/override mechanics.
-
-
-
-
- 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/type
-
-
-
- An annotation that specifies a method, property or constructor to patch
- The declaring class/type
- The argument types of the method or constructor to patch
-
-
-
- An annotation that specifies a method, property or constructor to patch
- The declaring class/type
- The name of the method, property or constructor to patch
-
-
-
- An annotation that specifies a method, property or constructor to patch
- The declaring class/type
- 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/type
- The name of the method, property or constructor to patch
- An array of argument types to target overloads
- Array of
-
-
-
- An annotation that specifies a method, property or constructor to patch
- The declaring class/type
- The
-
-
-
- An annotation that specifies a method, property or constructor to patch
- The declaring class/type
- The
- An array of argument types to target overloads
-
-
-
- An annotation that specifies a method, property or constructor to patch
- The declaring class/type
- The
- An array of argument types to target overloads
- Array of
-
-
-
- An annotation that specifies a method, property or constructor to patch
- The declaring class/type
- The name of the method, property or constructor to patch
- The
-
-
-
- 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
-
-
-
- An annotation that specifies a method, property or constructor to patch
- The name of the method, property or constructor to patch
- The
-
-
-
- An annotation that specifies a method, property or constructor to patch
- The
-
-
-
- An annotation that specifies a method, property or constructor to patch
- The
- An array of argument types to target overloads
-
-
-
- An annotation that specifies a method, property or constructor to patch
- The
- An array of argument types to target overloads
- An array of
-
-
-
- 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
-
-
-
- An annotation that specifies a method, property or constructor to patch
- The full name of the declaring class/type
- The name of the method, property or constructor to patch
- The
-
-
-
- Annotation to define the original method for delegate injection
-
-
-
- An annotation that specifies a class to patch
- The declaring class/type
-
-
-
- An annotation that specifies a method, property or constructor to patch
- The declaring class/type
- The argument types of the method or constructor to patch
-
-
-
- An annotation that specifies a method, property or constructor to patch
- The declaring class/type
- The name of the method, property or constructor to patch
-
-
-
- An annotation that specifies a method, property or constructor to patch
- The declaring class/type
- 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/type
- The name of the method, property or constructor to patch
- An array of argument types to target overloads
- Array of
-
-
-
- An annotation that specifies a method, property or constructor to patch
- The declaring class/type
- The
-
-
-
- An annotation that specifies a method, property or constructor to patch
- The declaring class/type
- The
- An array of argument types to target overloads
-
-
-
- An annotation that specifies a method, property or constructor to patch
- The declaring class/type
- The
- An array of argument types to target overloads
- Array of
-
-
-
- An annotation that specifies a method, property or constructor to patch
- The declaring class/type
- The name of the method, property or constructor to patch
- The
-
-
-
- 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
-
-
-
- An annotation that specifies a method, property or constructor to patch
- The name of the method, property or constructor to patch
- The
-
-
-
- An annotation that specifies call dispatching mechanics for the delegate
- The
-
-
-
- An annotation that specifies a method, property or constructor to patch
- The
- An array of argument types to target overloads
-
-
-
- An annotation that specifies a method, property or constructor to patch
- The
- An array of argument types to target overloads
- An array of
-
-
-
- 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
-
-
-
- Annotation to define your standin methods for reverse patching
-
-
-
- An annotation that specifies the type of reverse patching
- The of the reverse patch
-
-
-
- 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 array of harmony IDs of the other patches
-
-
-
- A Harmony annotation
-
-
- A Harmony annotation to define that a patch comes after another patch
- The array of harmony IDs of the other patches
-
-
-
- A Harmony annotation
-
-
- A Harmony annotation to debug a patch (output uses to log to your Desktop)
-
-
-
- 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
-
-
-
- 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 opcode
- The operand
-
-
-
- Create a full copy (including labels and exception blocks) of a CodeInstruction
- The 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 operand
- A copy of this CodeInstruction with a new operand
-
-
-
- Creates a CodeInstruction calling a method (CALL)
- The class/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 code instruction that calls the method matching the arguments
-
-
-
- Creates a CodeInstruction calling a method (CALL)
- The target method in the form TypeFullName:MethodName, where the type name matches a form recognized by Type.GetType like Some.Namespace.Type.
- Optional parameters to target a specific overload of the method
- Optional list of types that define the generic version of the method
- A code instruction that calls the method matching the arguments
-
-
-
- Creates a CodeInstruction calling a method (CALL)
- The lambda expression using the method
-
-
-
-
- Creates a CodeInstruction calling a method (CALL)
- The lambda expression using the method
-
-
-
-
- Creates a CodeInstruction calling a method (CALL)
- The lambda expression using the method
-
-
-
-
- Creates a CodeInstruction calling a method (CALL)
- The lambda expression using the method
-
-
-
-
- Returns an instruction to call the specified closure
- The delegate type to emit
- The closure that defines the method to call
- A that calls the closure as a method
-
-
-
- Creates a CodeInstruction loading a field (LD[S]FLD[A])
- The class/type where the field is defined
- The name of the field (case sensitive)
- Use address of field
-
-
-
- Creates a CodeInstruction storing to a field (ST[S]FLD)
- The class/type where the field is defined
- The name of the field (case sensitive)
-
-
-
- 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 (currently not supported to use in a patch)
-
-
-
- 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
- The
- The catch type
-
-
-
- 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 or use an environment variable to set HARMONY_DEBUG to '1' like this: cmd /C "set HARMONY_DEBUG=1 && game.exe"
- This is for full debugging. To debug only specific patches, use the attribute
-
-
-
- Creates a new Harmony instance
- A unique identifier (you choose your own)
- A Harmony instance
-
-
-
- Searches the current assembly for Harmony annotations and uses them to create patches
- This method can fail to use the correct assembly when being inlined. It calls StackTrace.GetFrame(1) which can point to the wrong method/assembly. If you are unsure or run into problems, use PatchAll(Assembly.GetExecutingAssembly())
instead.
-
-
-
- Creates a empty patch processor for an original method
- The original method/constructor
- A new instance
-
-
-
- Creates a patch class processor from an annotated class
- The class/type
- A new instance
-
-
-
- Creates a reverse patcher for one of your stub methods
- The original method/constructor
- The stand-in stub method as
- A new instance
-
-
-
- Searches an assembly for Harmony annotations and uses them to create patches
- The assembly
-
-
-
- Creates patches by manually specifying the methods
- The original method/constructor
- An optional prefix method wrapped in a object
- An optional postfix method wrapped in a object
- An optional transpiler method wrapped in a object
- An optional finalizer method wrapped in a object
- The replacement 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 as that will become the original. Needs to have the correct signature (either original or whatever your transpilers generates)
- An optional transpiler as method that will be applied during the process
- The replacement method that was created to patch the stub method
-
-
-
- Unpatches methods by patching them with zero patches. Fully unpatching is not supported. Be careful, unpatching is global
- The optional Harmony ID to restrict unpatching to a specific Harmony instance
- This method could be static if it wasn't for the fact that unpatching creates a new replacement method that contains your harmony ID
-
-
-
- Unpatches a method by patching it with zero patches. Fully unpatching is not supported. Be careful, unpatching is global
- The original method/constructor
- The
- The optional Harmony ID to restrict unpatching to a specific Harmony instance
-
-
-
- Unpatches a method by patching it with zero patches. Fully unpatching is not supported. Be careful, unpatching is global
- The original method/constructor
- The patch method as 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/constructor
- The patch information as
-
-
-
- Gets the methods this instance has patched
- An enumeration of original methods/constructors
-
-
-
- Gets all patched original methods in the appdomain
- An enumeration of patched original methods/constructors
-
-
-
- Gets the original method from a given replacement method
- A replacement method, for example from a stacktrace
- The original method/constructor or null if not found
-
-
-
- Tries to get the method from a stackframe including dynamic replacement methods
- The
- For normal frames, frame.GetMethod() is returned. For frames containing patched methods, the replacement method is returned or null if no method can be found
-
-
-
- Gets the original method from the stackframe and uses original if method is a dynamic replacement
- The
- The original method from that stackframe
-
-
- Gets Harmony version for all active Harmony instances
- [out] The current Harmony version
- A dictionary containing assembly versions keyed by Harmony IDs
-
-
-
- Under Mono, HarmonyException wraps IL compile errors with detailed information about the failure
-
-
-
- Default serialization constructor (not implemented)
- The info
- The context
-
-
-
- Get a list of IL instructions in pairs of offset+code
- A list of key/value pairs which represent an offset and the code at that offset
-
-
-
- Get a list of IL instructions without offsets
- A list of
-
-
-
- Get the error offset of the errornous IL instruction
- The offset
-
-
-
- Get the index of the errornous IL instruction
- The index into the list of instructions or -1 if not found
-
-
-
- A wrapper around a method to use it as a patch (for example a Prefix)
-
-
-
- The original method
-
-
-
- Class/type declaring this patch
-
-
-
- Patch method name
-
-
-
- Optional patch
-
-
-
- Array of argument types of the patch method
-
-
-
- of the patch
-
-
-
- Install this patch before patches with these Harmony IDs
-
-
-
- Install this patch after patches with these Harmony IDs
-
-
-
- Reverse patch type, see
-
-
-
- Create debug output for this patch
-
-
-
- Whether to use (true) or (false) mechanics
- for -attributed delegate
-
-
-
- Default constructor
-
-
-
- Creates a patch from a given method
- The original method
-
-
-
- Creates a patch from a given method
- The original method
- The patch
- A list of harmony IDs that should come after this patch
- A list of harmony IDs that should come before this patch
- Set to true to generate debug output
-
-
-
- Creates a patch from a given method
- The patch class/type
- The patch method name
- The optional argument types of the patch method (for overloaded methods)
-
-
-
- Gets the names of all internal patch info fields
- A list of field names
-
-
-
- Merges annotations
- The list of to merge
- The merged
-
-
-
- Returns a string that represents the annotation
- A string representation
-
-
-
- Annotation extensions
-
-
-
- Copies annotation information
- The source
- The destination
-
-
-
- Clones an annotation
- The to clone
- A copied
-
-
-
- Merges annotations
- The master
- The detail
- A new, merged
-
-
-
- Gets all annotations on a class/type
- The class/type
- A list of all
-
-
-
- Gets merged annotations on a class/type
- The class/type
- The merged
-
-
-
- Gets all annotations on a method
- The method/constructor
- A list of
-
-
-
- Gets merged annotations on a method
- The method/constructor
- The merged
-
-
-
-
- A mutable representation of an inline signature, similar to Mono.Cecil's CallSite.
- Used by the calli instruction, can be used by transpilers
-
-
-
-
- See
-
-
-
- See
-
-
-
- See
-
-
-
- The list of all parameter types or function pointer signatures received by the call site
-
-
-
- The return type or function pointer signature returned by the call site
-
-
-
- Returns a string representation of the inline signature
- A string representation of the inline signature
-
-
-
-
- A mutable representation of a parameter type with an attached type modifier,
- similar to Mono.Cecil's OptionalModifierType / RequiredModifierType and C#'s modopt / modreq
-
-
-
-
- Whether this is a modopt (optional modifier type) or a modreq (required modifier type)
-
-
-
- The modifier type attached to the parameter type
-
-
-
- The modified parameter type
-
-
-
- Returns a string representation of the modifier type
- A string representation of the modifier type
-
-
-
- Patch serialization
-
-
-
- Control the binding of a serialized object to a type
- Specifies the assembly name of the serialized object
- Specifies the type name of the serialized object
- The type of the object the formatter creates a new instance of
-
-
-
- Serializes a patch info
- The
- The serialized data
-
-
-
- Deserialize a patch info
- The serialized data
- A
-
-
-
- Compare function to sort patch priorities
- The patch
- Zero-based index
- The priority
- A standard sort integer (-1, 0, 1)
-
-
-
- Serializable patch information
-
-
-
- Prefixes as an array of
-
-
-
- Postfixes as an array of
-
-
-
- Transpilers as an array of
-
-
-
- Finalizers as an array of
-
-
-
- Returns if any of the patches wants debugging turned on
-
-
-
- Adds prefixes
- An owner (Harmony ID)
- The patch methods
-
-
-
- Adds a prefix
-
-
- Removes prefixes
- The owner of the prefixes, or * for all
-
-
-
- Adds postfixes
- An owner (Harmony ID)
- The patch methods
-
-
-
- Adds a postfix
-
-
- Removes postfixes
- The owner of the postfixes, or * for all
-
-
-
- Adds transpilers
- An owner (Harmony ID)
- The patch methods
-
-
-
- Adds a transpiler
-
-
- Removes transpilers
- The owner of the transpilers, or * for all
-
-
-
- Adds finalizers
- An owner (Harmony ID)
- The patch methods
-
-
-
- Adds a finalizer
-
-
- Removes finalizers
- The owner of the finalizers, or * for all
-
-
-
- Removes a patch using its method
- The method of the patch to remove
-
-
-
- Gets a concatenated list of patches
- The Harmony instance ID adding the new patches
- The patches to add
- The current patches
-
-
-
- Gets a list of patches with any from the given owner removed
- The owner of the methods, or * for all
- The current patches
-
-
-
- A serializable patch
-
-
-
- Zero-based index
-
-
-
- The owner (Harmony ID)
-
-
-
- The priority, see
-
-
-
- Keep this patch before the patches indicated in the list of Harmony IDs
-
-
-
- Keep this patch after the patches indicated in the list of Harmony IDs
-
-
-
- A flag that will log the replacement method via every time this patch is used to build the replacement, even in the future
-
-
-
- The method of the static patch method
-
-
-
- Creates a patch
- The method of the patch
- Zero-based index
- An owner (Harmony ID)
- The priority, see
- A list of Harmony IDs for patches that should run after this patch
- A list of Harmony IDs for patches that should run before this patch
- A flag that will log the replacement method via every time this patch is used to build the replacement, even in the future
-
-
-
- Creates a patch
- The method of the patch
- Zero-based index
- An owner (Harmony ID)
-
-
- Get the patch method or a DynamicMethod if original patch method is a patch factory
- The original method/constructor
- The method of the patch
-
-
-
- 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 PatchClassProcessor used to turn on a class/type into patches
-
-
-
- Creates a patch class processor by pointing out a class. Similar to PatchAll() but without searching through all classes.
- The Harmony instance
- The class to process (need to have at least a [HarmonyPatch] attribute)
-
-
-
- Applies the patches
- A list of all created replacement methods or null if patch class is not annotated
-
-
-
- A group of patches
-
-
-
- A collection of prefix
-
-
-
- A collection of postfix
-
-
-
- A collection of transpiler
-
-
-
- A collection of finalizer
-
-
-
- Gets all owners (Harmony IDs) or all known patches
- The patch owners
-
-
-
- Creates a group of patches
- An array of prefixes as
- An array of postfixes as
- An array of transpileres as
- An array of finalizeres as
-
-
-
- A PatchProcessor handles patches on a method/constructor
-
-
-
- Creates an empty patch processor
- The Harmony instance
- The original method/constructor
-
-
-
- Adds a prefix
- The prefix as a
- A for chaining calls
-
-
-
- Adds a prefix
- The prefix method
- A for chaining calls
-
-
-
- Adds a postfix
- The postfix as a
- A for chaining calls
-
-
-
- Adds a postfix
- The postfix method
- A for chaining calls
-
-
-
- Adds a transpiler
- The transpiler as a
- A for chaining calls
-
-
-
- Adds a transpiler
- The transpiler method
- A for chaining calls
-
-
-
- Adds a finalizer
- The finalizer as a
- A for chaining calls
-
-
-
- Adds a finalizer
- The finalizer method
- A for chaining calls
-
-
-
- Gets all patched original methods in the appdomain
- An enumeration of patched method/constructor
-
-
-
- Applies all registered patches
- The generated replacement method
-
-
-
- Unpatches patches of a given type and/or Harmony ID
- The patch type
- Harmony ID or * for any
- A for chaining calls
-
-
-
- Unpatches a specific patch
- The method of the patch
- A for chaining calls
-
-
-
- Gets patch information on an original
- The original method/constructor
- The patch information as
-
-
-
- Sort patch methods by their priority rules
- The original method
- Patches to sort
- The sorted patch methods
-
-
-
- Gets Harmony version for all active Harmony instances
- [out] The current Harmony version
- A dictionary containing assembly version keyed by Harmony ID
-
-
-
- Creates a new empty generator to use when reading method bodies
- A new
-
-
-
- Creates a new generator matching the method/constructor to use when reading method bodies
- The original method/constructor to copy method information from
- A new
-
-
-
- Returns the methods unmodified list of code instructions
- The original method/constructor
- 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
-
-
-
- Returns the methods unmodified list of code instructions
- The original method/constructor
- A new generator that now contains all local variables and labels contained in the result
- A list containing all the original
-
-
-
- Returns the methods current list of code instructions after all existing transpilers have been applied
- The original method/constructor
- Apply only the first count of transpilers
- 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 of
-
-
-
- Returns the methods current list of code instructions after all existing transpilers have been applied
- The original method/constructor
- A new generator that now contains all local variables and labels contained in the result
- Apply only the first count of transpilers
- A list of
-
-
-
- A low level way to read the body of a method. Used for quick searching in methods
- The original method
- All instructions as opcode/operand pairs
-
-
-
- A low level way to read the body of a method. Used for quick searching in methods
- The original method
- An existing generator that will be used to create all local variables and labels contained in the result
- All instructions as opcode/operand pairs
-
-
-
- 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
-
-
-
- A reverse patcher
-
-
-
- Creates a reverse patcher
- The Harmony instance
- The original method/constructor
- Your stand-in stub method as
-
-
-
- Applies the patch
- The type of patch, see
- The generated replacement method
-
-
-
- A collection of commonly used transpilers
-
-
-
- A transpiler that replaces all occurrences of a given method with another one using the same signature
- The enumeration of to act on
- Method or constructor to search for
- Method or constructor to replace with
- Modified enumeration of
-
-
-
- A transpiler that alters instructions that match a predicate by calling an action
- The enumeration of to act on
- A predicate selecting the instructions to change
- An action to apply to matching instructions
- Modified enumeration of
-
-
-
- A transpiler that logs a text at the beginning of the method
- The instructions to act on
- The log text
- Modified enumeration of
-
-
-
- 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
-
-
-
- Enumerates all assemblies in the current app domain, excluding visual studio assemblies
- An enumeration of
-
-
- Gets a type by name. Prefers a full name with namespace but falls back to the first type matching the name otherwise
- The name
- A type or null if not found
-
-
-
- Gets all successfully loaded types from a given assembly
- The assembly
- An array of types
-
- This calls and returns , while catching any thrown .
- If such an exception is thrown, returns the successfully loaded types (,
- filtered for non-null values).
-
-
-
-
- Enumerates all successfully loaded types in the current app domain, excluding visual studio assemblies
- An enumeration of all in all assemblies, excluding visual studio assemblies
-
-
- Applies a function going up the type hierarchy and stops at the first non-null result
- Result type of func()
- The class/type to start with
- The evaluation function returning T
- The first non-null result, or null if no match
-
- The type hierarchy of a class or value type (including struct) does NOT include implemented interfaces,
- and the type hierarchy of an interface is only itself (regardless of whether that interface implements other interfaces).
- The top-most type in the type hierarchy of all non-interface types (including value types) is .
-
-
-
-
- Applies a function going into inner types and stops at the first non-null result
- Generic type parameter
- The class/type to start with
- The evaluation function returning T
- The first non-null result, or null if no match
-
-
-
- Gets the reflection information for a directly declared field
- The class/type where the field is defined
- The name of the field
- A field or null when type/name is null or when the field cannot be found
-
-
-
- Gets the reflection information for a directly declared field
- The member in the form TypeFullName:MemberName, where TypeFullName matches the form recognized by Type.GetType like Some.Namespace.Type.
- A field or null when the field cannot be found
-
-
-
- Gets the reflection information for a field by searching the type and all its super types
- The class/type where the field is defined
- The name of the field (case sensitive)
- A field or null when type/name is null or when the field cannot be found
-
-
-
- Gets the reflection information for a field by searching the type and all its super types
- The member in the form TypeFullName:MemberName, where TypeFullName matches the form recognized by Type.GetType like Some.Namespace.Type.
- A field or null when the field cannot be found
-
-
-
- Gets the reflection information for a field
- The class/type where the field is declared
- The zero-based index of the field inside the class definition
- A field or null when type is null or when the field cannot be found
-
-
-
- Gets the reflection information for a directly declared property
- The class/type where the property is declared
- The name of the property (case sensitive)
- A property or null when type/name is null or when the property cannot be found
-
-
-
- Gets the reflection information for a directly declared property
- The member in the form TypeFullName:MemberName, where TypeFullName matches the form recognized by Type.GetType like Some.Namespace.Type.
- A property or null when the property cannot be found
-
-
-
- Gets the reflection information for the getter method of a directly declared property
- The class/type where the property is declared
- The name of the property (case sensitive)
- A method or null when type/name is null or when the property cannot be found
-
-
-
- Gets the reflection information for the getter method of a directly declared property
- The member in the form TypeFullName:MemberName, where TypeFullName matches the form recognized by Type.GetType like Some.Namespace.Type.
- A method or null when the property cannot be found
-
-
-
- Gets the reflection information for the setter method of a directly declared property
- The class/type where the property is declared
- The name of the property (case sensitive)
- A method or null when type/name is null or when the property cannot be found
-
-
-
- Gets the reflection information for the Setter method of a directly declared property
- The member in the form TypeFullName:MemberName, where TypeFullName matches the form recognized by Type.GetType like Some.Namespace.Type.
- A method or null when the property cannot be found
-
-
-
- Gets the reflection information for a property by searching the type and all its super types
- The class/type
- The name
- A property or null when type/name is null or when the property cannot be found
-
-
-
- Gets the reflection information for a property by searching the type and all its super types
- The member in the form TypeFullName:MemberName, where TypeFullName matches the form recognized by Type.GetType like Some.Namespace.Type.
- A property or null when the property cannot be found
-
-
-
- Gets the reflection information for the getter method of a property by searching the type and all its super types
- The class/type
- The name
- A method or null when type/name is null or when the property cannot be found
-
-
-
- Gets the reflection information for the getter method of a property by searching the type and all its super types
- The member in the form TypeFullName:MemberName, where TypeFullName matches the form recognized by Type.GetType like Some.Namespace.Type.
- A method or null when type/name is null or when the property cannot be found
-
-
-
- Gets the reflection information for the setter method of a property by searching the type and all its super types
- The class/type
- The name
- A method or null when type/name is null or when the property cannot be found
-
-
-
- Gets the reflection information for the setter method of a property by searching the type and all its super types
- The member in the form TypeFullName:MemberName, where TypeFullName matches the form recognized by Type.GetType like Some.Namespace.Type.
- A method or null when type/name is null or when the property cannot be found
-
-
-
- Gets the reflection information for a directly declared method
- The class/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 method or null when type/name is null or when the method cannot be found
-
-
-
- Gets the reflection information for a directly declared method
- The member in the form TypeFullName:MemberName, where TypeFullName matches the form recognized by Type.GetType like Some.Namespace.Type.
- Optional parameters to target a specific overload of the method
- Optional list of types that define the generic version of the method
- A method or null when the method cannot be found
-
-
-
- Gets the reflection information for a method by searching the type and all its super types
- The class/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 method or null when type/name is null or when the method cannot be found
-
-
-
- Gets the reflection information for a method by searching the type and all its super types
- The member in the form TypeFullName:MemberName, where TypeFullName matches the form recognized by Type.GetType like Some.Namespace.Type.
- Optional parameters to target a specific overload of the method
- Optional list of types that define the generic version of the method
- A method or null when the method cannot be found
-
-
-
- Gets the method of an enumerator method
- Enumerator method that creates the enumerator
- The internal method of the enumerator or null if no valid enumerator is detected
-
-
- Gets the names of all method that are declared in a type
- The declaring class/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 class/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 class/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 any class member of
- A member
- The class/type of this member
-
-
-
- Test if a class member is actually an concrete implementation
- 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 some base type
-
-
-
- Gets the reflection information for a directly declared constructor
- The class/type where the constructor is declared
- Optional parameters to target a specific overload of the constructor
- Optional parameters to only consider static constructors
- A constructor info or null when type is null or when the constructor cannot be found
-
-
-
- Gets the reflection information for a constructor by searching the type and all its super types
- The class/type where the constructor is declared
- Optional parameters to target a specific overload of the method
- Optional parameters to only consider static constructors
- A constructor info or null when type is null or when the method cannot be found
-
-
-
- Gets reflection information for all declared constructors
- The class/type where the constructors are declared
- Optional parameters to only consider static constructors
- A list of constructor infos
-
-
-
- Gets reflection information for all declared methods
- The class/type where the methods are declared
- A list of methods
-
-
-
- Gets reflection information for all declared properties
- The class/type where the properties are declared
- A list of properties
-
-
-
- Gets reflection information for all declared fields
- The class/type where the fields are declared
- A list of fields
-
-
-
- Gets the return type of a method or constructor
- The method/constructor
- The return type
-
-
-
- Given a type, returns the first inner type matching a recursive search by name
- The class/type to start searching at
- The name of the inner type (case sensitive)
- The inner type or null if type/name is null or if a type with that name cannot be found
-
-
-
- Given a type, returns the first inner type matching a recursive search with a predicate
- The class/type to start searching at
- The predicate to search with
- The inner type or null if type/predicate is null or if a type with that name cannot be found
-
-
-
- Given a type, returns the first method matching a predicate
- The class/type to start searching at
- The predicate to search with
- The method or null if type/predicate is null or if a type with that name cannot be found
-
-
-
- Given a type, returns the first constructor matching a predicate
- The class/type to start searching at
- The predicate to search with
- The constructor info or null if type/predicate is null or if a type with that name cannot be found
-
-
-
- Given a type, returns the first property matching a predicate
- The class/type to start searching at
- The predicate to search with
- The property or null if type/predicate is null or if a type with that name cannot be found
-
-
-
- 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 (if an object is null, the type for it will be object)
-
-
-
- Creates an array of input parameters for a given method and a given set of potential inputs
- The method/constructor you are planing to call
- The possible input parameters in any order
- An object array matching the method signature
-
-
-
- A readable/assignable reference delegate to an instance field of a class or static field (NOT an instance field of a struct)
-
- An arbitrary type if the field is static; otherwise the class that defines the field, or a parent class (including ),
- implemented interface, or derived class of this type
-
-
- The type of the field; or if the field's type is a reference type (a class or interface, NOT a struct or other value type),
- a type that is assignable from that type; or if the field's type is an enum type,
- either that type or the underlying integral type of that enum type
-
- The runtime instance to access the field (ignored and can be omitted for static fields)
- A readable/assignable reference to the field
- Null instance passed to a non-static field ref delegate
-
- Instance of invalid type passed to a non-static field ref delegate
- (this can happen if is a parent class or interface of the field's declaring type)
-
-
-
- This delegate cannot be used for instance fields of structs, since a struct instance passed to the delegate would be passed by
- value and thus would be a copy that only exists within the delegate's invocation. This is fine for a readonly reference,
- but makes assignment futile. Use instead.
-
-
- Note that is not required to be the field's declaring type. It can be a parent class (including ),
- implemented interface, or a derived class of the field's declaring type ("instanceOfT is FieldDeclaringType" must be possible).
- Specifically, must be assignable from OR to the field's declaring type.
- Technically, this allows Nullable, although Nullable is only relevant for structs, and since only static fields of structs
- are allowed for this delegate, and the instance passed to such a delegate is ignored, this hardly matters.
-
-
- Similarly, is not required to be the field's field type, unless that type is a non-enum value type.
- It can be a parent class (including object) or implemented interface of the field's field type. It cannot be a derived class.
- This variance is not allowed for value types, since that would require boxing/unboxing, which is not allowed for ref values.
- Special case for enum types: can also be the underlying integral type of the enum type.
- Specifically, for reference types, must be assignable from
- the field's field type; for non-enum value types, must be exactly the field's field type; for enum types,
- must be either the field's field type or the underyling integral type of that field type.
-
-
- This delegate supports static fields, even those defined in structs, for legacy reasons.
- For such static fields, is effectively ignored.
- Consider using (and StaticFieldRefAccess methods that return it) instead for static fields.
-
-
-
-
-
- Creates a field reference delegate for an instance field of a class
- The class that defines the instance field, or derived class of this type
-
- The type of the field; or if the field's type is a reference type (a class or interface, NOT a struct or other value type),
- a type that is assignable from that type; or if the field's type is an enum type,
- either that type or the underlying integral type of that enum type
-
- The name of the field
- A readable/assignable delegate
-
-
- For backwards compatibility, there is no class constraint on .
- Instead, the non-value-type check is done at runtime within the method.
-
-
-
-
-
- Creates an instance field reference for a specific instance of a class
- The class that defines the instance field, or derived class of this type
-
- The type of the field; or if the field's type is a reference type (a class or interface, NOT a struct or other value type),
- a type that is assignable from that type; or if the field's type is an enum type,
- either that type or the underlying integral type of that enum type
-
- The instance
- The name of the field
- A readable/assignable reference to the field
-
-
- This method is meant for one-off access to a field's value for a single instance.
- If you need to access a field's value for potentially multiple instances, use instead.
- FieldRefAccess<T, F>(instance, fieldName) is functionally equivalent to FieldRefAccess<T, F>(fieldName)(instance).
-
-
- For backwards compatibility, there is no class constraint on .
- Instead, the non-value-type check is done at runtime within the method.
-
-
-
-
-
- Creates a field reference delegate for an instance field of a class or static field (NOT an instance field of a struct)
-
- The type of the field; or if the field's type is a reference type (a class or interface, NOT a struct or other value type),
- a type that is assignable from that type; or if the field's type is an enum type,
- either that type or the underlying integral type of that enum type
-
-
- The type that defines the field, or derived class of this type; must not be a struct type unless the field is static
-
- The name of the field
-
- A readable/assignable delegate with T=object
- (for static fields, the instance delegate parameter is ignored)
-
-
-
- This method is meant for cases where the given type is only known at runtime and thus can't be used as a type parameter T
- in e.g. .
-
-
- This method supports static fields, even those defined in structs, for legacy reasons.
- Consider using (and other overloads) instead for static fields.
-
-
-
-
-
- Creates a field reference delegate for an instance field of a class or static field (NOT an instance field of a struct)
- type of the field
- The member in the form TypeFullName:MemberName, where TypeFullName matches the form recognized by Type.GetType like Some.Namespace.Type.
- A readable/assignable delegate with T=object
-
-
- Creates a field reference delegate for an instance field of a class or static field (NOT an instance field of a struct)
-
- An arbitrary type if the field is static; otherwise the class that defines the field, or a parent class (including ),
- implemented interface, or derived class of this type ("instanceOfT is FieldDeclaringType" must be possible)
-
-
- The type of the field; or if the field's type is a reference type (a class or interface, NOT a struct or other value type),
- a type that is assignable from that type; or if the field's type is an enum type,
- either that type or the underlying integral type of that enum type
-
- The field
- A readable/assignable delegate
-
-
- This method is meant for cases where the field has already been obtained, avoiding the field searching cost in
- e.g. .
-
-
- This method supports static fields, even those defined in structs, for legacy reasons.
- For such static fields, is effectively ignored.
- Consider using (and other overloads) instead for static fields.
-
-
- For backwards compatibility, there is no class constraint on .
- Instead, the non-value-type check is done at runtime within the method.
-
-
-
-
-
- Creates a field reference for an instance field of a class
-
- The type that defines the field; or a parent class (including ), implemented interface, or derived class of this type
- ("instanceOfT is FieldDeclaringType" must be possible)
-
-
- The type of the field; or if the field's type is a reference type (a class or interface, NOT a struct or other value type),
- a type that is assignable from that type; or if the field's type is an enum type,
- either that type or the underlying integral type of that enum type
-
- The instance
- The field
- A readable/assignable reference to the field
-
-
- This method is meant for one-off access to a field's value for a single instance and where the field has already been obtained.
- If you need to access a field's value for potentially multiple instances, use instead.
- FieldRefAccess<T, F>(instance, fieldInfo) is functionally equivalent to FieldRefAccess<T, F>(fieldInfo)(instance).
-
-
- For backwards compatibility, there is no class constraint on .
- Instead, the non-value-type check is done at runtime within the method.
-
-
-
-
-
- A readable/assignable reference delegate to an instance field of a struct
- The struct that defines the instance field
-
- The type of the field; or if the field's type is a reference type (a class or interface, NOT a struct or other value type),
- a type that is assignable from that type; or if the field's type is an enum type,
- either that type or the underlying integral type of that enum type
-
- A reference to the runtime instance to access the field
- A readable/assignable reference to the field
-
-
-
- Creates a field reference delegate for an instance field of a struct
- The struct that defines the instance field
-
- The type of the field; or if the field's type is a reference type (a class or interface, NOT a struct or other value type),
- a type that is assignable from that type; or if the field's type is an enum type,
- either that type or the underlying integral type of that enum type
-
- The name of the field
- A readable/assignable delegate
-
-
-
- Creates an instance field reference for a specific instance of a struct
- The struct that defines the instance field
-
- The type of the field; or if the field's type is a reference type (a class or interface, NOT a struct or other value type),
- a type that is assignable from that type; or if the field's type is an enum type,
- either that type or the underlying integral type of that enum type
-
- The instance
- The name of the field
- A readable/assignable reference to the field
-
-
- This method is meant for one-off access to a field's value for a single instance.
- If you need to access a field's value for potentially multiple instances, use instead.
- StructFieldRefAccess<T, F>(ref instance, fieldName) is functionally equivalent to StructFieldRefAccess<T, F>(fieldName)(ref instance).
-
-
-
-
-
- Creates a field reference delegate for an instance field of a struct
- The struct that defines the instance field
-
- The type of the field; or if the field's type is a reference type (a class or interface, NOT a struct or other value type),
- a type that is assignable from that type; or if the field's type is an enum type,
- either that type or the underlying integral type of that enum type
-
- The field
- A readable/assignable delegate
-
-
- This method is meant for cases where the field has already been obtained, avoiding the field searching cost in
- e.g. .
-
-
-
-
-
- Creates a field reference for an instance field of a struct
- The struct that defines the instance field
-
- The type of the field; or if the field's type is a reference type (a class or interface, NOT a struct or other value type),
- a type that is assignable from that type; or if the field's type is an enum type,
- either that type or the underlying integral type of that enum type
-
- The instance
- The field
- A readable/assignable reference to the field
-
-
- This method is meant for one-off access to a field's value for a single instance and where the field has already been obtained.
- If you need to access a field's value for potentially multiple instances, use instead.
- StructFieldRefAccess<T, F>(ref instance, fieldInfo) is functionally equivalent to StructFieldRefAccess<T, F>(fieldInfo)(ref instance).
-
-
-
-
-
- A readable/assignable reference delegate to a static field
-
- The type of the field; or if the field's type is a reference type (a class or interface, NOT a struct or other value type),
- a type that is assignable from that type; or if the field's type is an enum type,
- either that type or the underlying integral type of that enum type
-
- A readable/assignable reference to the field
-
-
-
- Creates a static field reference
- The type (can be class or struct) the field is defined in
-
- The type of the field; or if the field's type is a reference type (a class or interface, NOT a struct or other value type),
- a type that is assignable from that type; or if the field's type is an enum type,
- either that type or the underlying integral type of that enum type
-
- The name of the field
- A readable/assignable reference to the field
-
-
-
- Creates a static field reference
-
- The type of the field; or if the field's type is a reference type (a class or interface, NOT a struct or other value type),
- a type that is assignable from that type; or if the field's type is an enum type,
- either that type or the underlying integral type of that enum type
-
- The type (can be class or struct) the field is defined in
- The name of the field
- A readable/assignable reference to the field
-
-
-
- Creates a static field reference
- The type of the field
- The member in the form TypeFullName:MemberName, where TypeFullName matches the form recognized by Type.GetType like Some.Namespace.Type.
- A readable/assignable reference to the field
-
-
-
- Creates a static field reference
- An arbitrary type (by convention, the type the field is defined in)
-
- The type of the field; or if the field's type is a reference type (a class or interface, NOT a struct or other value type),
- a type that is assignable from that type; or if the field's type is an enum type,
- either that type or the underlying integral type of that enum type
-
- The field
- A readable/assignable reference to the field
-
- The type parameter is only used in exception messaging and to distinguish between this method overload
- and the overload (which returns a rather than a reference).
-
-
-
-
- Creates a static field reference delegate
-
- The type of the field; or if the field's type is a reference type (a class or interface, NOT a struct or other value type),
- a type that is assignable from that type; or if the field's type is an enum type,
- either that type or the underlying integral type of that enum type
-
- The field
- A readable/assignable delegate
-
-
-
- Creates a delegate to a given method
- The delegate Type
- The method to create a delegate from.
-
- Only applies for instance methods. If null (default), returned delegate is an open (a.k.a. unbound) instance delegate
- where an instance is supplied as the first argument to the delegate invocation; else, delegate is a closed (a.k.a. bound)
- instance delegate where the delegate invocation always applies to the given .
-
-
- Only applies for instance methods. If true (default) and is virtual, invocation of the delegate
- calls the instance method virtually (the instance type's most-derived/overriden implementation of the method is called);
- else, invocation of the delegate calls the exact specified (this is useful for calling base class methods)
- Note: if false and is an interface method, an ArgumentException is thrown.
-
- A delegate of given to given
-
-
- Delegate invocation is more performant and more convenient to use than
- at a one-time setup cost.
-
-
- Works for both type of static and instance methods, both open and closed (a.k.a. unbound and bound) instance methods,
- and both class and struct methods.
-
-
-
-
-
- Creates a delegate to a given method
- The delegate Type
- The method in the form TypeFullName:MemberName, where TypeFullName matches the form recognized by Type.GetType like Some.Namespace.Type.
-
- Only applies for instance methods. If null (default), returned delegate is an open (a.k.a. unbound) instance delegate
- where an instance is supplied as the first argument to the delegate invocation; else, delegate is a closed (a.k.a. bound)
- instance delegate where the delegate invocation always applies to the given .
-
-
- Only applies for instance methods. If true (default) and is virtual, invocation of the delegate
- calls the instance method virtually (the instance type's most-derived/overriden implementation of the method is called);
- else, invocation of the delegate calls the exact specified (this is useful for calling base class methods)
- Note: if false and is an interface method, an ArgumentException is thrown.
-
- A delegate of given to given
-
-
- Delegate invocation is more performant and more convenient to use than
- at a one-time setup cost.
-
-
- Works for both type of static and instance methods, both open and closed (a.k.a. unbound and bound) instance methods,
- and both class and struct methods.
-
-
-
-
-
- Creates a delegate for a given delegate definition, attributed with []
- The delegate Type, attributed with []
-
- Only applies for instance methods. If null (default), returned delegate is an open (a.k.a. unbound) instance delegate
- where an instance is supplied as the first argument to the delegate invocation; else, delegate is a closed (a.k.a. bound)
- instance delegate where the delegate invocation always applies to the given .
-
- A delegate of given to the method specified via []
- attributes on
-
- This calls with the method and virtualCall arguments
- determined from the [] attributes on ,
- and the given (for closed instance delegates).
-
-
-
-
- Returns who called the current method
- The calling method/constructor (excluding the caller)
-
-
-
- Rethrows an exception while preserving its stack trace (throw statement typically clobbers existing stack traces)
- The exception to rethrow
-
-
-
- True if the current runtime is based on Mono, false otherwise (.NET)
-
-
-
- True if the current runtime is .NET Framework, false otherwise (.NET Core or Mono, although latter isn't guaranteed)
-
-
-
- True if the current runtime is .NET Core, false otherwise (Mono or .NET Framework)
-
-
-
- Throws a missing member runtime exception
- The type that is involved
- A list of names
-
-
-
- Gets default value for a specific type
- The class/type
- The default value
-
-
-
- Creates an (possibly uninitialized) instance of a given type
- The class/type
- The new instance
-
-
-
- Creates an (possibly uninitialized) instance of a given type
- The class/type
- The new instance
-
-
-
-
- A cache for the or similar Add methods for different types.
-
-
-
- Makes a deep copy of any object
- The type of the instance that should be created; for legacy reasons, this must be a class or interface
- 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 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
-
-
-
- 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
-
-
-
- Tests whether a type or member is static, as defined in C#
- The type or member
- True if the type or member is static
-
-
-
- Tests whether a type is static, as defined in C#
- The type
- True if the type is static
-
-
-
- Tests whether a property is static, as defined in C#
- The property
- True if the property is static
-
-
-
- Tests whether an event is static, as defined in C#
- The event
- True if the event is static
-
-
-
- Calculates a combined hash code for an enumeration of objects
- The objects
- The hash code
-
-
-
- A CodeInstruction match
-
-
- The name of the match
-
-
- The matched opcodes
-
-
- The matched operands
-
-
- 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 that calls a method
- The lambda expression using the method
- The optional name
-
-
-
- Creates a code match that calls a method
- The lambda expression using the method
- 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
-
-
-
- Throw an InvalidOperationException if current state is invalid (position out of bounds / last match failed)
- Explanation of where/why the exception was thrown that will be added to the exception message
- The same code matcher
-
-
-
- Throw an InvalidOperationException if current state is invalid (position out of bounds / last match failed),
- or if the matches do not match at current position
- Explanation of where/why the exception was thrown that will be added to the exception message
- Some code matches
- The same code matcher
-
-
-
- Throw an InvalidOperationException if current state is invalid (position out of bounds / last match failed),
- or if the matches do not match at any point between current position and the end
- Explanation of where/why the exception was thrown that will be added to the exception message
- Some code matches
- The same code matcher
-
-
-
- Throw an InvalidOperationException if current state is invalid (position out of bounds / last match failed),
- or if the matches do not match at any point between current position and the start
- Explanation of where/why the exception was thrown that will be added to the exception message
- Some code matches
- The same code matcher
-
-
-
- Throw an InvalidOperationException if current state is invalid (position out of bounds / last match failed),
- or if the check function returns false
- Explanation of where/why the exception was thrown that will be added to the exception message
- Function that checks validity of current state. If it returns false, an exception is thrown
- The same code matcher
-
-
-
- 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
-
-
-
- Creates a label at a position
- The offset
- [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 from 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 to beginning of matching sequence
- Some code matches
- The same code matcher
-
-
-
- Matches forward and advances position to ending of matching sequence
- Some code matches
- The same code matcher
-
-
-
- Matches backwards and reverses position to beginning of matching sequence
- Some code matches
- The same code matcher
-
-
-
- Matches backwards and reverses position to ending of matching sequence
- 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
-
-
-
- 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/constructor
- A human readable description
-
-
-
- A helper converting parameter infos to types
- The array of parameter infos
- An array of 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
-
-
-
- Escapes Unicode and ASCII non printable characters
- The string to convert
- The string to convert
- A string literal surrounded by
-
-
-
- Extensions for
-
-
-
- Returns if an is initialized and valid
- The
-
-
-
- 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 testing whether the operand is equal to a non-null value
- The
- The value
- True if the operand is equal to the value
- This is an optimized version of for
-
-
-
- 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
-
-
-
- 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 is equal to the given operand
- This is an optimized version of for
-
-
-
- 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 string constant
- The
- The string
- 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 another one
- The to move the labels from
- The other to move the labels to
- The code instruction labels were moved from (now empty)
-
-
- Moves all labels from another code instruction to the current one
- The to move the labels to
- The other to move the labels from
- 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 another one
- The to move the ExceptionBlocks from
- The other to move the ExceptionBlocks to
- The code instruction blocks were moved from (now empty)
-
-
- Moves all ExceptionBlocks from another code instruction to the current one
- The to move the ExceptionBlocks to
- The other to move the ExceptionBlocks from
- 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
-
-
-
- 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 collections
-
-
-
- Tests a class member if it has an IL method body (external methods for example don't have a body)
- The member to test
- Returns true if the member has an IL body or false if not
-
-
- A file log for debugging
-
-
-
- Set this to make Harmony write its log content to this stream
-
-
-
- Full pathname of the log file, defaults to a file called harmony.log.txt on your Desktop
-
-
-
- The indent character. The default is tab
-
-
-
- The current indent level
-
-
-
- Changes the indentation level
- The value to add to the indentation 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
- A list of 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.
-
-
-
- Log a string directly to disk if Harmony.DEBUG is true. 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
-
-
-
- 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 method in the lambda expression
-
-
-
- Given a lambda expression that calls a method, returns the method info
- The generic type
- The lambda expression using the method
- The method in the lambda expression
-
-
-
- Given a lambda expression that calls a method, returns the method info
- The generic type
- The generic result type
- The lambda expression using the method
- 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 method in the lambda expression
-
-
-
- A reflection helper to read and write private elements
- The result type defined by GetValue()
-
-
-
- Creates a traverse instance from an existing instance
- The existing instance
-
-
-
- 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/type
- The class/type
- A instance
-
-
-
- Creates a new traverse instance from a class T
- The class
- A instance
-
-
-
- Creates a new traverse instance from an instance
- The object
- A instance
-
-
-
- Creates a new traverse instance from a named type
- The type name, for format see
- A instance
-
-
-
- Creates a new and empty traverse instance
-
-
-
- Creates a new traverse instance from a class/type
- The class/type
-
-
-
- Creates a new traverse instance from an instance
- The object
-
-
-
- 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
- True if its a field
-
-
-
- Checks if the current traverse instance is for a property
- True if its a property
-
-
-
- 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
-
-
-
- Iterates over all fields of the current type and executes a traverse action
- Original object
- The action receiving a instance for each field
-
-
-
- Iterates over all fields of the current type and executes a traverse action
- Original object
- Target object
- The action receiving a pair of instances for each field pair
-
-
-
- Iterates over all fields of the current type and executes a traverse action
- Original object
- Target object
- The action receiving a dot path representing the field pair and the instances
-
-
-
- Iterates over all properties of the current type and executes a traverse action
- Original object
- The action receiving a instance for each property
-
-
-
- Iterates over all properties of the current type and executes a traverse action
- Original object
- Target object
- The action receiving a pair of instances for each property pair
-
-
-
- Iterates over all properties of the current type and executes a traverse action
- Original object
- Target object
- The action receiving a dot path representing the property pair and the instances
-
-
-
- A default field action that copies fields to fields
-
-
-
- Returns a string that represents the current traverse
- A string representation
-
-
-
-
diff --git a/build/common.targets b/build/common.targets
index f7f57593..4022e5e5 100644
--- a/build/common.targets
+++ b/build/common.targets
@@ -20,7 +20,7 @@ repo. It imports the other MSBuild files as needed.
$(DefineConstants);SMAPI_FOR_WINDOWS
- true
+ false
None
@@ -50,10 +50,10 @@ repo. It imports the other MSBuild files as needed.
-
-
-
-
+
+
+
+
diff --git a/build/define-constant.targets b/build/define-constant.targets
index 3d3ae38f..9bf5fc32 100644
--- a/build/define-constant.targets
+++ b/build/define-constant.targets
@@ -8,11 +8,6 @@
False
- $(DefineConstants);HARMONY_1
- $(DefineConstants);SMAPI_FOR_MOBILE;ANDROID_TARGET_GOOGLE;ANDROID_TARGET_MOBILE_LEGACY;HARMONY_1
- $(DefineConstants);SMAPI_FOR_MOBILE;ANDROID_TARGET_GOOGLE;ANDROID_TARGET_GOOGLE_145;HARMONY_1
- $(DefineConstants);SMAPI_FOR_MOBILE;ANDROID_TARGET_GOOGLE;ANDROID_TARGET_GOOGLE_MONOANDROID10;MonoAndroid10;HARMONY_1
- $(DefineConstants);SMAPI_FOR_MOBILE;ANDROID_TARGET_AMAZON;HARMONY_1
- $(DefineConstants);SMAPI_FOR_MOBILE;ANDROID_TARGET_SAMSUNG;HARMONY_1
+ $(DefineConstants);SMAPI_FOR_MOBILE;ANDROID_TARGET_GOOGLE;MonoAndroid10
diff --git a/src/Loader/Loader.csproj b/src/Loader/Loader.csproj
index 47e38839..b7f498d2 100644
--- a/src/Loader/Loader.csproj
+++ b/src/Loader/Loader.csproj
@@ -17,7 +17,7 @@
Resource
Off
false
- v10.0
+ v12.0
Properties\AndroidManifest.xml
Resources
Assets
diff --git a/src/SMAPI.Internal/ConsoleWriting/ColorfulConsoleWriter.cs b/src/SMAPI.Internal/ConsoleWriting/ColorfulConsoleWriter.cs
index 78db0d65..7c94ae16 100644
--- a/src/SMAPI.Internal/ConsoleWriting/ColorfulConsoleWriter.cs
+++ b/src/SMAPI.Internal/ConsoleWriting/ColorfulConsoleWriter.cs
@@ -15,7 +15,7 @@ namespace StardewModdingAPI.Internal.ConsoleWriting
private readonly IDictionary? Colors;
/// Whether the current console supports color formatting.
- [MemberNotNullWhen(true, nameof(ColorfulConsoleWriter.Colors))]
+ // [MemberNotNullWhen(true, nameof(ColorfulConsoleWriter.Colors))]
private bool SupportsColor { get; }
diff --git a/src/SMAPI.Mods.VirtualKeyboard/SMAPI.Mods.VirtualKeyboard.csproj b/src/SMAPI.Mods.VirtualKeyboard/SMAPI.Mods.VirtualKeyboard.csproj
index 04de4130..47863bce 100644
--- a/src/SMAPI.Mods.VirtualKeyboard/SMAPI.Mods.VirtualKeyboard.csproj
+++ b/src/SMAPI.Mods.VirtualKeyboard/SMAPI.Mods.VirtualKeyboard.csproj
@@ -9,7 +9,7 @@
Properties
StardewModdingAPI.Mods.VirtualKeyboard
VirtualKeyboard
- v4.5
+ v4.8
512
true
diff --git a/src/SMAPI.Toolkit.CoreInterfaces/SMAPI.Toolkit.CoreInterfaces.csproj b/src/SMAPI.Toolkit.CoreInterfaces/SMAPI.Toolkit.CoreInterfaces.csproj
index 4c92b4db..fd920295 100644
--- a/src/SMAPI.Toolkit.CoreInterfaces/SMAPI.Toolkit.CoreInterfaces.csproj
+++ b/src/SMAPI.Toolkit.CoreInterfaces/SMAPI.Toolkit.CoreInterfaces.csproj
@@ -3,8 +3,9 @@
StardewModdingAPI
Provides toolkit interfaces which are available to SMAPI mods.
net5.0; netstandard2.0
+ latest
true
-
+
diff --git a/src/SMAPI.Toolkit/Framework/LowLevelEnvironmentUtility.cs b/src/SMAPI.Toolkit/Framework/LowLevelEnvironmentUtility.cs
index f464f4bb..03f6bfe7 100644
--- a/src/SMAPI.Toolkit/Framework/LowLevelEnvironmentUtility.cs
+++ b/src/SMAPI.Toolkit/Framework/LowLevelEnvironmentUtility.cs
@@ -3,9 +3,6 @@ using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;
-#if SMAPI_FOR_WINDOWS
-using System.Management;
-#endif
using System.Runtime.InteropServices;
using StardewModdingAPI.Toolkit.Utilities;
diff --git a/src/SMAPI.Toolkit/SMAPI.Toolkit.csproj b/src/SMAPI.Toolkit/SMAPI.Toolkit.csproj
index 033009c7..94d7fcbc 100644
--- a/src/SMAPI.Toolkit/SMAPI.Toolkit.csproj
+++ b/src/SMAPI.Toolkit/SMAPI.Toolkit.csproj
@@ -5,12 +5,14 @@
A library which encapsulates mod-handling logic for mod managers and tools. Not intended for use by mods.
net5.0; netstandard2.0
true
+ latest
-
+
+
diff --git a/src/SMAPI.sln b/src/SMAPI.sln
index d3f0ff4a..042b1ae1 100644
--- a/src/SMAPI.sln
+++ b/src/SMAPI.sln
@@ -27,8 +27,8 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{09CF91E5-5BAB-4650-A200-E5EA9A633046}"
ProjectSection(SolutionItems) = preProject
..\build\common.targets = ..\build\common.targets
- ..\build\deploy-local-smapi.targets = ..\build\deploy-local-smapi.targets
..\build\define-constant.targets = ..\build\define-constant.targets
+ ..\build\deploy-local-smapi.targets = ..\build\deploy-local-smapi.targets
..\build\find-game-folder.targets = ..\build\find-game-folder.targets
EndProjectSection
EndProject
@@ -59,14 +59,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SMAPI.ModBuildConfig.Analyz
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SMAPI.Tests", "SMAPI.Tests\SMAPI.Tests.csproj", "{AA95884B-7097-476E-92C8-D0500DE9D6D1}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SMAPI", "SMAPI\SMAPI.csproj", "{EBD13EAB-E70B-4D9F-92C2-C34A21E1FA32}"
-EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SMAPI.Installer", "SMAPI.Installer\SMAPI.Installer.csproj", "{0A9BB24F-15FF-4C26-B1A2-81F7AE316518}"
ProjectSection(ProjectDependencies) = postProject
{0634EA4C-3B8F-42DB-AEA6-CA9E4EF6E92F} = {0634EA4C-3B8F-42DB-AEA6-CA9E4EF6E92F}
{491E775B-EAD0-44D4-B6CA-F1FC3E316D33} = {491E775B-EAD0-44D4-B6CA-F1FC3E316D33}
{CD53AD6F-97F4-4872-A212-50C2A0FD3601} = {CD53AD6F-97F4-4872-A212-50C2A0FD3601}
- {EBD13EAB-E70B-4D9F-92C2-C34A21E1FA32} = {EBD13EAB-E70B-4D9F-92C2-C34A21E1FA32}
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SMAPI.ModBuildConfig", "SMAPI.ModBuildConfig\SMAPI.ModBuildConfig.csproj", "{1B3821E6-D030-402C-B3A1-7CA45C2800EA}"
@@ -113,17 +110,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SMAPI.Tests.ModApiProvider"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SMAPI.Tests.ModApiConsumer", "SMAPI.Tests.ModApiConsumer\SMAPI.Tests.ModApiConsumer.csproj", "{2A4DF030-E8B1-4BBD-AA93-D4DE68CB9D85}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SMAPI", "SMAPI\SMAPI.csproj", "{EBD13EAB-E70B-4D9F-92C2-C34A21E1FA32}"
+EndProject
Global
- GlobalSection(SharedMSBuildProjectFiles) = preSolution
- SMAPI.Internal\SMAPI.Internal.projitems*{0634ea4c-3b8f-42db-aea6-ca9e4ef6e92f}*SharedItemsImports = 5
- SMAPI.Internal\SMAPI.Internal.projitems*{0a9bb24f-15ff-4c26-b1a2-81f7ae316518}*SharedItemsImports = 5
- SMAPI.Internal.Patching\SMAPI.Internal.Patching.projitems*{6c16e948-3e5c-47a7-bf4b-07a7469a87a5}*SharedItemsImports = 13
- SMAPI.Internal\SMAPI.Internal.projitems*{80efd92f-728f-41e0-8a5b-9f6f49a91899}*SharedItemsImports = 5
- SMAPI.Internal\SMAPI.Internal.projitems*{85208f8d-6fd1-4531-be05-7142490f59fe}*SharedItemsImports = 13
- SMAPI.Internal\SMAPI.Internal.projitems*{cd53ad6f-97f4-4872-a212-50c2a0fd3601}*SharedItemsImports = 5
- SMAPI.Internal\SMAPI.Internal.projitems*{ebd13eab-e70b-4d9f-92c2-c34a21e1fa32}*SharedItemsImports = 5
- SMAPI.Internal.Patching\SMAPI.Internal.Patching.projitems*{e6da2198-7686-4f1d-b312-4a4dc70884c0}*SharedItemsImports = 5
- EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
@@ -134,15 +123,9 @@ Global
{680B2641-81EA-467C-86A5-0E81CDC57ED0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{680B2641-81EA-467C-86A5-0E81CDC57ED0}.Release|Any CPU.Build.0 = Release|Any CPU
{AA95884B-7097-476E-92C8-D0500DE9D6D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {AA95884B-7097-476E-92C8-D0500DE9D6D1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AA95884B-7097-476E-92C8-D0500DE9D6D1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AA95884B-7097-476E-92C8-D0500DE9D6D1}.Release|Any CPU.Build.0 = Release|Any CPU
- {EBD13EAB-E70B-4D9F-92C2-C34A21E1FA32}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {EBD13EAB-E70B-4D9F-92C2-C34A21E1FA32}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {EBD13EAB-E70B-4D9F-92C2-C34A21E1FA32}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {EBD13EAB-E70B-4D9F-92C2-C34A21E1FA32}.Release|Any CPU.Build.0 = Release|Any CPU
{0A9BB24F-15FF-4C26-B1A2-81F7AE316518}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {0A9BB24F-15FF-4C26-B1A2-81F7AE316518}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0A9BB24F-15FF-4C26-B1A2-81F7AE316518}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0A9BB24F-15FF-4C26-B1A2-81F7AE316518}.Release|Any CPU.Build.0 = Release|Any CPU
{1B3821E6-D030-402C-B3A1-7CA45C2800EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
@@ -174,7 +157,6 @@ Global
{ED8E41FA-DDFA-4A77-932E-9853D279A129}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ED8E41FA-DDFA-4A77-932E-9853D279A129}.Release|Any CPU.Build.0 = Release|Any CPU
{80EFD92F-728F-41E0-8A5B-9F6F49A91899}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {80EFD92F-728F-41E0-8A5B-9F6F49A91899}.Debug|Any CPU.Build.0 = Debug|Any CPU
{80EFD92F-728F-41E0-8A5B-9F6F49A91899}.Release|Any CPU.ActiveCfg = Release|Any CPU
{80EFD92F-728F-41E0-8A5B-9F6F49A91899}.Release|Any CPU.Build.0 = Release|Any CPU
{29CCE9C9-6811-415D-A681-A6D47073924D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
@@ -193,6 +175,10 @@ Global
{2A4DF030-E8B1-4BBD-AA93-D4DE68CB9D85}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2A4DF030-E8B1-4BBD-AA93-D4DE68CB9D85}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2A4DF030-E8B1-4BBD-AA93-D4DE68CB9D85}.Release|Any CPU.Build.0 = Release|Any CPU
+ {EBD13EAB-E70B-4D9F-92C2-C34A21E1FA32}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {EBD13EAB-E70B-4D9F-92C2-C34A21E1FA32}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {EBD13EAB-E70B-4D9F-92C2-C34A21E1FA32}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {EBD13EAB-E70B-4D9F-92C2-C34A21E1FA32}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -207,11 +193,11 @@ Global
{6C16E948-3E5C-47A7-BF4B-07A7469A87A5} = {82D22ED7-A0A7-4D64-8E92-4B6A5E74ED11}
{680B2641-81EA-467C-86A5-0E81CDC57ED0} = {82D22ED7-A0A7-4D64-8E92-4B6A5E74ED11}
{AA95884B-7097-476E-92C8-D0500DE9D6D1} = {82D22ED7-A0A7-4D64-8E92-4B6A5E74ED11}
- {29CCE9C9-6811-415D-A681-A6D47073924D} = {6BBCA4D1-213F-4843-B910-DF2D66E3D8CF}
- {45D7D2FB-6B70-45D1-A595-6E289D6A3468} = {6BBCA4D1-213F-4843-B910-DF2D66E3D8CF}
{0634EA4C-3B8F-42DB-AEA6-CA9E4EF6E92F} = {AE9A4D46-E910-4293-8BC4-673F85FFF6A5}
{491E775B-EAD0-44D4-B6CA-F1FC3E316D33} = {AE9A4D46-E910-4293-8BC4-673F85FFF6A5}
{CD53AD6F-97F4-4872-A212-50C2A0FD3601} = {AE9A4D46-E910-4293-8BC4-673F85FFF6A5}
+ {29CCE9C9-6811-415D-A681-A6D47073924D} = {6BBCA4D1-213F-4843-B910-DF2D66E3D8CF}
+ {45D7D2FB-6B70-45D1-A595-6E289D6A3468} = {6BBCA4D1-213F-4843-B910-DF2D66E3D8CF}
{4D661178-38FB-43E4-AA5F-9B0406919344} = {09CF91E5-5BAB-4650-A200-E5EA9A633046}
{CAA1488E-842B-433D-994D-1D3D0B5DD125} = {09CF91E5-5BAB-4650-A200-E5EA9A633046}
{3B5BF14D-F612-4C83-9EF6-E3EBFCD08766} = {4D661178-38FB-43E4-AA5F-9B0406919344}
@@ -221,4 +207,10 @@ Global
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {70143042-A862-47A8-A677-7C819DDC90DC}
EndGlobalSection
+ GlobalSection(SharedMSBuildProjectFiles) = preSolution
+ SMAPI.Internal\SMAPI.Internal.projitems*{0634ea4c-3b8f-42db-aea6-ca9e4ef6e92f}*SharedItemsImports = 5
+ SMAPI.Internal.Patching\SMAPI.Internal.Patching.projitems*{6c16e948-3e5c-47a7-bf4b-07a7469a87a5}*SharedItemsImports = 13
+ SMAPI.Internal\SMAPI.Internal.projitems*{85208f8d-6fd1-4531-be05-7142490f59fe}*SharedItemsImports = 13
+ SMAPI.Internal\SMAPI.Internal.projitems*{cd53ad6f-97f4-4872-a212-50c2a0fd3601}*SharedItemsImports = 5
+ EndGlobalSection
EndGlobal
diff --git a/src/SMAPI/Constants.cs b/src/SMAPI/Constants.cs
index 482ba291..1b80003c 100644
--- a/src/SMAPI/Constants.cs
+++ b/src/SMAPI/Constants.cs
@@ -13,11 +13,7 @@ using StardewModdingAPI.Framework.ModLoading;
using StardewModdingAPI.Toolkit.Framework;
using StardewModdingAPI.Toolkit.Utilities;
using StardewValley;
-#if HARMONY_2
using HarmonyLib;
-#else
-using Harmony;
-#endif
namespace StardewModdingAPI
{
/// Contains constants that are accessed before the game itself has been loaded.
@@ -44,6 +40,9 @@ namespace StardewModdingAPI
public static string StardewValleyBasePath { get; } = Path.Combine(EarlyConstants.StorageBasePath, "StardewValley");
/// The path to the internal folder.
public static string ExecutionPath { get; } = Path.Combine(EarlyConstants.StardewValleyBasePath, "smapi-internal");
+
+ /// The path to the game folder.
+ public static string GamePath { get; } = ExecutionPath;
#else
/// The path to the game folder.
public static string GamePath { get; } = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!;
diff --git a/src/SMAPI/Context.cs b/src/SMAPI/Context.cs
index c822908e..f27c9310 100644
--- a/src/SMAPI/Context.cs
+++ b/src/SMAPI/Context.cs
@@ -91,8 +91,11 @@ namespace StardewModdingAPI
public static bool HasRemotePlayers => Context.IsMultiplayer && !Game1.hasLocalClientsOnly;
/// Whether the current player is the main player. This is always true in single-player, and true when hosting in multiplayer.
+#if SMAPI_FOR_MOBILE
+ public static bool IsMainPlayer => Game1.IsMasterGame && Context.ScreenId == 0;// && TitleMenu.subMenu is not FarmhandMenu;
+#else
public static bool IsMainPlayer => Game1.IsMasterGame && Context.ScreenId == 0 && TitleMenu.subMenu is not FarmhandMenu;
-
+#endif
/*********
** Public methods
diff --git a/src/SMAPI/Events/AssetsInvalidatedEventArgs.cs b/src/SMAPI/Events/AssetsInvalidatedEventArgs.cs
index 614cdf49..b23dbbc0 100644
--- a/src/SMAPI/Events/AssetsInvalidatedEventArgs.cs
+++ b/src/SMAPI/Events/AssetsInvalidatedEventArgs.cs
@@ -11,11 +11,18 @@ namespace StardewModdingAPI.Events
** Accessors
*********/
/// The asset names that were invalidated.
+#if SMAPI_FOR_MOBILE
+ public IReadOnlyCollection Names { get; }
+#else
public IReadOnlySet Names { get; }
-
+#endif
/// The with any locale codes stripped.
/// For example, if contains a locale like Data/Bundles.fr-FR, this will have the name without locale like Data/Bundles. If the name has no locale, this field is equivalent.
+#if SMAPI_FOR_MOBILE
+ public IReadOnlyCollection NamesWithoutLocale { get; }
+#else
public IReadOnlySet NamesWithoutLocale { get; }
+#endif
/*********
diff --git a/src/SMAPI/Framework/ContentManagers/ModContentManager.cs b/src/SMAPI/Framework/ContentManagers/ModContentManager.cs
index 19d20d90..6088c7ac 100644
--- a/src/SMAPI/Framework/ContentManagers/ModContentManager.cs
+++ b/src/SMAPI/Framework/ContentManagers/ModContentManager.cs
@@ -88,8 +88,6 @@ namespace StardewModdingAPI.Framework.ContentManagers
#if SMAPI_FOR_MOBILE
this.Reflector = reflection;
#endif
- }
-
this.TryLocalizeKeys = false;
}
@@ -140,16 +138,7 @@ namespace StardewModdingAPI.Framework.ContentManagers
".json" => this.LoadDataFile(assetName, file),
".png" => this.LoadImageFile(assetName, file),
".tbin" or ".tmx" => this.LoadMapFile(assetName, file),
- ".xnb" => {
- asset = this.RawLoad(assetName, useCache: false);
- if (asset is Map map)
- {
- this.NormalizeTilesheetPaths(map);
- this.FixCustomTilesheetPaths(map, relativeMapPath: assetName);
- }
- this.ModedLoad(assetName, language)
- // this.LoadXnbFile(assetName)
- },
+ ".xnb" => this.LoadXnbFile(assetName),
_ => this.HandleUnknownFileType(assetName, file)
};
}
@@ -290,7 +279,11 @@ namespace StardewModdingAPI.Framework.ContentManagers
}
// convert to XNA pixel format
+#if SMAPI_FOR_MOBILE
+ var pixels = new Color[rawPixels.Length];
+#else
var pixels = GC.AllocateUninitializedArray(rawPixels.Length);
+#endif
for (int i = 0; i < pixels.Length; i++)
{
SKPMColor pixel = rawPixels[i];
@@ -322,6 +315,16 @@ namespace StardewModdingAPI.Framework.ContentManagers
/// The asset name relative to the loader root directory.
private T LoadXnbFile(IAssetName assetName)
{
+// #if SMAPI_FOR_MOBILE
+// T asset = this.RawLoad(assetName, useCache: false);
+// if (asset is Map map)
+// {
+// this.NormalizeTilesheetPaths(map);
+// this.FixCustomTilesheetPaths(map, relativeMapPath: assetName);
+// }
+//
+// return this.ModedLoad(assetName.Name, language);
+// #else
if (typeof(IRawTextureData).IsAssignableFrom(typeof(T)))
this.ThrowLoadError(assetName, ContentLoadErrorType.Other, $"can't read XNB file as type {typeof(IRawTextureData)}; that type can only be read from a PNG file.");
@@ -340,6 +343,7 @@ namespace StardewModdingAPI.Framework.ContentManagers
}
return asset;
+// #endif
}
/// Handle a request to load a file type that isn't supported by SMAPI.
diff --git a/src/SMAPI/Framework/Input/GamePadStateBuilder.cs b/src/SMAPI/Framework/Input/GamePadStateBuilder.cs
index 814ad9a8..007bf9c4 100644
--- a/src/SMAPI/Framework/Input/GamePadStateBuilder.cs
+++ b/src/SMAPI/Framework/Input/GamePadStateBuilder.cs
@@ -41,7 +41,7 @@ namespace StardewModdingAPI.Framework.Input
** Accessors
*********/
/// Whether the gamepad is currently connected.
- [MemberNotNullWhen(true, nameof(GamePadStateBuilder.ButtonStates))]
+ // [MemberNotNullWhen(true, nameof(GamePadStateBuilder.ButtonStates))]
public bool IsConnected { get; }
diff --git a/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs b/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs
index f4534dc1..1f529205 100644
--- a/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs
+++ b/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs
@@ -405,7 +405,7 @@ namespace StardewModdingAPI.Framework.ModLoading
}
// find or rewrite code
- InstructionMetadata instructionMetadata = new InstructionMetadata();
+ InstructionMetadata instructionMetadata = new InstructionMetadata(this.Monitor);
IInstructionHandler[] handlers = instructionMetadata.GetHandlers(this.ParanoidMode, platformChanged, this.RewriteMods).ToArray();
RecursiveRewriter rewriter = new RecursiveRewriter(
module: module,
diff --git a/src/SMAPI/Framework/ModLoading/AssemblyParseResult.cs b/src/SMAPI/Framework/ModLoading/AssemblyParseResult.cs
index b133f8d6..90ba4253 100644
--- a/src/SMAPI/Framework/ModLoading/AssemblyParseResult.cs
+++ b/src/SMAPI/Framework/ModLoading/AssemblyParseResult.cs
@@ -21,7 +21,7 @@ namespace StardewModdingAPI.Framework.ModLoading
public AssemblyLoadStatus Status;
/// Whether the is loaded and ready (i.e. the is not or ).
- [MemberNotNullWhen(true, nameof(AssemblyParseResult.Definition))]
+ // [MemberNotNullWhen(true, nameof(AssemblyParseResult.Definition))]
public bool HasDefinition => this.Status == AssemblyLoadStatus.Okay;
diff --git a/src/SMAPI/Framework/ModLoading/Finders/FieldFinder.cs b/src/SMAPI/Framework/ModLoading/Finders/FieldFinder.cs
index 1aaa6561..2cded71a 100644
--- a/src/SMAPI/Framework/ModLoading/Finders/FieldFinder.cs
+++ b/src/SMAPI/Framework/ModLoading/Finders/FieldFinder.cs
@@ -73,7 +73,7 @@ namespace StardewModdingAPI.Framework.ModLoading.Finders
return
fieldRef != null
&& fieldRef.DeclaringType.FullName == this.FullTypeName
- && fieldRef.Name == this.FieldName;
+ && this.FieldNames.Contains(fieldRef.Name);
}
}
}
diff --git a/src/SMAPI/Framework/ModLoading/ModMetadata.cs b/src/SMAPI/Framework/ModLoading/ModMetadata.cs
index ac7a6bbd..e7c6e43e 100644
--- a/src/SMAPI/Framework/ModLoading/ModMetadata.cs
+++ b/src/SMAPI/Framework/ModLoading/ModMetadata.cs
@@ -82,7 +82,7 @@ namespace StardewModdingAPI.Framework.ModLoading
public ModEntryModel? UpdateCheckData { get; private set; }
///
- [MemberNotNullWhen(true, nameof(ModMetadata.ContentPack))]
+ // [MemberNotNullWhen(true, nameof(ModMetadata.ContentPack))]
[SuppressMessage("ReSharper", "ConditionalAccessQualifierIsNonNullableAccordingToAPIContract", Justification = "The manifest may be null for broken mods while loading.")]
public bool IsContentPack => this.Manifest?.ContentPackFor != null;
@@ -184,7 +184,7 @@ namespace StardewModdingAPI.Framework.ModLoading
}
///
- [MemberNotNullWhen(true, nameof(IModInfo.Manifest))]
+ // [MemberNotNullWhen(true, nameof(IModInfo.Manifest))]
public bool HasManifest()
{
return this.Manifest != null;
diff --git a/src/SMAPI/Framework/ModLoading/PlatformAssemblyMap.cs b/src/SMAPI/Framework/ModLoading/PlatformAssemblyMap.cs
index 1b82935c..8187d036 100644
--- a/src/SMAPI/Framework/ModLoading/PlatformAssemblyMap.cs
+++ b/src/SMAPI/Framework/ModLoading/PlatformAssemblyMap.cs
@@ -55,7 +55,7 @@ namespace StardewModdingAPI.Framework.ModLoading
this.Targets = targetAssemblies;
this.TargetReferences = this.Targets.ToDictionary(assembly => assembly, assembly => AssemblyNameReference.Parse(assembly.FullName));
#if SMAPI_FOR_MOBILE
- this.TargetModules = this.Targets.ToDictionary(assembly => assembly, assembly => ModuleDefinition.ReadModule(Path.Combine(Constants.ExecutionPath, assembly.Modules.Single().FullyQualifiedName), new ReaderParameters { InMemory = true }));
+ this.TargetModules = this.Targets.ToDictionary(assembly => assembly, assembly => ModuleDefinition.ReadModule(Path.Combine(Constants.GamePath, assembly.Modules.Single().FullyQualifiedName), new ReaderParameters { InMemory = true }));
#else
this.TargetModules = this.Targets.ToDictionary(assembly => assembly, assembly => ModuleDefinition.ReadModule(assembly.Modules.Single().FullyQualifiedName, new ReaderParameters { InMemory = true }));
#endif
diff --git a/src/SMAPI/Framework/ModLoading/RewriteFacades/DebrisMethods.cs b/src/SMAPI/Framework/ModLoading/RewriteFacades/DebrisMethods.cs
deleted file mode 100644
index 9f05a576..00000000
--- a/src/SMAPI/Framework/ModLoading/RewriteFacades/DebrisMethods.cs
+++ /dev/null
@@ -1,85 +0,0 @@
-#if SMAPI_FOR_MOBILE
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Microsoft.Xna.Framework;
-using StardewValley;
-
-namespace StardewModdingAPI.Framework.ModLoading.RewriteFacades
-{
- public class DebrisMethods : Debris
- {
- public DebrisMethods(Item item, Vector2 debrisOrigin)
- : base()
- {
- base.init(item, debrisOrigin);
- }
-
- public DebrisMethods(int objectIndex, Vector2 debrisOrigin, Vector2 playerPosition)
- : base()
- {
- base.init(objectIndex, debrisOrigin, playerPosition);
- }
-
- public DebrisMethods(Item item, Vector2 debrisOrigin, Vector2 targetLocation)
- : base()
- {
- base.init(item, debrisOrigin, targetLocation);
- }
-
- public DebrisMethods(string spriteSheet, int numberOfChunks, Vector2 debrisOrigin)
- : base()
- {
- base.init(spriteSheet, numberOfChunks, debrisOrigin);
- }
-
- public DebrisMethods(string spriteSheet, Rectangle sourceRect, int numberOfChunks, Vector2 debrisOrigin)
- : base()
- {
- base.init(spriteSheet, sourceRect, numberOfChunks, debrisOrigin);
- }
-
- public DebrisMethods(int debrisType, int numberOfChunks, Vector2 debrisOrigin, Vector2 playerPosition)
- : base()
- {
- base.init(debrisType, numberOfChunks, debrisOrigin, playerPosition);
- }
-
- public DebrisMethods(int number, Vector2 debrisOrigin, Color messageColor, float scale, Character toHover)
- : base()
- {
- base.init(number, debrisOrigin, messageColor, scale, toHover);
- }
-
- public DebrisMethods(int debrisType, int numberOfChunks, Vector2 debrisOrigin, Vector2 playerPosition, float velocityMultiplayer)
- : base()
- {
- base.init(debrisType, numberOfChunks, debrisOrigin, playerPosition, velocityMultiplayer);
- }
-
- public DebrisMethods(string message, int numberOfChunks, Vector2 debrisOrigin, Color messageColor, float scale, float rotation)
- : base()
- {
- base.init(message, numberOfChunks, debrisOrigin, messageColor, scale, rotation);
- }
-
- public DebrisMethods(string spriteSheet, Rectangle sourceRect, int numberOfChunks, Vector2 debrisOrigin, Vector2 playerPosition, int groundLevel)
- : base()
- {
- base.init(spriteSheet, sourceRect, numberOfChunks, debrisOrigin, playerPosition, groundLevel);
- }
-
- public DebrisMethods(int type, int numberOfChunks, Vector2 debrisOrigin, Vector2 playerPosition, int groundLevel, int color = -1)
- : base()
- {
- base.init(type, numberOfChunks, debrisOrigin, playerPosition, groundLevel, color);
- }
- public DebrisMethods(string spriteSheet, Rectangle sourceRect, int numberOfChunks, Vector2 debrisOrigin, Vector2 playerPosition, int groundLevel, int sizeOfSourceRectSquares)
- : base()
- {
- base.init(spriteSheet, sourceRect, numberOfChunks, debrisOrigin, playerPosition, groundLevel, sizeOfSourceRectSquares);
- }
- }
-}
-#endif
diff --git a/src/SMAPI/Framework/ModLoading/RewriteFacades/Game1Methods.cs b/src/SMAPI/Framework/ModLoading/RewriteFacades/Game1Methods.cs
index cbc2dbc8..3954ff1c 100644
--- a/src/SMAPI/Framework/ModLoading/RewriteFacades/Game1Methods.cs
+++ b/src/SMAPI/Framework/ModLoading/RewriteFacades/Game1Methods.cs
@@ -11,6 +11,7 @@ namespace StardewModdingAPI.Framework.ModLoading.RewriteFacades
{
public class Game1Methods : Game1
{
+#if SMAPI_LEGACY_PATCH
public static RainDrop[] RainDropsProp => (typeof(RainManager).GetField("_rainDropList", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(RainManager.Instance) as List).ToArray();
public static bool IsRainingProp
@@ -45,6 +46,7 @@ namespace StardewModdingAPI.Framework.ModLoading.RewriteFacades
{
RainManager.Instance.Update(Game1.currentGameTime);
}
+#endif
[SuppressMessage("ReSharper", "CS0109", Justification = "The 'new' modifier applies when compiled on Windows.")]
public static new void warpFarmer(string locationName, int tileX, int tileY, bool flip)
@@ -54,7 +56,7 @@ namespace StardewModdingAPI.Framework.ModLoading.RewriteFacades
public static void removeSquareDebrisFromTile(int tileX, int tileY)
{
- Game1.currentLocation.debris.debrisNetCollection.Filter(debris => {
+ Game1.currentLocation.debris.Filter(debris => {
if ((debris.debrisType == 2) && (((int)(debris.Chunks[0].position.X / 64f)) == tileX))
{
return (debris.chunkFinalYLevel / 0x40) != tileY;
diff --git a/src/SMAPI/Framework/ModLoading/RewriteFacades/HarmonyInstanceMethods.cs b/src/SMAPI/Framework/ModLoading/RewriteFacades/HarmonyInstanceMethods.cs
index 236d3450..6130d0b2 100644
--- a/src/SMAPI/Framework/ModLoading/RewriteFacades/HarmonyInstanceMethods.cs
+++ b/src/SMAPI/Framework/ModLoading/RewriteFacades/HarmonyInstanceMethods.cs
@@ -1,22 +1,14 @@
#if SMAPI_FOR_MOBILE
using System.Reflection;
using System.Reflection.Emit;
-#if HARMONY_2
using HarmonyLib;
-#else
-using Harmony;
-#endif
namespace StardewModdingAPI.Framework.ModLoading.RewriteFacades
{
public class HarmonyInstanceMethods
{
public static MethodInfo Patch(
-#if HARMONY_2
Harmony instance,
-#else
- HarmonyInstance instance,
-#endif
MethodBase original,
HarmonyMethod prefix = null,
HarmonyMethod postfix = null,
@@ -33,22 +25,14 @@ namespace StardewModdingAPI.Framework.ModLoading.RewriteFacades
return null;
}
public static void PatchAll(
-#if HARMONY_2
Harmony instance
-#else
- HarmonyInstance instance
-#endif
)
{
if (Constants.HarmonyEnabled)
instance.PatchAll();
}
public static void PatchAllToAssembly(
-#if HARMONY_2
Harmony instance,
-#else
- HarmonyInstance instance,
-#endif
Assembly assembly)
{
if (Constants.HarmonyEnabled)
diff --git a/src/SMAPI/Framework/ModLoading/RewriteFacades/IClickableMenuMethods.cs b/src/SMAPI/Framework/ModLoading/RewriteFacades/IClickableMenuMethods.cs
index dba74484..edf67b0c 100644
--- a/src/SMAPI/Framework/ModLoading/RewriteFacades/IClickableMenuMethods.cs
+++ b/src/SMAPI/Framework/ModLoading/RewriteFacades/IClickableMenuMethods.cs
@@ -10,11 +10,14 @@ namespace StardewModdingAPI.Framework.ModLoading.RewriteFacades
{
public class IClickableMenuMethods : IClickableMenu
{
+#if SMAPI_LEGACY_PATCH
+
[SuppressMessage("ReSharper", "CS0109", Justification = "The 'new' modifier applies when compiled on Windows.")]
public static new void drawHoverText(SpriteBatch b, string text, SpriteFont font, int xOffset = 0, int yOffset = 0, int moneyAmounttoDisplayAtBottom = -1, string boldTitleText = null, int healAmountToDisplay = -1, string[] buffIconsToDsiplay = null, Item hoveredItem = null, int currencySymbol = 0, int extraItemToShowIndex = -1, int extraItemToShowAmount = -1, int overideX = -1, int overrideY = -1, float alpha = 1, CraftingRecipe craftingIngrediants = null, IList- additional_craft_materials = null)
{
drawHoverText(b, text, font, xOffset, yOffset, moneyAmounttoDisplayAtBottom, boldTitleText, healAmountToDisplay, buffIconsToDsiplay, hoveredItem, currencySymbol, extraItemToShowIndex, extraItemToShowAmount, overideX, overrideY, alpha, craftingIngrediants, -1, 80, -1, additional_craft_materials);
}
+#endif
[SuppressMessage("ReSharper", "CS0109", Justification = "The 'new' modifier applies when compiled on Windows.")]
public new void drawHorizontalPartition(SpriteBatch b, int yPosition, bool small = false, int red = -1, int green = -1, int blue = -1)
diff --git a/src/SMAPI/Framework/ModLoading/RewriteFacades/NPCMethods.cs b/src/SMAPI/Framework/ModLoading/RewriteFacades/NPCMethods.cs
deleted file mode 100644
index 05c37b7f..00000000
--- a/src/SMAPI/Framework/ModLoading/RewriteFacades/NPCMethods.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-#if SMAPI_FOR_MOBILE
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using StardewValley;
-
-namespace StardewModdingAPI.Framework.ModLoading.RewriteFacades
-{
- public class NPCMethods : NPC
- {
- public void reloadSprite()
- {
- base.reloadSprite(Game1.emergencyLoading);
- }
- public void checkSchedule(int timeOfDay)
- {
- base.checkSchedule(timeOfDay, Game1.emergencyLoading);
- }
- }
-}
-#endif
diff --git a/src/SMAPI/Framework/ModLoading/RewriteFacades/SpriteTextMethods.cs b/src/SMAPI/Framework/ModLoading/RewriteFacades/SpriteTextMethods.cs
index f11e6657..7f8e5b68 100644
--- a/src/SMAPI/Framework/ModLoading/RewriteFacades/SpriteTextMethods.cs
+++ b/src/SMAPI/Framework/ModLoading/RewriteFacades/SpriteTextMethods.cs
@@ -25,10 +25,12 @@ namespace StardewModdingAPI.Framework.ModLoading.RewriteFacades
SpriteText.drawString(b, s, x, y, 999999, -1, 999999, alpha, 0.088f, false, 0, placeHolderWidthText, color, scroll_text_alignment);
}
+#if SMAPI_LEGACY_PATCH
public static void drawStringWithScrollBackground(SpriteBatch b, string s, int x, int y, string placeHolderWidthText, float alpha, int color)
{
SpriteText.drawStringWithScrollBackground(b, s, x, y, placeHolderWidthText, alpha, color, 0.088f);
}
+#endif
}
}
#endif
diff --git a/src/SMAPI/Framework/ModLoading/RewriteFacades/WeatherDebrisMethods.cs b/src/SMAPI/Framework/ModLoading/RewriteFacades/WeatherDebrisMethods.cs
deleted file mode 100644
index 65c1338a..00000000
--- a/src/SMAPI/Framework/ModLoading/RewriteFacades/WeatherDebrisMethods.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-#if SMAPI_FOR_MOBILE
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Microsoft.Xna.Framework;
-using StardewValley;
-
-namespace StardewModdingAPI.Framework.ModLoading.RewriteFacades
-{
- public class WeatherDebrisMethods : WeatherDebris
- {
- public WeatherDebrisMethods(Vector2 position, int which, float rotationVelocity, float dx, float dy)
- : base(position, which, dx, dy)
- {
- }
- }
-}
-#endif
diff --git a/src/SMAPI/Framework/ModLoading/Rewriters/HeuristicFieldAccessibilityRewriter.cs b/src/SMAPI/Framework/ModLoading/Rewriters/HeuristicFieldAccessibilityRewriter.cs
index d85c9f38..b0530351 100644
--- a/src/SMAPI/Framework/ModLoading/Rewriters/HeuristicFieldAccessibilityRewriter.cs
+++ b/src/SMAPI/Framework/ModLoading/Rewriters/HeuristicFieldAccessibilityRewriter.cs
@@ -1,11 +1,7 @@
using System;
using System.Collections.Generic;
using System.Reflection;
-#if HARMONY_2
using HarmonyLib;
-#else
-using Harmony;
-#endif
using Mono.Cecil;
using Mono.Cecil.Cil;
using StardewModdingAPI.Framework.ModLoading.Framework;
@@ -27,10 +23,10 @@ namespace StardewModdingAPI.Framework.ModLoading.Rewriters
*********/
/// Construct an instance.
/// The assembly names to which to rewrite broken references.
- public HeuristicFieldAccessibilityRewriter(string[] rewriteReferencesToAssemblies)
+ public HeuristicFieldAccessibilityRewriter(HashSet rewriteReferencesToAssemblies)
: base(defaultPhrase: "field visibility changed to private") // ignored since we specify phrases
{
- this.RewriteReferencesToAssemblies = new HashSet(rewriteReferencesToAssemblies);
+ this.RewriteReferencesToAssemblies = rewriteReferencesToAssemblies;
}
///
diff --git a/src/SMAPI/Framework/ModLoading/Rewriters/ReferenceToMissingMemberRewriter.cs b/src/SMAPI/Framework/ModLoading/Rewriters/ReferenceToMissingMemberRewriter.cs
index 8f8bb5e3..0801b96b 100644
--- a/src/SMAPI/Framework/ModLoading/Rewriters/ReferenceToMissingMemberRewriter.cs
+++ b/src/SMAPI/Framework/ModLoading/Rewriters/ReferenceToMissingMemberRewriter.cs
@@ -1,6 +1,6 @@
using System.Collections.Generic;
using System.Linq;
-using Harmony;
+using HarmonyLib;
using Mono.Cecil;
using Mono.Cecil.Cil;
using StardewModdingAPI.Framework.ModLoading.Framework;
@@ -15,7 +15,7 @@ namespace StardewModdingAPI.Framework.ModLoading.Finders
** Fields
*********/
/// The assembly names to which to heuristically detect broken references.
- private readonly HashSet ValidateReferencesToAssemblies;
+ private readonly ISet ValidateReferencesToAssemblies;
/*********
@@ -23,10 +23,10 @@ namespace StardewModdingAPI.Framework.ModLoading.Finders
*********/
/// Construct an instance.
/// The assembly names to which to heuristically detect broken references.
- public ReferenceToMissingMemberRewriter(string[] validateReferencesToAssemblies)
+ public ReferenceToMissingMemberRewriter(ISet validateReferencesToAssemblies)
: base(defaultPhrase: "")
{
- this.ValidateReferencesToAssemblies = new HashSet(validateReferencesToAssemblies);
+ this.ValidateReferencesToAssemblies = validateReferencesToAssemblies;
}
///
diff --git a/src/SMAPI/Framework/Monitor.cs b/src/SMAPI/Framework/Monitor.cs
index 3940fc4a..37f629f7 100644
--- a/src/SMAPI/Framework/Monitor.cs
+++ b/src/SMAPI/Framework/Monitor.cs
@@ -25,10 +25,18 @@ namespace StardewModdingAPI.Framework
private readonly LogFileManager LogFile;
/// The maximum length of the values.
+#if SMAPI_FOR_MOBILE
+ private static readonly int MaxLevelLength = ((LogLevel[]) Enum.GetValues(typeof (LogLevel))).Max(level => level.ToString().Length);
+#else
private static readonly int MaxLevelLength = Enum.GetValues().Max(level => level.ToString().Length);
+#endif
/// The cached representation for each level when added to a log header.
+#if SMAPI_FOR_MOBILE
+ private static readonly Dictionary LogStrings = ((ConsoleLogLevel[]) Enum.GetValues(typeof (ConsoleLogLevel))).ToDictionary(level => level, level => level.ToString().ToUpper().PadRight(Monitor.MaxLevelLength));
+#else
private static readonly Dictionary LogStrings = Enum.GetValues().ToDictionary(level => level, level => level.ToString().ToUpper().PadRight(Monitor.MaxLevelLength));
+#endif
/// A cache of messages that should only be logged once.
private readonly HashSet LogOnceCache = new();
diff --git a/src/SMAPI/Framework/SCore.cs b/src/SMAPI/Framework/SCore.cs
index aecbcb6c..a95ddd8c 100644
--- a/src/SMAPI/Framework/SCore.cs
+++ b/src/SMAPI/Framework/SCore.cs
@@ -51,6 +51,7 @@ using StardewModdingAPI.Toolkit.Utilities;
using StardewModdingAPI.Toolkit.Utilities.PathLookups;
using StardewModdingAPI.Utilities;
using StardewValley;
+using StardewValley.Menus;
#if SMAPI_FOR_MOBILE
using StardewValley.Mobile;
#endif
@@ -111,10 +112,7 @@ namespace StardewModdingAPI.Framework
private SGameRunner Game = null!; // initialized very early
#endif
/// Manages input visible to the game.
- private SInputState Input => SGame.Input;
-
- /// The game's core multiplayer utility.
- private SMultiplayer Multiplayer => SGame.Multiplayer;
+ private SInputState Input => Instance.Input;
/// SMAPI's content manager.
private ContentCoordinator ContentCore = null!; // initialized very early
@@ -166,8 +164,11 @@ namespace StardewModdingAPI.Framework
#endif
/// A list of queued commands to parse and execute.
+#if SMAPI_FOR_MOBILE
+ internal readonly CommandQueue RawCommandQueue = new();
+#else
private readonly CommandQueue RawCommandQueue = new();
-
+#endif
/// A list of commands to execute on each screen.
private readonly PerScreen
> ScreenCommandQueue = new(() => new List());
@@ -314,14 +315,14 @@ namespace StardewModdingAPI.Framework
// new ScheduleErrorPatch(this.LogManager.MonitorForGame)
// );
// add exit handler
- this.CancellationToken.Token.Register(() =>
- {
- if (this.IsGameRunning)
- {
- this.LogManager.WriteCrashLog();
- this.Game.Exit();
- }
- });
+ // this.CancellationToken.Token.Register(() =>
+ // {
+ // if (this.IsGameRunning)
+ // {
+ // this.LogManager.WriteCrashLog();
+ // this.Game.Exit();
+ // }
+ // });
// set window titles
this.UpdateWindowTitles();
@@ -1677,6 +1678,7 @@ namespace StardewModdingAPI.Framework
this.Monitor.Log("Checking for updates...");
#if !SMAPI_FOR_MOBILE
+
// check SMAPI version
{
ISemanticVersion? updateFound = null;
diff --git a/src/SMAPI/Framework/SGame.cs b/src/SMAPI/Framework/SGame.cs
index 1646c4fa..851fad79 100644
--- a/src/SMAPI/Framework/SGame.cs
+++ b/src/SMAPI/Framework/SGame.cs
@@ -14,6 +14,7 @@ using StardewModdingAPI.Internal;
using StardewModdingAPI.Utilities;
using StardewValley;
using StardewValley.BellsAndWhistles;
+using StardewValley.Events;
using StardewValley.Locations;
using StardewValley.Menus;
using StardewValley.Tools;
@@ -22,6 +23,7 @@ using xTile.Layers;
using xTile.Tiles;
#if SMAPI_FOR_MOBILE
using System.Collections.Generic;
+using System.Threading.Tasks;
using StardewValley.Minigames;
using Rectangle = Microsoft.Xna.Framework.Rectangle;
using SObject = StardewValley.Object;
@@ -63,35 +65,10 @@ namespace StardewModdingAPI.Framework
private readonly Action OnContentLoaded;
#if SMAPI_FOR_MOBILE
- private readonly IReflectedField DrawActiveClickableMenuField;
- private readonly IReflectedField SpriteBatchBeginNextIDField;
- private readonly IReflectedField DrawHudField;
- private readonly IReflectedField> FarmerShadowsField;
private readonly IReflectedField DebugStringBuilderField;
- private readonly IReflectedField LightingBlendField;
+ private readonly IReflectedField NewDayTaskField;
- private readonly IReflectedMethod SpriteBatchBeginMethod;
- private readonly IReflectedMethod _spriteBatchBeginMethod;
- private readonly IReflectedMethod _spriteBatchEndMethod;
- private readonly IReflectedMethod DrawLoadingDotDotDotMethod;
- private readonly IReflectedMethod CheckToReloadGameLocationAfterDrawFailMethod;
private readonly IReflectedMethod DrawTapToMoveTargetMethod;
- private readonly IReflectedMethod DrawDayTimeMoneyBoxMethod;
- private readonly IReflectedMethod DrawAfterMapMethod;
- private readonly IReflectedMethod DrawToolbarMethod;
- private readonly IReflectedMethod DrawVirtualJoypadMethod;
- private readonly IReflectedMethod DrawMenuMouseCursorMethod;
- private readonly IReflectedMethod DrawFadeToBlackFullScreenRectMethod;
- private readonly IReflectedMethod DrawChatBoxMethod;
- private readonly IReflectedMethod DrawDialogueBoxForPinchZoomMethod;
- private readonly IReflectedMethod DrawUnscaledActiveClickableMenuForPinchZoomMethod;
- private readonly IReflectedMethod DrawNativeScaledActiveClickableMenuForPinchZoomMethod;
-
- // ReSharper disable once InconsistentNaming
- private readonly IReflectedMethod DrawHUDMessagesMethod;
-
- // ReSharper disable once InconsistentNaming
- private readonly IReflectedMethod DrawTutorialUIMethod;
private readonly IReflectedMethod DrawGreenPlacementBoundsMethod;
#endif
@@ -125,16 +102,7 @@ namespace StardewModdingAPI.Framework
/// Construct a content manager to read game content files.
/// This must be static because the game accesses it before the constructor is called.
- [NonInstancedStatic]
- public static Func? CreateContentManagerImpl;
-
-#if SMAPI_FOR_MOBILE
- public static SGame instance;
-
- public bool IsGameSuspended;
-
- public bool IsAfterInitialize = false;
-#endif
+ [NonInstancedStatic] public static Func? CreateContentManagerImpl;
/*********
** Public methods
@@ -161,7 +129,7 @@ namespace StardewModdingAPI.Framework
Game1.input = this.InitialInput = input;
Game1.multiplayer = this.InitialMultiplayer = multiplayer;
Game1.hooks = modHooks;
- this._locations = new ObservableCollection();
+ // this._locations = new ObservableCollection();
// init SMAPI
this.Monitor = monitor;
@@ -172,33 +140,12 @@ namespace StardewModdingAPI.Framework
this.OnContentLoaded = onContentLoaded;
#if SMAPI_FOR_MOBILE
- SGame.instance = this;
// init reflection fields
- this.DrawActiveClickableMenuField = this.Reflection.GetField(this, "_drawActiveClickableMenu");
- this.SpriteBatchBeginNextIDField = this.Reflection.GetField(typeof(Game1), "_spriteBatchBeginNextID");
- this.DrawHudField = this.Reflection.GetField(this, "_drawHUD");
- this.FarmerShadowsField = this.Reflection.GetField>(this, "_farmerShadows");
this.DebugStringBuilderField = this.Reflection.GetField(typeof(Game1), "_debugStringBuilder");
- this.LightingBlendField = this.Reflection.GetField(this, "lightingBlend");
- this.SpriteBatchBeginMethod = this.Reflection.GetMethod(this, "SpriteBatchBegin", new[] {typeof(float)});
- this._spriteBatchBeginMethod = this.Reflection.GetMethod(this, "_spriteBatchBegin", new[] {typeof(SpriteSortMode), typeof(BlendState), typeof(SamplerState), typeof(DepthStencilState), typeof(RasterizerState), typeof(Effect), typeof(Matrix)});
- this._spriteBatchEndMethod = this.Reflection.GetMethod(this, "_spriteBatchEnd", new Type[] { });
- this.DrawLoadingDotDotDotMethod = this.Reflection.GetMethod(this, "DrawLoadingDotDotDot", new[] {typeof(GameTime)});
- this.CheckToReloadGameLocationAfterDrawFailMethod = this.Reflection.GetMethod(this, "CheckToReloadGameLocationAfterDrawFail", new[] {typeof(string), typeof(Exception)});
- this.DrawTapToMoveTargetMethod = this.Reflection.GetMethod(this, "DrawTapToMoveTarget", new Type[] { });
- this.DrawDayTimeMoneyBoxMethod = this.Reflection.GetMethod(this, "DrawDayTimeMoneyBox", new Type[] { });
- this.DrawAfterMapMethod = this.Reflection.GetMethod(this, "DrawAfterMap", new Type[] { });
- this.DrawToolbarMethod = this.Reflection.GetMethod(this, "DrawToolbar", new Type[] { });
- this.DrawVirtualJoypadMethod = this.Reflection.GetMethod(this, "DrawVirtualJoypad", new Type[] { });
- this.DrawMenuMouseCursorMethod = this.Reflection.GetMethod(this, "DrawMenuMouseCursor", new Type[] { });
- this.DrawFadeToBlackFullScreenRectMethod = this.Reflection.GetMethod(this, "DrawFadeToBlackFullScreenRect", new Type[] { });
- this.DrawChatBoxMethod = this.Reflection.GetMethod(this, "DrawChatBox", new Type[] { });
- this.DrawDialogueBoxForPinchZoomMethod = this.Reflection.GetMethod(this, "DrawDialogueBoxForPinchZoom", new Type[] { });
- this.DrawUnscaledActiveClickableMenuForPinchZoomMethod = this.Reflection.GetMethod(this, "DrawUnscaledActiveClickableMenuForPinchZoom", new Type[] { });
- this.DrawNativeScaledActiveClickableMenuForPinchZoomMethod = this.Reflection.GetMethod(this, "DrawNativeScaledActiveClickableMenuForPinchZoom", new Type[] { });
- this.DrawHUDMessagesMethod = this.Reflection.GetMethod(this, "DrawHUDMessages", new Type[] { });
- this.DrawTutorialUIMethod = this.Reflection.GetMethod(this, "DrawTutorialUI", new Type[] { });
- this.DrawGreenPlacementBoundsMethod = this.Reflection.GetMethod(this, "DrawGreenPlacementBounds", new Type[] { });
+ this.NewDayTaskField = this.Reflection.GetField(this, "_newDayTask");
+
+ this.DrawTapToMoveTargetMethod = this.Reflection.GetMethod(this, "DrawTapToMoveTarget");
+ this.DrawGreenPlacementBoundsMethod = this.Reflection.GetMethod(this, "DrawGreenPlacementBounds");
#endif
}
@@ -257,7 +204,7 @@ namespace StardewModdingAPI.Framework
if (this.IsFirstTick)
{
this.Input.TrueUpdate();
- this.Watchers = new WatcherCore(this.Input, (ObservableCollection)this._locations);
+ this.Watchers = new WatcherCore(this.Input, this._locations);
}
// update
@@ -277,7 +224,7 @@ namespace StardewModdingAPI.Framework
/// The render target, if any.
[SuppressMessage("ReSharper", "InconsistentNaming", Justification = "copied from game code as-is")]
#if SMAPI_FOR_MOBILE
- protected override void _draw(GameTime gameTime, RenderTarget2D target_screen, RenderTarget2D toBuffer = null)
+ protected override void _draw(GameTime gameTime, RenderTarget2D target_screen)
{
Context.IsInDrawLoop = true;
try
@@ -316,7 +263,7 @@ namespace StardewModdingAPI.Framework
return;
}
- this.DrawImpl(gameTime, target_screen, toBuffer);
+ this.DrawImpl(gameTime, target_screen);
this.DrawCrashTimer.Reset();
}
catch (Exception ex)
@@ -415,1200 +362,766 @@ namespace StardewModdingAPI.Framework
[SuppressMessage("SMAPI.CommonErrors", "AvoidNetField", Justification = "copied from game code as-is")]
[SuppressMessage("ReSharper", "ConditionIsAlwaysTrueOrFalse", Justification = "Deliberate to minimize chance of errors when copying event calls into new versions of this code.")]
#if SMAPI_FOR_MOBILE
- private void DrawImpl(GameTime gameTime, RenderTarget2D target_screen, RenderTarget2D toBuffer = null)
+ private void DrawImpl(GameTime gameTime, RenderTarget2D target_screen)
{
- var events = this.Events;
- if (Game1.skipNextDrawCall)
+ showingHealthBar = false;
+ if ((this.NewDayTaskField.GetValue() != null) || this.isLocalMultiplayerNewDayActive)
{
- Game1.skipNextDrawCall = false;
+ base.GraphicsDevice.Clear(bgColor);
}
else
{
- this.DrawHudField.SetValue(false);
- this.DrawActiveClickableMenuField.SetValue(false);
- Game1.showingHealthBar = false;
- if (Game1._newDayTask != null)
+ Matrix? nullable;
+ if (target_screen != null)
{
- if (!Game1.showInterDayScroll)
- return;
- this.DrawSavingDotDotDot();
+ SetRenderTarget(target_screen);
+ }
+
+ if (this.IsSaving)
+ {
+ base.GraphicsDevice.Clear(bgColor);
+ PushUIMode();
+ IClickableMenu activeClickableMenu = Game1.activeClickableMenu;
+ if (activeClickableMenu != null)
+ {
+ nullable = null;
+ spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null, nullable);
+ activeClickableMenu.draw(spriteBatch);
+ spriteBatch.End();
+ }
+
+ if (overlayMenu != null)
+ {
+ spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null, null);
+ overlayMenu.draw(spriteBatch);
+ spriteBatch.End();
+ }
+
+ PopUIMode();
}
else
{
- if (target_screen != null && toBuffer == null)
+ base.GraphicsDevice.Clear(bgColor);
+ if (((Game1.activeClickableMenu != null) && options.showMenuBackground) && (Game1.activeClickableMenu.showWithoutTransparencyIfOptionIsSet() && !this.takingMapScreenshot))
{
- this.GraphicsDevice.SetRenderTarget(target_screen);
- }
-
- if (this.IsSaving)
- {
- this.GraphicsDevice.Clear(Game1.bgColor);
- this.renderScreenBuffer(BlendState.Opaque, toBuffer);
- if (Game1.activeClickableMenu != null)
+ PushUIMode();
+ spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null, null);
+ Game1.activeClickableMenu.drawBackground(spriteBatch);
+ for (IClickableMenu menu2 = Game1.activeClickableMenu; menu2 != null; menu2 = menu2.GetChildMenu())
{
- if (Game1.IsActiveClickableMenuNativeScaled)
- {
- Game1.BackupViewportAndZoom(divideByZoom: true);
- Game1.SetSpriteBatchBeginNextID("A1");
- this.SpriteBatchBeginMethod.Invoke(Game1.NativeZoomLevel);
- events.Rendering.RaiseEmpty();
- try
- {
- events.RenderingActiveMenu.RaiseEmpty();
- Game1.activeClickableMenu.draw(Game1.spriteBatch);
- events.RenderedActiveMenu.RaiseEmpty();
- }
- catch (Exception ex)
- {
- this.Monitor.Log($"The {Game1.activeClickableMenu.GetType().FullName} menu crashed while drawing itself during save. SMAPI will force it to exit to avoid crashing the game.\n{ex.GetLogSummary()}", LogLevel.Error);
- Game1.activeClickableMenu.exitThisMenu();
- }
-
- this._spriteBatchEndMethod.Invoke();
- Game1.RestoreViewportAndZoom();
- }
- else
- {
- Game1.BackupViewportAndZoom();
- Game1.SetSpriteBatchBeginNextID("A2");
- this.SpriteBatchBeginMethod.Invoke(1f);
- events.Rendering.RaiseEmpty();
- try
- {
- events.RenderingActiveMenu.RaiseEmpty();
- Game1.activeClickableMenu.draw(Game1.spriteBatch);
- events.RenderedActiveMenu.RaiseEmpty();
- }
- catch (Exception ex)
- {
- this.Monitor.Log($"The {Game1.activeClickableMenu.GetType().FullName} menu crashed while drawing itself during save. SMAPI will force it to exit to avoid crashing the game.\n{ex.GetLogSummary()}", LogLevel.Error);
- Game1.activeClickableMenu.exitThisMenu();
- }
-
- events.Rendered.RaiseEmpty();
- this._spriteBatchEndMethod.Invoke();
- Game1.RestoreViewportAndZoom();
- }
+ menu2.draw(spriteBatch);
}
- if (Game1.overlayMenu == null)
- return;
- Game1.BackupViewportAndZoom();
- Game1.SetSpriteBatchBeginNextID("B");
- this._spriteBatchBeginMethod.Invoke(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null, null);
- Game1.overlayMenu.draw(Game1.spriteBatch);
- this._spriteBatchEndMethod.Invoke();
- Game1.RestoreViewportAndZoom();
+ if (specialCurrencyDisplay != null)
+ {
+ specialCurrencyDisplay.Draw(spriteBatch);
+ }
+
+ spriteBatch.End();
+ this.drawOverlays(spriteBatch);
+ PopUIMode();
}
else
{
- this.GraphicsDevice.Clear(Game1.bgColor);
- if (Game1.activeClickableMenu != null && Game1.options.showMenuBackground && Game1.activeClickableMenu.showWithoutTransparencyIfOptionIsSet() && !this.takingMapScreenshot)
+ if (emergencyLoading)
{
- Matrix scale = Matrix.CreateScale(1f);
- Game1.SetSpriteBatchBeginNextID("C");
- this._spriteBatchBeginMethod.Invoke(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null, scale);
- events.Rendering.RaiseEmpty();
- try
+ if (!SeenConcernedApeLogo)
{
- Game1.activeClickableMenu.drawBackground(Game1.spriteBatch);
- events.RenderingActiveMenu.RaiseEmpty();
- Game1.activeClickableMenu.draw(Game1.spriteBatch);
- events.RenderedActiveMenu.RaiseEmpty();
- }
- catch (Exception ex)
- {
- this.Monitor.Log($"The {Game1.activeClickableMenu.GetType().FullName} menu crashed while drawing itself. SMAPI will force it to exit to avoid crashing the game.\n{ex.GetLogSummary()}", LogLevel.Error);
- Game1.activeClickableMenu.exitThisMenu();
+ PushUIMode();
+ nullable = null;
+ spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null, nullable);
+ if (logoFadeTimer < 0x1388)
+ {
+ spriteBatch.Draw(staminaRect, new Rectangle(0, 0, Game1.viewport.Width, Game1.viewport.Height), Color.White);
+ }
+
+ if (logoFadeTimer > 0x1194)
+ {
+ float num = Math.Min((float)1f, (float)(((float)(logoFadeTimer - 0x1194)) / 500f));
+ spriteBatch.Draw(staminaRect, new Rectangle(0, 0, Game1.viewport.Width, Game1.viewport.Height), Color.Black * num);
+ }
+
+ spriteBatch.Draw(titleButtonsTexture, new Vector2((float)(Game1.viewport.Width / 2), (float)((Game1.viewport.Height / 2) - 90)), new Rectangle(0xab + ((((logoFadeTimer / 100) % 2) == 0) ? 0x6f : 0), 0x137, 0x6f, 60), Color.White * ((logoFadeTimer < 500) ? (((float)logoFadeTimer) / 500f) : ((logoFadeTimer > 0x1194) ? (1f - (((float)(logoFadeTimer - 0x1194)) / 500f)) : 1f)), 0f, Vector2.Zero, (float)3f, SpriteEffects.None, 0.2f);
+ spriteBatch.Draw(titleButtonsTexture, new Vector2((float)((Game1.viewport.Width / 2) - 0x105), (float)((Game1.viewport.Height / 2) - 0x66)), new Rectangle((((logoFadeTimer / 100) % 2) == 0) ? 0x55 : 0, 0x132, 0x55, 0x45), Color.White * ((logoFadeTimer < 500) ? (((float)logoFadeTimer) / 500f) : ((logoFadeTimer > 0x1194) ? (1f - (((float)(logoFadeTimer - 0x1194)) / 500f)) : 1f)), 0f, Vector2.Zero, (float)3f, SpriteEffects.None, 0.2f);
+ spriteBatch.End();
+ PopUIMode();
}
- events.Rendered.RaiseEmpty();
- this._spriteBatchEndMethod.Invoke();
- this.drawOverlays(Game1.spriteBatch);
- this.renderScreenBufferTargetScreen(target_screen);
- if (Game1.overlayMenu == null)
- return;
- Game1.SetSpriteBatchBeginNextID("D");
- this._spriteBatchBeginMethod.Invoke(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null, new Matrix?());
- Game1.overlayMenu.draw(Game1.spriteBatch);
- this._spriteBatchEndMethod.Invoke();
+ logoFadeTimer -= gameTime.ElapsedGameTime.Milliseconds;
+ }
+
+ if (Game1.gameMode == 11)
+ {
+ spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null, null);
+ spriteBatch.DrawString(dialogueFont, content.LoadString(@"Strings\StringsFromCSFiles:Game1.cs.3685"), new Vector2(16f, 16f), Color.HotPink);
+ spriteBatch.DrawString(dialogueFont, content.LoadString(@"Strings\StringsFromCSFiles:Game1.cs.3686"), new Vector2(16f, 32f), new Color(0, 0xff, 0));
+ spriteBatch.DrawString(dialogueFont, parseText(errorMessage, dialogueFont, graphics.GraphicsDevice.Viewport.Width, 1f), new Vector2(16f, 48f), Color.White);
+ spriteBatch.End();
+ }
+ else if (currentMinigame != null)
+ {
+ currentMinigame.draw(spriteBatch);
+ if ((globalFade && !menuUp) && (!nameSelectUp || messagePause))
+ {
+ PushUIMode();
+ spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null, null);
+ spriteBatch.Draw(fadeToBlackRect, graphics.GraphicsDevice.Viewport.Bounds, Color.Black * ((Game1.gameMode == 0) ? (1f - fadeToBlackAlpha) : fadeToBlackAlpha));
+ spriteBatch.End();
+ PopUIMode();
+ }
+
+ PushUIMode();
+ this.drawOverlays(spriteBatch);
+ PopUIMode();
+ SetRenderTarget(target_screen);
+ }
+ else if (showingEndOfNightStuff)
+ {
+ PushUIMode();
+ spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null, null);
+ if (Game1.activeClickableMenu != null)
+ {
+ for (IClickableMenu menu3 = Game1.activeClickableMenu; menu3 != null; menu3 = menu3.GetChildMenu())
+ {
+ menu3.draw(spriteBatch);
+ }
+ }
+
+ spriteBatch.End();
+ this.drawOverlays(spriteBatch);
+ PopUIMode();
+ }
+ else if ((Game1.gameMode == 6) || ((Game1.gameMode == 3) && (currentLocation == null)))
+ {
+ PushUIMode();
+ base.GraphicsDevice.Clear(bgColor);
+ spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null, null);
+ string str = "";
+ for (int i = 0; i < ((gameTime.TotalGameTime.TotalMilliseconds % 999.0) / 333.0); i++)
+ {
+ str = str + ".";
+ }
+
+ string text1 = content.LoadString(@"Strings\StringsFromCSFiles:Game1.cs.3688");
+ string s = text1 + str;
+ string str3 = text1 + "... ";
+ int width = SpriteText.getWidthOfString(str3, 0xf423f);
+ int height = 0x40;
+ int x = 0x40;
+ int y = graphics.GraphicsDevice.Viewport.GetTitleSafeArea().Bottom - height;
+ int num6 = 20;
+ x = (xEdge > 0) ? (0x33 + xEdge) : (0x33 + num6);
+ y = (uiViewport.Height - 0x3f) - num6;
+ SpriteText.drawString(spriteBatch, s, x, y, 0xf423f, width, height, 1f, 0.88f, false, 0, str3, -1, SpriteText.ScrollTextAlignment.Left);
+ spriteBatch.End();
+ this.drawOverlays(spriteBatch);
+ byte gameMode = Game1.gameMode;
+ PopUIMode();
}
else
{
- if (Game1.emergencyLoading)
+ if (Game1.gameMode == 0)
{
- if (!Game1.SeenConcernedApeLogo)
- {
- Game1.SetSpriteBatchBeginNextID("E");
- this._spriteBatchBeginMethod.Invoke(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null, new Matrix?());
- if (Game1.logoFadeTimer < 5000)
- {
- Game1.spriteBatch.Draw(Game1.staminaRect, new Rectangle(0, 0, Game1.viewport.Width, Game1.viewport.Height), Color.White);
- }
-
- if (Game1.logoFadeTimer > 4500)
- {
- float scale = Math.Min(1f, (Game1.logoFadeTimer - 4500) / 500f);
- Game1.spriteBatch.Draw(Game1.staminaRect, new Rectangle(0, 0, Game1.viewport.Width, Game1.viewport.Height), Color.Black * scale);
- }
-
- Game1.spriteBatch.Draw(
- Game1.titleButtonsTexture,
- new Vector2(Game1.viewport.Width / 2, Game1.viewport.Height / 2 - 90),
- new Rectangle(171 + (Game1.logoFadeTimer / 100 % 2 == 0 ? 111 : 0), 311, 111, 60),
- Color.White * (Game1.logoFadeTimer < 500 ? Game1.logoFadeTimer / 500f : Game1.logoFadeTimer > 4500 ? 1f - (Game1.logoFadeTimer - 4500) / 500f : 1f),
- 0f,
- Vector2.Zero,
- 3f,
- SpriteEffects.None,
- 0.2f);
- Game1.spriteBatch.Draw(
- Game1.titleButtonsTexture,
- new Vector2(Game1.viewport.Width / 2 - 261, Game1.viewport.Height / 2 - 102),
- new Rectangle(Game1.logoFadeTimer / 100 % 2 == 0 ? 85 : 0, 306, 85, 69),
- Color.White * (Game1.logoFadeTimer < 500 ? Game1.logoFadeTimer / 500f : Game1.logoFadeTimer > 4500 ? 1f - (Game1.logoFadeTimer - 4500) / 500f : 1f),
- 0f,
- Vector2.Zero,
- 3f,
- SpriteEffects.None,
- 0.2f);
- this._spriteBatchEndMethod.Invoke();
- }
-
- Game1.logoFadeTimer -= gameTime.ElapsedGameTime.Milliseconds;
- }
-
- if (Game1.gameMode == Game1.errorLogMode)
- {
- Game1.SetSpriteBatchBeginNextID("F");
- this._spriteBatchBeginMethod.Invoke(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null, new Matrix?());
- events.Rendering.RaiseEmpty();
- Game1.spriteBatch.DrawString(Game1.dialogueFont, Game1.content.LoadString("Strings\\StringsFromCSFiles:Game1.cs.3685"), new Vector2(16f, 16f), Color.HotPink);
- Game1.spriteBatch.DrawString(Game1.dialogueFont, Game1.content.LoadString("Strings\\StringsFromCSFiles:Game1.cs.3686"), new Vector2(16f, 32f), new Color(0, 255, 0));
- Game1.spriteBatch.DrawString(Game1.dialogueFont, Game1.parseText(Game1.errorMessage, Game1.dialogueFont, Game1.graphics.GraphicsDevice.Viewport.Width), new Vector2(16f, 48f), Color.White);
- events.Rendered.RaiseEmpty();
- this._spriteBatchEndMethod.Invoke();
- }
- else if (Game1.currentMinigame != null)
- {
- Game1.currentMinigame.draw(Game1.spriteBatch);
- if (Game1.globalFade && !Game1.menuUp && (!Game1.nameSelectUp || Game1.messagePause))
- {
- Game1.SetSpriteBatchBeginNextID("G");
- this._spriteBatchBeginMethod.Invoke(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null, new Matrix?());
- Game1.spriteBatch.Draw(Game1.fadeToBlackRect, Game1.graphics.GraphicsDevice.Viewport.Bounds,
- Color.Black * (Game1.gameMode == Game1.titleScreenGameMode ? 1f - Game1.fadeToBlackAlpha : Game1.fadeToBlackAlpha));
- this._spriteBatchEndMethod.Invoke();
- }
-
- this.drawOverlays(Game1.spriteBatch);
- this.renderScreenBufferTargetScreen(target_screen);
- if (Game1.currentMinigame is FishingGame && Game1.activeClickableMenu != null)
- {
- Game1.SetSpriteBatchBeginNextID("A-A");
- this.SpriteBatchBeginMethod.Invoke(1f);
- Game1.activeClickableMenu.draw(Game1.spriteBatch);
- this._spriteBatchEndMethod.Invoke();
- this.drawOverlays(Game1.spriteBatch);
- }
- else if (Game1.currentMinigame is FantasyBoardGame && Game1.activeClickableMenu != null)
- {
- if (Game1.IsActiveClickableMenuNativeScaled)
- {
- Game1.BackupViewportAndZoom(true);
- Game1.SetSpriteBatchBeginNextID("A1");
- this.SpriteBatchBeginMethod.Invoke(Game1.NativeZoomLevel);
- Game1.activeClickableMenu.draw(Game1.spriteBatch);
- this._spriteBatchEndMethod.Invoke();
- Game1.RestoreViewportAndZoom();
- }
- else
- {
- Game1.BackupViewportAndZoom();
- Game1.SetSpriteBatchBeginNextID("A2");
- this.SpriteBatchBeginMethod.Invoke(1f);
- Game1.activeClickableMenu.draw(Game1.spriteBatch);
- this._spriteBatchEndMethod.Invoke();
- Game1.RestoreViewportAndZoom();
- }
- }
-
- this.DrawVirtualJoypadMethod.Invoke();
- }
- else if (Game1.showingEndOfNightStuff)
- {
- this.renderScreenBuffer(BlendState.Opaque);
- Game1.BackupViewportAndZoom(divideByZoom: true);
- Game1.SetSpriteBatchBeginNextID("A-B");
- this.SpriteBatchBeginMethod.Invoke(Game1.NativeZoomLevel);
- events.Rendering.RaiseEmpty();
- if (Game1.activeClickableMenu != null)
- {
- try
- {
- events.RenderingActiveMenu.RaiseEmpty();
- Game1.activeClickableMenu.draw(Game1.spriteBatch);
- events.RenderedActiveMenu.RaiseEmpty();
- }
- catch (Exception ex)
- {
- this.Monitor.Log($"The {Game1.activeClickableMenu.GetType().FullName} menu crashed while drawing itself during end-of-night-stuff. SMAPI will force it to exit to avoid crashing the game.\n{ex.GetLogSummary()}", LogLevel.Error);
- Game1.activeClickableMenu.exitThisMenu();
- }
- }
-
- events.Rendered.RaiseEmpty();
- this._spriteBatchEndMethod.Invoke();
- this.drawOverlays(Game1.spriteBatch);
- Game1.RestoreViewportAndZoom();
- }
- else if (Game1.gameMode == Game1.loadingMode || Game1.gameMode == Game1.playingGameMode && Game1.currentLocation == null)
- {
- this.SpriteBatchBeginMethod.Invoke(1f);
- events.Rendering.RaiseEmpty();
- this._spriteBatchEndMethod.Invoke();
- this.DrawLoadingDotDotDotMethod.Invoke(gameTime);
- this.SpriteBatchBeginMethod.Invoke(1f);
- events.Rendered.RaiseEmpty();
- this._spriteBatchEndMethod.Invoke();
- this.drawOverlays(Game1.spriteBatch);
- this.renderScreenBufferTargetScreen(target_screen);
- if (Game1.overlayMenu != null)
- {
- Game1.SetSpriteBatchBeginNextID("H");
- this._spriteBatchBeginMethod.Invoke(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null, new Matrix?());
- Game1.overlayMenu.draw(Game1.spriteBatch);
- this._spriteBatchEndMethod.Invoke();
- }
-
- //base.Draw(gameTime);
+ nullable = null;
+ spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null, nullable);
}
else
{
- Rectangle rectangle;
- byte batchOpens = 0;
- if (Game1.gameMode == Game1.titleScreenGameMode)
+ if (((Game1.gameMode == 3) && (dayOfMonth == 0)) && newDay)
{
- Game1.SetSpriteBatchBeginNextID("I");
- this._spriteBatchBeginMethod.Invoke(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null, new Matrix?());
- if (++batchOpens == 1)
- events.Rendering.RaiseEmpty();
+ base.Draw(gameTime);
+ return;
}
- else if (!Game1.drawGame)
+
+ if (drawLighting)
{
- Game1.SetSpriteBatchBeginNextID("J");
- this._spriteBatchBeginMethod.Invoke(SpriteSortMode.Deferred, BlendState.NonPremultiplied, SamplerState.PointClamp, null, null, null, new Matrix?());
- if (++batchOpens == 1)
- events.Rendering.RaiseEmpty();
- }
- else if (Game1.drawGame)
- {
- if (Game1.drawLighting && Game1.currentLocation != null)
+ Color ambientLight;
+ SetRenderTarget(lightmap);
+ base.GraphicsDevice.Clear(Color.White * 0f);
+ Matrix identity = Matrix.Identity;
+ if (this.useUnscaledLighting)
{
- this.GraphicsDevice.SetRenderTarget(Game1.lightmap);
- this.GraphicsDevice.Clear(Color.White * 0f);
- Game1.SetSpriteBatchBeginNextID("K");
- this._spriteBatchBeginMethod.Invoke(SpriteSortMode.Deferred, BlendState.NonPremultiplied, SamplerState.PointClamp, null, null, null, new Matrix?());
- if (++batchOpens == 1)
- events.Rendering.RaiseEmpty();
- Color color1 = !Game1.currentLocation.Name.StartsWith("UndergroundMine") || !(Game1.currentLocation is MineShaft)
- ? Game1.ambientLight.Equals(Color.White) || RainManager.Instance.isRaining && (bool) Game1.currentLocation.isOutdoors ? Game1.outdoorLight :
- Game1.ambientLight
- : ((MineShaft) Game1.currentLocation).getLightingColor(gameTime);
- Game1.spriteBatch.Draw(Game1.staminaRect, Game1.lightmap.Bounds, color1);
- foreach (LightSource currentLightSource in Game1.currentLightSources)
- {
- if (!RainManager.Instance.isRaining && !Game1.isDarkOut() || currentLightSource.lightContext.Value != LightSource.LightContext.WindowLight)
- {
- if (currentLightSource.PlayerID != 0L && currentLightSource.PlayerID != Game1.player.UniqueMultiplayerID)
- {
- Farmer farmerMaybeOffline = Game1.getFarmerMaybeOffline(currentLightSource.PlayerID);
- if (farmerMaybeOffline == null || farmerMaybeOffline.currentLocation != null && farmerMaybeOffline.currentLocation.Name != Game1.currentLocation.Name || farmerMaybeOffline.hidden)
- continue;
- }
- }
-
- if (Utility.isOnScreen(currentLightSource.position, (int) (currentLightSource.radius * 64.0 * 4.0)))
- {
- Texture2D lightTexture = currentLightSource.lightTexture;
- Vector2 position = Game1.GlobalToLocal(Game1.viewport, currentLightSource.position) / (Game1.options.lightingQuality / 2);
- Rectangle? sourceRectangle = currentLightSource.lightTexture.Bounds;
- Color color = currentLightSource.color;
- Rectangle bounds = currentLightSource.lightTexture.Bounds;
- double x = bounds.Center.X;
- bounds = currentLightSource.lightTexture.Bounds;
- double y = bounds.Center.Y;
- Vector2 origin = new Vector2((float) x, (float) y);
- double num = (double) currentLightSource.radius / (Game1.options.lightingQuality / 2);
- Game1.spriteBatch.Draw(lightTexture, position, sourceRectangle, color, 0.0f, origin, (float) num, SpriteEffects.None, 0.9f);
- }
- }
-
- this._spriteBatchEndMethod.Invoke();
- this.GraphicsDevice.SetRenderTarget(target_screen);
+ identity = Matrix.CreateScale(options.zoomLevel);
}
- if (Game1.bloomDay && Game1.bloom != null)
+ spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, SamplerState.PointClamp, null, null, null, new Matrix?(identity));
+ if (currentLocation.Name.StartsWith("UndergroundMine") && (currentLocation is MineShaft))
{
- Game1.bloom.BeginDraw();
+ ambientLight = (currentLocation as MineShaft).getLightingColor(gameTime);
}
-
- this.GraphicsDevice.Clear(Game1.bgColor);
- Game1.SetSpriteBatchBeginNextID("L");
- this._spriteBatchBeginMethod.Invoke(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null, new Matrix?());
- if (++batchOpens == 1)
- events.Rendering.RaiseEmpty();
- events.RenderingWorld.RaiseEmpty();
- this.SpriteBatchBeginNextIDField.SetValue("L1");
- if (Game1.background != null)
+ else if (!Game1.ambientLight.Equals(Color.White) && (!IsRainingHere(null) || (currentLocation.isOutdoors == null)))
{
- Game1.background.draw(Game1.spriteBatch);
- }
-
- this.SpriteBatchBeginNextIDField.SetValue("L2");
- Game1.mapDisplayDevice.BeginScene(Game1.spriteBatch);
- this.SpriteBatchBeginNextIDField.SetValue("L3");
- try
- {
- if (Game1.currentLocation != null)
- {
- Game1.currentLocation.Map.GetLayer("Back").Draw(Game1.mapDisplayDevice, Game1.viewport, Location.Origin, wrapAround: false, 4);
- this.SpriteBatchBeginNextIDField.SetValue("L4");
- }
- }
- catch (KeyNotFoundException exception)
- {
- this.CheckToReloadGameLocationAfterDrawFailMethod.Invoke("Back", exception);
- }
-
- this.SpriteBatchBeginNextIDField.SetValue("L5");
- if (Game1.currentLocation != null)
- {
- Game1.currentLocation.drawWater(Game1.spriteBatch);
- }
-
- this.SpriteBatchBeginNextIDField.SetValue("L6");
- this.FarmerShadowsField.GetValue().Clear();
- this.SpriteBatchBeginNextIDField.SetValue("L7");
- if (Game1.currentLocation != null && Game1.currentLocation.currentEvent != null && !Game1.currentLocation.currentEvent.isFestival && Game1.currentLocation.currentEvent.farmerActors.Count > 0)
- {
- this.SpriteBatchBeginNextIDField.SetValue("L8");
- foreach (Farmer farmerActor in Game1.currentLocation.currentEvent.farmerActors)
- {
- if (farmerActor.IsLocalPlayer && Game1.displayFarmer || !farmerActor.hidden)
- {
- this.FarmerShadowsField.GetValue().Add(farmerActor);
- }
- }
-
- this.SpriteBatchBeginNextIDField.SetValue("L9");
+ ambientLight = Game1.ambientLight;
}
else
{
- this.SpriteBatchBeginNextIDField.SetValue("L10");
- if (Game1.currentLocation != null)
- {
- this.SpriteBatchBeginNextIDField.SetValue("L11");
- foreach (Farmer farmer in Game1.currentLocation.farmers)
- {
- if (farmer.IsLocalPlayer && Game1.displayFarmer || !farmer.hidden)
- {
- this.FarmerShadowsField.GetValue().Add(farmer);
- }
- }
-
- this.SpriteBatchBeginNextIDField.SetValue("L12");
- }
+ ambientLight = outdoorLight;
}
- this.SpriteBatchBeginNextIDField.SetValue("L13");
- if (Game1.currentLocation != null && !Game1.currentLocation.shouldHideCharacters())
+ float num8 = 1f;
+ if (player.hasBuff(0x1a))
{
- this.SpriteBatchBeginNextIDField.SetValue("L14");
- if (Game1.CurrentEvent == null)
+ if (ambientLight == Color.White)
{
- this.SpriteBatchBeginNextIDField.SetValue("L15");
- foreach (NPC character in Game1.currentLocation.characters)
- {
- try
- {
- if (!character.swimming)
- {
- if (!character.HideShadow)
- {
- if (!character.IsInvisible)
- {
- if (!Game1.currentLocation.shouldShadowBeDrawnAboveBuildingsLayer(character.getTileLocation()))
- Game1.spriteBatch.Draw(
- Game1.shadowTexture,
- Game1.GlobalToLocal(Game1.viewport, character.Position + new Vector2(character.Sprite.SpriteWidth * 4 / 2f, character.GetBoundingBox().Height + (character.IsMonster ? 0 : 12))),
- Game1.shadowTexture.Bounds,
- Color.White,
- 0.0f,
- new Vector2(Game1.shadowTexture.Bounds.Center.X, Game1.shadowTexture.Bounds.Center.Y),
- (float) (4.0 + character.yJumpOffset / 40.0) * (float) character.scale,
- SpriteEffects.None,
- Math.Max(0.0f, character.getStandingY() / 10000f) - 1E-06f);
- }
- }
- }
- }
- catch (Exception ex)
- {
- Dictionary dictionary1 = new Dictionary();
- if (character != null)
- {
- dictionary1["name"] = character.name;
- dictionary1["Sprite"] = (character.Sprite != null).ToString();
- Dictionary dictionary2 = dictionary1;
- character.GetBoundingBox();
- bool flag = true;
- string str1 = flag.ToString();
- dictionary2["BoundingBox"] = str1;
- Dictionary dictionary3 = dictionary1;
- flag = true;
- string str2 = flag.ToString();
- dictionary3["shadowTexture.Bounds"] = str2;
- Dictionary dictionary4 = dictionary1;
- flag = Game1.currentLocation != null;
- string str3 = flag.ToString();
- dictionary4["currentLocation"] = str3;
- }
-
- Dictionary dictionary5 = dictionary1;
- Microsoft.AppCenter.Crashes.ErrorAttachmentLog[] errorAttachmentLogArray = Array.Empty();
- Microsoft.AppCenter.Crashes.Crashes.TrackError(ex, dictionary5, errorAttachmentLogArray);
- }
- }
-
- this.SpriteBatchBeginNextIDField.SetValue("L16");
+ ambientLight = new Color(0.75f, 0.75f, 0.75f);
}
else
{
- this.SpriteBatchBeginNextIDField.SetValue("L17");
- foreach (NPC actor in Game1.CurrentEvent.actors)
+ ambientLight.R = (byte)Utility.Lerp((float)ambientLight.R, 255f, 0.5f);
+ ambientLight.G = (byte)Utility.Lerp((float)ambientLight.G, 255f, 0.5f);
+ ambientLight.B = (byte)Utility.Lerp((float)ambientLight.B, 255f, 0.5f);
+ }
+
+ num8 = 0.33f;
+ }
+
+ spriteBatch.Draw(staminaRect, lightmap.Bounds, ambientLight);
+ foreach (LightSource source in currentLightSources)
+ {
+ if ((!IsRainingHere(null) && !isDarkOut()) || (source.lightContext.Value != LightSource.LightContext.WindowLight))
+ {
+ if ((source.PlayerID != 0) && (source.PlayerID != player.UniqueMultiplayerID))
{
- if (!actor.swimming && !actor.HideShadow && !Game1.currentLocation.shouldShadowBeDrawnAboveBuildingsLayer(actor.getTileLocation()))
+ Farmer farmer = getFarmerMaybeOffline(source.PlayerID);
+ if (((farmer == null) || ((farmer.currentLocation != null) && (farmer.currentLocation.Name != currentLocation.Name))) || (farmer.hidden != null))
{
- Game1.spriteBatch.Draw(Game1.shadowTexture, Game1.GlobalToLocal(Game1.viewport, actor.Position + new Vector2(actor.Sprite.SpriteWidth * 4 / 2f, actor.GetBoundingBox().Height + (!actor.IsMonster ? actor.Sprite.SpriteHeight <= 16 ? -4 : 12 : 0))), Game1.shadowTexture.Bounds, Color.White, 0f, new Vector2(Game1.shadowTexture.Bounds.Center.X, Game1.shadowTexture.Bounds.Center.Y), (4f + actor.yJumpOffset / 40f) * (float) actor.scale, SpriteEffects.None, Math.Max(0f, actor.getStandingY() / 10000f) - 1E-06f);
+ continue;
}
}
- this.SpriteBatchBeginNextIDField.SetValue("L18");
- }
-
- this.SpriteBatchBeginNextIDField.SetValue("L19");
- foreach (Farmer farmerShadow in this.FarmerShadowsField.GetValue())
- {
- if (!Game1.multiplayer.isDisconnecting(farmerShadow.UniqueMultiplayerID) &&
- !farmerShadow.swimming &&
- !farmerShadow.isRidingHorse() &&
- (Game1.currentLocation == null || !Game1.currentLocation.shouldShadowBeDrawnAboveBuildingsLayer(farmerShadow.getTileLocation())))
+ if (Utility.isOnScreen((Vector2)source.position, (int)((source.radius * 64f) * 4f)))
{
- Game1.spriteBatch.Draw(
- Game1.shadowTexture,
- Game1.GlobalToLocal(farmerShadow.Position + new Vector2(32f, 24f)),
- Game1.shadowTexture.Bounds,
- Color.White,
- 0.0f,
- new Vector2(Game1.shadowTexture.Bounds.Center.X, Game1.shadowTexture.Bounds.Center.Y), (float) (4.0 - (!farmerShadow.running && !farmerShadow.UsingTool || farmerShadow.FarmerSprite.currentAnimationIndex <= 1 ? 0.0 : Math.Abs(FarmerRenderer.featureYOffsetPerFrame[farmerShadow.FarmerSprite.CurrentFrame]) * 0.5)),
- SpriteEffects.None,
- 0.0f);
+ spriteBatch.Draw(source.lightTexture, GlobalToLocal(Game1.viewport, (Vector2)source.position) / ((float)(options.lightingQuality / 2)), new Rectangle?(source.lightTexture.Bounds), source.color.Value * num8, 0f, new Vector2((float)(source.lightTexture.Bounds.Width / 2), (float)(source.lightTexture.Bounds.Height / 2)), (float)(source.radius / ((float)(options.lightingQuality / 2))), SpriteEffects.None, 0.9f);
}
}
-
- this.SpriteBatchBeginNextIDField.SetValue("L20");
}
- this.SpriteBatchBeginNextIDField.SetValue("L21");
- try
+ spriteBatch.End();
+ SetRenderTarget(target_screen);
+ }
+
+ base.GraphicsDevice.Clear(bgColor);
+ nullable = null;
+ spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null, nullable);
+ if (background != null)
+ {
+ background.draw(spriteBatch);
+ }
+
+ currentLocation.drawBackground(spriteBatch);
+ mapDisplayDevice.BeginScene(spriteBatch);
+ currentLocation.Map.GetLayer("Back").Draw(mapDisplayDevice, Game1.viewport, Location.Origin, false, 4);
+ currentLocation.drawWater(spriteBatch);
+ spriteBatch.End();
+ nullable = null;
+ spriteBatch.Begin(SpriteSortMode.FrontToBack, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null, nullable);
+ currentLocation.drawFloorDecorations(spriteBatch);
+ spriteBatch.End();
+ nullable = null;
+ spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null, nullable);
+ this._farmerShadows.Clear();
+ if (((currentLocation.currentEvent != null) && !currentLocation.currentEvent.isFestival) && (currentLocation.currentEvent.farmerActors.Count > 0))
+ {
+ foreach (Farmer farmer2 in currentLocation.currentEvent.farmerActors)
{
- if (Game1.currentLocation != null)
+ if ((farmer2.IsLocalPlayer && displayFarmer) || (farmer2.hidden == null))
{
- Game1.currentLocation.Map.GetLayer("Buildings").Draw(Game1.mapDisplayDevice, Game1.viewport, Location.Origin, wrapAround: false, 4);
+ this._farmerShadows.Add(farmer2);
}
}
- catch (KeyNotFoundException exception2)
+ }
+ else
+ {
+ foreach (Farmer farmer3 in currentLocation.farmers)
{
- this.CheckToReloadGameLocationAfterDrawFailMethod.Invoke("Buildings", exception2);
- }
-
- this.SpriteBatchBeginNextIDField.SetValue("L22");
- Game1.mapDisplayDevice.EndScene();
- this.SpriteBatchBeginNextIDField.SetValue("L23");
- if (Game1.currentLocation != null && Game1.currentLocation.tapToMove.targetNPC != null)
- {
- Game1.spriteBatch.Draw(Game1.mouseCursors, Game1.GlobalToLocal(Game1.viewport, Game1.currentLocation.tapToMove.targetNPC.Position + new Vector2(Game1.currentLocation.tapToMove.targetNPC.Sprite.SpriteWidth * 4 / 2f - 32f, Game1.currentLocation.tapToMove.targetNPC.GetBoundingBox().Height + (!Game1.currentLocation.tapToMove.targetNPC.IsMonster ? 12 : 0) - 32)), new Rectangle(194, 388, 16, 16), Color.White, 0f, Vector2.Zero, 4f, SpriteEffects.None, 0.58f);
- }
-
- this.SpriteBatchBeginNextIDField.SetValue("L24");
- this._spriteBatchEndMethod.Invoke();
- this.SpriteBatchBeginNextIDField.SetValue("L25");
- Game1.SetSpriteBatchBeginNextID("M");
- this._spriteBatchBeginMethod.Invoke(SpriteSortMode.FrontToBack, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null, new Matrix?());
- this.SpriteBatchBeginNextIDField.SetValue("M1");
- if (Game1.currentLocation != null && !Game1.currentLocation.shouldHideCharacters())
- {
- this.SpriteBatchBeginNextIDField.SetValue("M2");
- if (Game1.CurrentEvent == null)
+ if ((farmer3.IsLocalPlayer && displayFarmer) || (farmer3.hidden == null))
{
- this.SpriteBatchBeginNextIDField.SetValue("M3");
- foreach (NPC character2 in Game1.currentLocation.characters)
+ this._farmerShadows.Add(farmer3);
+ }
+ }
+ }
+
+ if (!currentLocation.shouldHideCharacters())
+ {
+ if (CurrentEvent == null)
+ {
+ foreach (NPC npc in currentLocation.characters)
+ {
+ if (((npc.swimming == null) && !npc.HideShadow) && (!npc.IsInvisible && !this.checkCharacterTilesForShadowDrawFlag(npc)))
{
- if (!character2.swimming && !character2.HideShadow && Game1.currentLocation.shouldShadowBeDrawnAboveBuildingsLayer(character2.getTileLocation()))
- {
- Game1.spriteBatch.Draw(
- Game1.shadowTexture,
- Game1.GlobalToLocal(Game1.viewport, character2.Position + new Vector2(character2.Sprite.SpriteWidth * 4 / 2f, character2.GetBoundingBox().Height + (!character2.IsMonster ? 12 : 0))),
- Game1.shadowTexture.Bounds,
- Color.White,
- 0f,
- new Vector2(Game1.shadowTexture.Bounds.Center.X, Game1.shadowTexture.Bounds.Center.Y),
- (4f + character2.yJumpOffset / 40f) * (float) character2.scale, SpriteEffects.None,
- Math.Max(0f, character2.getStandingY() / 10000f) - 1E-06f);
- }
+ spriteBatch.Draw(shadowTexture, GlobalToLocal(Game1.viewport, (npc.GetShadowOffset() + npc.Position) + new Vector2(((float)(npc.GetSpriteWidthForPositioning() * 4)) / 2f, (float)(npc.GetBoundingBox().Height + (npc.IsMonster ? 0 : 12)))), new Rectangle?(shadowTexture.Bounds), Color.White, 0f, new Vector2((float)shadowTexture.Bounds.Center.X, (float)shadowTexture.Bounds.Center.Y), Math.Max((float)0f, (float)((4f + (((float)npc.yJumpOffset) / 40f)) * npc.scale)), SpriteEffects.None, Math.Max((float)0f, (float)(((float)npc.getStandingY()) / 10000f)) - 1E-06f);
}
-
- this.SpriteBatchBeginNextIDField.SetValue("M4");
}
- else
+ }
+ else
+ {
+ foreach (NPC npc2 in CurrentEvent.actors)
{
- this.SpriteBatchBeginNextIDField.SetValue("M5");
- foreach (NPC actor2 in Game1.CurrentEvent.actors)
+ if ((((CurrentEvent == null) || !CurrentEvent.ShouldHideCharacter(npc2)) && ((npc2.swimming == null) && !npc2.HideShadow)) && !this.checkCharacterTilesForShadowDrawFlag(npc2))
{
- if (!actor2.swimming && !actor2.HideShadow && Game1.currentLocation.shouldShadowBeDrawnAboveBuildingsLayer(actor2.getTileLocation()))
- {
- Game1.spriteBatch.Draw(
- Game1.shadowTexture,
- Game1.GlobalToLocal(Game1.viewport, actor2.Position + new Vector2(actor2.Sprite.SpriteWidth * 4 / 2f, actor2.GetBoundingBox().Height + (!actor2.IsMonster ? 12 : 0))),
- Game1.shadowTexture.Bounds,
- Color.White,
- 0f,
- new Vector2(Game1.shadowTexture.Bounds.Center.X, Game1.shadowTexture.Bounds.Center.Y),
- (4f + actor2.yJumpOffset / 40f) * (float) actor2.scale,
- SpriteEffects.None,
- Math.Max(0f, actor2.getStandingY() / 10000f) - 1E-06f);
- }
+ spriteBatch.Draw(shadowTexture, GlobalToLocal(Game1.viewport, (npc2.GetShadowOffset() + npc2.Position) + new Vector2(((float)(npc2.GetSpriteWidthForPositioning() * 4)) / 2f, (float)(npc2.GetBoundingBox().Height + (npc2.IsMonster ? 0 : ((npc2.Sprite.SpriteHeight <= 0x10) ? -4 : 12))))), new Rectangle?(shadowTexture.Bounds), Color.White, 0f, new Vector2((float)shadowTexture.Bounds.Center.X, (float)shadowTexture.Bounds.Center.Y), (float)(Math.Max((float)0f, (float)(4f + (((float)npc2.yJumpOffset) / 40f))) * npc2.scale), SpriteEffects.None, Math.Max((float)0f, (float)(((float)npc2.getStandingY()) / 10000f)) - 1E-06f);
}
-
- this.SpriteBatchBeginNextIDField.SetValue("M6");
}
+ }
- foreach (Farmer farmerShadow in this.FarmerShadowsField.GetValue())
+ foreach (Farmer farmer4 in this._farmerShadows)
+ {
+ if (((!multiplayer.isDisconnecting(farmer4.UniqueMultiplayerID) && (farmer4.swimming == null)) && (!farmer4.isRidingHorse() && !farmer4.IsSitting())) && ((currentLocation == null) || !this.checkCharacterTilesForShadowDrawFlag(farmer4)))
{
- this.SpriteBatchBeginNextIDField.SetValue("M7");
- float layerDepth = System.Math.Max(0.0001f, farmerShadow.getDrawLayer() + 0.00011f) - 0.0001f;
- if (!farmerShadow.swimming && !farmerShadow.isRidingHorse() && Game1.currentLocation != null && Game1.currentLocation.shouldShadowBeDrawnAboveBuildingsLayer(farmerShadow.getTileLocation()))
+ spriteBatch.Draw(shadowTexture, GlobalToLocal((farmer4.GetShadowOffset() + farmer4.Position) + new Vector2(32f, 24f)), new Rectangle?(shadowTexture.Bounds), Color.White, 0f, new Vector2((float)shadowTexture.Bounds.Center.X, (float)shadowTexture.Bounds.Center.Y), (float)(4f - (((farmer4.running || farmer4.UsingTool) && (farmer4.FarmerSprite.currentAnimationIndex > 1)) ? (Math.Abs(FarmerRenderer.featureYOffsetPerFrame[farmer4.FarmerSprite.CurrentFrame]) * 0.5f) : 0f)), SpriteEffects.None, 0f);
+ }
+ }
+ }
+
+ Layer layer = currentLocation.Map.GetLayer("Buildings");
+ layer.Draw(mapDisplayDevice, Game1.viewport, Location.Origin, false, 4);
+ mapDisplayDevice.EndScene();
+ if ((currentLocation != null) && (currentLocation.tapToMove.targetNPC != null))
+ {
+ spriteBatch.Draw(mouseCursors, GlobalToLocal(Game1.viewport, currentLocation.tapToMove.targetNPC.Position + new Vector2((((float)(currentLocation.tapToMove.targetNPC.Sprite.SpriteWidth * 4)) / 2f) - 32f, (float)((currentLocation.tapToMove.targetNPC.GetBoundingBox().Height + (currentLocation.tapToMove.targetNPC.IsMonster ? 0 : 12)) - 0x20))), new Rectangle(0xc2, 0x184, 0x10, 0x10), Color.White, 0f, Vector2.Zero, (float)4f, SpriteEffects.None, 0.58f);
+ }
+
+ spriteBatch.End();
+ nullable = null;
+ spriteBatch.Begin(SpriteSortMode.FrontToBack, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null, nullable);
+ if (!currentLocation.shouldHideCharacters())
+ {
+ if (CurrentEvent == null)
+ {
+ foreach (NPC npc3 in currentLocation.characters)
+ {
+ if (((npc3.swimming == null) && !npc3.HideShadow) && ((npc3.isInvisible == null) && this.checkCharacterTilesForShadowDrawFlag(npc3)))
{
- Game1.spriteBatch.Draw(
- Game1.shadowTexture,
- Game1.GlobalToLocal(farmerShadow.Position + new Vector2(32f, 24f)),
- Game1.shadowTexture.Bounds,
- Color.White,
- 0.0f,
- new Vector2(Game1.shadowTexture.Bounds.Center.X, Game1.shadowTexture.Bounds.Center.Y),
- (float) (4.0 - (!farmerShadow.running && !farmerShadow.UsingTool || farmerShadow.FarmerSprite.currentAnimationIndex <= 1 ? 0.0 : Math.Abs(FarmerRenderer.featureYOffsetPerFrame[farmerShadow.FarmerSprite.CurrentFrame]) * 0.5)),
- SpriteEffects.None,
- layerDepth);
+ spriteBatch.Draw(shadowTexture, GlobalToLocal(Game1.viewport, (npc3.GetShadowOffset() + npc3.Position) + new Vector2(((float)(npc3.GetSpriteWidthForPositioning() * 4)) / 2f, (float)(npc3.GetBoundingBox().Height + (npc3.IsMonster ? 0 : 12)))), new Rectangle?(shadowTexture.Bounds), Color.White, 0f, new Vector2((float)shadowTexture.Bounds.Center.X, (float)shadowTexture.Bounds.Center.Y), Math.Max((float)0f, (float)((4f + (((float)npc3.yJumpOffset) / 40f)) * npc3.scale)), SpriteEffects.None, Math.Max((float)0f, (float)(((float)npc3.getStandingY()) / 10000f)) - 1E-06f);
}
-
- this.SpriteBatchBeginNextIDField.SetValue("M8");
}
}
-
- this.SpriteBatchBeginNextIDField.SetValue("M9");
- if ((Game1.eventUp || Game1.killScreen) && !Game1.killScreen && Game1.currentLocation?.currentEvent != null)
+ else
{
- this.SpriteBatchBeginNextIDField.SetValue("M10");
- Game1.currentLocation.currentEvent.draw(Game1.spriteBatch);
- this.SpriteBatchBeginNextIDField.SetValue("M11");
- }
-
- this.SpriteBatchBeginNextIDField.SetValue("M12");
- if (Game1.currentLocation != null && Game1.player.currentUpgrade != null && Game1.player.currentUpgrade.daysLeftTillUpgradeDone <= 3 && Game1.currentLocation.Name.Equals("Farm"))
- {
- this.SpriteBatchBeginNextIDField.SetValue("M13");
- Game1.spriteBatch.Draw(
- Game1.player.currentUpgrade.workerTexture,
- Game1.GlobalToLocal(Game1.viewport, Game1.player.currentUpgrade.positionOfCarpenter),
- Game1.player.currentUpgrade.getSourceRectangle(),
- Color.White,
- 0f,
- Vector2.Zero,
- 1f,
- SpriteEffects.None,
- (Game1.player.currentUpgrade.positionOfCarpenter.Y + 48f) / 10000f);
- this.SpriteBatchBeginNextIDField.SetValue("M14");
- }
-
- this.SpriteBatchBeginNextIDField.SetValue("M15");
- Game1.currentLocation?.draw(Game1.spriteBatch);
- foreach (Vector2 key in Game1.crabPotOverlayTiles.Keys)
- {
- Tile tile = Game1.currentLocation.Map.GetLayer("Buildings").Tiles[(int) key.X, (int) key.Y];
- if (tile != null)
+ foreach (NPC npc4 in CurrentEvent.actors)
{
- Vector2 local = Game1.GlobalToLocal(Game1.viewport, key * 64f);
- Location location = new Location((int) local.X, (int) local.Y);
- Game1.mapDisplayDevice.DrawTile(tile, location, (float) (((double) key.Y * 64.0 - 1.0) / 10000.0));
- }
- }
-
- this.SpriteBatchBeginNextIDField.SetValue("M16");
- if (Game1.player.ActiveObject == null && (Game1.player.UsingTool || Game1.pickingTool) && Game1.player.CurrentTool != null && (!Game1.player.CurrentTool.Name.Equals("Seeds") || Game1.pickingTool))
- {
- this.SpriteBatchBeginNextIDField.SetValue("M17");
- Game1.drawTool(Game1.player);
- this.SpriteBatchBeginNextIDField.SetValue("M18");
- }
-
- this.SpriteBatchBeginNextIDField.SetValue("M19");
- if (Game1.currentLocation != null && Game1.currentLocation.Name.Equals("Farm"))
- {
- this.SpriteBatchBeginNextIDField.SetValue("M20");
- this.drawFarmBuildings();
- this.SpriteBatchBeginNextIDField.SetValue("M21");
- }
-
- if (Game1.tvStation >= 0)
- {
- this.SpriteBatchBeginNextIDField.SetValue("M22");
- Game1.spriteBatch.Draw(
- Game1.tvStationTexture,
- Game1.GlobalToLocal(Game1.viewport, new Vector2(400f, 160f)),
- new Rectangle(Game1.tvStation * 24, 0, 24, 15),
- Color.White,
- 0f,
- Vector2.Zero,
- 4f,
- SpriteEffects.None,
- 1E-08f);
- this.SpriteBatchBeginNextIDField.SetValue("M23");
- }
-
- this.SpriteBatchBeginNextIDField.SetValue("M24");
- if (Game1.panMode)
- {
- this.SpriteBatchBeginNextIDField.SetValue("M25");
- Game1.spriteBatch.Draw(Game1.fadeToBlackRect, new Rectangle((int) Math.Floor((Game1.getOldMouseX() + Game1.viewport.X) / 64.0) * 64 - Game1.viewport.X, (int) Math.Floor((Game1.getOldMouseY() + Game1.viewport.Y) / 64.0) * 64 - Game1.viewport.Y, 64, 64), Color.Lime * 0.75f);
- this.SpriteBatchBeginNextIDField.SetValue("M26");
- foreach (Warp warp in Game1.currentLocation?.warps)
- {
- Game1.spriteBatch.Draw(Game1.fadeToBlackRect, new Rectangle(warp.X * 64 - Game1.viewport.X, warp.Y * 64 - Game1.viewport.Y, 64, 64), Color.Red * 0.75f);
- }
-
- this.SpriteBatchBeginNextIDField.SetValue("M27");
- }
-
- this.SpriteBatchBeginNextIDField.SetValue("M28");
- Game1.mapDisplayDevice.BeginScene(Game1.spriteBatch);
- this.SpriteBatchBeginNextIDField.SetValue("M29");
- try
- {
- Game1.currentLocation?.Map.GetLayer("Front").Draw(Game1.mapDisplayDevice, Game1.viewport, Location.Origin, wrapAround: false, 4);
- this.SpriteBatchBeginNextIDField.SetValue("M30");
- }
- catch (KeyNotFoundException exception3)
- {
- this.CheckToReloadGameLocationAfterDrawFailMethod.Invoke("Front", exception3);
- }
-
- this.SpriteBatchBeginNextIDField.SetValue("M31");
- Game1.mapDisplayDevice.EndScene();
- this.SpriteBatchBeginNextIDField.SetValue("M32");
- Game1.currentLocation?.drawAboveFrontLayer(Game1.spriteBatch);
- this.SpriteBatchBeginNextIDField.SetValue("M33");
- if (Game1.currentLocation != null &&
- Game1.currentLocation.tapToMove.targetNPC == null &&
- (Game1.displayHUD || Game1.eventUp) &&
- Game1.currentBillboard == 0 &&
- Game1.gameMode == Game1.playingGameMode &&
- !Game1.freezeControls &&
- !Game1.panMode &&
- !Game1.HostPaused)
- {
- this.SpriteBatchBeginNextIDField.SetValue("M34");
- this.DrawTapToMoveTargetMethod.Invoke();
- this.SpriteBatchBeginNextIDField.SetValue("M35");
- }
-
- this.SpriteBatchBeginNextIDField.SetValue("M36");
- this._spriteBatchEndMethod.Invoke();
- Game1.SetSpriteBatchBeginNextID("N");
- this._spriteBatchBeginMethod.Invoke(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null, new Matrix?());
- if (Game1.currentLocation != null &&
- Game1.displayFarmer &&
- Game1.player.ActiveObject != null &&
- (bool) Game1.player.ActiveObject.bigCraftable &&
- this.checkBigCraftableBoundariesForFrontLayer() &&
- Game1.currentLocation.Map.GetLayer("Front").PickTile(new Location(Game1.player.getStandingX(), Game1.player.getStandingY()), Game1.viewport.Size) == null)
- {
- Game1.drawPlayerHeldObject(Game1.player);
- }
- else if (Game1.displayFarmer && Game1.player.ActiveObject != null)
- {
- if (Game1.currentLocation != null && Game1.currentLocation.Map.GetLayer("Front").PickTile(new Location((int) Game1.player.Position.X, (int) Game1.player.Position.Y - 38), Game1.viewport.Size) == null || Game1.currentLocation.Map.GetLayer("Front").PickTile(new Location((int) Game1.player.Position.X, (int) Game1.player.Position.Y - 38), Game1.viewport.Size).TileIndexProperties.ContainsKey("FrontAlways"))
- {
- Layer layer1 = Game1.currentLocation.Map.GetLayer("Front");
- rectangle = Game1.player.GetBoundingBox();
- Location mapDisplayLocation1 = new Location(rectangle.Right, (int) Game1.player.Position.Y - 38);
- Size size1 = Game1.viewport.Size;
- if (layer1.PickTile(mapDisplayLocation1, size1) != null)
+ if ((((CurrentEvent == null) || !CurrentEvent.ShouldHideCharacter(npc4)) && ((npc4.swimming == null) && !npc4.HideShadow)) && this.checkCharacterTilesForShadowDrawFlag(npc4))
{
- Layer layer2 = Game1.currentLocation.Map.GetLayer("Front");
- rectangle = Game1.player.GetBoundingBox();
- Location mapDisplayLocation2 = new Location(rectangle.Right, (int) Game1.player.Position.Y - 38);
- Size size2 = Game1.viewport.Size;
- if (layer2.PickTile(mapDisplayLocation2, size2).TileIndexProperties.ContainsKey("FrontAlways"))
- goto label_183;
+ spriteBatch.Draw(shadowTexture, GlobalToLocal(Game1.viewport, (npc4.GetShadowOffset() + npc4.Position) + new Vector2(((float)(npc4.GetSpriteWidthForPositioning() * 4)) / 2f, (float)(npc4.GetBoundingBox().Height + (npc4.IsMonster ? 0 : 12)))), new Rectangle?(shadowTexture.Bounds), Color.White, 0f, new Vector2((float)shadowTexture.Bounds.Center.X, (float)shadowTexture.Bounds.Center.Y), Math.Max((float)0f, (float)((4f + (((float)npc4.yJumpOffset) / 40f)) * npc4.scale)), SpriteEffects.None, Math.Max((float)0f, (float)(((float)npc4.getStandingY()) / 10000f)) - 1E-06f);
}
- else
- goto label_183;
}
-
- Game1.drawPlayerHeldObject(Game1.player);
}
- label_183:
- if (Game1.currentLocation != null
- && (Game1.player.UsingTool || Game1.pickingTool)
- && Game1.player.CurrentTool != null
- && (!Game1.player.CurrentTool.Name.Equals("Seeds") || Game1.pickingTool)
- && Game1.currentLocation.Map.GetLayer("Front").PickTile(new Location(Game1.player.getStandingX(), (int) Game1.player.Position.Y - 38), Game1.viewport.Size) != null && Game1.currentLocation.Map.GetLayer("Front").PickTile(new Location(Game1.player.getStandingX(), Game1.player.getStandingY()), Game1.viewport.Size) == null)
- Game1.drawTool(Game1.player);
- if (Game1.currentLocation != null && Game1.currentLocation.Map.GetLayer("AlwaysFront") != null)
+ foreach (Farmer farmer5 in this._farmerShadows)
{
- Game1.mapDisplayDevice.BeginScene(Game1.spriteBatch);
- try
+ float layerDepth = Math.Max((float)0.0001f, (float)(farmer5.getDrawLayer() + 0.00011f)) - 0.0001f;
+ if ((((farmer5.swimming == null) && !farmer5.isRidingHorse()) && (!farmer5.IsSitting() && (currentLocation != null))) && this.checkCharacterTilesForShadowDrawFlag(farmer5))
{
- Game1.currentLocation.Map.GetLayer("AlwaysFront").Draw(Game1.mapDisplayDevice, Game1.viewport, Location.Origin, wrapAround: false, 4);
+ spriteBatch.Draw(shadowTexture, GlobalToLocal((farmer5.GetShadowOffset() + farmer5.Position) + new Vector2(32f, 24f)), new Rectangle?(shadowTexture.Bounds), Color.White, 0f, new Vector2((float)shadowTexture.Bounds.Center.X, (float)shadowTexture.Bounds.Center.Y), (float)(4f - (((farmer5.running || farmer5.UsingTool) && (farmer5.FarmerSprite.currentAnimationIndex > 1)) ? (Math.Abs(FarmerRenderer.featureYOffsetPerFrame[farmer5.FarmerSprite.CurrentFrame]) * 0.5f) : 0f)), SpriteEffects.None, layerDepth);
}
- catch (KeyNotFoundException exception4)
- {
- this.CheckToReloadGameLocationAfterDrawFailMethod.Invoke("AlwaysFront", exception4);
- }
-
- Game1.mapDisplayDevice.EndScene();
}
+ }
- if (Game1.toolHold > 400f && Game1.player.CurrentTool.UpgradeLevel >= 1 && Game1.player.canReleaseTool)
+ if ((eventUp || killScreen) && (!killScreen && (currentLocation.currentEvent != null)))
+ {
+ currentLocation.currentEvent.draw(spriteBatch);
+ }
+
+ if (((player.currentUpgrade != null) && (player.currentUpgrade.daysLeftTillUpgradeDone <= 3)) && currentLocation.Name.Equals("Farm"))
+ {
+ spriteBatch.Draw(player.currentUpgrade.workerTexture, GlobalToLocal(Game1.viewport, player.currentUpgrade.positionOfCarpenter), new Rectangle?(player.currentUpgrade.getSourceRectangle()), Color.White, 0f, Vector2.Zero, (float)1f, SpriteEffects.None, (player.currentUpgrade.positionOfCarpenter.Y + 48f) / 10000f);
+ }
+
+ currentLocation.draw(spriteBatch);
+ foreach (KeyValuePair pair in crabPotOverlayTiles)
+ {
+ Vector2 key = pair.Key;
+ Tile tile = layer.Tiles[(int)key.X, (int)key.Y];
+ if (tile != null)
{
- Color color = Color.White;
- switch ((int) ((double) Game1.toolHold / 600.0) + 2)
- {
- case 1:
- color = Tool.copperColor;
- break;
- case 2:
- color = Tool.steelColor;
- break;
- case 3:
- color = Tool.goldColor;
- break;
- case 4:
- color = Tool.iridiumColor;
- break;
- }
+ Vector2 vector2 = GlobalToLocal(Game1.viewport, key * 64f);
+ Location location = new Location((int)vector2.X, (int)vector2.Y);
+ mapDisplayDevice.DrawTile(tile, location, ((key.Y * 64f) - 1f) / 10000f);
+ }
+ }
- Game1.spriteBatch.Draw(Game1.littleEffect, new Rectangle((int) Game1.player.getLocalPosition(Game1.viewport).X - 2, (int) Game1.player.getLocalPosition(Game1.viewport).Y - (!Game1.player.CurrentTool.Name.Equals("Watering Can") ? 64 : 0) - 2, (int) (Game1.toolHold % 600f * 0.08f) + 4, 12), Color.Black);
- Game1.spriteBatch.Draw(Game1.littleEffect, new Rectangle((int) Game1.player.getLocalPosition(Game1.viewport).X, (int) Game1.player.getLocalPosition(Game1.viewport).Y - (!Game1.player.CurrentTool.Name.Equals("Watering Can") ? 64 : 0), (int) (Game1.toolHold % 600f * 0.08f), 8), color);
+ if (eventUp && (currentLocation.currentEvent != null))
+ {
+ string messageToScreen = currentLocation.currentEvent.messageToScreen;
+ }
+
+ if (((player.ActiveObject == null) && (player.UsingTool || pickingTool)) && ((player.CurrentTool != null) && (!player.CurrentTool.Name.Equals("Seeds") || pickingTool)))
+ {
+ drawTool(player);
+ }
+
+ if (currentLocation.Name.Equals("Farm"))
+ {
+ this.drawFarmBuildings();
+ }
+
+ if (tvStation >= 0)
+ {
+ spriteBatch.Draw(tvStationTexture, GlobalToLocal(Game1.viewport, new Vector2(400f, 160f)), new Rectangle(tvStation * 0x18, 0, 0x18, 15), Color.White, 0f, Vector2.Zero, (float)4f, SpriteEffects.None, 1E-08f);
+ }
+
+ if (panMode)
+ {
+ spriteBatch.Draw(fadeToBlackRect, new Rectangle((((int)Math.Floor((double)(((double)(getOldMouseX() + Game1.viewport.X)) / 64.0))) * 0x40) - Game1.viewport.X, (((int)Math.Floor((double)(((double)(getOldMouseY() + Game1.viewport.Y)) / 64.0))) * 0x40) - Game1.viewport.Y, 0x40, 0x40), Color.Lime * 0.75f);
+ foreach (Warp warp in currentLocation.warps)
+ {
+ spriteBatch.Draw(fadeToBlackRect, new Rectangle((warp.X * 0x40) - Game1.viewport.X, (warp.Y * 0x40) - Game1.viewport.Y, 0x40, 0x40), Color.Red * 0.75f);
+ }
+ }
+
+ mapDisplayDevice.BeginScene(spriteBatch);
+ currentLocation.Map.GetLayer("Front").Draw(mapDisplayDevice, Game1.viewport, Location.Origin, false, 4);
+ mapDisplayDevice.EndScene();
+ currentLocation.drawAboveFrontLayer(spriteBatch);
+ if ((((currentLocation.tapToMove.targetNPC == null) && (displayHUD || eventUp)) && (((currentBillboard == 0) && (Game1.gameMode == 3)) && (!freezeControls && !panMode))) && !HostPaused)
+ {
+ this.DrawTapToMoveTargetMethod.Invoke();
+ }
+
+ spriteBatch.End();
+ nullable = null;
+ spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null, nullable);
+ if (currentLocation.Map.GetLayer("AlwaysFront") != null)
+ {
+ mapDisplayDevice.BeginScene(spriteBatch);
+ currentLocation.Map.GetLayer("AlwaysFront").Draw(mapDisplayDevice, Game1.viewport, Location.Origin, false, 4);
+ mapDisplayDevice.EndScene();
+ }
+
+ if (((toolHold > 400f) && (player.CurrentTool.UpgradeLevel >= 1)) && player.canReleaseTool)
+ {
+ Color white = Color.White;
+ switch ((((int)(toolHold / 600f)) + 2))
+ {
+ case 1:
+ white = Tool.copperColor;
+ break;
+
+ case 2:
+ white = Tool.steelColor;
+ break;
+
+ case 3:
+ white = Tool.goldColor;
+ break;
+
+ case 4:
+ white = Tool.iridiumColor;
+ break;
}
+ spriteBatch.Draw(littleEffect, new Rectangle(((int)player.getLocalPosition(Game1.viewport).X) - 2, (((int)player.getLocalPosition(Game1.viewport).Y) - (player.CurrentTool.Name.Equals("Watering Can") ? 0 : 0x40)) - 2, ((int)((toolHold % 600f) * 0.08f)) + 4, 12), Color.Black);
+ spriteBatch.Draw(littleEffect, new Rectangle((int)player.getLocalPosition(Game1.viewport).X, ((int)player.getLocalPosition(Game1.viewport).Y) - (player.CurrentTool.Name.Equals("Watering Can") ? 0 : 0x40), (int)((toolHold % 600f) * 0.08f), 8), white);
+ }
+
+ if (!IsFakedBlackScreen())
+ {
this.drawWeather(gameTime, target_screen);
- if (Game1.farmEvent != null)
- {
- Game1.farmEvent.draw(Game1.spriteBatch);
- }
-
- if (Game1.currentLocation != null && Game1.currentLocation.LightLevel > 0f && Game1.timeOfDay < 2000)
- {
- Game1.spriteBatch.Draw(Game1.fadeToBlackRect, Game1.graphics.GraphicsDevice.Viewport.Bounds, Color.Black * Game1.currentLocation.LightLevel);
- }
-
- if (Game1.screenGlow)
- {
- Game1.spriteBatch.Draw(Game1.fadeToBlackRect, Game1.graphics.GraphicsDevice.Viewport.Bounds, Game1.screenGlowColor * Game1.screenGlowAlpha);
- }
-
- Game1.currentLocation?.drawAboveAlwaysFrontLayer(Game1.spriteBatch);
- if (Game1.player.CurrentTool != null && Game1.player.CurrentTool is FishingRod && ((Game1.player.CurrentTool as FishingRod).isTimingCast || (Game1.player.CurrentTool as FishingRod).castingChosenCountdown > 0f || (Game1.player.CurrentTool as FishingRod).fishCaught || (Game1.player.CurrentTool as FishingRod).showingTreasure))
- {
- Game1.player.CurrentTool.draw(Game1.spriteBatch);
- }
-
- this._spriteBatchEndMethod.Invoke();
- Game1.SetSpriteBatchBeginNextID("O");
- this._spriteBatchBeginMethod.Invoke(SpriteSortMode.FrontToBack, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null, new Matrix?());
- if (Game1.eventUp && Game1.currentLocation != null && Game1.currentLocation.currentEvent != null)
- {
- Game1.currentLocation.currentEvent.drawAboveAlwaysFrontLayer(Game1.spriteBatch);
- foreach (NPC actor in Game1.currentLocation.currentEvent.actors)
- {
- if (actor.isEmoting)
- {
- Vector2 localPosition = actor.getLocalPosition(Game1.viewport);
- localPosition.Y -= 140f;
- if (actor.Age == 2)
- {
- localPosition.Y += 32f;
- }
- else if (actor.Gender == 1)
- {
- localPosition.Y += 10f;
- }
-
- Game1.spriteBatch.Draw(Game1.emoteSpriteSheet, localPosition, new Rectangle(actor.CurrentEmoteIndex * 16 % Game1.emoteSpriteSheet.Width, actor.CurrentEmoteIndex * 16 / Game1.emoteSpriteSheet.Width * 16, 16, 16), Color.White, 0f, Vector2.Zero, 4f, SpriteEffects.None, actor.getStandingY() / 10000f);
- }
- }
- }
-
- this._spriteBatchEndMethod.Invoke();
- if (Game1.drawLighting)
- {
- Game1.SetSpriteBatchBeginNextID("P");
- this._spriteBatchBeginMethod.Invoke(SpriteSortMode.Deferred, this.LightingBlendField.GetValue(), SamplerState.LinearClamp, null, null, null, new Matrix?());
- Game1.spriteBatch.Draw(Game1.lightmap, Vector2.Zero, Game1.lightmap.Bounds, Color.White, 0f, Vector2.Zero, Game1.options.lightingQuality / 2, SpriteEffects.None, 1f);
- if (RainManager.Instance.isRaining && Game1.currentLocation != null && (bool) Game1.currentLocation.isOutdoors && !(Game1.currentLocation is Desert))
- {
- Game1.spriteBatch.Draw(Game1.staminaRect, Game1.graphics.GraphicsDevice.Viewport.Bounds, Color.OrangeRed * 0.45f);
- }
-
- this._spriteBatchEndMethod.Invoke();
- }
-
- Game1.SetSpriteBatchBeginNextID("Q");
- this._spriteBatchBeginMethod.Invoke(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null, new Matrix?());
- events.RenderedWorld.RaiseEmpty();
- if (Game1.drawGrid)
- {
- int num = -Game1.viewport.X % 64;
- float num2 = -Game1.viewport.Y % 64;
- int num3 = num;
- while (true)
- {
- int num4 = num3;
- int width = Game1.graphics.GraphicsDevice.Viewport.Width;
- if (num4 < width)
- {
- int x = num3;
- int y = (int) num2;
- int height = Game1.graphics.GraphicsDevice.Viewport.Height;
- Rectangle destinationRectangle = new Rectangle(x, y, 1, height);
- Color color = Color.Red * 0.5f;
- Game1.spriteBatch.Draw(Game1.staminaRect, destinationRectangle, color);
- num3 += 64;
- }
- else
- break;
- }
-
- float num5 = num2;
- while (true)
- {
- double num4 = num5;
- double height = Game1.graphics.GraphicsDevice.Viewport.Height;
- if (num4 < height)
- {
- int x = num;
- int y = (int) num5;
- int width = Game1.graphics.GraphicsDevice.Viewport.Width;
- Rectangle destinationRectangle = new Rectangle(x, y, width, 1);
- Color color = Color.Red * 0.5f;
- Game1.spriteBatch.Draw(Game1.staminaRect, destinationRectangle, color);
- num5 += 64f;
- }
- else
- break;
- }
- }
-
- if (Game1.currentBillboard != 0 && !this.takingMapScreenshot)
- this.drawBillboard();
- if ((Game1.displayHUD || Game1.eventUp)
- && Game1.currentBillboard == 0
- && Game1.gameMode == Game1.playingGameMode
- && !Game1.freezeControls
- && !Game1.panMode
- && !Game1.HostPaused)
- {
- if (Game1.currentLocation != null
- && !Game1.eventUp
- && Game1.farmEvent == null
-// && Game1.currentBillboard == 0
-// && Game1.gameMode == Game1.playingGameMode
- && !this.takingMapScreenshot
- && Game1.isOutdoorMapSmallerThanViewport())
- {
- int width1 = -Math.Min(Game1.viewport.X, 4096);
- int height1 = Game1.graphics.GraphicsDevice.Viewport.Height;
- Rectangle destinationRectangle1 = new Rectangle(0, 0, width1, height1);
- Color black1 = Color.Black;
- Game1.spriteBatch.Draw(Game1.fadeToBlackRect, destinationRectangle1, black1);
- int x = -Game1.viewport.X + Game1.currentLocation.map.Layers[0].LayerWidth * 64;
- int width2 = Math.Min(4096, Game1.graphics.GraphicsDevice.Viewport.Width - (-Game1.viewport.X + Game1.currentLocation.map.Layers[0].LayerWidth * 64));
- int height2 = Game1.graphics.GraphicsDevice.Viewport.Height;
- Rectangle destinationRectangle2 = new Rectangle(x, 0, width2, height2);
- Color black2 = Color.Black;
- Game1.spriteBatch.Draw(Game1.fadeToBlackRect, destinationRectangle2, black2);
- }
-
- this.DrawHudField.SetValue(false);
- if ((Game1.displayHUD || Game1.eventUp) && Game1.currentBillboard == 0 && Game1.gameMode == 3 && !Game1.freezeControls && !Game1.panMode && !Game1.HostPaused && !this.takingMapScreenshot) this.DrawHudField.SetValue(true);
- this.DrawGreenPlacementBoundsMethod.Invoke();
- }
}
if (Game1.farmEvent != null)
{
- Game1.farmEvent.draw(Game1.spriteBatch);
+ Game1.farmEvent.draw(spriteBatch);
}
- if (Game1.dialogueUp && !Game1.nameSelectUp && !Game1.messagePause && (Game1.activeClickableMenu == null || !(Game1.activeClickableMenu is DialogueBox)))
+ if ((currentLocation.LightLevel > 0f) && (timeOfDay < 0x7d0))
{
- this.drawDialogueBox();
+ spriteBatch.Draw(fadeToBlackRect, graphics.GraphicsDevice.Viewport.Bounds, Color.Black * currentLocation.LightLevel);
}
- if (Game1.progressBar && !this.takingMapScreenshot)
+ if (screenGlow)
{
- int x1 = (Game1.graphics.GraphicsDevice.Viewport.GetTitleSafeArea().Width - Game1.dialogueWidth) / 2;
- rectangle = Game1.graphics.GraphicsDevice.Viewport.GetTitleSafeArea();
- int y1 = rectangle.Bottom - 128;
- Rectangle destinationRectangle1 = new Rectangle(x1, y1, Game1.dialogueWidth, 32);
- Game1.spriteBatch.Draw(Game1.fadeToBlackRect, destinationRectangle1, Color.LightGray);
- int x2 = (Game1.graphics.GraphicsDevice.Viewport.GetTitleSafeArea().Width - Game1.dialogueWidth) / 2;
- rectangle = Game1.graphics.GraphicsDevice.Viewport.GetTitleSafeArea();
- int y2 = rectangle.Bottom - 128;
- int width = (int) (Game1.pauseAccumulator / (double) Game1.pauseTime * Game1.dialogueWidth);
- Rectangle destinationRectangle2 = new Rectangle(x2, y2, width, 32);
- Game1.spriteBatch.Draw(Game1.staminaRect, destinationRectangle2, Color.DimGray);
+ spriteBatch.Draw(fadeToBlackRect, graphics.GraphicsDevice.Viewport.Bounds, screenGlowColor * screenGlowAlpha);
}
- if (RainManager.Instance.isRaining && Game1.currentLocation != null && (bool) Game1.currentLocation.isOutdoors && !(Game1.currentLocation is Desert))
+ currentLocation.drawAboveAlwaysFrontLayer(spriteBatch);
+ if (((player.CurrentTool != null) && (player.CurrentTool is FishingRod)) && (((player.CurrentTool as FishingRod).isTimingCast || ((player.CurrentTool as FishingRod).castingChosenCountdown > 0f)) || ((player.CurrentTool as FishingRod).fishCaught || (player.CurrentTool as FishingRod).showingTreasure)))
{
- Rectangle bounds = Game1.graphics.GraphicsDevice.Viewport.Bounds;
- Color color = Color.Blue * 0.2f;
- Game1.spriteBatch.Draw(Game1.staminaRect, bounds, color);
+ player.CurrentTool.draw(spriteBatch);
}
- if ((Game1.messagePause || Game1.globalFade) && Game1.dialogueUp && !this.takingMapScreenshot)
+ spriteBatch.End();
+ nullable = null;
+ spriteBatch.Begin(SpriteSortMode.FrontToBack, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null, nullable);
+ if (eventUp && (currentLocation.currentEvent != null))
{
- this.drawDialogueBox();
- }
-
- if (!this.takingMapScreenshot)
- {
- foreach (TemporaryAnimatedSprite overlayTempSprite in Game1.screenOverlayTempSprites)
+ foreach (NPC npc5 in currentLocation.currentEvent.actors)
{
- overlayTempSprite.draw(Game1.spriteBatch, localPosition: true);
- }
- }
-
- if (Game1.debugMode)
- {
- StringBuilder debugStringBuilder = this.DebugStringBuilderField.GetValue();
- debugStringBuilder.Clear();
- if (Game1.panMode)
- {
- debugStringBuilder.Append((Game1.getOldMouseX() + Game1.viewport.X) / 64);
- debugStringBuilder.Append(",");
- debugStringBuilder.Append((Game1.getOldMouseY() + Game1.viewport.Y) / 64);
- }
- else
- {
- debugStringBuilder.Append("player: ");
- debugStringBuilder.Append(Game1.player.getStandingX() / 64);
- debugStringBuilder.Append(", ");
- debugStringBuilder.Append(Game1.player.getStandingY() / 64);
- }
-
- debugStringBuilder.Append(" mouseTransparency: ");
- debugStringBuilder.Append(Game1.mouseCursorTransparency);
- debugStringBuilder.Append(" mousePosition: ");
- debugStringBuilder.Append(Game1.getMouseX());
- debugStringBuilder.Append(",");
- debugStringBuilder.Append(Game1.getMouseY());
- debugStringBuilder.Append(Environment.NewLine);
- debugStringBuilder.Append(" mouseWorldPosition: ");
- debugStringBuilder.Append(Game1.getMouseX() + Game1.viewport.X);
- debugStringBuilder.Append(",");
- debugStringBuilder.Append(Game1.getMouseY() + Game1.viewport.Y);
- debugStringBuilder.Append("debugOutput: ");
- debugStringBuilder.Append(Game1.debugOutput);
- Game1.spriteBatch.DrawString(Game1.smallFont, debugStringBuilder, new Vector2(this.GraphicsDevice.Viewport.GetTitleSafeArea().X, this.GraphicsDevice.Viewport.GetTitleSafeArea().Y + Game1.smallFont.LineSpacing * 8), Color.Red, 0f, Vector2.Zero, 1f, SpriteEffects.None, 0.09999999f);
- }
-
- if (Game1.showKeyHelp && !this.takingMapScreenshot)
- {
- Game1.spriteBatch.DrawString(Game1.smallFont, Game1.keyHelpString, new Vector2(64f, Game1.viewport.Height - 64 - (Game1.dialogueUp ? 192 + (Game1.isQuestion ? Game1.questionChoices.Count * 64 : 0) : 0) - Game1.smallFont.MeasureString(Game1.keyHelpString).Y), Color.LightGray, 0f, Vector2.Zero, 1f, SpriteEffects.None, 0.9999999f);
- }
-
- if (Game1.activeClickableMenu != null)
- {
- this.DrawActiveClickableMenuField.SetValue(true);
- if (Game1.activeClickableMenu is CarpenterMenu)
- {
- ((CarpenterMenu) Game1.activeClickableMenu).DrawPlacementSquares(Game1.spriteBatch);
- }
- else if (Game1.activeClickableMenu is MuseumMenu)
- {
- ((MuseumMenu) Game1.activeClickableMenu).DrawPlacementGrid(Game1.spriteBatch);
- }
-
- if (!Game1.IsActiveClickableMenuUnscaled && !Game1.IsActiveClickableMenuNativeScaled)
- {
- try
+ if (npc5.isEmoting)
{
+ Vector2 position = npc5.getLocalPosition(Game1.viewport);
+ if (npc5.NeedsBirdieEmoteHack())
+ {
+ position.X += 64f;
+ }
- events.RenderingActiveMenu.RaiseEmpty();
- Game1.activeClickableMenu.draw(Game1.spriteBatch);
- events.RenderedActiveMenu.RaiseEmpty();
- }
- catch (Exception ex)
- {
- this.Monitor.Log($"The {Game1.activeClickableMenu.GetType().FullName} menu crashed while drawing itself during end-of-night-stuff. SMAPI will force it to exit to avoid crashing the game.\n{ex.GetLogSummary()}", LogLevel.Error);
- Game1.activeClickableMenu.exitThisMenu();
+ position.Y -= 140f;
+ if (npc5.Age == 2)
+ {
+ position.Y += 32f;
+ }
+ else if (npc5.Gender == 1)
+ {
+ position.Y += 10f;
+ }
+
+ spriteBatch.Draw(emoteSpriteSheet, position, new Rectangle((npc5.CurrentEmoteIndex * 0x10) % emoteSpriteSheet.Width, ((npc5.CurrentEmoteIndex * 0x10) / emoteSpriteSheet.Width) * 0x10, 0x10, 0x10), Color.White, 0f, Vector2.Zero, (float)4f, SpriteEffects.None, ((float)npc5.getStandingY()) / 10000f);
}
}
-
- }
- else if (Game1.farmEvent != null)
- {
- Game1.farmEvent.drawAboveEverything(Game1.spriteBatch);
}
- if (Game1.emoteMenu != null && !this.takingMapScreenshot)
- Game1.emoteMenu.draw(Game1.spriteBatch);
- if (Game1.HostPaused)
+ spriteBatch.End();
+ if (drawLighting && !IsFakedBlackScreen())
{
- string s = Game1.content.LoadString("Strings\\StringsFromCSFiles:DayTimeMoneyBox.cs.10378");
- SpriteText.drawStringWithScrollCenteredAt(Game1.spriteBatch, s, 96, 32);
- }
-
- this._spriteBatchEndMethod.Invoke();
- this.drawOverlays(Game1.spriteBatch, false);
- this.renderScreenBuffer(BlendState.Opaque, toBuffer);
- if (this.DrawHudField.GetValue())
- {
- this.DrawDayTimeMoneyBoxMethod.Invoke();
- Game1.SetSpriteBatchBeginNextID("A-C");
- this.SpriteBatchBeginMethod.Invoke(1f);
- events.RenderingHud.RaiseEmpty();
- this.DrawHUD();
- events.RenderedHud.RaiseEmpty();
- if (Game1.currentLocation != null && !(Game1.activeClickableMenu is GameMenu) && !(Game1.activeClickableMenu is QuestLog))
- Game1.currentLocation.drawAboveAlwaysFrontLayerText(Game1.spriteBatch);
-
- this.DrawAfterMapMethod.Invoke();
- this._spriteBatchEndMethod.Invoke();
- if (TutorialManager.Instance != null)
+ nullable = null;
+ spriteBatch.Begin(SpriteSortMode.Deferred, this.lightingBlend, SamplerState.LinearClamp, null, null, null, nullable);
+ Viewport viewport = base.GraphicsDevice.Viewport;
+ viewport.Bounds = (target_screen != null) ? target_screen.Bounds : base.GraphicsDevice.PresentationParameters.Bounds;
+ base.GraphicsDevice.Viewport = viewport;
+ float scale = options.lightingQuality / 2;
+ if (this.useUnscaledLighting)
{
- Game1.SetSpriteBatchBeginNextID("A-D");
- this.SpriteBatchBeginMethod.Invoke(Game1.options.zoomLevel);
- TutorialManager.Instance.draw(Game1.spriteBatch);
- this._spriteBatchEndMethod.Invoke();
+ scale /= options.zoomLevel;
}
- this.DrawToolbarMethod.Invoke();
- this.DrawMenuMouseCursorMethod.Invoke();
+ spriteBatch.Draw(lightmap, Vector2.Zero, new Rectangle?(lightmap.Bounds), Color.White, 0f, Vector2.Zero, scale, SpriteEffects.None, 1f);
+ if ((IsRainingHere(null) && (currentLocation.isOutdoors != null)) && !(currentLocation is Desert))
+ {
+ spriteBatch.Draw(staminaRect, viewport.Bounds, Color.OrangeRed * 0.45f);
+ }
+
+ spriteBatch.End();
}
- if (this.DrawHudField.GetValue() || Game1.player.CanMove) this.DrawVirtualJoypadMethod.Invoke();
- this.DrawFadeToBlackFullScreenRectMethod.Invoke();
- Game1.SetSpriteBatchBeginNextID("A-E");
- this.SpriteBatchBeginMethod.Invoke(1f);
- this.DrawChatBoxMethod.Invoke();
- this._spriteBatchEndMethod.Invoke();
- if (this.DrawActiveClickableMenuField.GetValue())
+ nullable = null;
+ spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null, nullable);
+ if (drawGrid)
{
- try
+ int x = -Game1.viewport.X % 0x40;
+ float num13 = -Game1.viewport.Y % 0x40;
+ for (int i = x; i < graphics.GraphicsDevice.Viewport.Width; i += 0x40)
{
- if (Game1.activeClickableMenu is DialogueBox)
- {
- Game1.BackupViewportAndZoom(true);
- this.SpriteBatchBeginMethod.Invoke(Game1.NativeZoomLevel);
- events.RenderingActiveMenu.RaiseEmpty();
- this._spriteBatchEndMethod.Invoke();
- Game1.RestoreViewportAndZoom();
-
- this.DrawDialogueBoxForPinchZoomMethod.Invoke();
-
- Game1.BackupViewportAndZoom(true);
- this.SpriteBatchBeginMethod.Invoke(Game1.NativeZoomLevel);
- events.RenderedActiveMenu.RaiseEmpty();
- this._spriteBatchEndMethod.Invoke();
- Game1.RestoreViewportAndZoom();
- }
- if (Game1.IsActiveClickableMenuUnscaled && !(Game1.activeClickableMenu is DialogueBox))
- {
- Game1.BackupViewportAndZoom();
- this.SpriteBatchBeginMethod.Invoke(1f);
- events.RenderingActiveMenu.RaiseEmpty();
- this._spriteBatchEndMethod.Invoke();
- Game1.RestoreViewportAndZoom();
-
- this.DrawUnscaledActiveClickableMenuForPinchZoomMethod.Invoke();
-
- Game1.BackupViewportAndZoom();
- this.SpriteBatchBeginMethod.Invoke(1f);
- events.RenderedActiveMenu.RaiseEmpty();
- this._spriteBatchEndMethod.Invoke();
- Game1.RestoreViewportAndZoom();
- }
- if (Game1.IsActiveClickableMenuNativeScaled)
- {
- Game1.BackupViewportAndZoom(true);
- this.SpriteBatchBeginMethod.Invoke(Game1.NativeZoomLevel);
- events.RenderingActiveMenu.RaiseEmpty();
- this._spriteBatchEndMethod.Invoke();
- Game1.RestoreViewportAndZoom();
-
- this.DrawNativeScaledActiveClickableMenuForPinchZoomMethod.Invoke();
-
- Game1.BackupViewportAndZoom(true);
- this.SpriteBatchBeginMethod.Invoke(Game1.NativeZoomLevel);
- events.RenderedActiveMenu.RaiseEmpty();
- this._spriteBatchEndMethod.Invoke();
- Game1.RestoreViewportAndZoom();
- }
- }
- catch (Exception ex)
- {
- this.Monitor.Log($"The {Game1.activeClickableMenu.GetType().FullName} menu crashed while drawing itself during end-of-night-stuff. SMAPI will force it to exit to avoid crashing the game.\n{ex.GetLogSummary()}", LogLevel.Error);
- Game1.activeClickableMenu.exitThisMenu();
+ spriteBatch.Draw(staminaRect, new Rectangle(i, (int)num13, 1, graphics.GraphicsDevice.Viewport.Height), Color.Red * 0.5f);
}
- if (Game1.IsActiveClickableMenuNativeScaled)
- this.SpriteBatchBeginMethod.Invoke(Game1.NativeZoomLevel);
- else
- this.SpriteBatchBeginMethod.Invoke(Game1.options.zoomLevel);
- events.Rendered.RaiseEmpty();
- this._spriteBatchEndMethod.Invoke();
+ for (float j = num13; j < graphics.GraphicsDevice.Viewport.Height; j += 64f)
+ {
+ spriteBatch.Draw(staminaRect, new Rectangle(x, (int)j, graphics.GraphicsDevice.Viewport.Width, 1), Color.Red * 0.5f);
+ }
+ }
+
+ if (ShouldShowOnscreenUsernames() && (currentLocation != null))
+ {
+ currentLocation.DrawFarmerUsernames(spriteBatch);
+ }
+
+ if ((currentBillboard != 0) && !this.takingMapScreenshot)
+ {
+ this.drawBillboard();
+ }
+
+ if (((!eventUp && (Game1.farmEvent == null)) && ((currentBillboard == 0) && (Game1.gameMode == 3))) && (!this.takingMapScreenshot && isOutdoorMapSmallerThanViewport()))
+ {
+ spriteBatch.Draw(fadeToBlackRect, new Rectangle(0, 0, -Game1.viewport.X, graphics.GraphicsDevice.Viewport.Height), Color.Black);
+ spriteBatch.Draw(fadeToBlackRect, new Rectangle(-Game1.viewport.X + (currentLocation.map.Layers[0].LayerWidth * 0x40), 0, graphics.GraphicsDevice.Viewport.Width - (-Game1.viewport.X + (currentLocation.map.Layers[0].LayerWidth * 0x40)), graphics.GraphicsDevice.Viewport.Height), Color.Black);
+ spriteBatch.Draw(fadeToBlackRect, new Rectangle(0, 0, graphics.GraphicsDevice.Viewport.Width, -Game1.viewport.Y), Color.Black);
+ spriteBatch.Draw(fadeToBlackRect, new Rectangle(0, -Game1.viewport.Y + (currentLocation.map.Layers[0].LayerHeight * 0x40), graphics.GraphicsDevice.Viewport.Width, graphics.GraphicsDevice.Viewport.Height - (-Game1.viewport.Y + (currentLocation.map.Layers[0].LayerHeight * 0x40))), Color.Black);
+ }
+
+ spriteBatch.End();
+ PushUIMode();
+ nullable = null;
+ spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null, nullable);
+ if (((displayHUD || eventUp) && ((currentBillboard == 0) && (Game1.gameMode == 3))) && ((!freezeControls && !panMode) && (!HostPaused && !this.takingMapScreenshot)))
+ {
+ this.drawHUD();
+ if (!this.takingMapScreenshot)
+ {
+ this.DrawGreenPlacementBoundsMethod.Invoke();
+ }
+ }
+ else if (Game1.activeClickableMenu == null)
+ {
+ FarmEvent farmEvent = Game1.farmEvent;
+ }
+
+ if ((hudMessages.Count > 0) && !this.takingMapScreenshot)
+ {
+ for (int i = hudMessages.Count - 1; i >= 0; i--)
+ {
+ hudMessages[i].draw(spriteBatch, i);
+ }
+ }
+
+ spriteBatch.End();
+ PopUIMode();
+ nullable = null;
+ spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null, nullable);
+ }
+
+ if (Game1.farmEvent != null)
+ {
+ Game1.farmEvent.draw(spriteBatch);
+ spriteBatch.End();
+ nullable = null;
+ spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null, nullable);
+ }
+
+ PushUIMode();
+ if (((dialogueUp && !nameSelectUp) && !messagePause) && (((Game1.activeClickableMenu == null) || !(Game1.activeClickableMenu is DialogueBox)) && !this.takingMapScreenshot))
+ {
+ this.drawDialogueBox();
+ }
+
+ if (progressBar && !this.takingMapScreenshot)
+ {
+ spriteBatch.Draw(fadeToBlackRect, new Rectangle((graphics.GraphicsDevice.Viewport.GetTitleSafeArea().Width - dialogueWidth) / 2, graphics.GraphicsDevice.Viewport.GetTitleSafeArea().Bottom - 0x80, dialogueWidth, 0x20), Color.LightGray);
+ spriteBatch.Draw(staminaRect, new Rectangle((graphics.GraphicsDevice.Viewport.GetTitleSafeArea().Width - dialogueWidth) / 2, graphics.GraphicsDevice.Viewport.GetTitleSafeArea().Bottom - 0x80, (int)((pauseAccumulator / pauseTime) * dialogueWidth), 0x20), Color.DimGray);
+ }
+
+ spriteBatch.End();
+ PopUIMode();
+ nullable = null;
+ spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null, nullable);
+ if ((eventUp && (currentLocation != null)) && (currentLocation.currentEvent != null))
+ {
+ currentLocation.currentEvent.drawAfterMap(spriteBatch);
+ }
+
+ if (((!IsFakedBlackScreen() && IsRainingHere(null)) && ((currentLocation != null) && (currentLocation.isOutdoors != null))) && !(currentLocation is Desert))
+ {
+ spriteBatch.Draw(staminaRect, graphics.GraphicsDevice.Viewport.Bounds, Color.Blue * 0.2f);
+ }
+
+ if (((fadeToBlack || globalFade) && !menuUp) && ((!nameSelectUp || messagePause) && !this.takingMapScreenshot))
+ {
+ spriteBatch.End();
+ PushUIMode();
+ nullable = null;
+ spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null, nullable);
+ spriteBatch.Draw(fadeToBlackRect, graphics.GraphicsDevice.Viewport.Bounds, Color.Black * ((Game1.gameMode == 0) ? (1f - fadeToBlackAlpha) : fadeToBlackAlpha));
+ spriteBatch.End();
+ PopUIMode();
+ nullable = null;
+ spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null, nullable);
+ }
+ else if ((flashAlpha > 0f) && !this.takingMapScreenshot)
+ {
+ if (options.screenFlash)
+ {
+ spriteBatch.Draw(fadeToBlackRect, graphics.GraphicsDevice.Viewport.Bounds, Color.White * Math.Min(1f, flashAlpha));
+ }
+
+ flashAlpha -= 0.1f;
+ }
+
+ if ((messagePause || globalFade) && (dialogueUp && !this.takingMapScreenshot))
+ {
+ this.drawDialogueBox();
+ }
+
+ if (!this.takingMapScreenshot)
+ {
+ List.Enumerator enumerator7;
+ using (enumerator7 = screenOverlayTempSprites.GetEnumerator())
+ {
+ while (enumerator7.MoveNext())
+ {
+ enumerator7.Current.draw(spriteBatch, true, 0, 0, 1f);
+ }
+ }
+
+ spriteBatch.End();
+ PushUIMode();
+ nullable = null;
+ spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null, nullable);
+ using (enumerator7 = uiOverlayTempSprites.GetEnumerator())
+ {
+ while (enumerator7.MoveNext())
+ {
+ enumerator7.Current.draw(spriteBatch, true, 0, 0, 1f);
+ }
+ }
+
+ spriteBatch.End();
+ PopUIMode();
+ nullable = null;
+ spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null, nullable);
+ }
+
+ if (debugMode)
+ {
+ StringBuilder text = this.DebugStringBuilderField.GetValue();
+ text.Clear();
+ if (panMode)
+ {
+ text.Append((int)((getOldMouseX() + Game1.viewport.X) / 0x40));
+ text.Append(",");
+ text.Append((int)((getOldMouseY() + Game1.viewport.Y) / 0x40));
}
else
{
- this.SpriteBatchBeginMethod.Invoke(Game1.options.zoomLevel);
- events.Rendered.RaiseEmpty();
- this._spriteBatchEndMethod.Invoke();
+ text.Append("player: ");
+ text.Append((int)(player.getStandingX() / 0x40));
+ text.Append(", ");
+ text.Append((int)(player.getStandingY() / 0x40));
}
- if (this.DrawHudField.GetValue() && Game1.hudMessages.Count > 0 && (!Game1.eventUp || Game1.isFestival()))
- {
- Game1.SetSpriteBatchBeginNextID("A-F");
- this.SpriteBatchBeginMethod.Invoke(Game1.NativeZoomLevel);
- this.DrawHUDMessagesMethod.Invoke();
- this._spriteBatchEndMethod.Invoke();
- }
-
- if (Game1.CurrentEvent != null && Game1.CurrentEvent.skippable && !Game1.CurrentEvent.skipped && (Game1.activeClickableMenu == null || Game1.activeClickableMenu != null && !(Game1.activeClickableMenu is MenuWithInventory)))
- {
- Game1.SetSpriteBatchBeginNextID("A-G");
- this.SpriteBatchBeginMethod.Invoke(Game1.NativeZoomLevel);
- Game1.CurrentEvent.DrawSkipButton(Game1.spriteBatch);
- this._spriteBatchEndMethod.Invoke();
- }
-
- this.DrawTutorialUIMethod.Invoke();
+ text.Append(" mouseTransparency: ");
+ text.Append(mouseCursorTransparency);
+ text.Append(" mousePosition: ");
+ text.Append(getMouseX());
+ text.Append(",");
+ text.Append(getMouseY());
+ text.Append(Environment.NewLine);
+ text.Append(" mouseWorldPosition: ");
+ text.Append((int)(getMouseX() + Game1.viewport.X));
+ text.Append(",");
+ text.Append((int)(getMouseY() + Game1.viewport.Y));
+ text.Append(" debugOutput: ");
+ text.Append(debugOutput);
+ spriteBatch.DrawString(smallFont, text, new Vector2((float)base.GraphicsDevice.Viewport.GetTitleSafeArea().X, (float)(base.GraphicsDevice.Viewport.GetTitleSafeArea().Y + (smallFont.LineSpacing * 8))), Color.Red, 0f, Vector2.Zero, (float)1f, SpriteEffects.None, 0.9999999f);
}
+
+ spriteBatch.End();
+ PushUIMode();
+ spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null, null);
+ if (showKeyHelp && !this.takingMapScreenshot)
+ {
+ spriteBatch.DrawString(smallFont, keyHelpString, new Vector2(64f, ((Game1.viewport.Height - 0x40) - (dialogueUp ? (0xc0 + (isQuestion ? (questionChoices.Count * 0x40) : 0)) : 0)) - smallFont.MeasureString(keyHelpString).Y), Color.LightGray, 0f, Vector2.Zero, (float)1f, SpriteEffects.None, 0.9999999f);
+ }
+
+ if ((Game1.activeClickableMenu != null) && !this.takingMapScreenshot)
+ {
+ for (IClickableMenu menu4 = Game1.activeClickableMenu; menu4 != null; menu4 = menu4.GetChildMenu())
+ {
+ menu4.draw(spriteBatch);
+ }
+ }
+ else if (Game1.farmEvent != null)
+ {
+ Game1.farmEvent.drawAboveEverything(spriteBatch);
+ }
+
+ if (specialCurrencyDisplay != null)
+ {
+ specialCurrencyDisplay.Draw(spriteBatch);
+ }
+
+ if ((emoteMenu != null) && !this.takingMapScreenshot)
+ {
+ emoteMenu.draw(spriteBatch);
+ }
+
+ if (HostPaused && !this.takingMapScreenshot)
+ {
+ string s = content.LoadString(@"Strings\StringsFromCSFiles:DayTimeMoneyBox.cs.10378");
+ SpriteText.drawStringWithScrollBackground(spriteBatch, s, 0x60, 0x20, "", 1f, -1, SpriteText.ScrollTextAlignment.Left);
+ }
+
+ spriteBatch.End();
+ this.drawOverlays(spriteBatch);
+ PopUIMode();
}
}
}
diff --git a/src/SMAPI/Framework/SGameRunner.cs b/src/SMAPI/Framework/SGameRunner.cs
index 213fe561..e021263a 100644
--- a/src/SMAPI/Framework/SGameRunner.cs
+++ b/src/SMAPI/Framework/SGameRunner.cs
@@ -53,6 +53,12 @@ namespace StardewModdingAPI.Framework
/// The singleton instance.
public static SGameRunner Instance => (SGameRunner)GameRunner.instance;
+#if SMAPI_FOR_MOBILE
+ public bool IsGameSuspended;
+
+ public bool IsAfterInitialize = false;
+#endif
+
/*********
** Public methods
diff --git a/src/SMAPI/Framework/StateTracking/LocationTracker.cs b/src/SMAPI/Framework/StateTracking/LocationTracker.cs
index 8ba1bee1..7ed6baf7 100644
--- a/src/SMAPI/Framework/StateTracking/LocationTracker.cs
+++ b/src/SMAPI/Framework/StateTracking/LocationTracker.cs
@@ -70,17 +70,19 @@ namespace StardewModdingAPI.Framework.StateTracking
this.Location = location;
// init watchers
- this.BuildingsWatcher = location is BuildableGameLocation buildableLocation ? WatcherFactory.ForNetCollection(buildableLocation.buildings) : WatcherFactory.ForImmutableCollection();
+ this.BuildingsWatcher = location is BuildableGameLocation buildableLocation ?
+ WatcherFactory.ForNetCollection($"{this.Name}.{nameof(buildableLocation.buildings)}", buildableLocation.buildings) :
+ WatcherFactory.ForImmutableCollection();
#if SMAPI_FOR_MOBILE
- this.DebrisWatcher = WatcherFactory.ForNetCollection(location.debris.debrisNetCollection);
- // this.DebrisWatcher = WatcherFactory.ForNetCollection($"{this.Name}.{nameof(location.debris)}", location.debris);
+ // this.DebrisWatcher = WatcherFactory.ForNetCollection(location.debris.debrisNetCollection);
+ this.DebrisWatcher = WatcherFactory.ForNetCollection($"{this.Name}.{nameof(location.debris)}", location.debris);
#else
this.DebrisWatcher = WatcherFactory.ForNetCollection(location.debris);
#endif
- this.LargeTerrainFeaturesWatcher = WatcherFactory.ForNetCollection(location.largeTerrainFeatures);
- this.NpcsWatcher = WatcherFactory.ForNetCollection(location.characters);
- this.ObjectsWatcher = WatcherFactory.ForNetDictionary(location.netObjects);
- this.TerrainFeaturesWatcher = WatcherFactory.ForNetDictionary(location.terrainFeatures);
+ this.LargeTerrainFeaturesWatcher = WatcherFactory.ForNetCollection($"{this.Name}.{nameof(location.largeTerrainFeatures)}", location.largeTerrainFeatures);
+ this.NpcsWatcher = WatcherFactory.ForNetCollection($"{this.Name}.{nameof(location.characters)}", location.characters);
+ this.ObjectsWatcher = WatcherFactory.ForNetDictionary($"{this.Name}.{nameof(location.netObjects)}", location.netObjects);
+ this.TerrainFeaturesWatcher = WatcherFactory.ForNetDictionary($"{this.Name}.{nameof(location.terrainFeatures)}", location.terrainFeatures);
this.FurnitureWatcher = WatcherFactory.ForNetCollection($"{this.Name}.{nameof(location.furniture)}", location.furniture);
this.Watchers.AddRange(new IWatcher[]
diff --git a/src/SMAPI/Framework/StateTracking/WorldLocationsTracker.cs b/src/SMAPI/Framework/StateTracking/WorldLocationsTracker.cs
index ca6988ad..cbb09bf2 100644
--- a/src/SMAPI/Framework/StateTracking/WorldLocationsTracker.cs
+++ b/src/SMAPI/Framework/StateTracking/WorldLocationsTracker.cs
@@ -60,9 +60,9 @@ namespace StardewModdingAPI.Framework.StateTracking
/// The game's list of locations.
/// The game's list of active mine locations.
/// The game's list of active volcano locations.
- public WorldLocationsTracker(ObservableCollection locations, IList activeMineLocations, IList activeVolcanoLocations)
+ public WorldLocationsTracker(IList locations, IList activeMineLocations, IList activeVolcanoLocations)
{
- this.LocationListWatcher = WatcherFactory.ForObservableCollection($"{this.Name}.{nameof(locations)}", locations);
+ this.LocationListWatcher = WatcherFactory.ForReferenceList($"{this.Name}.{nameof(locations)}", locations);
this.MineLocationListWatcher = WatcherFactory.ForReferenceList($"{this.Name}.{nameof(activeMineLocations)}", activeMineLocations);
this.VolcanoLocationListWatcher = WatcherFactory.ForReferenceList($"{this.Name}.{nameof(activeVolcanoLocations)}", activeVolcanoLocations);
}
diff --git a/src/SMAPI/Framework/Translator.cs b/src/SMAPI/Framework/Translator.cs
index 3beee250..adc78a82 100644
--- a/src/SMAPI/Framework/Translator.cs
+++ b/src/SMAPI/Framework/Translator.cs
@@ -41,7 +41,7 @@ namespace StardewModdingAPI.Framework
/// Set the current locale and pre-cache translations.
/// The current locale.
/// The game's current language code.
- [MemberNotNull(nameof(Translator.ForLocale), nameof(Translator.Locale))]
+ // [MemberNotNull(nameof(Translator.ForLocale), nameof(Translator.Locale))]
public void SetLocale(string locale, LocalizedContentManager.LanguageCode localeEnum)
{
this.Locale = locale.ToLower().Trim();
diff --git a/src/SMAPI/Framework/WatcherCore.cs b/src/SMAPI/Framework/WatcherCore.cs
index 35f27cc7..82cdeccb 100644
--- a/src/SMAPI/Framework/WatcherCore.cs
+++ b/src/SMAPI/Framework/WatcherCore.cs
@@ -57,7 +57,7 @@ namespace StardewModdingAPI.Framework
/// Construct an instance.
/// Manages input visible to the game.
/// The observable list of game locations.
- public WatcherCore(SInputState inputState, ObservableCollection gameLocations)
+ public WatcherCore(SInputState inputState, IList gameLocations)
{
// init watchers
this.CursorWatcher = WatcherFactory.ForEquatable(nameof(inputState.CursorPosition), () => inputState.CursorPosition);
diff --git a/src/SMAPI/IMultiplayerPeer.cs b/src/SMAPI/IMultiplayerPeer.cs
index 8b0062b5..faaefba4 100644
--- a/src/SMAPI/IMultiplayerPeer.cs
+++ b/src/SMAPI/IMultiplayerPeer.cs
@@ -19,7 +19,7 @@ namespace StardewModdingAPI
bool IsSplitScreen { get; }
/// Whether the player has SMAPI installed.
- [MemberNotNullWhen(true, nameof(IMultiplayerPeer.Platform), nameof(IMultiplayerPeer.GameVersion), nameof(IMultiplayerPeer.ApiVersion), nameof(IMultiplayerPeer.Mods))]
+ // [MemberNotNullWhen(true, nameof(IMultiplayerPeer.Platform), nameof(IMultiplayerPeer.GameVersion), nameof(IMultiplayerPeer.ApiVersion), nameof(IMultiplayerPeer.Mods))]
bool HasSmapi { get; }
/// The player's screen ID, if applicable.
diff --git a/src/SMAPI/Metadata/CoreAssetPropagator.cs b/src/SMAPI/Metadata/CoreAssetPropagator.cs
index 4cf457e7..9cc2f342 100644
--- a/src/SMAPI/Metadata/CoreAssetPropagator.cs
+++ b/src/SMAPI/Metadata/CoreAssetPropagator.cs
@@ -444,7 +444,7 @@ namespace StardewModdingAPI.Metadata
return true;
#if SMAPI_FOR_MOBILE
- case "loosesprites\\mobileatlas_manually_made": // Game1.LoadContent
+ case "loosesprites/mobileatlas_manually_made": // Game1.LoadContent
Game1.mobileSpriteSheet = content.Load(key);
Game1.dayTimeMoneyBox.questButton.texture = Game1.mobileSpriteSheet;
Game1.dayTimeMoneyBox.buttonF8.texture = Game1.mobileSpriteSheet;
@@ -452,49 +452,6 @@ namespace StardewModdingAPI.Metadata
return true;
#endif
- /****
- ** Content\TileSheets
- ****/
- case "tilesheets\\critters": // Critter constructor
- this.ReloadCritterTextures(content, key);
- return true;
-
- case "tilesheets\\crops": // Game1.LoadContent
- Game1.cropSpriteSheet = content.Load(key);
- return true;
-
- case "tilesheets\\debris": // Game1.LoadContent
- Game1.debrisSpriteSheet = content.Load(key);
- return true;
-
- case "tilesheets\\emotes": // Game1.LoadContent
- Game1.emoteSpriteSheet = content.Load(key);
- return true;
-
- case "tilesheets\\furniture": // Game1.LoadContent
- Furniture.furnitureTexture = content.Load(key);
- return true;
-
- case "tilesheets\\projectiles": // Game1.LoadContent
- Projectile.projectileSheet = content.Load(key);
- return true;
-
- case "tilesheets\\rain": // Game1.LoadContent
- Game1.rainTexture = content.Load(key);
- return true;
-
- case "tilesheets\\tools": // Game1.ResetToolSpriteSheet
-#if SMAPI_FOR_MOBILE
- Game1.toolSpriteSheet = content.Load(key);
-#else
- Game1.ResetToolSpriteSheet();
-#endif
- return true;
-
- case "tilesheets\\weapons": // Game1.LoadContent
- Tool.weaponsTexture = content.Load(key);
- return true;
-
case "loosesprites/suspensionbridge": // SuspensionBridge constructor
return changed | (!ignoreWorld && this.UpdateSuspensionBridges(content, assetName));
diff --git a/src/SMAPI/Metadata/InstructionMetadata.cs b/src/SMAPI/Metadata/InstructionMetadata.cs
index 23ac0917..8dcf24bd 100644
--- a/src/SMAPI/Metadata/InstructionMetadata.cs
+++ b/src/SMAPI/Metadata/InstructionMetadata.cs
@@ -1,10 +1,6 @@
using System;
using System.Collections.Generic;
-#if HARMONY_2
using HarmonyLib;
-#else
-using Harmony;
-#endif
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using StardewModdingAPI.Events;
@@ -29,7 +25,7 @@ namespace StardewModdingAPI.Metadata
*********/
/// The assembly names to which to heuristically detect broken references.
/// The current implementation only works correctly with assemblies that should always be present.
- private readonly ISet ValidateReferencesToAssemblies = new HashSet { "StardewModdingAPI", "Stardew Valley", "StardewValley", "Netcode" };
+ private readonly HashSet ValidateReferencesToAssemblies = new() { "StardewModdingAPI", "Stardew Valley", "StardewValley", "Netcode" };
private readonly IMonitor Monitor;
@@ -57,9 +53,13 @@ namespace StardewModdingAPI.Metadata
yield return new FieldReplaceRewriter()
.AddField(typeof(DecoratableLocation), "furniture", typeof(GameLocation), nameof(GameLocation.furniture))
.AddField(typeof(Farm), "resourceClumps", typeof(GameLocation), nameof(GameLocation.resourceClumps))
+#if SMAPI_FOR_MOBILE
+ .AddField(typeof(ItemGrabMenu), "context", typeof(ItemGrabMenu), "specialObject")
+#endif
.AddField(typeof(MineShaft), "resourceClumps", typeof(GameLocation), nameof(GameLocation.resourceClumps));
#if SMAPI_FOR_MOBILE
+#if SMAPI_LEGACY_PATCH
// Redirect reference
yield return new TypeFieldToAnotherTypePropertyRewriter(typeof(Game1), typeof(Game1Methods), "isRaining", nameof(Game1Methods.IsRainingProp));
#if !ANDROID_TARGET_MOBILE_LEGACY
@@ -67,10 +67,12 @@ namespace StardewModdingAPI.Metadata
#endif
yield return new TypeFieldToAnotherTypePropertyRewriter(typeof(Game1), typeof(Game1Methods), "isDebrisWeather", nameof(Game1Methods.IsDebrisWeatherProp));
yield return new TypeFieldToAnotherTypePropertyRewriter(typeof(Game1), typeof(Game1Methods), "rainDrops", nameof(Game1Methods.RainDropsProp));
- yield return new TypeFieldToAnotherTypePropertyRewriter(typeof(Game1), typeof(WeatherDebrisManager), "debrisWeather","weatherDebrisList", "Instance");
+
+ // yield return new TypeFieldToAnotherTypePropertyRewriter(typeof(Game1), typeof(WeatherDebrisManager), "debrisWeather","weatherDebrisList", "Instance");
+#endif
yield return new TypeFieldToAnotherTypePropertyRewriter(typeof(Game1), typeof(Game1Methods), "onScreenMenus", "onScreenMenus");
yield return new PropertyToFieldRewriter(typeof(Game1), "toolSpriteSheet", "toolSpriteSheet");
- yield return new TypeFieldToAnotherTypeFieldRewriter(typeof(GameLocation), typeof(DebrisManager), "debris", this.Monitor, "debrisNetCollection");
+ // yield return new TypeFieldToAnotherTypeFieldRewriter(typeof(GameLocation), typeof(DebrisManager), "debris", this.Monitor, "debrisNetCollection");
// Menu fix
yield return new TypeFieldToAnotherTypePropertyRewriter(typeof(MenuWithInventory), typeof(MenuWithInventoryMethods), "trashCan", nameof(MenuWithInventoryMethods.TrashCanProp));
@@ -89,22 +91,16 @@ namespace StardewModdingAPI.Metadata
yield return new MethodParentRewriter(typeof(Game1), typeof(Game1Methods));
yield return new MethodParentRewriter(typeof(IClickableMenu), typeof(IClickableMenuMethods));
yield return new MethodParentRewriter(typeof(SpriteText), typeof(SpriteTextMethods));
- yield return new MethodParentRewriter(typeof(NPC), typeof(NPCMethods));
yield return new MethodParentRewriter(typeof(Utility), typeof(UtilityMethods));
//Constructor Rewrites
yield return new MethodParentRewriter(typeof(MapPage), typeof(MapPageMethods));
yield return new MethodParentRewriter(typeof(ItemGrabMenu), typeof(ItemGrabMenuMethods));
- yield return new MethodParentRewriter(typeof(WeatherDebris), typeof(WeatherDebrisMethods));
- yield return new MethodParentRewriter(typeof(Debris), typeof(DebrisMethods));
yield return new MethodParentRewriter(typeof(InventoryMenu), typeof(InventoryMenuMethods));
yield return new MethodParentRewriter(typeof(MenuWithInventory), typeof(MenuWithInventoryMethods));
yield return new MethodParentRewriter(typeof(GameMenu), typeof(GameMenuMethods));
yield return new MethodParentRewriter(typeof(CraftingPageMobile), typeof(CraftingPageMobileMethods));
- //Field Rewriters
- yield return new FieldReplaceRewriter(typeof(ItemGrabMenu), "context", "specialObject");
-
#endif
// heuristic rewrites
@@ -129,15 +125,9 @@ namespace StardewModdingAPI.Metadata
// MonoMod fix
if (!Constants.HarmonyEnabled)
{
-#if HARMONY_2
yield return new MethodToAnotherStaticMethodRewriter(typeof(Harmony), (method) => method.Name == "Patch", typeof(HarmonyInstanceMethods), "Patch");
yield return new MethodToAnotherStaticMethodRewriter(typeof(Harmony), (method) => method.Name == "PatchAll" && method.Parameters.Count == 0, typeof(HarmonyInstanceMethods), "PatchAll");
yield return new MethodToAnotherStaticMethodRewriter(typeof(Harmony), (method) => method.Name == "PatchAll" && method.Parameters.Count == 1, typeof(HarmonyInstanceMethods), "PatchAllToAssembly");
-#else
- yield return new MethodToAnotherStaticMethodRewriter(typeof(HarmonyInstance), (method) => method.Name == "Patch", typeof(HarmonyInstanceMethods), "Patch");
- yield return new MethodToAnotherStaticMethodRewriter(typeof(HarmonyInstance), (method) => method.Name == "PatchAll" && method.Parameters.Count == 0, typeof(HarmonyInstanceMethods), "PatchAll");
- yield return new MethodToAnotherStaticMethodRewriter(typeof(HarmonyInstance), (method) => method.Name == "PatchAll" && method.Parameters.Count == 1, typeof(HarmonyInstanceMethods), "PatchAllToAssembly");
-#endif
}
if(Constants.RewriteMissing)
diff --git a/src/SMAPI/Mobile/IsExternalInit.cs b/src/SMAPI/Mobile/IsExternalInit.cs
new file mode 100644
index 00000000..66a88a4c
--- /dev/null
+++ b/src/SMAPI/Mobile/IsExternalInit.cs
@@ -0,0 +1,7 @@
+using System.ComponentModel;
+
+namespace System.Runtime.CompilerServices
+{
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ internal class IsExternalInit{}
+}
diff --git a/src/SMAPI/Mobile/MobileMemoryExtension.cs b/src/SMAPI/Mobile/MobileMemoryExtension.cs
new file mode 100644
index 00000000..034d72a5
--- /dev/null
+++ b/src/SMAPI/Mobile/MobileMemoryExtension.cs
@@ -0,0 +1,23 @@
+namespace System;
+using Internal.Runtime.CompilerServices;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Text;
+
+public static class MobileMemoryExtension
+{
+
+ /// Indicates whether a specified value is found in a read-only span. Values are compared using IEquatable{T}.Equals(T).
+ /// The span to search.
+ /// The value to search for.
+ /// The type of the span.
+ ///
+ /// if found, otherwise.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool Contains(this ReadOnlySpan span, T value) where T : IEquatable
+ {
+ return span.IndexOf(value) >= 0;
+ }
+}
diff --git a/src/SMAPI/Mobile/MobileTypeExtension.cs b/src/SMAPI/Mobile/MobileTypeExtension.cs
new file mode 100644
index 00000000..a51847b0
--- /dev/null
+++ b/src/SMAPI/Mobile/MobileTypeExtension.cs
@@ -0,0 +1,34 @@
+namespace System;
+
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+using System.Globalization;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Threading;
+
+public static class MobileTypeExtension
+{
+
+ /// Determines whether the current type can be assigned to a variable of the specified .
+ /// The type to compare with the current type.
+ ///
+ /// if any of the following conditions is true:
+ ///
+ /// - The current instance and represent the same type.
+ ///
+ /// - The current type is derived either directly or indirectly from . The current type is derived directly from if it inherits from ; the current type is derived indirectly from if it inherits from a succession of one or more classes that inherit from .
+ ///
+ /// - is an interface that the current type implements.
+ ///
+ /// - The current type is a generic type parameter, and represents one of the constraints of the current type.
+ ///
+ /// - The current type represents a value type, and represents Nullable<c> (Nullable(Of c) in Visual Basic).
+ ///
+ /// if none of these conditions are true, or if or is .
+ public static bool IsAssignableTo(this Type type, [NotNullWhen(true)] Type? targetType) => (object) targetType != null && targetType.IsAssignableFrom(type);
+
+}
diff --git a/src/SMAPI/Patches/JunimoHarvesterPatch.cs b/src/SMAPI/Patches/JunimoHarvesterPatch.cs
index ebc8adbf..fabcc488 100644
--- a/src/SMAPI/Patches/JunimoHarvesterPatch.cs
+++ b/src/SMAPI/Patches/JunimoHarvesterPatch.cs
@@ -4,13 +4,9 @@ using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
-#if HARMONY_2
using HarmonyLib;
-#else
-using Harmony;
-#endif
using Microsoft.Xna.Framework;
-using StardewModdingAPI.Framework.Patching;
+using StardewModdingAPI.Internal.Patching;
using StardewValley;
using StardewValley.Buildings;
using StardewValley.Characters;
@@ -21,7 +17,7 @@ namespace StardewModdingAPI.Patches
/// Patch methods must be static for Harmony to work correctly. See the Harmony documentation before renaming patch arguments.
[SuppressMessage("ReSharper", "InconsistentNaming", Justification = "Argument names are defined by Harmony and methods are named for clarity.")]
[SuppressMessage("ReSharper", "IdentifierTypo", Justification = "Argument names are defined by Harmony and methods are named for clarity.")]
- internal class JunimoHarvesterPatch : IHarmonyPatch
+ internal class JunimoHarvesterPatch : BasePatcher
{
/*********
** Fields
@@ -43,22 +39,9 @@ namespace StardewModdingAPI.Patches
/*********
** Public methods
*********/
- /// Construct an instance.
- /// Writes messages to the console and log file on behalf of the game.
- public JunimoHarvesterPatch(IMonitor monitor)
- {
- Monitor = monitor;
- }
-
/// Apply the Harmony patch.
/// The Harmony instance.
- public void Apply(
-#if HARMONY_2
- Harmony harmony
-#else
- HarmonyInstance harmony
-#endif
- )
+ public override void Apply(Harmony harmony, IMonitor monitor)
{
harmony.Patch(
original: AccessTools.DeclaredConstructor(typeof(JunimoHarvester), new System.Type[] { typeof(Vector2), typeof(JunimoHut), typeof(int), typeof(Color?)}),
@@ -67,6 +50,13 @@ namespace StardewModdingAPI.Patches
);
}
+ /// Construct an instance.
+ /// Writes messages to the console and log file on behalf of the game.
+ public JunimoHarvesterPatch(IMonitor monitor)
+ {
+ Monitor = monitor;
+ }
+
/*********
** Private methods
diff --git a/src/SMAPI/Patches/LocationSwitchPatch.cs b/src/SMAPI/Patches/LocationSwitchPatch.cs
index ee30af08..d5a8de9c 100644
--- a/src/SMAPI/Patches/LocationSwitchPatch.cs
+++ b/src/SMAPI/Patches/LocationSwitchPatch.cs
@@ -1,12 +1,8 @@
#if SMAPI_FOR_MOBILE
using System;
using System.Diagnostics.CodeAnalysis;
-#if HARMONY_2
using HarmonyLib;
-#else
-using Harmony;
-#endif
-using StardewModdingAPI.Framework.Patching;
+using StardewModdingAPI.Internal.Patching;
using StardewValley;
using StardewValley.Characters;
@@ -16,7 +12,7 @@ namespace StardewModdingAPI.Patches
/// Patch methods must be static for Harmony to work correctly. See the Harmony documentation before renaming patch arguments.
[SuppressMessage("ReSharper", "InconsistentNaming", Justification = "Argument names are defined by Harmony and methods are named for clarity.")]
[SuppressMessage("ReSharper", "IdentifierTypo", Justification = "Argument names are defined by Harmony and methods are named for clarity.")]
- internal class LocationSwitchPatch : IHarmonyPatch
+ internal class LocationSwitchPatch : BasePatcher
{
/*********
** Fields
@@ -47,13 +43,7 @@ namespace StardewModdingAPI.Patches
/// Apply the Harmony patch.
/// The Harmony instance.
- public void Apply(
-#if HARMONY_2
- Harmony harmony
-#else
- HarmonyInstance harmony
-#endif
- )
+ public override void Apply(Harmony harmony, IMonitor monitor)
{
harmony.Patch(
original: AccessTools.Property(typeof(Game1), "currentLocation").SetMethod,
diff --git a/src/SMAPI/Patches/MusicBankPatch.cs b/src/SMAPI/Patches/MusicBankPatch.cs
index 7c1ebed6..e0110bd9 100644
--- a/src/SMAPI/Patches/MusicBankPatch.cs
+++ b/src/SMAPI/Patches/MusicBankPatch.cs
@@ -3,19 +3,15 @@ using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
-using Microsoft.AppCenter.Crashes;
-#if HARMONY_2
+// using Microsoft.AppCenter.Crashes;
using HarmonyLib;
-#else
-using Harmony;
-#endif
using StardewModdingAPI.Framework;
-using StardewModdingAPI.Framework.Patching;
+using StardewModdingAPI.Internal.Patching;
using StardewValley;
namespace StardewModdingAPI.Patches
{
- internal class MusicBankPatch : IHarmonyPatch
+ internal class MusicBankPatch : BasePatcher
{
/*********
** Accessors
@@ -37,7 +33,7 @@ namespace StardewModdingAPI.Patches
/// Apply the Harmony patch.
/// The Harmony instance.
- public void Apply(HarmonyInstance harmony)
+ public override void Apply(Harmony harmony, IMonitor monitor)
{
harmony.Patch(AccessTools.Method(typeof(Game1), "FetchMusicXWBPath"),
new HarmonyMethod(AccessTools.Method(this.GetType(), nameof(MusicBankPatch.Game_FetchMusicXWBPathPrefix))));
@@ -68,7 +64,7 @@ namespace StardewModdingAPI.Patches
}
catch (System.Exception ex)
{
- Microsoft.AppCenter.Crashes.Crashes.TrackError(ex, (IDictionary) null, Array.Empty());
+ // Microsoft.AppCenter.Crashes.Crashes.TrackError(ex, (IDictionary) null, Array.Empty());
return true;
}
__result = str;
diff --git a/src/SMAPI/Patches/OnAppPausePatch.cs b/src/SMAPI/Patches/OnAppPausePatch.cs
index 8751dc3e..95f8e31f 100644
--- a/src/SMAPI/Patches/OnAppPausePatch.cs
+++ b/src/SMAPI/Patches/OnAppPausePatch.cs
@@ -2,18 +2,14 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
-#if HARMONY_2
using HarmonyLib;
-#else
-using Harmony;
-#endif
using StardewModdingAPI.Framework;
-using StardewModdingAPI.Framework.Patching;
+using StardewModdingAPI.Internal.Patching;
using StardewValley;
namespace StardewModdingAPI.Patches
{
- internal class OnAppPausePatch : IHarmonyPatch
+ internal class OnAppPausePatch : BasePatcher
{
/*********
** Accessors
@@ -35,19 +31,11 @@ namespace StardewModdingAPI.Patches
/// Apply the Harmony patch.
/// The Harmony instance.
-#if HARMONY_2
- public void Apply(Harmony harmony)
+ public override void Apply(Harmony harmony, IMonitor monitor)
{
harmony.Patch(AccessTools.Method(typeof(Game1), nameof(Game1.OnAppPause)),
- finalizer:new HarmonyMethod(AccessTools.Method(this.GetType(), nameof(OnAppPausePatch.Game_OnAppPauseFinalizer))));
+ finalizer: new HarmonyMethod(AccessTools.Method(this.GetType(), nameof(OnAppPausePatch.Game_OnAppPauseFinalizer))));
}
-#else
- public void Apply(HarmonyInstance harmony)
- {
- harmony.Patch(AccessTools.Method(typeof(Game1), nameof(Game1.OnAppPause)),
- new HarmonyMethod(AccessTools.Method(this.GetType(), nameof(OnAppPausePatch.Game_OnAppPausePrefix))));
- }
-#endif
/*********
** Private methods
@@ -55,36 +43,16 @@ namespace StardewModdingAPI.Patches
/// The method to call instead of .
/// This method must be static for Harmony to work correctly. See the Harmony documentation before renaming arguments.
[SuppressMessage("ReSharper", "InconsistentNaming", Justification = "Argument names are defined by Harmony.")]
-#if HARMONY_2
private static Exception Game_OnAppPauseFinalizer(Exception __exception)
{
if (__exception != null)
{
OnAppPausePatch.Monitor.Log($"Failed during OnAppPause method :\n{__exception.InnerException ?? __exception}", LogLevel.Error);
}
+
return null;
}
-#else
- private static bool Game_OnAppPausePrefix(Game1 __instance, MethodInfo __originalMethod)
- {
- const string key = nameof(OnAppPausePatch.Game_OnAppPausePrefix);
- if (!PatchHelper.StartIntercept(key))
- return true;
- try
- {
- __originalMethod.Invoke(__instance, new object[] { });
- }
- catch (Exception ex)
- {
- OnAppPausePatch.Monitor.Log($"Failed during OnAppPause method :\n{ex.InnerException ?? ex}", LogLevel.Error);
- }
- finally
- {
- PatchHelper.StopIntercept(key);
- }
- return false;
- }
}
-#endif
}
#endif
+
diff --git a/src/SMAPI/Patches/SaveBackupPatch.cs b/src/SMAPI/Patches/SaveBackupPatch.cs
index 4a437b67..74c4c247 100644
--- a/src/SMAPI/Patches/SaveBackupPatch.cs
+++ b/src/SMAPI/Patches/SaveBackupPatch.cs
@@ -2,19 +2,15 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
-#if HARMONY_2
using HarmonyLib;
-#else
-using Harmony;
-#endif
using StardewModdingAPI.Framework;
using StardewModdingAPI.Framework.Events;
-using StardewModdingAPI.Framework.Patching;
+using StardewModdingAPI.Internal.Patching;
using StardewValley;
namespace StardewModdingAPI.Patches
{
- internal class SaveBackupPatch : IHarmonyPatch
+ internal class SaveBackupPatch : BasePatcher
{
/*********
** Accessors
@@ -44,8 +40,7 @@ namespace StardewModdingAPI.Patches
/// Apply the Harmony patch.
/// The Harmony instance.
-#if HARMONY_2
- public void Apply(Harmony harmony)
+ public override void Apply(Harmony harmony, IMonitor monitor)
{
MethodInfo makeFullBackup = AccessTools.Method(typeof(Game1), nameof(Game1.MakeFullBackup));
MethodInfo saveWholeBackup = AccessTools.Method(typeof(Game1), nameof(Game1.saveWholeBackup));
@@ -56,25 +51,13 @@ namespace StardewModdingAPI.Patches
harmony.Patch(makeFullBackup, new HarmonyMethod(prefix), finalizer: new HarmonyMethod(finalizer));
harmony.Patch(saveWholeBackup, new HarmonyMethod(prefix), finalizer: new HarmonyMethod(finalizer));
}
-#else
- public void Apply(HarmonyInstance harmony)
- {
- MethodInfo makeFullBackup = AccessTools.Method(typeof(Game1), nameof(Game1.MakeFullBackup));
- MethodInfo saveWholeBackup = AccessTools.Method(typeof(Game1), nameof(Game1.saveWholeBackup));
- MethodInfo prefix = AccessTools.Method(this.GetType(), nameof(SaveBackupPatch.GameSave_Prefix));
-
- harmony.Patch(makeFullBackup, new HarmonyMethod(prefix));
- harmony.Patch(saveWholeBackup, new HarmonyMethod(prefix));
- }
-#endif
/*********
** Private methods
*********/
/// The method to call instead of .
/// This method must be static for Harmony to work correctly. See the Harmony documentation before renaming arguments.
[SuppressMessage("ReSharper", "InconsistentNaming", Justification = "Argument names are defined by Harmony.")]
-#if HARMONY_2
private static bool GameSave_Prefix()
{
SaveBackupPatch.Events.Saving.RaiseEmpty();
@@ -92,30 +75,6 @@ namespace StardewModdingAPI.Patches
SaveBackupPatch.Events.Saved.RaiseEmpty();
return null;
}
-#else
- private static bool GameSave_Prefix(MethodInfo __originalMethod)
- {
- const string key = nameof(SaveBackupPatch.GameSave_Prefix);
- if (!PatchHelper.StartIntercept(key))
- return true;
- SaveBackupPatch.Events.Saving.RaiseEmpty();
- try
- {
- __originalMethod.Invoke(null, new object[] { });
- }
- catch (Exception ex)
- {
- SaveBackupPatch.Monitor.Log($"Failed to save the game :\n{ex.InnerException ?? ex}", LogLevel.Error);
- Game1.addHUDMessage(new HUDMessage("An error occurs during save the game.Check the error log for details.", HUDMessage.error_type));
- }
- finally
- {
- PatchHelper.StopIntercept(key);
- }
- SaveBackupPatch.Events.Saved.RaiseEmpty();
- return false;
- }
-#endif
}
}
#endif
diff --git a/src/SMAPI/Patches/SaveGamePatch.cs b/src/SMAPI/Patches/SaveGamePatch.cs
index d6b1a9b4..77a2b74a 100644
--- a/src/SMAPI/Patches/SaveGamePatch.cs
+++ b/src/SMAPI/Patches/SaveGamePatch.cs
@@ -4,21 +4,17 @@ using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Reflection;
-#if HARMONY_2
using HarmonyLib;
-#else
-using Harmony;
-#endif
-using Microsoft.AppCenter.Crashes;
+// using Microsoft.AppCenter.Crashes;
using Microsoft.Xna.Framework;
using StardewModdingAPI.Framework;
-using StardewModdingAPI.Framework.Patching;
+using StardewModdingAPI.Internal.Patching;
using StardewValley;
using StardewValley.Menus;
namespace StardewModdingAPI.Patches
{
- internal class SaveGamePatch : IHarmonyPatch
+ internal class SaveGamePatch : BasePatcher
{
/*********
** Accessors
@@ -47,8 +43,7 @@ namespace StardewModdingAPI.Patches
/// Apply the Harmony patch.
/// The Harmony instance.
-#if HARMONY_2
- public void Apply(Harmony harmony)
+ public override void Apply(Harmony harmony, IMonitor monitor)
{
harmony.Patch(
original: AccessTools.Method(typeof(SaveGame), "HandleLoadError"),
@@ -59,19 +54,6 @@ namespace StardewModdingAPI.Patches
finalizer: new HarmonyMethod(this.GetType(), nameof(SaveGamePatch.SaveGameMenu_UpdateFinalizer))
);
}
-#else
- public void Apply(HarmonyInstance harmony)
- {
- harmony.Patch(
- original: AccessTools.Method(typeof(SaveGame), "HandleLoadError"),
- prefix: new HarmonyMethod(this.GetType(), nameof(SaveGamePatch.Prefix))
- );
- harmony.Patch(
- original: AccessTools.Method(typeof(SaveGameMenu), "update"),
- prefix: new HarmonyMethod(this.GetType(), nameof(SaveGamePatch.SaveGameMenu_UpdatePrefix))
- );
- }
-#endif
/*********
** Private methods
@@ -138,8 +120,8 @@ namespace StardewModdingAPI.Patches
}
catch (Exception ex)
{
- ErrorAttachmentLog[] errorAttachmentLogArray = Array.Empty();
- Crashes.TrackError(ex, null, errorAttachmentLogArray);
+ // ErrorAttachmentLog[] errorAttachmentLogArray = Array.Empty();
+ // Crashes.TrackError(ex, null, errorAttachmentLogArray);
failed = true;
}
}
@@ -174,7 +156,6 @@ namespace StardewModdingAPI.Patches
/// The method to call instead of .
/// This method must be static for Harmony to work correctly. See the Harmony documentation before renaming arguments.
[SuppressMessage("ReSharper", "InconsistentNaming", Justification = "Argument names are defined by Harmony.")]
-#if HARMONY_2
private static Exception SaveGameMenu_UpdateFinalizer(SaveGameMenu __instance, Exception __exception)
{
if(__exception != null) {
@@ -184,29 +165,6 @@ namespace StardewModdingAPI.Patches
}
return null;
}
-#else
- private static bool SaveGameMenu_UpdatePrefix(SaveGameMenu __instance, GameTime time, MethodInfo __originalMethod)
- {
- const string key = nameof(SaveGamePatch.SaveGameMenu_UpdatePrefix);
- if (!PatchHelper.StartIntercept(key))
- return true;
- try
- {
- __originalMethod.Invoke(__instance, new object[] {time});
- }
- catch (Exception ex)
- {
- SaveGamePatch.Monitor.Log($"Failed during SaveGameMenu.update method :\n{ex.InnerException ?? ex}", LogLevel.Error);
- __instance.complete();
- Game1.addHUDMessage(new HUDMessage("An error occurs during save the game.Check the error log for details.", HUDMessage.error_type));
- }
- finally
- {
- PatchHelper.StopIntercept(key);
- }
- return false;
- }
-#endif
}
}
#endif
diff --git a/src/SMAPI/Patches/SpriteFontPatch.cs b/src/SMAPI/Patches/SpriteFontPatch.cs
index 6b49a5d6..937d664f 100644
--- a/src/SMAPI/Patches/SpriteFontPatch.cs
+++ b/src/SMAPI/Patches/SpriteFontPatch.cs
@@ -1,12 +1,8 @@
#if SMAPI_FOR_MOBILE
using System.Diagnostics.CodeAnalysis;
-#if HARMONY_2
using HarmonyLib;
-#else
-using Harmony;
-#endif
using Microsoft.Xna.Framework.Graphics;
-using StardewModdingAPI.Framework.Patching;
+using StardewModdingAPI.Internal.Patching;
using StardewValley.Characters;
namespace StardewModdingAPI.Patches
@@ -15,7 +11,7 @@ namespace StardewModdingAPI.Patches
/// Patch methods must be static for Harmony to work correctly. See the Harmony documentation before renaming patch arguments.
[SuppressMessage("ReSharper", "InconsistentNaming", Justification = "Argument names are defined by Harmony and methods are named for clarity.")]
[SuppressMessage("ReSharper", "IdentifierTypo", Justification = "Argument names are defined by Harmony and methods are named for clarity.")]
- internal class SpriteFontPatch : IHarmonyPatch
+ internal class SpriteFontPatch : BasePatcher
{
/*********
** Fields
@@ -46,13 +42,7 @@ namespace StardewModdingAPI.Patches
/// Apply the Harmony patch.
/// The Harmony instance.
- public void Apply(
-#if HARMONY_2
- Harmony harmony
-#else
- HarmonyInstance harmony
-#endif
- )
+ public override void Apply(Harmony harmony, IMonitor monitor)
{
harmony.Patch(
original: AccessTools.Method(typeof(SpriteFont), "MeasureString", new System.Type[] { typeof(string)}),
diff --git a/src/SMAPI/Patches/ThreadSilenceExitPatch.cs b/src/SMAPI/Patches/ThreadSilenceExitPatch.cs
index 55a39804..ffc529d7 100644
--- a/src/SMAPI/Patches/ThreadSilenceExitPatch.cs
+++ b/src/SMAPI/Patches/ThreadSilenceExitPatch.cs
@@ -2,12 +2,8 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Threading;
-#if HARMONY_2
using HarmonyLib;
-#else
-using Harmony;
-#endif
-using StardewModdingAPI.Framework.Patching;
+using StardewModdingAPI.Internal.Patching;
namespace StardewModdingAPI.Patches
{
@@ -15,7 +11,7 @@ namespace StardewModdingAPI.Patches
/// Patch methods must be static for Harmony to work correctly. See the Harmony documentation before renaming patch arguments.
[SuppressMessage("ReSharper", "InconsistentNaming", Justification = "Argument names are defined by Harmony and methods are named for clarity.")]
[SuppressMessage("ReSharper", "IdentifierTypo", Justification = "Argument names are defined by Harmony and methods are named for clarity.")]
- internal class ThreadSilenceExitPatch : IHarmonyPatch
+ internal class ThreadSilenceExitPatch : BasePatcher
{
/*********
** Fields
@@ -46,23 +42,13 @@ namespace StardewModdingAPI.Patches
/// Apply the Harmony patch.
/// The Harmony instance.
-#if HARMONY_2
- public void Apply(Harmony harmony)
+ public override void Apply(Harmony harmony, IMonitor monitor)
{
harmony.Patch(
original: AccessTools.Method(Type.GetType("System.Threading.ThreadHelper"), "ThreadStart_Context"),
finalizer: new HarmonyMethod(this.GetType(), nameof(ThreadSilenceExitPatch.ThreadStart_Finalizer))
);
}
-#else
- public void Apply(HarmonyInstance harmony)
- {
- harmony.Patch(
- original: AccessTools.Method(Type.GetType("System.Threading.ThreadHelper"), "ThreadStart_Context"),
- prefix: new HarmonyMethod(this.GetType(), nameof(ThreadSilenceExitPatch.ThreadStart_Finalizer))
- );
- }
-#endif
/*********
** Private methods
@@ -70,7 +56,6 @@ namespace StardewModdingAPI.Patches
/// The method to call instead of .
/// The thread context.
/// Returns whether to execute the original method.
-#if HARMONY_2
private static Exception ThreadStart_Finalizer(Exception __exception)
{
if (__exception != null) {
@@ -78,29 +63,6 @@ namespace StardewModdingAPI.Patches
}
return null;
}
-#else
- private static bool ThreadStart_Finalizer(object state)
- {
- try
- {
- object _start = state.GetType().GetField("_start", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).GetValue(state);
- if (_start is ThreadStart)
- {
- ((ThreadStart)_start)();
- }
- else
- {
- object _startArg = state.GetType().GetField("_startArg", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).GetValue(state);
- ((ParameterizedThreadStart)_start)(_startArg);
- }
- }
- catch (Exception ex)
- {
- Monitor.Log($"Thread failed:\n{ex.InnerException ?? ex}", LogLevel.Error);
- }
- return false;
- }
-#endif
}
}
#endif
diff --git a/src/SMAPI/Resources/Resource.designer.cs b/src/SMAPI/Resources/Resource.designer.cs
index cc1e943b..03941b5c 100644
--- a/src/SMAPI/Resources/Resource.designer.cs
+++ b/src/SMAPI/Resources/Resource.designer.cs
@@ -14,7 +14,7 @@ namespace StardewModdingAPI
{
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "1.0.0.0")]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "13.1.0.5")]
public partial class Resource
{
@@ -244,97 +244,73 @@ namespace StardewModdingAPI
public static int action_text = 2131034115;
// aapt resource value: 0x7F050005
- public static int appIcon = 2131034117;
+ public static int async = 2131034117;
// aapt resource value: 0x7F050006
- public static int async = 2131034118;
+ public static int blocking = 2131034118;
// aapt resource value: 0x7F050007
- public static int blocking = 2131034119;
+ public static int chronometer = 2131034119;
// aapt resource value: 0x7F050008
- public static int chronometer = 2131034120;
+ public static int forever = 2131034120;
// aapt resource value: 0x7F050009
- public static int description = 2131034121;
+ public static int icon = 2131034121;
// aapt resource value: 0x7F05000A
- public static int forever = 2131034122;
+ public static int icon_group = 2131034122;
// aapt resource value: 0x7F05000B
- public static int icon = 2131034123;
+ public static int info = 2131034123;
// aapt resource value: 0x7F05000C
- public static int icon_group = 2131034124;
+ public static int italic = 2131034124;
// aapt resource value: 0x7F05000D
- public static int info = 2131034125;
+ public static int line1 = 2131034125;
// aapt resource value: 0x7F05000E
- public static int italic = 2131034126;
+ public static int line3 = 2131034126;
// aapt resource value: 0x7F05000F
- public static int line1 = 2131034127;
+ public static int normal = 2131034127;
// aapt resource value: 0x7F050010
- public static int line3 = 2131034128;
+ public static int notification_background = 2131034128;
// aapt resource value: 0x7F050011
- public static int normal = 2131034129;
+ public static int notification_main_column = 2131034129;
// aapt resource value: 0x7F050012
- public static int notificationLayout = 2131034130;
+ public static int notification_main_column_container = 2131034130;
// aapt resource value: 0x7F050013
- public static int notification_background = 2131034131;
+ public static int right_icon = 2131034131;
// aapt resource value: 0x7F050014
- public static int notification_main_column = 2131034132;
+ public static int right_side = 2131034132;
// aapt resource value: 0x7F050015
- public static int notification_main_column_container = 2131034133;
+ public static int tag_transition_group = 2131034133;
// aapt resource value: 0x7F050016
- public static int progress_bar = 2131034134;
+ public static int tag_unhandled_key_event_manager = 2131034134;
// aapt resource value: 0x7F050017
- public static int progress_bar_frame = 2131034135;
+ public static int tag_unhandled_key_listeners = 2131034135;
// aapt resource value: 0x7F050018
- public static int progress_text = 2131034136;
+ public static int text = 2131034136;
// aapt resource value: 0x7F050019
- public static int right_icon = 2131034137;
+ public static int text2 = 2131034137;
// aapt resource value: 0x7F05001A
- public static int right_side = 2131034138;
+ public static int time = 2131034138;
// aapt resource value: 0x7F05001B
- public static int spacer = 2131034139;
-
- // aapt resource value: 0x7F05001C
- public static int tag_transition_group = 2131034140;
-
- // aapt resource value: 0x7F05001D
- public static int tag_unhandled_key_event_manager = 2131034141;
-
- // aapt resource value: 0x7F05001E
- public static int tag_unhandled_key_listeners = 2131034142;
-
- // aapt resource value: 0x7F05001F
- public static int text = 2131034143;
-
- // aapt resource value: 0x7F050020
- public static int text2 = 2131034144;
-
- // aapt resource value: 0x7F050021
- public static int time = 2131034145;
-
- // aapt resource value: 0x7F050022
- public static int time_remaining = 2131034146;
-
- // aapt resource value: 0x7F050023
- public static int title = 2131034147;
+ public static int title = 2131034139;
static Id()
{
@@ -383,9 +359,6 @@ namespace StardewModdingAPI
// aapt resource value: 0x7F070005
public static int notification_template_part_time = 2131165189;
- // aapt resource value: 0x7F070006
- public static int status_bar_ongoing_event_progress_bar = 2131165190;
-
static Layout()
{
global::Android.Runtime.ResourceIdManager.UpdateIdValues();
@@ -406,76 +379,7 @@ namespace StardewModdingAPI
public static int hello = 2131230721;
// aapt resource value: 0x7F080002
- public static int kilobytes_per_second = 2131230722;
-
- // aapt resource value: 0x7F080003
- public static int notification_download_complete = 2131230723;
-
- // aapt resource value: 0x7F080004
- public static int notification_download_failed = 2131230724;
-
- // aapt resource value: 0x7F080005
- public static int state_completed = 2131230725;
-
- // aapt resource value: 0x7F080006
- public static int state_connecting = 2131230726;
-
- // aapt resource value: 0x7F080007
- public static int state_downloading = 2131230727;
-
- // aapt resource value: 0x7F080008
- public static int state_failed = 2131230728;
-
- // aapt resource value: 0x7F080009
- public static int state_failed_cancelled = 2131230729;
-
- // aapt resource value: 0x7F08000A
- public static int state_failed_fetching_url = 2131230730;
-
- // aapt resource value: 0x7F08000B
- public static int state_failed_sdcard_full = 2131230731;
-
- // aapt resource value: 0x7F08000C
- public static int state_failed_unlicensed = 2131230732;
-
- // aapt resource value: 0x7F08000D
- public static int state_fetching_url = 2131230733;
-
- // aapt resource value: 0x7F08000E
- public static int state_idle = 2131230734;
-
- // aapt resource value: 0x7F08000F
- public static int state_paused_by_request = 2131230735;
-
- // aapt resource value: 0x7F080010
- public static int state_paused_network_setup_failure = 2131230736;
-
- // aapt resource value: 0x7F080011
- public static int state_paused_network_unavailable = 2131230737;
-
- // aapt resource value: 0x7F080012
- public static int state_paused_roaming = 2131230738;
-
- // aapt resource value: 0x7F080013
- public static int state_paused_sdcard_unavailable = 2131230739;
-
- // aapt resource value: 0x7F080014
- public static int state_paused_wifi_disabled = 2131230740;
-
- // aapt resource value: 0x7F080015
- public static int state_paused_wifi_unavailable = 2131230741;
-
- // aapt resource value: 0x7F080016
- public static int state_unknown = 2131230742;
-
- // aapt resource value: 0x7F080017
- public static int status_bar_notification_info_overflow = 2131230743;
-
- // aapt resource value: 0x7F080018
- public static int time_remaining = 2131230744;
-
- // aapt resource value: 0x7F080019
- public static int time_remaining_notification = 2131230745;
+ public static int status_bar_notification_info_overflow = 2131230722;
static String()
{
@@ -491,40 +395,25 @@ namespace StardewModdingAPI
{
// aapt resource value: 0x7F090000
- public static int ButtonBackground = 2131296256;
+ public static int TextAppearance_Compat_Notification = 2131296256;
// aapt resource value: 0x7F090001
- public static int NotificationText = 2131296257;
+ public static int TextAppearance_Compat_Notification_Info = 2131296257;
// aapt resource value: 0x7F090002
- public static int NotificationTextSecondary = 2131296258;
+ public static int TextAppearance_Compat_Notification_Line2 = 2131296258;
// aapt resource value: 0x7F090003
- public static int NotificationTextShadow = 2131296259;
+ public static int TextAppearance_Compat_Notification_Time = 2131296259;
// aapt resource value: 0x7F090004
- public static int NotificationTitle = 2131296260;
+ public static int TextAppearance_Compat_Notification_Title = 2131296260;
// aapt resource value: 0x7F090005
- public static int TextAppearance_Compat_Notification = 2131296261;
+ public static int Widget_Compat_NotificationActionContainer = 2131296261;
// aapt resource value: 0x7F090006
- public static int TextAppearance_Compat_Notification_Info = 2131296262;
-
- // aapt resource value: 0x7F090007
- public static int TextAppearance_Compat_Notification_Line2 = 2131296263;
-
- // aapt resource value: 0x7F090008
- public static int TextAppearance_Compat_Notification_Time = 2131296264;
-
- // aapt resource value: 0x7F090009
- public static int TextAppearance_Compat_Notification_Title = 2131296265;
-
- // aapt resource value: 0x7F09000A
- public static int Widget_Compat_NotificationActionContainer = 2131296266;
-
- // aapt resource value: 0x7F09000B
- public static int Widget_Compat_NotificationActionText = 2131296267;
+ public static int Widget_Compat_NotificationActionText = 2131296262;
static Style()
{
diff --git a/src/SMAPI/SGameConsole.cs b/src/SMAPI/SGameConsole.cs
index 01e55788..85bfbbe3 100644
--- a/src/SMAPI/SGameConsole.cs
+++ b/src/SMAPI/SGameConsole.cs
@@ -108,10 +108,10 @@ namespace StardewModdingAPI
this.isVisible = false;
Game1.activeClickableMenu = null;
Game1.playSound("bigDeSelect");
- SMainActivity.Instance.core.CommandQueue.Enqueue(command);
+ SMainActivity.Instance.core.RawCommandQueue.Add(command);
return;
}
- SMainActivity.Instance.core.CommandQueue.Enqueue(command);
+ SMainActivity.Instance.core.RawCommandQueue.Add(command);
}
}
diff --git a/src/SMAPI/SMAPI.csproj b/src/SMAPI/SMAPI.csproj
index 4df2c9e1..c611d153 100644
--- a/src/SMAPI/SMAPI.csproj
+++ b/src/SMAPI/SMAPI.csproj
@@ -18,8 +18,8 @@
Resources\Resource.designer.cs
Off
false
- MonoAndroid
- v10.0
+ v12.0
+ net5.0-android
true
$(DefineConstants)
@@ -33,7 +33,6 @@
prompt
4
latest
- 8.0
armeabi-v7a;x86;arm64-v8a;x86_64
@@ -44,7 +43,7 @@
$(DefineConstants);TRACE
prompt
4
- 8.0
+ latest
armeabi-v7a;x86;arm64-v8a;x86_64
false
None
@@ -70,7 +69,7 @@
app.manifest
-
+
@@ -85,7 +84,6 @@
-
@@ -115,99 +113,24 @@
-
-
- 2.0.0
-
-
- 2.0.0
-
-
- 2.0.0
-
-
-
-
-
-
-
+
- ..\..\..\Downloads\StardewValleyAndroidStuff\base_1.4.5.151\assemblies_decrypt\StardewValley.dll
+ ..\..\..\Downloads\StardewValleyAndroidStuff\base_1.5.6.31\assemblies\StardewValley.dll
- ..\..\..\Downloads\StardewValleyAndroidStuff\base_1.4.5.151\assemblies_decrypt\StardewValley.GameData.dll
+ ..\..\..\Downloads\StardewValleyAndroidStuff\base_1.5.6.31\assemblies\StardewValley.GameData.dll
- ..\..\..\Downloads\StardewValleyAndroidStuff\base_1.4.5.151\assemblies_decrypt\xTile.dll
+ ..\..\..\Downloads\StardewValleyAndroidStuff\base_1.5.6.31\assemblies\xTile.dll
-
-
-
-
- ..\..\..\Downloads\StardewValleyAndroidStuff\base_1.4.5.145\assemblies\StardewValley.dll
-
-
- ..\..\..\Downloads\StardewValleyAndroidStuff\base_1.4.5.145\assemblies\StardewValley.GameData.dll
-
-
- ..\..\..\Downloads\StardewValleyAndroidStuff\base_1.4.5.145\assemblies\MonoGame.Framework.dll
-
-
- ..\..\..\Downloads\StardewValleyAndroidStuff\base_1.4.5.145\assemblies\xTile.dll
-
-
-
-
-
- ..\..\..\Downloads\StardewValleyAndroidStuff\base_1.4.4.128\assemblies\StardewValley.dll
-
-
- ..\..\..\Downloads\StardewValleyAndroidStuff\base_1.4.4.128\assemblies\MonoGame.Framework.dll
-
-
- ..\..\..\Downloads\StardewValleyAndroidStuff\base_1.4.4.128\assemblies\xTile.dll
-
-
-
-
-
- ..\..\..\Downloads\StardewValleyAndroidStuff\samsung_base_1.4.5.144\assemblies\StardewValley.dll
-
-
- ..\..\..\Downloads\StardewValleyAndroidStuff\samsung_base_1.4.5.144\assemblies\StardewValley.GameData.dll
-
-
- ..\..\..\Downloads\StardewValleyAndroidStuff\samsung_base_1.4.5.144\assemblies\MonoGame.Framework.dll
-
-
- ..\..\..\Downloads\StardewValleyAndroidStuff\samsung_base_1.4.5.144\assemblies\xTile.dll
-
-
-
-
-
- ..\..\..\Downloads\StardewValleyAndroidStuff\amazon_base_1.4.5.144\assemblies\StardewValley.dll
-
-
- ..\..\..\Downloads\StardewValleyAndroidStuff\amazon_base_1.4.5.144\assemblies\StardewValley.GameData.dll
-
-
- ..\..\..\Downloads\StardewValleyAndroidStuff\amazon_base_1.4.5.144\assemblies\MonoGame.Framework.dll
-
-
- ..\..\..\Downloads\StardewValleyAndroidStuff\amazon_base_1.4.5.144\assemblies\xTile.dll
+
+ ..\..\..\Downloads\StardewValleyAndroidStuff\base_1.5.6.31\assemblies\BmFont.dll
-
- 3.6.0.862
-
- ..\..\..\Downloads\StardewValleyAndroidStuff\base_1.4.5.145\assemblies\MonoGame.Framework.dll
-
-
- ..\..\..\Downloads\StardewValleyAndroidStuff\base_1.4.5.145\assemblies\MonoGame.Framework.Content.Pipeline.dll
+ ..\..\..\Downloads\StardewValleyAndroidStuff\base_1.5.6.31\assemblies\MonoGame.Framework.dll
@@ -219,45 +142,39 @@
..\..\build\0Harmony.dll
-
- ..\Loader\libs\MonoMod.RuntimeDetour.dll
-
-
- ..\Loader\libs\MonoMod.Utils.dll
-
- ..\SMAPI.Toolkit\bin\Debug\net4.5\SMAPI.Toolkit.dll
+ ..\SMAPI.Toolkit\bin\Debug\netstandard2.0\SMAPI.Toolkit.dll
- ..\SMAPI.Toolkit.CoreInterfaces\bin\Debug\net4.5\SMAPI.Toolkit.CoreInterfaces.dll
+ ..\SMAPI.Toolkit.CoreInterfaces\bin\Debug\netstandard2.0\SMAPI.Toolkit.CoreInterfaces.dll
-
- ..\Loader\libs\TMXTile.dll
-
-
- ..\Loader\libs\Microsoft.AppCenter.dll
-
-
- ..\Loader\libs\Microsoft.AppCenter.Analytics.dll
-
-
- ..\Loader\libs\Microsoft.AppCenter.Analytics.Android.Bindings.dll
-
-
- ..\Loader\libs\Microsoft.AppCenter.Android.Bindings.dll
-
-
- ..\Loader\libs\Microsoft.AppCenter.Crashes.dll
-
-
- ..\Loader\libs\Microsoft.AppCenter.Crashes.Android.Bindings.dll
-
-
-
+
+ 3.8.1.303
+
+
+ 2.88.3
+
28.0.0.3
+
+ 28.0.0.3
+
+
+
+
+
+
+ ..\..\build\Pintail.dll
+
+
+ ..\..\build\TMXTile.dll
+
+
+
+
+
@@ -274,6 +191,10 @@
+
+
+
+
diff --git a/src/SMAPI/SMainActivity.cs b/src/SMAPI/SMainActivity.cs
index 002cdd43..7c94fae2 100644
--- a/src/SMAPI/SMainActivity.cs
+++ b/src/SMAPI/SMainActivity.cs
@@ -7,7 +7,6 @@ using Android.Runtime;
using Android.Support.V4.App;
using Android.Support.V4.Content;
using Android.Views;
-using Google.Android.Vending.Licensing;
using System;
using System.Collections.Generic;
using StardewModdingAPI.Framework;
@@ -16,9 +15,7 @@ using System.Reflection;
using Java.Interop;
using System.Linq;
using File = Java.IO.File;
-using Microsoft.AppCenter;
using Newtonsoft.Json;
-using Microsoft.AppCenter.Crashes;
using Android.Content;
using Android.Util;
using Java.Lang;
@@ -29,17 +26,9 @@ using Thread = System.Threading.Thread;
namespace StardewModdingAPI
{
[Activity(Label = "SMAPI Stardew Valley", Icon = "@mipmap/ic_launcher", Theme = "@style/Theme.Splash", MainLauncher = true, AlwaysRetainTaskState = true, LaunchMode = LaunchMode.SingleInstance, ScreenOrientation = ScreenOrientation.SensorLandscape, ConfigurationChanges = (ConfigChanges.Keyboard | ConfigChanges.KeyboardHidden | ConfigChanges.Orientation | ConfigChanges.ScreenLayout | ConfigChanges.ScreenSize | ConfigChanges.UiMode))]
-#if !ANDROID_TARGET_GOOGLE
public class SMainActivity: MainActivity
-#else
- public class SMainActivity : MainActivity, ILicenseCheckerCallback, IJavaObject, IDisposable, IJavaPeerable
-#endif
{
internal SCore core;
- private LicenseChecker _licenseChecker;
-#if ANDROID_TARGET_GOOGLE
- private ServerManagedPolicyExtended _serverManagedPolicyExtended;
-#endif
public static SMainActivity Instance;
@@ -124,10 +113,6 @@ namespace StardewModdingAPI
}
catch (Exception) { }
}
- Type[] services = {typeof(Microsoft.AppCenter.Analytics.Analytics), typeof(Microsoft.AppCenter.Crashes.Crashes)};
- AppCenter.Start(Constants.MicrosoftAppSecret, services);
- AppCenter.SetUserId(Constants.ApiVersion.ToString());
-
}
catch
{
@@ -164,7 +149,7 @@ namespace StardewModdingAPI
modPath = "StardewValley/Mods";
}
- this.core = new SCore(System.IO.Path.Combine(EarlyConstants.StorageBasePath, modPath), false);
+ this.core = new SCore(System.IO.Path.Combine(EarlyConstants.StorageBasePath, modPath), false, false);
this.core.RunInteractively();
typeof(MainActivity).GetField("_game1", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(this, this.core.Game);
@@ -187,7 +172,6 @@ namespace StardewModdingAPI
SAlertDialogUtil.AlertMessage($"SMAPI failed to initialize: {ex}",
callback: type =>
{
- Crashes.TrackError(ex);
this.Finish();
});
}
@@ -223,49 +207,8 @@ namespace StardewModdingAPI
private void CheckUsingServerManagedPolicy()
{
-#if ANDROID_TARGET_GOOGLE
- this._serverManagedPolicyExtended = new ServerManagedPolicyExtended(this, new AESObfuscator(new byte[15]
- {
- 46,
- 65,
- 30,
- 128,
- 103,
- 57,
- 74,
- 64,
- 51,
- 88,
- 95,
- 45,
- 77,
- 117,
- 36
- }, this.PackageName, Settings.Secure.GetString(this.ContentResolver, "android_id")));
- this._licenseChecker = new LicenseChecker(this, this._serverManagedPolicyExtended, "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAry4fecehDpCohQk4XhiIZX9ylIGUThWZxfN9qwvQyTh53hvnpQl/lCrjfflKoPz6gz5jJn6JI1PTnoBy/iXVx1+kbO99qBgJE2V8PS5pq+Usbeqqmqqzx4lEzhiYQ2um92v4qkldNYZFwbTODYPIMbSbaLm7eK9ZyemaRbg9ssAl4QYs0EVxzDK1DjuXilRk28WxiK3lNJTz4cT38bfs4q6Zvuk1vWUvnMqcxiugox6c/9j4zZS5C4+k+WY6mHjUMuwssjCY3G+aImWDSwnU3w9G41q8EoPvJ1049PIi7GJXErusTYZITmqfonyejmSFLPt8LHtux9AmJgFSrC3UhwIDAQAB");
- this._licenseChecker.CheckAccess(this);
-#endif
}
-#if ANDROID_TARGET_GOOGLE
- public new void Allow(PolicyResponse response)
- {
- typeof(MainActivity).GetMethod("CheckToDownloadExpansion", BindingFlags.Instance | BindingFlags.NonPublic)?.Invoke(this, null);
- }
-
- public new void DontAllow(PolicyResponse response)
- {
- switch (response)
- {
- case PolicyResponse.Retry:
- typeof(MainActivity).GetMethod("WaitThenCheckForValidLicence")?.Invoke(this, null);
- break;
- case PolicyResponse.Licensed:
- typeof(MainActivity).GetMethod("CheckToDownloadExpansion", BindingFlags.Instance | BindingFlags.NonPublic)?.Invoke(this, null);
- break;
- }
- }
-#endif
}
}
#endif
diff --git a/src/SMAPI/Utilities/Keybind.cs b/src/SMAPI/Utilities/Keybind.cs
index 3532620d..2622f376 100644
--- a/src/SMAPI/Utilities/Keybind.cs
+++ b/src/SMAPI/Utilities/Keybind.cs
@@ -54,7 +54,11 @@ namespace StardewModdingAPI.Utilities
}
// parse buttons
+#if SMAPI_FOR_MOBILE
+ string[] rawButtons = input.Split('+', StringSplitOptions.RemoveEmptyEntries);
+#else
string[] rawButtons = input.Split('+', StringSplitOptions.TrimEntries);
+#endif
SButton[] buttons = new SButton[rawButtons.Length];
List rawErrors = new List();
for (int i = 0; i < buttons.Length; i++)