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++)