diff --git a/.gitignore b/.gitignore index 50f9ec9..4dbc2d9 100644 --- a/.gitignore +++ b/.gitignore @@ -329,3 +329,4 @@ ASALocalRun/ # MFractors (Xamarin productivity tool) working folder .mfractor/ +/SRMP/_info.txt diff --git a/Libs/Assembly-CSharp_publicized.dll b/Libs/Assembly-CSharp_publicized.dll new file mode 100644 index 0000000..8486c97 Binary files /dev/null and b/Libs/Assembly-CSharp_publicized.dll differ diff --git a/Libs/Newtonsoft.Json.dll b/Libs/Newtonsoft.Json.dll new file mode 100644 index 0000000..4881a56 Binary files /dev/null and b/Libs/Newtonsoft.Json.dll differ diff --git a/Libs/SRML.Editor.dll b/Libs/SRML.Editor.dll new file mode 100644 index 0000000..ceca19f Binary files /dev/null and b/Libs/SRML.Editor.dll differ diff --git a/Libs/SRML.dll b/Libs/SRML.dll new file mode 100644 index 0000000..7efefd3 Binary files /dev/null and b/Libs/SRML.dll differ diff --git a/Libs/SRML.xml b/Libs/SRML.xml new file mode 100644 index 0000000..6382d6c --- /dev/null +++ b/Libs/SRML.xml @@ -0,0 +1,3810 @@ + + + + SRML + + + + + A command to add a user defined button to the command menu + + + + + A command to clear the console + + + + + A command that dumps stuff to dump files + + + + + A command to edit a user defined button + + + + + A command to display all commands + + + + + A command to display all mods + + + + + A command to reload the mods + + + + + A command to remove a user defined button from the command menu + + + + + Controls the in-game console + + + + + The event that triggers when the Reload Command is called + + + + + Initializes the console + + + + + Registers a new command into the console + + Command to register + True if registered succesfully, false otherwise + + + + Registers a new console button + + The id of the button + Button to register + True if registered succesfully, false otherwise + + + + Registers a new dump action for the dump command + + The id to use for the dump command argument + The dump action to run + True if registered succesfully, false otherwise + + + + Registers a command catcher which allows commands to be processed and their execution controlled by outside methods + + The method to catch the commands + + + + Logs a info message + + Message to log + Should log to file? + + + + Logs a success message + + Message to log + Should log to file? + + + + Logs a warning message + + Message to log + Should log to file? + + + + Logs an error message + + Message to log + Should log to file? + + + + Binds user commands to the console command menu + + + + + Reads all bindings + + + + + Registers a new bind + + The id of the button + The text to show on the button + The command to execute + + + + Removes a bind + + The id of the bind to remove + True if the bind got removed, false otherwise + + + + Removes all binds + + + + + Gets all the binds registered + + + + + A button for the console menu + + + + + Text to display on the button + + + + + Command to execute when the button is pressed + + + + + Creates a new console button button + + Text to display on the button + Command to execute when the button is pressed + + + + Base class for all console commands + + + + + The ID of this command (Always lowercase) + + + + + The usage info of this command + + + + + The description of this command + + + + + The extended description of this command, with a description of each argument to + display when you use help command on this command (Multiline is supported) + + + + + Executes the command + + The arguments passed in the console (null if no arguments are provided) + True if it executed, false otherwise + + + + Gets the auto complete list (word filter is done by the system) + + The index of the argument in the command string + The text of the argument + The list of auto complete options + + + + Gets the auto complete list (word filter is done by the system) + + The index of the argument in the command string + A list of inputted arguments + The list of auto complete options + + + + The arguments are out of bounds (either too many or too little) + + Amount of arguments + Minimun amount + Maximun amount + True if arguments are out of bounds, false otherwise + + + + Draws the window for the in-game console + + + + + Attachs the window to a scene + + + + + The logger for the log file + + + + + Initializes the file logger (run this before Console.Init) + + + + + Logs a info message + + Message to log + + + + Logs a warning message + + Message to log + + + + Logs an error message + + Message to log + + + + Allows adding values to any Enum + + + + + Add a new enum value to the given with the first free value + + Type of enum to add the value to + Name of the new enum value + The new enum value + + + + Add a new enum value to the given with the first free value + + Type of enum to add the value to + Name of the new enum value + The new enum value + + + + Add a new value to the given + + Enum to add the new value to + Value to add to the enum + The name of the new value + + + + Add a new value to the given + + Enum to add the new value to + Value to add to the enum + The name of the new value + + + + Get first undefined value in an enum + + + The first undefined enum value + + + + Get first undefined value in an enum + + + The first undefined enum value + + + + Serializable table that maps enum values from placeholder numerical values to their string counterparts + Used to assure that enum values map properly between game loads, even if registration order changes + Mapped values are always negative + + + + + Get the next free value for the given enumType + + The enum type + The next free value + + + + Generate a translation table for a list of enumValues + + List of enum values to translate + + + + Replace missing enum values with default values, or remove them all together + + + + + Translate an enum value + + Original enum value + Translated integer + + + + Register an EnumFixer that allows for objects of type to have their enum values processed by an enumtranslator + + + + + + + Fix enum values in an object using the registered EnumFixer + + the to use for translating + Whether to translate TO or FROM the translated form + Object to fix + + + + Class used to generate an error message + + + + + Checks if a path exists and creates it if it doesn't + + Path to be checked + returns the original path argument + + + + When called from a mod, gets the base path of that mod + + The base path of the current executing mod + + + + Gets a mods config path + + The mod whose config path is needed + The config path + + + + Gets the current mods config path + + The config path + + + + Utility class to help manage the main SRML harmony instance + + + + + Utilities for communication between mods + + + + + Called before GameContext.Awake() + + + + + Called before GameContext.Start() + + + + + Called after Load + + + + + Called before
+ Used to register things such as enum values, and to do Harmony patching +
+
+ + + Called before
+ Used to register things that require a loaded GameContext +
+
+ + + Called after every mod's Load has finished (not a registry step)
+ Used for editing existing assets in the game +
+
+ + + Register a modded achievement into the registry. + + The id of the achievement to register. + The tracker to track achievement progress. + The tier the achievement goes into. + + + + Register an achievement tier into the registry. + + The id of the tier. + The icon to be displayed in the achievement UI. + + + + Check if an achievement is modded. + + The id of the achievement to check. + True if achievement id belongs to a modded achievement, otherwise false. + + + + Tiers for an achievement to be put into. + + + + + Register an ammo prefab to allow it to be put in a player's ammos (use ) + + to register the prefab to + + + + + Allow an to be put into a players inventory + + Which inventory to allow the into + The to allow + + + + Allow an Identifiable.Id to be put into a inventory + + + + + + + Allow an Identifiable to be put into the Refinery + + + + + + Creates a and registers it into the enum + + + + + + + + + Creates a and registers it into the enum + + + + + + + + + Registers a + + + + + + See if a is modded + + + True if given is from a mod + + + + See if a is modded + + + True if given is from a mod + + + + Registers an offset for a fashion. + + The of the fashion to offset. + How far the fashion gets offset. + The condition that the fashion gets offset in. + + + + Registers a slot for a fashion to be placed in. + + The that belongs to the slot. + The hierarchal path to the bone. + The that the slot attaches to. + + + + Adds an to a . + + The to add to. + The to be added. + + + + Registers a range of s into a . + + The to add to. + The s to be added. + + + + Registers a range of s into a . + + The to add to. + The s to be added. + + + + Registers a range of s into a . + + The s to be added. + + + + Registers a range of s into a . + + The s to be added. + + + + Removes an from a . + + The to be removed from. + The to be removed. + + + + Removes an from a . + + The to be removed. + The to be removed from. + + + + Adds an to a . + + The to be added. + The to add to. + + + + Automatically adds an to a . + + The to be added. + + + + Registers a rule for what to register a into. + + The condition that the is registered into the + The to register an into. + + + + Adds a rank into the 7Zee Rewards catalogue. If the rank already exists, then combine with the pre-existing one. + + The level of the rank. + How much it costs to purchase the rank. + The rewards for the rank. + The banner to show behind the rank name. If null, then it will set to the highest rank's banner. + + + + Adds a reward to a rank. + + The rank to add a reward to. + The to add. + + + + A special way to register rewards with a unique translation key. + + + + + Registers a region into the . + + The of the region. + The bounds and values of the region. + + + + Adds a zone into a region. + + The to be added. + The of the region to add to. + + + + Class for handling string ID's for the save system + + + + + Class allowing for the addition of arbitrary data to Actors, similar to Minecraft's NBT system + + + + + Instantiate an an Actor with the given data + + + + + + + + + + + A participant of the data system + + + + + A participant of the data system. When on a slime, if the slime transforms, it will copy to the resulting object. + + + + + Register a serializable + + The actor model to register + The mod specific integer ID that the save system will use to refer to this + + + + Register a serializable + + Gadget model to register + The mod specific integer ID that the save system will use to refer to this + + + + Register a serializable + + LandPlot model to register + The mod specific integer ID that the save system will use to refer to this + + + + Register a that will take part in the extended data system + + Type of the participant to register + + + + Allows an to go onto a gordo snare. + + The to register. + + + if secret styles is installed, otherwise . + + + + Register a secret style in a + + Slime definition to register the secret style for + Secret style to register + + + + Registers a targeter. + + The condition in which the targeter is used. + A function getting the name of the targeted object, with the first bundle being the UI bundle, and the second being the pedia bundle. + A function getting the description of the targeted object, with the first bundle being the UI bundle, and the second being the pedia bundle. + + + + Combines two keys' resulting translations. + + The bundle containing the keys. + The key to be added to. + The key to be added. + The composed description. + + + + Composes a type description translation. + + The bundle containing the type key. + The key belonging to the type's translation. + + + + + Composes a diet description translation. + + The bundle containing the diet key. + The key belonging to the diet's translation. + + + + Create a new instance of an IdHandler + + + + + + + + Register an as a drone target. + + + + + + Registers a rancher. + + + + + + Registers a rancher's id + + + + + + Registers an offer id + + + + + + Registers a category for exchange requests/rewards + + The category to register + The ids in the category + + + + Registers an item to be unlocked in a category + + The to be unlocked. + The progress required to unlock it + The value used in the offer generator for count + + + + Registers an item that's automatically unlocked in a category + + The to be unlocked. + The value used in the offer generator for count + + + + Checks if a rancher or offer ID is modded. + + The ID to check. + True if the ID belongs to a mod, otherwise false. + + + + Checks if a rancher is modded. + + The rancher to check. + True if the rancher belongs to a mod, otherwise false. + + + + Checks if a category is modded. + + The category to check. + True if the category belongs to a mod, otherwise false. + + + + Creates a . + + What value is assigned to the . + The name of the . + The created . + Throws if ran outside of PreLoad + + + + Check if a belongs to a modded gadget. + + The to check. + True if belongs to a modded gadget, otherwise false. + + + + Associates an with a + + The to associate. + The to associate + + + + Registers a locker for a blueprint. + + The of the blueprint. + The locker for the blueprint. + + + + Register a blueprint. + + The of the blueprint. + + + + Register a blueprint that's automatically available. + + The of the blueprint. + + + + Manually set the of the + + + + + + + Remove all instances of an from every class in + + + + + + Puts a into one of the vanilla categories based on its name prefix (see )
+ WARNING: Will not categorize decorations properly! +
+ +
+ + + Put an into one of the vanilla categories + + + + + + + Creates an . + + What value is assigned to the . + The name of the . + The created . + Throws if ran outside of PreLoad + + + + Creates an . + + What value is assigned to the . + The name of the . + If the should automatically be categorized into 's classes. + The created . + Throws if ran outside of PreLoad + + + + Manually set the of the + + + + + + + Remove all instances of an from every class in + + + + + + + Check if an was registered by a mod + + + True if the was registered by a mod, otherwise false. + + + + Gets every registered by a mod. + + The ID of the mod to check. + All s reigstered by a mod. + + + + Registers a rule for an id prefix to link to + + The prefix for the id to check for. + The rule that the specified prefix links to. + + + + Registers a rule for an id suffix to link to + + The suffix for the id to check for. + The rule that the specified prefix links to. + + + + Puts an into one of the vanilla categories based on its name (see ) + + + + + + Put an into one of the vanilla categories + + + + + + + Register a keybind into the options UI. + + The action associated with the keybind. + + + + Creates and registers a . + + The name of the action. + The created action + + + + Creates and registers a , then registers it into the options UI. + + The name of the action. + The created action + + + + Creates and registers a , adds it into the options UI, and adds a translation. + + The name of the action. + The translated name of the action. + The created action + + + + Check if an action is modded. + + The action to check. + True if action belongs to a mod, otherwise false. + + + + Register all 's in a Type + + Type holding the 's + + + + Creates a . + + What value is assigned to the . + The name of the . + The created . + Throws if ran outside of PreLoad + + + + Check if an was registered by a mod + + + True if the was registered by a mod, otherwise false. + + + + Registers a land plot. + + The land plot to register. + + + + Creates a . + + What value is assigned to the . + The name of the . + The created . + Throws if ran outside of PreLoad + + + + Registers an land plot upgrade. + + The type of land plot to register it to. + The upgrade to register. + + + + Registers a to a land plot. + + The to register. + The to register the to + Throws if the is already registered. + + + + Sets the callback of the . + + The callback + + + + + Sets the from translation. + + The translated text. + + + + + Sets the body translation. + + The translated text. + + + + Sets the subject translation. + + The translated text. + + + + Registers a . + + The to register. + The registered + + + + Registers a . + + The key of the to register. + The registered + + + + Gets the default renderer for a Slimepedia entry. + + The setting to get the renderer from. + The default renderer for the specified setting. + + + + Creates a . + + What value is assigned to the . + The name of the . + The created . + Throws if ran outside of PreLoad + + + + Registers a tab for the Slimepedia. + + The tab to register + + + + Registers a into the Slimepedia. + + The to register. + + + + Creates and registers a . + + The belonging to the entry. + The icon belonging to the entry. + + + + Registers an entry renderer for the Slimepedia. + + The assigned to the entry. + The renderer the Slimepedia entry should use. + + + + Registers an entry to already be unlocked in a new game + + The that belongs to the entry. + + + + Creates a link between an and a . + + The entry mapping both values. + + + + Creates a link between an and a . + + The to link. + The to link. + + + + Sorts a Slimepedia category based on a rule. + + The Slimepedia category to sort. + The rules to sort it. + + + + Assigns a to a Slimepedia category. + + The to assign. + The Slimepedia category to assign the to. + + + + Registers an event to be run when a awakes. + + The event to be ran. + + + + Registers a link between a plant plot and an . + + The entry of the link. + + + + Registers a link between a plant plot and an , which only is used if a condition is met. + + The condition that the link is established. + The entry of the link. + + + + Predicate for choosing purchasable ui's + + The type of the Purchasable UI + The UI instance + + + + + Creates purchasables on demand + + The that the will be added to + + + + + Creates a purchasable on demand + + + The UI that the will be added to + + + + + Delegate for arbitarily manipulating a list of purchasables + + + + + + + + Delegate for arbitarily manipulating a list of purchasables + + + + + Register a to all UI's pointed to by the + + The prediate for filtering the Purchasable UI + The creator of the new purchasable + + + + Register a compararer to sort a list of purchasables + + Filter for PurchasableUI's + Comparer to use when sorting + + + + Register a compararer to sort a list of purchasables + + The type of the UI + Comparer used for sorting + + + + Registers a plort entry into the Plort Market. + + The plort's market entry. + + + + Creates and registers a plort entry into the Plort Market. + + The belonging to the plort. + The progress required to show the plort as unlocked. + + + + Creates and registers a plort entry into the Plort Market that is automatically unlocked. + + The belonging to the plort. + + + + Registers an economy entry into the Plort Market. + + The entry to register. + + + + Creates and registers an economy entry into the Plort Market. + + The belonging to the plort. + The base value of the plort. + How many plorts needed to saturate the market (cut the price in half). + + + + Creates and registers an economy entry into the Plort Market. + + The belonging to the plort. + The base value of the plort. + How many plorts needed to saturate the market (cut the price in half). + Throws if ran in PreLoad. + + + + Creates and registers a plort entry, as well as an economy entry into the Plort Market. + + The belonging to the plort. + The base value of the plort. + How many plorts needed to saturate the market (cut the price in half). + + + + Register an Identifiable Prefab into the + + The prefab to register. + + + + Register an Identifiable Prefab into the + + The belonging to the prefab to register. + + + + Register into the + + + + + + Register a landplot prefab into the + + The prefab to register + + + + Register a gadget entry to the + + + + + + Register a vacuumable item into the + + Id of the vacuumable item + Color of the background of the inventory slot + Icon that will be used for the item in inventory + + + + Register into the + + Upgrade Entry to register + + + + Create and register an upgrade entry + + Upgrade ID + Icon that will show up in the upgrade shop + The cost of the upgrade + + + + Register a into the + + + + + + Register a gordo prefab into the + + + + + + Register into the + + Liquid to register + + + + Register into the + + Entry to register + + + + Register a toy (note: does not register the identifiable itself, only the toy, do that separately) + + of the toy + Icon for the toy in the toy store + How much the toy costs in the toy store + + + + + Register a slime definition in the database + + Slime definition to register + + + + Register a slime definition in the database + + Slime definition to register + Whether or not to refresh the EatMaps of the slime and its bases. + + + + Registers a . + + The that the is assigned to. + The to be registered. + + + + Combines two s into a largo . + + The base . + The addon . + The to register the into. + The properties controlling the way the s are combined. + The stripe shader to be used, if any. + The created . + + + + Creates a largo from two base s. + + The belonging to the resulting largo. + The belonging to the base slime. + The belonging to the addon slime. + The properties controlling the way the s are combined. + The created . + + + + Combines the s of the bases of a into one . + + The largo's . + The created . + + + + Combines two slimes into a largo. + + The belonging to the resulting largo. + The belonging to the base slime. + The belonging to the addon slime. + The properties controlling the way the slimes are combined. + The properties controlling the base Secret Style and the addon normal s are combined. + The properties controlling the base normal and the addon Secret Style s are combined. + The properties controlling the base Secret Style and the addon Secret Style s are combined. + + + + Combines two slimes into a largo. + + The belonging to the resulting largo. + The belonging to the base slime. + The belonging to the addon slime. + The properties controlling the way the slimes are combined. + The properties controlling the base Secret Style and the addon normal s are combined. + The properties controlling the base normal and the addon Secret Style s are combined. + The properties controlling the base Secret Style and the addon Secret Style s are combined. + The of the created largo. + The of the created largo. + The of the created largo. + + + + Takes an and formats it into a largo name. + + The belonging to the largo. + The resulting name. + + + + Creates a . + + What value is assigned to the . + The name of the . + The created . + Throws if ran outside of PreLoad + + + + Represents a template game object, used to contain templates to turn into + Runtime Prefabs + + + + + A template to create new animals + + + + + Template to create new animals + + The name of the object (prefixes are recommended, but not needed) + The Identifiable ID for this animal + The model's mesh for this animal + The materials that compose this animal's model + The animator used by the animal + Is this animal a child? + + + + Sets the reproduction objects (not needed for childs or males) + + The male mate of this female + The resulting child + + + + Sets the elder version of this (not needed for childs) + + The elder version + + + + Sets the movement component to a new one (Default is the Chicken Movement) + + New component to use + + + + Sets the vacuumable size + + The vac size to set + + + + Sets the reproduction infos (not needed for childs or males) + + Min. Reproduction hours + Max. Reproduction hours + + + + Sets the bones and skinned mesh of this animal (default are the ones from the Chicken/Hen) + The skinned mesh would be an object like mesh_body1 of the Hen's Prefab + The bones would be an object like root of the Hen's Prefab + + The new skinned mesh to use for the animal + The new bones to use for the animal + + + + Sets the child info (only needed for childs) + + The number of hours before becoming an adult + The number of hours before hatching the egg + The egg object + + + + Sets the translation for this animal's name + + The translated name + + + + Creates the object of the template (To get the prefab version use .ToPrefab() after calling this) + + + + + A template to create new Craft Resources + + + + + Template to create new Craft Resources + + The name of the object (prefixes are recommend, but not needed) + The Identifiable ID for this resource + The pedia ID for this resource + The model's mesh for this resource + The materials that compose this resource's model + + + + Sets the vacuumable size + + The vac size to set + + + + Sets the transform values for the model + + New values to set + + + + Sets the collider radius for this craft resource (Use this to ajust the collider to the model) + + The radius of the collider + + + + Sets the scale for the Delaunch Trigger (do not change if you don't know what you are doing) + + The new scale to set + + + + Sets the translation for this resource's name + + The translated name + + + + Creates the object of the template (To get the prefab version use .ToPrefab() after calling this) + + + + + A template to create new crates + + + + + Template to create new crates + + The name of the object (prefixes are recommended, but not needed) + The Identifiable ID for this crate + The materials that compose this crate's model + + + + Sets the vacuumable size + + The vac size to set + + + + Sets the spawn options for the crate + + List of options + + + + Sets the info for spawning items + + The min amount of things to spawn + The max amount of things to spawn + + + + Creates the object of the template (To get the prefab version use .ToPrefab() after calling this) + + + + + A template to create new fashion attachments (the part that gets attached to the object) + + + + + Template to create new fashion attachments + + The name of the object (prefixes are recommend, but not needed) + The Identifiable ID for this fashion attachment + The model's mesh for this fashion attachment + The materials that compose this fashion attachment's model + + + + Sets the transform values for the model + + New values to set + + + + Adds a new layer + + The mesh to add to the layer + The materials to add to the layer + + + + Creates the object of the template (To get the prefab version use .ToPrefab() after calling this) + + + + + A template to create new fashions (the actual fashion not the pod) + + + + + Template to create new fashions + + The name of the object (prefixes are recommended, but not needed) + The Identifiable ID for this fashion + The prefab to attach to the target + The icon for this fashion + The slot it occupied when attached + + + + Sets the vacuumable size + + The vac size to set + + + + Sets the translation for this fashion's name + + The translated name + + + + Creates the object of the template (To get the prefab version use .ToPrefab() after calling this) + + + + + A template to create floating decorations like ornaments or echos + + + + + Template to create floating decorations + + The name of the object (prefixes are recommended, but not needed) + The Identifiable ID for this decoration + The type of decoration + The model's mesh for this decoration + The materials that compose this decoration's model + + + + Sets the vacuumable size + + The vac size to set + + + + Sets the clip (For the type ECHO_NOTE) + + The number of clip to set + + + + Sets the transform values + + New values to set + + + + Sets the color for the material (For the type ECHO or ECHO_NOTE) (only if you want to use the default material for echos and change the color) + + New color to set + + + + Sets the translation for this deco's name + + The translated name + + + + Creates the object of the template (To get the prefab version use .ToPrefab() after calling this) + + + + + A template to create new foods + + + + + Template to create new foods + + The name of the object (prefixes are recommended, but not needed) + The Identifiable ID for this food + The pedia ID for this resource + The type of food + The model's mesh for this food + The materials that compose this food's model + + + + Sets the vacuumable size + + The vac size to set + + + + Sets the info of the resource cycle + + The number of game hours before the food is ready to collect + The number of game hours the food stays in place to be riped + The number of game hours the food can be eaten + The number of game hours the food takes to rot + + + + Sets the rotten material + + The rotten material + + + + Sets the Audio Cues for the food (Only needed for type CUSTOM) + + The cue triggered when the food is released from a farmable zone + The cue triggered when the food hits something + + + + Sets the scale for the Delaunch Trigger (do not change if you don't know what you are doing) + + The new scale to set + + + + Sets the scale for the model, only needed if the default doesn't work + + The new scale to set + + + + Sets the option to eject the food when mature (only needed if the food is farmable) + + The new state to set + + + + Sets the translation for this slime's name + + The translated name + + + + Creates the object of the template (To get the prefab version use .ToPrefab() after calling this) + + + + + A template to create new gordos + + + + + Template to create new gordos + + The name of the object (prefixes are recommend, but not needed) + The identifiable ID for this gordo + The definition of the slime this gordo is based on + The materials to use on the model of this gordo + + + + Adds a new behaviour to the slime + + The component containing the new behaviour + + + + Adds a new behaviour to the slime + + The component containing the new behaviour + A list of components containing the new behaviour + + + + Sets a new bone structure for the slime (Starting at the Vibrating part) + + The new bone structure as a game object (to add to the prefab) + + + + Sets the translation for this gordo's name + + The translated name + + + + Creates the object of the template (To get the prefab version use .ToPrefab() after calling this) + + + + + A template to create new liquids + + + + + Template to create new liquids + + The name of the object (prefixes are recommended, but not needed) + The Identifiable ID for this liquid + The materials that compose this liquid's model + + + + Sets the vacuumable size + + The vac size to set + + + + Sets the color for the material (only if you want to use the default material for water and change the color) + DO NOT USE THIS IF YOU SET A CUSTOM MATERIAL, THIS WILL OVERRIDE THAT MATERIAL + + New color to set + + + + Sets the translation for this slime's name + + The translated name + + + + Creates the object of the template (To get the prefab version use .ToPrefab() after calling this) + + + + + A template to create new plorts + + + + + Template to create new plorts + + The name of the object (prefixes are recommended, but not needed) + The Identifiable ID for this plort + The materials that compose this plort's model + + + + Sets the vacuumable size + + The vac size to set + + + + Sets the translation for this plort's name + + The translated name + + + + Sets the scale for the plort + + The scale to set + + + + Creates the object of the template (To get the prefab version use .ToPrefab() after calling this) + + + + + A template to create new slimes + + + + + Template to create new slimes + + The name of the object (prefixes are recommend, but not needed) + The definition for this slime + + + + Sets the vacuumable size + + The vac size to set + + + + Sets the eat info + + The min. drive required for the slime to eat + How much the drive is reduced once fed + How much the agitation is reduced once fed + How much the agitation is reduced once fed it's favorite + + + + Sets the max. health of this slime + + The max. health to set + + + + Sets the possibility of having a feral state + + Can the slime be afected by a feral state + + + + Sets the possibility of turning into a glitch if spawned in the Slimeulation + + Can the slime be turned into a glitch inside the Slimeulation + + + + Sets the fear profile + + The fear profile to set + + + + Sets the starting emotions of this slime + + The initial state for Hunger + The initial state for Agitation + The initial state for Fear + + + + Sets the scale for the Delaunch Trigger (do not change if you don't know what you are doing) + + The new scale to set + + + + Adds a new behaviour to the slime + + The component containing the new behaviour + + + + Adds a new behaviour to the slime + + The component containing the new behaviour + A list of components containing the new behaviour + + + + Sets a new bone structure for the slime (Starting at the Appearance part) + + The new bone structure as a game object (to add to the prefab) + + + + Sets the translation for this slime's name + + The translated name + + + + Creates the object of the template (To get the prefab version use .ToPrefab() after calling this) + + + + + Generates the largos for this slime (use this if you want the slime to be largoable) + + Can the largos from the slime become tarr? + Use this to add extra behaviours to the largos + A list of all IDs made for the largos created + + + + Generates a roaming Gordo Slime for this slime (use this if you want the slime to have a Gordo counter part) + Roaming gordos are normal slimes scaled as a gordo and contains almost no behaviours, also it doesnt eat. Use PrefabFunctions to give it + behaviours + + The ID for the gordo + The slime template for the Roaming Gordo (YOU NEED TO CLASS .Create TO FINISH THE PROCESS) + + + + Generates a Gordo Slime for this slime (use this if you want the slime to have a Gordo counter part) + + The ID for the gordo + The gordo template for the static gordo (YOU NEED TO CLASS .Create TO FINISH THE PROCESS) + + + + Builds the module for this slime + + + + + Builds the definition for this slime + + + + + A template to create new toys + + + + + Template to create new toys + + The name of the object (prefixes are recommended, but not needed) + The Identifiable ID for this toy + The model's mesh for this toy + The materials that compose this toy's model + The audio cue when this toy hits something + + + + Sets the vacuumable size + + The vac size to set + + + + Sets what fashion is required to react with this toy + + The ID of said fashion (NONE to remove the required fashion) + + + + Sets the translation for this toy's name + + The translated name + + + + Creates the object of the template (To get the prefab version use .ToPrefab() after calling this) + + + + + A template ti create new Tech Activators + + + + + Template to create new Tech Activators + + The name of the object (prefixes are recommended, but not needed) + The prefab UI to display + + + + Creates the object of the template (To get the prefab version use .ToPrefab() after calling this) + + + + + Interface used to make lists of Mod Prefabs (as lists can't have different generic constructs) + + + + + Simple prefab like class, used to make the structure for templates + + + + + Creates the object of the template (To get the prefab version use .ToPrefab() after calling this) + + + + + Adds a new start action to the pile + + ID of the action (as registered in TemplateActions) + + + + Adds a new awake action to the pile + + ID of the action (as registered in TemplateActions) + + + + Adds a prefab function (they are executed when ToPrefab is called) + + Action to add to the pile + + + + Adds a prefab function (they are executed when ToPrefab is called) + + Actions to add to the pile + + + + Sets the translation for the prefab, not all templates implement this, so it might do nothing. + + The translated name + + + + Turns this ModPrefab/Template into a runtime prefab + + + + + Returns this prefab as a template + + + + + Returns this prefab as a clone of the template + + + + + A template to create new bush plantables + + + + + Template to create new veggie plantables + + The name of the object (prefixes are recommended, but not needed) + Is this plantable for the deluxe version of the garden? + The ID of the identifiable spawned by this plantable + The spawn resource id for this plantable + The list of things to spawn (null to get it from the ID provided) + + + + Sets the bonus info + + The min. amount selected from the bonus list + The change to select extras + + + + Sets the list of bonus spawns + + The list to set + + + + Adds a new bonus spawn to the list + + The ID for the spawnable + + + + Adds a new bonus spawwn to the list + + The game object of the identifiable to spawn + + + + Sets the list of spawns + + The list to set + + + + Adds a spawn to the list + + The ID for the spawnable + + + + Adds a spawn to the list + + The game object of the identifiable to spawn + + + + Sets the tree to be used + + The tree's mesh + The materials for that tree + The tree's mesh for the collider + + + + Sets the tree to be used based on the SpawnResource ID (only works for those already in the game) + + The ID to get the tree from + + + + Sets the leaves to be used + + The leaves's mesh + The materials for that leaves + The leaves's mesh for the collider + + + + Sets the leaves to be used based on the SpawnResource ID (only works for those already in the game) + + The ID to get the leaves from + + + + Sets the position for the leaves (uses the same for normal and deluxe) + + The new position to set + + + + Sets the position for the leaves (uses different ones for normal and deluxe versions) + + The new position to set for normal + The new position to set for deluxe + + + + Sets the scale for the leaves (uses the same for normal and deluxe) + + The new scale to set + + + + Sets the scale for the leaves (uses different ones for normal and deluxe versions) + + The new scale to set for normal + The new scale to set for deluxe + + + + Sets the scale for the tree (uses the same for normal and deluxe) + + The new scale to set + + + + Sets the scale for the tree (uses different ones for normal and deluxe versions) + + The new scale to set for normal + The new scale to set for deluxe + + + + Sets the spawn info + + Min. number of items to spawn + Max. number of items to spawn + Min. hours to be ready to spawn + Max. hours to be ready to spawn + Min. value of nutrients, related to growth rate + The number of hours the water lasts in the soil + + + + Sets the model of the spawn points (used to display the growth of the items) + + The mesh for the model + The materials for the model + + + + Sets the spawn joints (the list needs to have 20 for non-deluxe and 34 for deluxe) + + New spawn joints to set + + + + Creates the object of the template (To get the prefab version use .ToPrefab() after calling this) + + + + + A template to create new fruit plantables + + + + + Template to create new veggie plantables + + The name of the object (prefixes are recommended, but not needed) + Is this plantable for the deluxe version of the garden? + The ID of the identifiable spawned by this plantable + The spawn resource id for this plantable + The list of things to spawn (null to get it from the ID provided) + + + + Sets the bonus info + + The min. amount selected from the bonus list + The change to select extras + + + + Sets the list of bonus spawns + + The list to set + + + + Adds a new bonus spawn to the list + + The ID for the spawnable + + + + Adds a new bonus spawwn to the list + + The game object of the identifiable to spawn + + + + Sets the list of spawns + + The list to set + + + + Adds a spawn to the list + + The ID for the spawnable + + + + Adds a spawn to the list + + The game object of the identifiable to spawn + + + + Sets the tree to be used + + The tree's mesh + The materials for that tree + The tree's mesh for the collider + + + + Sets the tree to be used based on the SpawnResource ID (only works for those already in the game) + + The ID to get the tree from + + + + Sets the leaves to be used + + The leaves's mesh + The materials for that leaves + The leaves's mesh for the collider + + + + Sets the leaves to be used based on the SpawnResource ID (only works for those already in the game) + + The ID to get the leaves from + + + + Sets the position for the leaves (uses the same for normal and deluxe) + + The new position to set + + + + Sets the position for the leaves (uses different ones for normal and deluxe versions) + + The new position to set for normal + The new position to set for deluxe + + + + Sets the scale for the leaves (uses the same for normal and deluxe) + + The new scale to set + + + + Sets the scale for the leaves (uses different ones for normal and deluxe versions) + + The new scale to set for normal + The new scale to set for deluxe + + + + Sets the scale for the tree (uses the same for normal and deluxe) + + The new scale to set + + + + Sets the scale for the tree (uses different ones for normal and deluxe versions) + + The new scale to set for normal + The new scale to set for deluxe + + + + Sets the spawn info + + Min. number of items to spawn + Max. number of items to spawn + Min. hours to be ready to spawn + Max. hours to be ready to spawn + Min. value of nutrients, related to growth rate + The number of hours the water lasts in the soil + + + + Sets the model of the spawn points (used to display the growth of the items) + + The mesh for the model + The materials for the model + + + + Sets the spawn joints (the list needs to have 20 for non-deluxe and 34 for deluxe) + + New spawn joints to set + + + + Creates the object of the template (To get the prefab version use .ToPrefab() after calling this) + + + + + A template to create new veggie plantables + + + + + Template to create new veggie plantables + + The name of the object (prefixes are recommended, but not needed) + Is this plantable for the deluxe version of the garden? + The ID of the identifiable spawned by this plantable + The spawn resource id for this plantable + The list of things to spawn (null to get it from the ID provided) + + + + Sets the bonus info + + The min. amount selected from the bonus list + The change to select extras + + + + Sets the list of bonus spawns + + The list to set + + + + Adds a new bonus spawn to the list + + The ID for the spawnable + + + + Adds a new bonus spawwn to the list + + The game object of the identifiable to spawn + + + + Sets the list of spawns + + The list to set + + + + Adds a spawn to the list + + The ID for the spawnable + + + + Adds a spawn to the list + + The game object of the identifiable to spawn + + + + Sets the sprout to be used (null can also be provided to use the default one) + + The sprout's mesh + The material for that sprout + + + + Sets the sprout to be used based on the SpawnResource ID (only works for those already in the game) + + The ID to get the sprout from + + + + Sets the spawn info + + Min. number of items to spawn + Max. number of items to spawn + Min. hours to be ready to spawn + Max. hours to be ready to spawn + Min. value of nutrients, related to growth rate + The number of hours the water lasts in the soil + + + + Sets the model of the spawn points (used to display the growth of the items) + + The mesh for the model + The materials for the model + + + + Sets the spawn joints (the list needs to have 20 for non-deluxe and 34 for deluxe) + + New spawn joints to set + + + + Creates the object of the template (To get the prefab version use .ToPrefab() after calling this) + + + + + A template to create new plots + + + + + Template to create new plots + + The name of the object (prefixes are recommended, but not needed) + The Plot ID for this plot + + + + Sets the Activator Transform values + + The position to set + The rotation to set + The scale to set + + + + Sets the Activator Transform values + + The values to set + + + + Sets the game object for the UI of this plot + + The game object to set + + + + Creates the object of the template (To get the prefab version use .ToPrefab() after calling this) + + + + + A template to create a plot frame (use this if you want to create a custom frame by adding prefab functions to it) + + + + + Template to create a plot frame + + The name of the object + + + + Creates the object of the template (To get the prefab version use .ToPrefab() after calling this) + + + + + Interface used to make lists of PlotUpgradeTemplate (as lists can't have different generic constructs) + + + + + A template to create a plot upgrade + This template is a bit more complex than the others, it's structure is entirely built by you. It only exists for covinience when adding to custom plots. + + + + + Template to create a plot upgrade + + The name of the object + The upgrade for this land plot + The upgrader component to add to the main object + The action to setup the component after creation + + + + Creates the object of the template (To get the prefab version use .ToPrefab() after calling this) + + + + + Creates the object of the template (To get the prefab version use .ToPrefab() after calling this) + + The action to construct the template + + + + A template to create new activator UIs + + + + + Template to create new activator UIs + + The name of the object (prefixes are recommended, but not needed) + The UI component to add + + + + Creates the object of the template (To get the prefab version use .ToPrefab() after calling this) + + + + + Registers a toy into the first group of toys. + + The belonging to the toy. + + + + Registers a toy into the second group of toys. + + The belonging to the toy. + + + + Localization + + + + + Add a plaintext translation for a localization key + + Key bundle the localization key is located in + The localization key + The plain text translation + + + + Add a plaintext translation for a localization key in the 'pedia' bundle + + The localization key + The plain text translation + + + + Add a plaintext translation for a localization key in the 'actor' bundle + + The localization key + The plain text translation + + + + Add a plaintext translation for a localization key in the 'ui' bundle + + The localization key + The plain text translation + + + + Add a plaintext translation for a localization key in the 'achieve' bundle + + The localization key + The plain text translation + + + + Add a plaintext translation for a localization key in the 'exchange' bundle + + The localization key + The plain text translation + + + + Add a plaintext translation for a localization key in the 'global' bundle + + The localization key + The plain text translation + + + + Add a plaintext translation for a localization key in the 'mail' bundle + + The localization key + The plain text translation + + + + Add a plaintext translation for a localization key in the 'tutorial' bundle + + The localization key + The plain text translation + + + + Add a plaintext translation for localization for SRML error messages + + The language to be translated to + The plain text translation for the text saying it's an error + The plain text translation for the text saying mod-loading is aborting + + + + Creates a . + + What value is assigned to the . + The name of the . + The created . + Throws if ran outside of PreLoad + + + + Check if a belongs to a modded upgrade. + + The to check. + True if belongs to a modded upgrade, otherwise false. + + + + Registers a callback to be called when an upgrade is bought. + + The that calls the callback. + The callback to be called. + + + + Registers an upgrade locker. + + The to be locked. + The locker locking the . + + + + Registers an upgrade that's automatically unlocked. + + The to be unlocked. + + + + An utility class to help with Enums + + + + + Parses an enum in a easier way + + Type of the enum + Value to parse + The parsed enum on success, null on failure. + + + + Parses an enum in a easier way + + Type of the enum + Value to parse + true to ignore case; false to regard case. + The parsed enum on success, null on failure. + + + + Converts int to enum + + Type of the enum + Int to convert to enum + The enum equal to the int + + + + Gets all names in an enum + + Type of the enum + The list of names in the enum + + + + Gets all enum values in an enum + + Type of the enum + The list of all values in the enum + + + + Checks if an enum is defined. + + Type of the enum + Value to check + true if defined, false if not. + + + + Checks all names in an enum to see if what you need exists. + + Type of the enum + Value to find + true if found, false if not. + + + + Parses an enum in a easier way + + Type of the enum + Value to parse + What to return if the parse fails. + The parsed enum on success, on failure. + + + + Parses an enum in a easier way + + Type of the enum + Value to parse + true to ignore case; false to regard case. + What to return if the parse fails. + The parsed enum on success, on failure. + + + + Converts int to enum + + Type of the enum + Int to convert to enum + The enum equal to the int + + + + Gets all names in an enum + + Type of the enum + The list of names in the enum + + + + Gets all enum values in an enum + + Type of the enum + What to return if the parse fails. + The list of all values in the enum + + + + Checks if an enum is defined. + + Type of the enum + Value to check + true if defined, false if not. + + + + Checks all names in an enum to see if what you need exists. + + Type of the enum + Value to find + true if found, false if not. + + + + A basic mod data class that is safe to share between mods (no logic in it) + + + + + Data structure to simplify versioning and the comparing of versions + + + + + Actual internal implementation of a mod + + + + + Mods associated SRModInfo object + + + + + Path of the mod (usually the directory where the core modinfo.json is located) + + + + + Gets the current executing mod as an SRMod instance + + The current executing mod + + + + Forces a certain mod to be returned from + + The mod to be forced + + + + Clears the current mod context + + + + + Searches for valid mods and their assemblies, and decides the load order based on their settings + + + + + Check if corresponds with a valid mod + + Mod ID to check + Whether or not the mod exists + + + + Gets the associated for the associated + + Relevant Mod ID + The associated ModInfo + + + + Get an instance from a Mod ID + + The ModID + The corresponding instance, or null + + + + Utility class to help with the discovery and loading of mod assemblies + + + + + Class that represents a mod before it has been loaded or fully processed + + + + + Create a protomod from json info + + Path of the json file + The parsed + + + + Try to create a protomod from an embedded modinfo json in a DLL + + Path to the DLL file to process + The parsed , or null + Whether the parsing was successful + + + + Make sure fields are in the correct form and not null + + + + + Turn the protomod into a proper instance + + Converted + + + + Reverses the order of the elements in the entire . + + + + + Reverses a array + + + + + Swap two elements in array + + + + + Creates a from a . + + A that contains elements from the input sequence except + + + + + Attempts to get a value from a collection. + + True if an element in the collection matches the specified condition, otherwise false. + + + + Returns new array without element at index + + + + + Returns new array with inserted empty element at index + + + + + Returns random element from collection + + + + + Returns random element from collection + + + + + Returns random element from collection + + + + + Is array null or empty + + + + + Is collection null or empty + + + + + Is enumerable null or empty. IEnumerable is relatively slow. Use Array or Collection implementation if possible + + + + + Get next index for circular array. i.e. -1 will result with last element index, Length + 1 is 0 + + Example (infinite loop first->last->first): + i = myArray.NextIndex(i++); + var nextItem = myArray[i]; + + + + + Returns -1 if none found + + + + + Is Elements in two collections are the same + + + + + Is Keys in MyDictionary is the same as some collection + + + + + Is Values in MyDictionary is the same as some collection + + + + + Gets the value associated with the specified key if it exists, or + return the default value for the value type if it doesn't. + + + + + Gets the value associated with the specified key if it exists, or + generate a value for the new key if it doesn't. + + + + + Performs an action on each element of a collection. + + + + + Performs a function on each element of a collection. + + + + + Find the element of a collection that has the highest selected value. + + + + + Find the element of a collection that has the lowest selected value. + + + + + Returns new Color with Alpha set to a + + + + + Set Alpha of Renderer.Color + + + + + To string of "#b5ff4f" format + + + + + Returns a color lighter than the given color. + + + + + + + Returns a color darker than the given color. + + + + + + + Brightness offset with 1 is brightest and -1 is darkest + + + + + Converts unix timestamp to with high precision. + + Unix timestamp. + DateTime object that represents the same moment in time as provided Unix time. + + + + Converts to unix timestamp with high precision + + DateTime date representation. + unix timestamp that represents the same moment in time as provided DateTime object. + + + + Stop value from going above max or below min values. + + + + + Stop value from going above max or below min values. + + + + + Stop value from going above max or below min values. + + + + + Swap two reference values + + + + + Snap to grid of "round" size + + + + + Snap to grid of "round" size + + + + + Returns the sign 1/-1 evaluated at the given value. + + + + + Value is in [0, 1) range. + + + + + Value is in [closedLeft, openRight) range. + + + + + Value is in [closedLeft, closedRight] range, max-inclusive. + + + + + Clamp value to less than min or more than max + + + + + Clamp value to less than min or more than max + + + + + Return point A or B, closest to num + + + + + Contains extension methods for + + + + + Performs a TRUE null-check. + + An object to check. + Returns if object is null, otherwise. + + + + Performs a TRUE not-null-check. + + An object to check. + Returns if object is null, otherwise. + + + + Invokes a method + + The object you are invoking the method in + The name of the method + parameters + + + + Invokes a method + + Type of return + The object you are invoking the method in + The name of the method + parameters + + + + Sets the value of a field + + The object to set the field value of + The name of the field + The value to set + + + + Sets the value of a field + + The object to set the field value of + The name of the field + The value to set + Type of value + + + + Gets the value of a field + + The object to get the value from + The name of the field + + + + Gets the value of a field + + The object to get the value from + The name of the field + Type of value + + + + Sets the value of a property + + The object to set the property value of + The name of the property + The value to set + Type of value + + + + Sets the value of a property + + The object to set the property value of + The name of the property + The value to set + Type of value + + + + Gets the value of a property + + The object to get the value from + The name of the property + + + + Gets the value of a property + + The object to get the value from + The name of the property + Type of value + + + + Contains extension methods for + + + + + Clones the Scriptable Object + + + + Indicates whether the specified string is or an empty string (""). + if the parameter is or an empty string (""); otherwise, . + + + Indicates whether a specified string is , empty, or consists only of white-space characters. + if the parameter is or , or if consists exclusively of white-space characters. + + + + Returns a String array containing the substrings in this string that are delimited by elements of a specified + String array. A parameter specifies whether to return empty array elements. + + The @this to act on. + A string that delimit the substrings in this string. + + (Optional) Specify RemoveEmptyEntries to omit empty array elements from the array returned, + or None to include empty array elements in the array returned. + + + An array whose elements contain the substrings in this string that are delimited by the separator. + + + + + Reverses the string + + + + + Convert a string value to an Enum value. + + + + + Number presented in Roman numerals + + + + + Get the "message" string with the "surround" string at the both sides + + + + + Get the "message" string with the "start" at the beginning and "end" at the end of the string + + + + + Surround string with "color" tag + + + + + Surround string with "color" tag + + + + + Surround string with "size" tag + + + + + Surround string with "u" tag + + + + + Surround string with "b" tag + + + + + Surround string with "i" tag + + + + + Removes anything after the parameter + + The string to seek + Whether to remove the + + + + Removes anything after the parameter + + The string to seek + Whether to remove the + + + + Retrieves specified symbols amount from the end of the string. + + Source string. + Amount of symbols + Specified symbols amount from the end of the string. + + + + Removes specified symbols amount from the end of the string. + + Source string. + Amount of symbols + Modified string. + + + + Retrieves specified symbols amount from the beginning of the string. + + Source string. + Amount of symbols + Specified symbols amount from the beginning of the string. + + + + Method will return all the indexes for a matched string. + + Source string. + String Value to look for. + Comparison Type. + Indexes for a matched string. + + + + + Removes all the leading occurrences of specified string from the current string. + + Current string. + A string to remove. + The string that remains after all occurrences of trimString parameter are removed from the start of the current string. + + + + Removes all the trailing occurrences of specified string from the current string. + + Current string + A string to remove. + The string that remains after all occurrences of trimString parameter are removed from the end of the current string. + + + + Represents list of supported by Unity Console color names + + + + + Create new sprite out of Texture + + A texture to created sprite from. + New sprite instance. + + + + Change texture size (and scale accordingly) + + + + + Crop texture to desired size. + Somehow cropped image seemed darker, brightness offset may fix this + + + + + Will texture with solid color + + + + + Convert png representation to base64 string. + + Texture to convert. + Converted texture as base64 string + + + + Loads texture content from base64 string. + + Texture to load image content into. + Base64 string image representation. + Updated texture. + + + + Resets `anchorMin`, `anchorMax`, `offsetMin`, `offsetMax` to `Vector2.zero`. + + RectTransform to operate with. + + + + Get's the screen rect of provided RectTransform. + + RectTransform to operate with. + Screen rect. + + + + Method to get Rect related to ScreenSpace, from given RectTransform. + This will give the real position of this Rect on screen. + + Original RectTransform of some object + New Rect instance. + + + + Sets value. + + Transform component. + New lossyScale value. + + + + Reset component position, scale and rotation. + + Transform component. + + + + Removes all transform children. + + Transform component. + Will ignore disabled game-objects when set to true. + + + + + Find or create child with name. + + Transform component. + Child name. + Child component instance. + + + + + + + + + + + + + + Set position to Vector3.zero. + + + + + Set sizeDelta to Vector2.Zero. + + + + + Snap to grid of snapValue + + + + + Snap to grid of snapValue + + + + + Snap to grid of snapValue + + + + + Snap position to grid of snapValue + + + + + Snap to one unit grid + + + + + Snap to one unit grid + + + + + Snap to one unit grid + + + + + Finds the position closest to the given one. + + World position. + Other world positions. + Closest position. + + + + Get vector between source and destination + + + + + Get vector between source and destination + + + + + Get vector between source and destination + + + + + Get vector between source and target + + + + + Get vector between source and target + + + + + Get vector between source and target + + + + + Get vector between source and target + + + + + Calculates a squared distance between current and given vectors. + + The current vector. + The given vector. + Returns squared distance between current and given vectors. + + + + Multiplies each element in Vector3 by the given scalar. + + The current vector. + The given scalar. + Returns new Vector3 containing the multiplied components. + + + + Multiplies each element in Vector3 a by the corresponding element of b. + + The current vector. + The given vector. + Returns new Vector3 containing the multiplied components of the given vectors. + + + + Smoothes a Vector3 that represents euler angles. + + The current Vector3 value. + The target Vector3 value. + A refernce Vector3 used internally. + The time to smooth, in seconds. + The smoothed Vector3 value. + + + + Calculates a squared distance between current and given vectors. + + The current vector. + The given vector. + Returns squared distance between current and given vectors. + + + + Multiplies each element in Vector2 by the given scalar. + + The current vector. + The given scalar. + Returns new Vector2 containing the multiplied components. + + + + Multiplies each element in Vector2 a by the corresponding element of b. + + The current vector. + The given vector. + Returns new Vector2 containing the multiplied components of the given vectors. + + + + Handles identification of Modded ID's + + + + + Adds more methods to to allow for more flexable addition + + +
+
diff --git a/Libs/System.Runtime.Serialization.dll b/Libs/System.Runtime.Serialization.dll new file mode 100644 index 0000000..0397ac5 Binary files /dev/null and b/Libs/System.Runtime.Serialization.dll differ diff --git a/README.md b/README.md index ffcd6d2..03db211 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,42 @@ # srmp-public +This is the code for the Slime Rancher MultiPlayer Mod (SRMP) by SatyPardus. -It's bad. It's really really bad. +The user manual which includes information about compatability information, download and installation instructions and standard troubleshooting can be found [here](/manual.md). -There is so much to clean up in this project, I would not even know where to begin. -Kinda the reason why it's already uploaded. No idea where and how to clean it up. -But this is the source code of my Slime Rancher Multiplayer mod. -It went through many iterations and each new one had stuff copy pasted. +## Bug Status +Note: Bug list compiled from last known bug list of version 1488 -It's a mess within a mess. -Oh god, forgive me. +FIXED: +- Multiplayer window doesn't show up on resolutions < 1920x1080 +- Exchange sometimes skips rewards if multiple players put items in at the same time +- Exchange chest disappears without rewards +- +IN PROGRESS: N/A ---------------------------------------------------------------------------------- +Known Bugs: +- Plort collectors don't work properly sometimes (Playing effect but not pulling anything) +- Nutcracker doesn't spit out right amount, or spits out "babies" +- Slimes sometimes appear "angry" for other players +- Game stutters when placing/removing gadgets +- First time using the mod can apparently break a lot of things (falling through world, slimes not eating) - Restarting the game fixes it +- DLCs don't seem to be loaded correctly when leaving and joining +- DLC are not initialized on game start, making the "You need following DLCs:" message pop up (Can be fixed by loading the "Manage DLCs" menu and trying again) +- Gordos don't drop things sometimes +- Slimes sometimes dont produce plorts +- Drones get stuck in place sometimes +- Chat sometimes empty for remote players +- Upgrades sometimes does not get applied to All players -But for real. Have fun digging through my unoptimized and undocumented code. -I never thought I actually gonna release this, yet here we are. -Would have dressed differently if I would have known. -Don't judge me tho. It still .... "works". -Just not as good as it could! +## Current Status +[@Twirlbug](https://github.com/Twirlbug) +- Currently working on going through the code, adding notes and fixing some of the bugs in my free time. +- I adore this mod and want to give both credit and a huge thank you to Saty for the origional creation of the mod. +I am slowly working my way through the list of bugs as seen above. + +### Notation Status +Files in the following folders still need more notation: +- Networking +- Packets +- Patches diff --git a/SRMP.sln b/SRMP.sln index 285d74f..bf9122f 100644 --- a/SRMP.sln +++ b/SRMP.sln @@ -1,32 +1,37 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.28307.1267 +# Visual Studio Version 17 +VisualStudioVersion = 17.6.33815.320 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SRMP", "SRMP\SRMP.csproj", "{E1BF7CDA-F2AE-4042-A992-DCBF62E79238}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{623884D3-E475-43F6-A6DF-64B8860E3EDD}" + ProjectSection(SolutionItems) = preProject + SRMP\_info.txt = SRMP\_info.txt + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU - SRML|Any CPU = SRML|Any CPU SRML NoVer|Any CPU = SRML NoVer|Any CPU - Standalone|Any CPU = Standalone|Any CPU + SRML|Any CPU = SRML|Any CPU Standalone NoVer|Any CPU = Standalone NoVer|Any CPU + Standalone|Any CPU = Standalone|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {E1BF7CDA-F2AE-4042-A992-DCBF62E79238}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E1BF7CDA-F2AE-4042-A992-DCBF62E79238}.Debug|Any CPU.Build.0 = Debug|Any CPU {E1BF7CDA-F2AE-4042-A992-DCBF62E79238}.Release|Any CPU.ActiveCfg = Release|Any CPU {E1BF7CDA-F2AE-4042-A992-DCBF62E79238}.Release|Any CPU.Build.0 = Release|Any CPU - {E1BF7CDA-F2AE-4042-A992-DCBF62E79238}.SRML|Any CPU.ActiveCfg = SRML|Any CPU - {E1BF7CDA-F2AE-4042-A992-DCBF62E79238}.SRML|Any CPU.Build.0 = SRML|Any CPU {E1BF7CDA-F2AE-4042-A992-DCBF62E79238}.SRML NoVer|Any CPU.ActiveCfg = SRML NoVer|Any CPU {E1BF7CDA-F2AE-4042-A992-DCBF62E79238}.SRML NoVer|Any CPU.Build.0 = SRML NoVer|Any CPU - {E1BF7CDA-F2AE-4042-A992-DCBF62E79238}.Standalone|Any CPU.ActiveCfg = Standalone|Any CPU - {E1BF7CDA-F2AE-4042-A992-DCBF62E79238}.Standalone|Any CPU.Build.0 = Standalone|Any CPU + {E1BF7CDA-F2AE-4042-A992-DCBF62E79238}.SRML|Any CPU.ActiveCfg = SRML|Any CPU + {E1BF7CDA-F2AE-4042-A992-DCBF62E79238}.SRML|Any CPU.Build.0 = SRML|Any CPU {E1BF7CDA-F2AE-4042-A992-DCBF62E79238}.Standalone NoVer|Any CPU.ActiveCfg = Standalone NoVer|Any CPU {E1BF7CDA-F2AE-4042-A992-DCBF62E79238}.Standalone NoVer|Any CPU.Build.0 = Standalone NoVer|Any CPU + {E1BF7CDA-F2AE-4042-A992-DCBF62E79238}.Standalone|Any CPU.ActiveCfg = Standalone|Any CPU + {E1BF7CDA-F2AE-4042-A992-DCBF62E79238}.Standalone|Any CPU.Build.0 = Standalone|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/SRMP/Console/Console Commands.txt b/SRMP/Console/Console Commands.txt new file mode 100644 index 0000000..b010d48 --- /dev/null +++ b/SRMP/Console/Console Commands.txt @@ -0,0 +1,27 @@ +The following console Commands work in the pop up console + +cheat money [amount] + Add or Remove the given amount from the curret money score + +cheat keys [amount] + Add or Remove the given amount of keys from the current amount + +cheat allgadgets + Unlocks all of the gagets in the game + +cheat spawn [id] ([amount]) + spawns given item for the given ammount + +tp [(optional)TargetPlayer] [DestinationPlayer] + Teleports the player in spot 1 to player/destination entered + if spot 1 is empty the palayer that entered in the command in infered as the target +listplayers + Prints the list of current players to the console + +sleep [Hours] + Sleep command followed by the time in in game hours to "sleep"". Fast forwards the game the alotted hours. + +console [enable/disable] [logtype] + Sets whether a specific log type should be displaying in the console. + All type default to enabled. + Log Types: Error, Assert, Warning, Log, Exception \ No newline at end of file diff --git a/SRMP/Console/ConsoleInput.cs b/SRMP/Console/ConsoleInput.cs index cf52165..34076eb 100644 --- a/SRMP/Console/ConsoleInput.cs +++ b/SRMP/Console/ConsoleInput.cs @@ -1,4 +1,5 @@ -using System; +using Microsoft.Win32; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -9,7 +10,46 @@ namespace SRMultiplayer { public string inputString = ""; public event Action OnInputText; - + + /// + /// Handle updates the console + /// This is to catch key presses and process them + /// + public void Update() + { + if (Console.KeyAvailable) + { + ConsoleKeyInfo consoleKeyInfo = Console.ReadKey(); + + switch (consoleKeyInfo.Key) + { + case ConsoleKey.Enter: this.OnEnter(); break; + case ConsoleKey.Backspace: this.OnBackspace(); break; + case ConsoleKey.Escape: this.OnEscape(); break; + case ConsoleKey.UpArrow: this.GetCommand(1); break; + case ConsoleKey.DownArrow: this.GetCommand(-1); break; + default: + //check if pressed key is a character + bool flag = consoleKeyInfo.KeyChar > '\0'; + if (flag) + { + //if so at it tothe input line + this.inputString += consoleKeyInfo.KeyChar.ToString(); + this.RedrawInputLine(); + } + break; + } + } + + + + } + + + #region Console Processors + /// + /// Clears out the current console line + /// public void ClearLine() { Console.CursorLeft = 0; @@ -17,7 +57,9 @@ namespace SRMultiplayer Console.CursorTop--; Console.CursorLeft = 0; } - + /// + /// Used to redraw the input line incase we had to hold for console write lines + /// public void RedrawInputLine() { bool flag = Console.CursorLeft > 0; @@ -29,7 +71,12 @@ namespace SRMultiplayer Console.Write("> "); Console.Write(this.inputString); } - + #endregion region + + #region Key Press Events + /// + /// Process Backspace pressed + /// internal void OnBackspace() { bool flag = this.inputString.Length <= 0; @@ -39,7 +86,9 @@ namespace SRMultiplayer this.RedrawInputLine(); } } - + /// + /// Process Escape pressed + /// internal void OnEscape() { this.ClearLine(); @@ -47,6 +96,9 @@ namespace SRMultiplayer this.RedrawInputLine(); } + /// + /// Process Enter pressed + /// internal void OnEnter() { this.ClearLine(); @@ -57,47 +109,56 @@ namespace SRMultiplayer bool flag = this.OnInputText != null; if (flag) { + //on text inputed reset the search loc and cycle the search tree + searchLoc = -1; //searchLoc set to -1 to always go to place 0 on first arrow + AddToCommandTree(obj); + this.OnInputText(obj); } } - - public void Update() + + #endregion + + #region Command History Retrieval + List cmdTree = new List(); + int maxCommands = 10; + /// + /// Manages the Command tree for the up and down arrows + /// + /// + internal void AddToCommandTree(string cmdText) { - bool flag = !Console.KeyAvailable; - if (!flag) + cmdTree.Insert(0, cmdText); + + //if tree gets larger than 10 remove the 11th item + if (cmdTree.Count > maxCommands) { cmdTree.RemoveAt(10); }; + } + + + //handle internal cycling of last 10 commands + int searchLoc = -1; + /// + /// Gets the command at the designaed slot from the current possition + /// + /// Possition from the current Command + internal void GetCommand(int diff) + { + if (cmdTree.Count > 0) { - ConsoleKeyInfo consoleKeyInfo = Console.ReadKey(); - bool flag2 = consoleKeyInfo.Key == ConsoleKey.Enter; - if (flag2) - { - this.OnEnter(); - } - else - { - bool flag3 = consoleKeyInfo.Key == ConsoleKey.Backspace; - if (flag3) - { - this.OnBackspace(); - } - else - { - bool flag4 = consoleKeyInfo.Key == ConsoleKey.Escape; - if (flag4) - { - this.OnEscape(); - } - else - { - bool flag5 = consoleKeyInfo.KeyChar > '\0'; - if (flag5) - { - this.inputString += consoleKeyInfo.KeyChar.ToString(); - this.RedrawInputLine(); - } - } - } - } + searchLoc = searchLoc + diff; + //prevent below 0 or over max position + if (searchLoc > (cmdTree.Count - 1)) searchLoc = (cmdTree.Count - 1); + if (searchLoc < 0) searchLoc = 0; + + //if a new location is found enter the search text in the input and redraw it. + this.inputString = cmdTree[searchLoc]; + this.RedrawInputLine(); + } + else + { + Console.WriteLine("cmdTree is empty"); } } + #endregion } -} +} \ No newline at end of file diff --git a/SRMP/Console/ConsoleWindow.cs b/SRMP/Console/ConsoleWindow.cs index 0f4ff33..862784c 100644 --- a/SRMP/Console/ConsoleWindow.cs +++ b/SRMP/Console/ConsoleWindow.cs @@ -14,7 +14,9 @@ namespace SRMultiplayer private TextWriter oldOutput; private const int STD_OUTPUT_HANDLE = -11; - + /// + /// Create the console window + /// public void Initialize() { bool flag = !ConsoleWindow.AttachConsole(uint.MaxValue); diff --git a/SRMP/Console/SRMPConsole.cs b/SRMP/Console/SRMPConsole.cs new file mode 100644 index 0000000..d309f3a --- /dev/null +++ b/SRMP/Console/SRMPConsole.cs @@ -0,0 +1,482 @@ +using JetBrains.Annotations; +using MonomiPark.SlimeRancher.Regions; +using SRMultiplayer.Networking; +using SRMultiplayer.Packets; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net.Sockets; +using UnityEngine; + +namespace SRMultiplayer +{ + enum LogItems + { + CLIENT, + SERVER, + PLAYERAMMO, + EXCHANGE + } + + + public class SRMPConsole : MonoBehaviour + { + ConsoleWindow console = new ConsoleWindow(); + ConsoleInput input = new ConsoleInput(); + + // + // Create console window, register callbacks + // + void Awake() + { + DontDestroyOnLoad(gameObject); + + console.Initialize(); + console.SetTitle("Slime Rancher"); + + input.OnInputText += OnInputText; + + Application.logMessageReceived += Application_logMessageReceived; + + SRMP.Log("Console Started"); + } + + //used to prevent duplicate messages displaying and list what number duplicate it is + string LastMessage = ""; + int duplicateCount = 0; + + //types of console types that can be enabled/disabled + //server automatically starts with all active + List blockMessages = new List(); //keeps a list of message types that have been disabled + List blockLogs = new List(); //keeps a list of log message types that have been disabled + bool DisplayTrace = false; + private void Application_logMessageReceived(string condition, string stackTrace, LogType type) + { + // We're half way through typing something, so clear this line .. + if (Console.CursorLeft != 0) + input.ClearLine(); + + //construct message + string message = condition; + if (!string.IsNullOrEmpty(stackTrace) && DisplayTrace) + { + //add stack strace if included + message += Environment.NewLine + stackTrace; + } + + if (message == LastMessage) + { + //do not process duplicate marks if the last item was not written + if (duplicateCount > 0) duplicateCount++; + } + else + { + //add write line for duplicate notices if necessary + if (duplicateCount > 0) + { + Console.ForegroundColor = ConsoleColor.Gray; + Console.WriteLine("Output Duplicated: " + duplicateCount); + } + + //format color for message + if (type == LogType.Warning) + Console.ForegroundColor = ConsoleColor.Yellow; + else if (type == LogType.Error) + Console.ForegroundColor = ConsoleColor.Red; + else + Console.ForegroundColor = ConsoleColor.White; + + // mark new message + LastMessage = message; + + bool displayLog = true; + + //if log type is blocked turn off display + if (blockMessages.Contains(type)) displayLog = false; + + //check data for specific inner types + string data = condition; + + //remove the srmp tag and the time to check inner tags + if (type == LogType.Log && data.StartsWith("[SRMP]")) + { + data = data.Substring(17); + + //if is still able to display make sure the log message blocker isnt blocking it + if (displayLog) + { + //try to pase the log message + if (Enum.TryParse(data.Split("]"[0])[0].Substring(1), true, out LogItems logMessage)) + { + if (blockLogs.Contains(logMessage)) displayLog = false; + } + } + } + + + //always allow console reply to display + if (data.StartsWith("[Console]")) displayLog = true; + + //only write the message type if its not blocked + if (displayLog) + { + //write the new line if not blocked + duplicateCount = 0; + Console.WriteLine(message); + } + else + { + //for testing log disabled display + //Console.ForegroundColor = ConsoleColor.Magenta; + Console.WriteLine(type.ToString() + " Dismissed"); + + //mark dupilcate count to -1 + //prevent duplicate count for supressed messages from displaying + duplicateCount = -1; + } + } + + + + // If we were typing something re-add it. + input.RedrawInputLine(); + } + + //create a log call that marks all console sent replys + void ConsoleLog(string message) + { + SRMP.Log(message, "Console"); + } + + + + // + // Text has been entered into the console + // Run it as a console command + // + void OnInputText(string obj) + { + var args = obj.Split(' '); + var cmd = args.FirstOrDefault(); + args = args.Skip(1).ToArray(); + + switch (cmd.ToLower()) + { + case "cheat": + { + if (args.Length > 0) + { + if (args[0].Equals("money")) + { + if (args.Length != 2 || !int.TryParse(args[1], out int money)) + { + ConsoleLog("Usage: cheat money "); + } + else + { + if (money > 0) + SRSingleton.Instance.PlayerState.AddCurrency(money); + else + SRSingleton.Instance.PlayerState.SpendCurrency(money); + } + } + else if (args[0].Equals("enable")) + { + //TestUI.Instance.cheat = !TestUI.Instance.cheat; + } + else if (args[0].Equals("keys")) + { + if (args.Length != 2 || !int.TryParse(args[1], out int value)) + { + ConsoleLog("Usage: cheat keys "); + } + else + { + SRSingleton.Instance.PlayerState.model.keys = value; + } + } + else if (args[0].Equals("allgadgets")) + { + foreach (var data in (Gadget.Id[])Enum.GetValues(typeof(Gadget.Id))) + { + SRSingleton.Instance.GadgetDirector.model.gadgets[data] = int.MaxValue; + } + foreach (var data in Identifiable.CRAFT_CLASS.Union(Identifiable.PLORT_CLASS)) + { + SRSingleton.Instance.GadgetDirector.model.craftMatCounts[data] = int.MaxValue; + } + } + else if (args[0].Equals("spawn")) + { + if (args.Length == 2) + { + if (Enum.TryParse(args[1].ToUpper(), out Identifiable.Id id)) + { + GameObject prefab = SRSingleton.Instance.LookupDirector.GetPrefab(id); + if (prefab != null) + { + SRBehaviour.InstantiateActor(prefab, SRSingleton.Instance.GameModel.player.currRegionSetId, SRSingleton.Instance.GameModel.player.GetPos() + new Vector3(0, 4, 0), Quaternion.identity, false); + } + else + { + ConsoleLog(id + " can not be spawned"); + } + } + else + { + var data = Enum.GetNames(typeof(Identifiable.Id)).Where(n => n.ToLower().Contains(args[1].ToLower())); + SRMP.Log(args[1] + " not found. " + (data.Count() > 0 ? " Did you mean one of these?" : "")); + foreach (var name in data) + { + ConsoleLog(name); + } + } + } + else if (args.Length == 3 && int.TryParse(args[2], out int amount)) + { + if (Enum.TryParse(args[1].ToUpper(), out Identifiable.Id id)) + { + GameObject prefab = SRSingleton.Instance.LookupDirector.GetPrefab(id); + if (prefab != null) + { + for (int i = 0; i < amount; i++) + { + SRBehaviour.InstantiateActor(prefab, SRSingleton.Instance.GameModel.player.currRegionSetId, SRSingleton.Instance.GameModel.player.GetPos() + new Vector3(0, 4, 0), Quaternion.identity, false); + } + } + else + { + SRMP.Log(id + " can not be spawned"); + } + } + else + { + var data = Enum.GetNames(typeof(Identifiable.Id)).Where(n => n.ToLower().Contains(args[1].ToLower())); + ConsoleLog(args[1] + " not found. " + (data.Count() > 0 ? " Did you mean one of these?" : "")); + foreach (var name in data) + { + ConsoleLog(name); + } + } + } + else + { + ConsoleLog("Usage: cheat spawn ()"); + } + } + } + else + { + ConsoleLog("Available sub commands:"); + ConsoleLog("cheat money "); + ConsoleLog("cheat keys "); + ConsoleLog("cheat spawn ()"); + ConsoleLog("cheat allgadgets"); + } + } + break; + case "tp": + { + if (args.Length < 1 || args.Length > 2) + { + ConsoleLog("Usage: tp <(optional)target:username> "); + return; + } + + //mark target and destination seperately + string target = args.Length == 2 ? args[0] : ""; + string destination = args.Length == 2 ? args[1] : args[0]; + + //mark target transform location + PacketPlayerPosition packet = null; + string destSummary = ""; + + //first check distination + switch (destination.ToLower()) + { + case "home": + + var home = SRSingleton.Instance.GetWakeUpDestination(); + packet = new PacketPlayerPosition() + { + Position = home.transform.position, + Rotation = home.transform.eulerAngles.y, + RegionSet = (byte)home.GetRegionSetId() + }; + + destSummary = "Home"; + break; + default: //check for a player name + var play = Globals.Players.Values.FirstOrDefault(p => p.Username.Equals(destination, StringComparison.CurrentCultureIgnoreCase)); + + if (play == null) + { + ConsoleLog("Destination not found"); + return; + } + packet = new PacketPlayerPosition() + { + Position = play.transform.position, + Rotation = play.transform.eulerAngles.y, + RegionSet = (byte)play.CurrentRegionSet + }; + destSummary = play.Username; + break; + } + + + if (packet != null) + { + //set as not load destination + packet.OnLoad = false; + + NetworkPlayer targetPlayer = null; + if (target.Length > 0) + { + targetPlayer = Globals.Players.Values.FirstOrDefault(p => p.Username.Equals(target, StringComparison.CurrentCultureIgnoreCase)); + } + else + { + targetPlayer = Globals.LocalPlayer; + } + //check if target is local user + if (targetPlayer == null) + { + ConsoleLog("Target Player not found"); + return; + } + + ConsoleLog("Teleporting " + targetPlayer.Username + " to " + destSummary); + + if (!targetPlayer.IsLocal) + { + //if a target is located and is not the local player send the teleport command + packet.ID = targetPlayer.ID; + packet.WeaponY = targetPlayer.GetWeaponLocation(); + packet.Send(); + return; + } + else + { + //if we have have made it here the tp in question is for the instances player + //so move that player + SRSingleton.Instance.player.transform.position = packet.Position; + SRSingleton.Instance.player.transform.eulerAngles = new Vector3(0, packet.Rotation, 0); + SRSingleton.Instance.PlayerState.model.SetCurrRegionSet((RegionRegistry.RegionSetId)packet.RegionSet); + // play the teleport animation + SRSingleton.Instance.PlayTeleport(); + } + + } + else + { + ConsoleLog("Destination not found"); + } + + } + break; + case "listplayers": + { + ConsoleLog("Players:"); + foreach (var player in Globals.Players.Values) + { + SRMP.Log(player.Username); + } + } + break; + case "sleep": + { + if (args.Length == 1) + { + SRSingleton.Instance.TimeDirector.FastForwardTo(SRSingleton.Instance.TimeDirector.HoursFromNow(float.Parse(args[0]))); + ConsoleLog("Sleeoing for " + args[0] + " hours"); + } + else + { + ConsoleLog("Usage: sleep "); + } + } + break; + case "console": //add toggle option for turning on and off logging types + + if (args.Length > 1 && (args[0] == "enable" || args[0] == "disable")) + { + bool enable = args[0] == "enable"; + //double check type + if (Enum.TryParse(args[1], true, out LogType logType)) //check for main log type + { + if (enable) + { + if (!blockMessages.Contains(logType)) blockMessages.Remove(logType); + ConsoleLog(logType.ToString() + " Messages Enabled"); + } + else + { + if (blockMessages.Contains(logType)) blockMessages.Add(logType); + ConsoleLog("[Console] " + logType.ToString() + " Messages Disabled"); + } + } + else if (Enum.TryParse(args[1], true, out LogItems logMessage)) //check for log message item types + { + if (enable) + { + if (!blockLogs.Contains(logMessage)) blockLogs.Remove(logMessage); + ConsoleLog(logMessage.ToString() + " Log Messages Enabled"); + } + else + { + if (blockLogs.Contains(logMessage)) blockLogs.Add(logMessage); + ConsoleLog(logMessage.ToString() + " Log Messages Disabled"); + } + } + else if (args[1].Equals("stacktrace", StringComparison.InvariantCultureIgnoreCase) || args[1].Equals("stack_trace", StringComparison.InvariantCultureIgnoreCase)) + { + if (enable) + { + DisplayTrace = true; + ConsoleLog("Stack Trace Information Enabled"); + } + else + { + DisplayTrace = false; + ConsoleLog("Stack Trace Information Disabled"); + } + } + else + { + ConsoleLog("Invalid Feed back Type"); + ConsoleLog("Valid Types: "); + ConsoleLog(string.Join(", ", Enum.GetValues(typeof(LogType)))); + ConsoleLog(string.Join(", ", Enum.GetValues(typeof(LogItems)))); + } + } + else + { + ConsoleLog("Usage: console "); + } + break; + + } + } + + // + // Update the input every frame + // This gets new key input and calls the OnInputText callback + // + void Update() + { + input.Update(); + } + + // + // It's important to call console.ShutDown in OnDestroy + // because compiling will error out in the editor if you don't + // because we redirected output. This sets it back to normal. + // + void OnDestroy() + { + console.Shutdown(); + } + } +} \ No newline at end of file diff --git a/SRMP/ChatUI.cs b/SRMP/Custom UI/ChatUI.cs similarity index 75% rename from SRMP/ChatUI.cs rename to SRMP/Custom UI/ChatUI.cs index 9518920..7f10ffa 100644 --- a/SRMP/ChatUI.cs +++ b/SRMP/Custom UI/ChatUI.cs @@ -13,7 +13,11 @@ public class ChatUI : SRSingleton private float fadeTime; private List messages = new List(); private Vector2 chatScroll; + int maxWidth = 290; + /// + /// create a chat message to be displayed + /// public class ChatMessage { public string Text; @@ -27,52 +31,68 @@ public class ChatUI : SRSingleton Time = DateTime.Now; } } - + /// + /// On chat ui update triggered, handle it + /// private void Update() { + //only display chat if in multiplayer mode if (!Globals.IsMultiplayer) { openChat = false; message = ""; return; } - + //if enter is pressed start chat typing mode if (Input.GetKeyUp(KeyCode.Return)) { StartCoroutine(FocusChat()); } } - + /// + /// Crreate the Chat gui + /// private void OnGUI() { + //only mess with the gui in multiplayer mode if (!Globals.IsMultiplayer) return; if (openChat) { - GUILayout.BeginArea(new Rect(20, Screen.height / 2, 500, 300), GUI.skin.box); + //draw chat area + GUILayout.BeginArea(new Rect(20, Screen.height / 2, maxWidth + 10, 300), GUI.skin.box); chatScroll = GUILayout.BeginScrollView(chatScroll); var skin = GUI.skin.box; skin.wordWrap = true; skin.alignment = TextAnchor.MiddleLeft; + + //add each mesage into the chat box scroller foreach (var msg in messages) { - GUILayout.Label(wrapString(msg.Text, 490), skin, GUILayout.MaxWidth(490)); + GUILayout.Label(wrapString(msg.Text, maxWidth), skin, GUILayout.MaxWidth(maxWidth)); } GUILayout.EndScrollView(); + + //add display for text input area GUI.SetNextControlName("ChatInput"); message = GUILayout.TextField(message); GUILayout.EndArea(); + //focus the input GUI.FocusControl("ChatInput"); + //watch for changes to the text input Event e = Event.current; if (e.rawType == EventType.KeyUp && e.keyCode == KeyCode.Return) { + //on send close chat openChat = !openChat; if (!string.IsNullOrWhiteSpace(message)) { + //if server send message to all plauers if (Globals.IsServer) { + //if server send it to the server AddChatMessage(Globals.Username + ": " + message); new PacketPlayerChat() { @@ -81,6 +101,7 @@ public class ChatUI : SRSingleton } else { + //if player send it to the server new PacketPlayerChat() { message = message @@ -90,13 +111,16 @@ public class ChatUI : SRSingleton } } } - else + else //if chat isnt open yet { - GUILayout.BeginArea(new Rect(20, Screen.height / 2, 500, 300)); + //draw chat area + GUILayout.BeginArea(new Rect(20, Screen.height / 2, maxWidth+ 10, 300)); chatScroll = GUILayout.BeginScrollView(chatScroll); var skin = GUI.skin.box; skin.wordWrap = true; skin.alignment = TextAnchor.MiddleLeft; + + //add each mesage into the chat box scroller foreach (var msg in messages) { if (msg.FadeTime > 0f) @@ -105,26 +129,34 @@ public class ChatUI : SRSingleton var c = GUI.color; c.a = (msg.FadeTime / 5f); GUI.color = c; - GUILayout.Label(wrapString(msg.Text, 490), skin, GUILayout.MaxWidth(490)); + GUILayout.Label(wrapString(msg.Text, maxWidth), skin, GUILayout.MaxWidth(maxWidth)); } } GUILayout.EndScrollView(); GUILayout.EndArea(); } } - + /// + /// Add a chat message to be displayed + /// + /// Message to display public void AddChatMessage(string message) { fadeTime = 10f; messages.Add(new ChatMessage(message)); chatScroll = new Vector2(0, 100000); } - + /// + /// Trigger a full clear of the chat + /// public void Clear() { messages.Clear(); } + /// + /// Trigger focus on the chat box for when the uer hits enter + /// private IEnumerator FocusChat() { yield return new WaitForEndOfFrame(); @@ -133,6 +165,12 @@ public class ChatUI : SRSingleton GUI.FocusControl("ChatInput"); } + /// + /// Create the wrapped string to display in the chat box + /// + /// Message to display + /// Width of the chat box + /// string wrapString(string msg, int width) { string[] words = msg.Split(" "[0]); diff --git a/SRMP/MultiplayerUI.cs b/SRMP/Custom UI/MultiplayerUI.cs similarity index 57% rename from SRMP/MultiplayerUI.cs rename to SRMP/Custom UI/MultiplayerUI.cs index b48b521..a3940a4 100644 --- a/SRMP/MultiplayerUI.cs +++ b/SRMP/Custom UI/MultiplayerUI.cs @@ -8,18 +8,38 @@ using SRMultiplayer.Networking; public class MultiplayerUI : SRSingleton { - private Rect windowRect = new Rect(Screen.width - 300, 20, 300, 500); + private Rect windowRect = new Rect(Screen.width - 300 - 20, 20, 300, 500); private Vector2 playersScroll = Vector2.zero; private string ipaddress = "localhost"; private string port = "16500"; private string servercode = ""; - private bool menuOpen; + + //use internal name with getter and setter to allow the menu panel to remember the users last choice + private int _menuOpen; + private int menuOpen //menu open hold the current menu state (0 colapsed, 1 minimized, 2 open) + { + get + { + return _menuOpen; + } + set + { + _menuOpen = value; + + //save users setting + PlayerPrefs.SetInt("SRMP_Menu", menuOpen); + } + } + + private string username; private float lastCodeUse; private ConnectError error; private ConnectHelp help; private string errorMessage; + + public enum ConnectError { None, @@ -36,65 +56,228 @@ public class MultiplayerUI : SRSingleton Hosting, } + /// + /// Creation of gui with side panel is last display state + /// public override void Awake() { base.Awake(); + //set default ui location width adapting numbers for smaller resolutions + float width = 300; + if (Screen.width / 4 < width) width = Screen.width / 4; + windowRect = new Rect(Screen.width - width - 20, 20, width, 500); + Globals.Username = PlayerPrefs.GetString("SRMP_Username", ""); ipaddress = PlayerPrefs.GetString("SRMP_IP", "localhost"); port = PlayerPrefs.GetString("SRMP_Port", "16500"); - menuOpen = true; + menuOpen = PlayerPrefs.GetInt("SRMP_Menu", 2); ; //start panel open by default + username = Globals.Username; } + /// + /// Update of panel display + /// private void Update() { - if(lastCodeUse > 0f) + if (lastCodeUse > 0f) { var prevTime = lastCodeUse; lastCodeUse -= Time.deltaTime; - if(prevTime > 0f && lastCodeUse <= 0f) + if (prevTime > 0f && lastCodeUse <= 0f) { error = ConnectError.ServerCodeTimeout; } } - if(Input.GetKeyDown(KeyCode.F4)) + + //this sets presskey senarios + if (Input.GetKeyDown(KeyCode.F4)) { - menuOpen = !menuOpen; + //use the f4 key to swap between collapsed and minimized + menuOpen = menuOpen == 2 ? 0 : 2; + } + if (Input.GetKeyDown(KeyCode.F3)) + { + //use the f3 key to set minimized or maximized + menuOpen = menuOpen < 2 ? 2 : 1; } } - + /// + /// Handle draw event of the gui + /// private void OnGUI() { - if (!menuOpen || (!Levels.isMainMenu() && !Globals.IsMultiplayer && Globals.PauseState != PauseState.Pause)) return; + //verify on a window that the menu can be drawn on + if ((!Levels.isMainMenu() && !Globals.IsMultiplayer && Globals.PauseState != PauseState.Pause)) return; if (Globals.IsMultiplayer && Globals.PauseState != PauseState.Pause) return; + //if yes draw the window for the given state if (SceneManager.GetActiveScene().buildIndex >= 2) { - windowRect = GUI.Window(1, windowRect, MultiplayerWindow, "SRMP v" + Globals.Version); + //check to make sure the panel is taking less than 25% of the screen if possible + float width = 300; + if(Screen.width/ 4 < width) width = Screen.width/4; + windowRect.width = width; + + //check to see if the windows needs to move due to it being off the screen from size change + //also prevent the user from dragging it off the screen + if (windowRect.x + 20 + windowRect.width > Screen.width) windowRect.x = Screen.width - windowRect.width - 20; + if (windowRect.y + 20 + windowRect.height > Screen.height) windowRect.y = (Screen.height - windowRect.height - 20) >= 20 ? (Screen.height - windowRect.height - 20) : 20; + if (windowRect.x < 20) windowRect.x = 20; + if (windowRect.y < 20) windowRect.y = 20; + + + + //drawn in the window + switch (menuOpen) + { + case 0: //collapsed + windowRect.height = 50; + windowRect = GUILayout.Window(1, windowRect, ClosedWindow, "SRMP v" + Globals.Version); + break; + case 1: //minimized + windowRect.height = 100; + windowRect = GUILayout.Window(1, windowRect, MiniWindow, "SRMP v" + Globals.Version); + break; + case 2: //open + windowRect.height = 500; + windowRect = GUILayout.Window(1, windowRect, MultiplayerWindow, "SRMP v" + Globals.Version); + break; + } + + } } + /// + /// display for the function keyps section of the gui + /// + private void FunctionKeys() + { + if (menuOpen != 0) + { + GUILayout.Label("Press Button or Key To Change Style"); + } + GUILayout.BeginHorizontal(); + if (GUILayout.Button(menuOpen == 1 ? "F3 - Full" : "F3 - Mini")) + { + menuOpen = menuOpen == 1 ? 2 : 1; + } + GUILayout.FlexibleSpace(); + if (GUILayout.Button(menuOpen == 0 ? "F4 - Full" : "F4 - Colapsed")) + { + menuOpen = menuOpen == 0 ? 2 : 0; + } + GUILayout.EndHorizontal(); + } + /// + /// Sets the window display for collapsed + /// Only activated if the id is the id for the window + /// + private void ClosedWindow(int id) + { + if (id != 1) return; + //display f3 and f4 commands + FunctionKeys(); + GUI.DragWindow(new Rect(0, 0, 10000, 10000)); + } + /// + /// Sets the window display for summary mode + /// Only activated if the id is the id for the window + /// + private void MiniWindow(int id) + { + if (id != 1) return; + + //display f3 and f4 commands + FunctionKeys(); + + //show username and current connection status + GUIStyle standard = new GUIStyle(GUI.skin.label); + GUIStyle red = new GUIStyle(GUI.skin.label); + red.normal.textColor = Color.red; + + + if (string.IsNullOrWhiteSpace(Globals.Username)) + { + GUILayout.Label("Username: Not Set", red); + } + else + { + GUILayout.Label("Username: " + Globals.Username); + + if (Globals.IsServer) + { + GUILayout.Label("Status: Host"); + } + else if (Globals.IsClient) + { + + GUIStyle green = new GUIStyle(GUI.skin.label); + green.normal.textColor = Color.green; + GUILayout.Label("Status: Client", green); + } + else + { + bool canHost = true; + //check if user can host the session + if (!int.TryParse(port, out int numport) || numport < 1000 || numport > 65000) + { + canHost = false; + } + + GUILayout.BeginHorizontal(); + GUILayout.Label("Status: Disconnected", red); + + GUILayout.FlexibleSpace(); + if (canHost) + { + //only show host if not main menu + if (!Levels.isMainMenu()) + { + if (GUILayout.Button("Host")) + { + NetworkServer.Instance.StartServer(numport); + SaveSettings(); + } + } + } + GUILayout.EndHorizontal(); + if (!canHost) + { + GUILayout.Label("Invalid Port Settings", red); + } + } + + } + GUI.DragWindow(new Rect(0, 0, 10000, 10000)); + } + /// + /// Sets the window display for full display mode + /// Only activated if the id is the id for the window + /// private void MultiplayerWindow(int id) { if (id != 1) return; - GUILayout.Label("You can close this menu with F4"); - GUILayout.Space(20); + //display f3 and f4 commands + FunctionKeys(); - if(string.IsNullOrWhiteSpace(Globals.Username)) + //now display standard + if (string.IsNullOrWhiteSpace(Globals.Username)) { UsernameGUI(); } else { - if(Globals.IsServer) + if (Globals.IsServer) { ServerGUI(); } - else if(Globals.IsClient) + else if (Globals.IsClient) { ClientGUI(); } @@ -104,13 +287,13 @@ public class MultiplayerUI : SRSingleton { ErrorGUI(); } - else if(help != ConnectHelp.None) + else if (help != ConnectHelp.None) { HelpGUI(); } else { - if(lastCodeUse > 0f) + if (lastCodeUse > 0f) { GUILayout.Label("Trying to connect with server code..."); } @@ -129,6 +312,9 @@ public class MultiplayerUI : SRSingleton GUI.DragWindow(new Rect(0, 0, 10000, 10000)); } + /// + /// Display the active server info part of the gui + /// private void ServerGUI() { GUILayout.Label("You are the server"); @@ -143,7 +329,7 @@ public class MultiplayerUI : SRSingleton GUILayout.BeginHorizontal(); GUILayout.Label(player.Username); - if(GUILayout.Button("Kick")) + if (GUILayout.Button("Kick")) { player.Connection.Disconnect("kicked"); } @@ -151,7 +337,9 @@ public class MultiplayerUI : SRSingleton } GUILayout.EndScrollView(); } - + /// + /// Display the client info part of the gui + /// private void ClientGUI() { GUILayout.Label("You are a client"); @@ -169,7 +357,11 @@ public class MultiplayerUI : SRSingleton } GUILayout.EndScrollView(); } - + /// + /// Display the connection information of the gui + /// this section includes user information, + /// how to and other imbedded sections for handling display + /// private void ConnectGUI() { GUILayout.Label("Username: " + Globals.Username); @@ -179,7 +371,7 @@ public class MultiplayerUI : SRSingleton return; } GUILayout.Space(20); - if(GUILayout.Button("How do I host a game?")) + if (GUILayout.Button("How do I host a game?")) { help = ConnectHelp.Hosting; } @@ -250,6 +442,9 @@ public class MultiplayerUI : SRSingleton } } + /// + /// Display the hosting info part of the gui + /// private void HostGUI() { GUILayout.Label("Username: " + Globals.Username); @@ -277,10 +472,12 @@ public class MultiplayerUI : SRSingleton } } } - + /// + /// Display the Help info part of the gui with instructions for hosting + /// private void HelpGUI() { - switch(help) + switch (help) { case ConnectHelp.ServerCode: { @@ -301,10 +498,12 @@ public class MultiplayerUI : SRSingleton break; } } - + /// + /// Display the Error summaries in the gui + /// private void ErrorGUI() { - switch(error) + switch (error) { case ConnectError.InvalidServerCode: { @@ -354,7 +553,9 @@ public class MultiplayerUI : SRSingleton break; } } - + /// + /// Display the Current user information + /// private void UsernameGUI() { GUILayout.BeginHorizontal(); @@ -376,14 +577,18 @@ public class MultiplayerUI : SRSingleton } } } - + /// + /// Saves the gui settings for the user + /// private void SaveSettings() { PlayerPrefs.SetString("SRMP_Username", Globals.Username); PlayerPrefs.SetString("SRMP_IP", ipaddress); PlayerPrefs.GetString("SRMP_Port", port); } - + /// + /// Handles connection resonces display when connection is lost from the server + /// public void ConnectResponse(ConnectError connectError, string message = "") { lastCodeUse = 0f; diff --git a/SRMP/TestUI.cs b/SRMP/Custom UI/TestUI.cs similarity index 95% rename from SRMP/TestUI.cs rename to SRMP/Custom UI/TestUI.cs index 98b7c0c..2998448 100644 --- a/SRMP/TestUI.cs +++ b/SRMP/Custom UI/TestUI.cs @@ -8,6 +8,24 @@ //using UnityEngine; //using UnityEngine.SceneManagement; +/* + * TestUi is a version of the multiplayer ui that adds the following information + * Added + Chat + Cheats + + + * More stats + Quick silver race is active + client status + server status + server code + send and recieve sizes + packet sizes + */ + + + //namespace SRMultiplayer //{ // class TestUI : SRSingleton @@ -130,11 +148,11 @@ // { // SRSingleton.Instance.PlayerState.AddCurrency(1000000); // } -// if(GUILayout.Button("Remove all actors")) +// if (GUILayout.Button("Remove all actors")) // { -// foreach(var actor in SRSingleton.Instance.GameModel.AllActors().Values.ToList()) +// foreach (var actor in SRSingleton.Instance.GameModel.AllActors().Values.ToList()) // { -// if(actor != null && actor.transform != null && actor.transform.gameObject.activeInHierarchy && !Identifiable.SCENE_OBJECTS.Contains(actor.ident)) +// if (actor != null && actor.transform != null && actor.transform.gameObject.activeInHierarchy && !Identifiable.SCENE_OBJECTS.Contains(actor.ident)) // { // Destroyer.DestroyActor(actor.transform.gameObject, "Get.Removed"); // } @@ -265,10 +283,10 @@ // { // try // { -// if (GUILayout.Button("Clear " + ident.ToString())) -// { +// if (GUILayout.Button("Clear " + ident.ToString())) +// { // SRSingleton.Instance.ExchangeDirector.ClearOffer(ident); -// } +// } // } // catch { } // } @@ -535,10 +553,10 @@ // if (Globals.IsMultiplayer) // { // QuicksilverEnergyGenerator generator = null; -// foreach(var region in Globals.LocalPlayer.Regions) +// foreach (var region in Globals.LocalPlayer.Regions) // { // generator = region.GetComponent(); -// if(generator != null) +// if (generator != null) // { // break; // } @@ -546,13 +564,13 @@ // GUILayout.Label("Is In Race: " + (generator != null ? generator.id : "None")); // GUILayout.Label($"Client Status: {NetworkClient.Instance.Status}"); // GUILayout.Label($"Server Status: {NetworkServer.Instance.Status}"); -// if(!string.IsNullOrWhiteSpace(Globals.ServerCode)) +// if (!string.IsNullOrWhiteSpace(Globals.ServerCode)) // { // GUILayout.Label($"Server Code: {Globals.ServerCode}"); // } -// //GUILayout.Label("Received Messages: " + SRSingleton.Instance.Statistics.ReceivedMessages); -// //GUILayout.Label("Send Messages: " + SRSingleton.Instance.Statistics.SentMessages); +// GUILayout.Label("Received Messages: " + SRSingleton.Instance.Statistics.ReceivedMessages); +// GUILayout.Label("Send Messages: " + SRSingleton.Instance.Statistics.SentMessages); // if (NetworkServer.Instance != null && NetworkServer.Instance.Status == NetworkServer.ServerStatus.Running) // { @@ -567,7 +585,7 @@ // //GUILayout.Space(20); // //GUILayout.Label("Chat"); // chatScroll = GUILayout.BeginScrollView(chatScroll, GUI.skin.box); -// foreach(var sizes in Globals.PacketSize.OrderByDescending(c => c.Value)) +// foreach (var sizes in Globals.PacketSize.OrderByDescending(c => c.Value)) // { // GUILayout.Label(sizes.Key + ": " + Utils.GetHumanReadableFileSize(sizes.Value)); // } diff --git a/SRMP/Globals.cs b/SRMP/Globals.cs index dac99cf..9010532 100644 --- a/SRMP/Globals.cs +++ b/SRMP/Globals.cs @@ -11,12 +11,12 @@ namespace SRMultiplayer { public static class Globals { + + //setup global objects for refrence usage public static int Version; public static UserData UserData; public static GameObject BeatrixModel; public static RuntimeAnimatorController BeatrixController; - public static GameObject IngameMultiplayerMenuPrefab; - public static GameObject MainMultiplayerMenuPrefab; public static Dictionary Players = new Dictionary(); public static string Username; public static string ServerCode; @@ -53,6 +53,10 @@ namespace SRMultiplayer public static List LemonTrees = new List(); public static Dictionary PacketSize = new Dictionary(); + /// + /// get list of current installed mods + /// Excluding supporting files + /// public static List Mods { get diff --git a/SRMP/MainSRML.cs b/SRMP/MainSRML.cs index d37551a..898d534 100644 --- a/SRMP/MainSRML.cs +++ b/SRMP/MainSRML.cs @@ -14,6 +14,10 @@ using UnityEngine; namespace SRMultiplayer { + /// + /// Handles mod being loaded from SRML + /// Takes the place of the Main Standalone file, but caters to the SRML + /// public class MainSRML : ModEntryPoint { private static GameObject m_GameObject; @@ -35,10 +39,12 @@ namespace SRMultiplayer SRMP.Log("Loading SRMP SRML Version"); + //create the mod directory in the install folder if needed if (!Directory.Exists(SRMP.ModDataPath)) { Directory.CreateDirectory(SRMP.ModDataPath); } + //create the user data file if not created yet if (!File.Exists(Path.Combine(SRMP.ModDataPath, "userdata.json"))) { Globals.UserData = new UserData() @@ -50,7 +56,7 @@ namespace SRMultiplayer File.WriteAllText(Path.Combine(SRMP.ModDataPath, "userdata.json"), JsonConvert.SerializeObject(Globals.UserData)); SRMP.Log("Created userdata with UUID " + Globals.UserData.UUID); } - else + else //if alreayd created load in the data { Globals.UserData = JsonConvert.DeserializeObject(File.ReadAllText(Path.Combine(SRMP.ModDataPath, "userdata.json"))); if(Globals.UserData.IgnoredMods == null) @@ -60,6 +66,7 @@ namespace SRMultiplayer SRMP.Log("Loaded userdata with UUID " + Globals.UserData.UUID); } + //create the mods main game objects and start connecting everything string[] args = System.Environment.GetCommandLineArgs(); m_GameObject = new GameObject("SRMP"); @@ -71,12 +78,16 @@ namespace SRMultiplayer m_GameObject.AddComponent(); m_GameObject.AddComponent(); + //mark all mod objects and do not destroy GameObject.DontDestroyOnLoad(m_GameObject); + //get current mod version Globals.Version = Assembly.GetExecutingAssembly().GetName().Version.Revision; + //mark the mod as a background task Application.runInBackground = true; + //initialize connect to the harmony patcher HarmonyPatcher.GetInstance().PatchAll(Assembly.GetExecutingAssembly()); } diff --git a/SRMP/MainStandalone.cs b/SRMP/MainStandalone.cs index f769e4f..274ec8a 100644 --- a/SRMP/MainStandalone.cs +++ b/SRMP/MainStandalone.cs @@ -8,7 +8,9 @@ using UnityCoreMod; using UnityEngine; namespace SRMultiplayer -{ +{ // + /// Handles mod being loaded from directly without the mod loader + /// public class MainSaty : IUnityMod { private static GameObject m_GameObject; @@ -19,10 +21,12 @@ namespace SRMultiplayer SRMP.Log("Loading SRMP Standalone Version"); + //create the mod directory in the install folder if needed if (!Directory.Exists(SRMP.ModDataPath)) { Directory.CreateDirectory(SRMP.ModDataPath); } + //create the user data file if not created yet if (!File.Exists(Path.Combine(SRMP.ModDataPath, "userdata.json"))) { Globals.UserData = new UserData() @@ -34,8 +38,9 @@ namespace SRMultiplayer File.WriteAllText(Path.Combine(SRMP.ModDataPath, "userdata.json"), JsonConvert.SerializeObject(Globals.UserData)); SRMP.Log("Created userdata with UUID " + Globals.UserData.UUID); } - else + else //if alreayd created load in the data { + Globals.UserData = JsonConvert.DeserializeObject(File.ReadAllText(Path.Combine(SRMP.ModDataPath, "userdata.json"))); if(Globals.UserData.IgnoredMods == null) { @@ -44,6 +49,7 @@ namespace SRMultiplayer SRMP.Log("Loaded userdata with UUID " + Globals.UserData.UUID); } + //create the mods main game objects and start connecting everything string[] args = System.Environment.GetCommandLineArgs(); m_GameObject = new GameObject("SRMP"); @@ -55,13 +61,17 @@ namespace SRMultiplayer m_GameObject.AddComponent(); m_GameObject.AddComponent(); + //mark all mod objects and do not destroy GameObject.DontDestroyOnLoad(m_GameObject); + //get current mod version Globals.Version = Assembly.GetExecutingAssembly().GetName().Version.Revision; + //initialize harmony and init the patches var harmony = new Harmony("saty.mod.srmp"); harmony.PatchAll(Assembly.GetExecutingAssembly()); + //mark the mod as a background task Application.runInBackground = true; } diff --git a/SRMP/Networking/NetworkClient.cs b/SRMP/Networking/Communication/NetworkClient.cs similarity index 100% rename from SRMP/Networking/NetworkClient.cs rename to SRMP/Networking/Communication/NetworkClient.cs diff --git a/SRMP/Networking/NetworkHandlerClient.cs b/SRMP/Networking/Communication/NetworkHandlerClient.cs similarity index 92% rename from SRMP/Networking/NetworkHandlerClient.cs rename to SRMP/Networking/Communication/NetworkHandlerClient.cs index ae0119f..29a5fa7 100644 --- a/SRMP/Networking/NetworkHandlerClient.cs +++ b/SRMP/Networking/Communication/NetworkHandlerClient.cs @@ -1,16 +1,12 @@ -using Assets.Script.Util.Extensions; -using DG.Tweening; +using DG.Tweening; using Lidgren.Network; using MonomiPark.SlimeRancher.DataModel; -using MonomiPark.SlimeRancher.Persist; using MonomiPark.SlimeRancher.Regions; using SRMultiplayer.Packets; using System; using System.Collections.Generic; using System.IO; using System.Linq; -using System.Text; -using System.Threading.Tasks; using UnityEngine; namespace SRMultiplayer.Networking @@ -24,22 +20,24 @@ namespace SRMultiplayer.Networking Globals.PacketSize[type] += im.LengthBytes; switch (type) { + //Player amimations + case PacketType.PlayerAnimation: OnPlayerAnimation(new PacketPlayerAnimation(im)); break; + //Players case PacketType.PlayerJoined: OnPlayerJoined(new PacketPlayerJoined(im)); break; case PacketType.PlayerLeft: OnPlayerLeft(new PacketPlayerLeft(im)); break; case PacketType.PlayerLoaded: OnPlayerLoaded(new PacketPlayerLoaded(im)); break; case PacketType.PlayerPosition: OnPlayerPosition(new PacketPlayerPosition(im)); break; - case PacketType.PlayerAnimationLayer: OnPlayerAnimationLayer(im); break; - case PacketType.PlayerAnimationParameters: OnPlayerAnimationParameters(im); break; - case PacketType.PlayerAnimationSpeed: OnPlayerAnimationSpeed(im); break; case PacketType.PlayerFX: OnPlayerFX(new PacketPlayerFX(im)); break; case PacketType.PlayerCurrency: OnPlayerCurrency(new PacketPlayerCurrency(im)); break; case PacketType.PlayerCurrencyDisplay: OnPlayerCurrencyDisplay(new PacketPlayerCurrencyDisplay(im)); break; case PacketType.PlayerUpgrade: OnPlayerUpgrade(new PacketPlayerUpgrade(im)); break; case PacketType.PlayerUpgradeUnlock: OnPlayerUpgradeUnlock(new PacketPlayerUpgradeUnlock(im)); break; case PacketType.PlayerChat: OnPlayerChat(new PacketPlayerChat(im)); break; + // Region case PacketType.RegionOwner: OnRegionOwner(new PacketRegionOwner(im)); break; + //Actors case PacketType.Actors: OnActors(new PacketActors(im)); break; case PacketType.ActorSpawn: OnActorSpawn(new PacketActorSpawn(im)); break; @@ -153,7 +151,7 @@ namespace SRMultiplayer.Networking case PacketType.RaceTime: OnRaceTime(new PacketRaceTime(im)); break; case PacketType.RaceTrigger: OnRaceTrigger(new PacketRaceTrigger(im)); break; default: - SRMP.Log($"Got unhandled packet: {type}"); + SRMP.Log($"Got unhandled packet: {type} " + Enum.GetName(typeof(PacketType), type)); break; } } @@ -274,7 +272,7 @@ namespace SRMultiplayer.Networking private static void OnFireColumnActivate(PacketFireColumnActivate packet) { - if(Globals.FireColumns.TryGetValue(packet.ID, out NetworkFireColumn netColumn)) + if (Globals.FireColumns.TryGetValue(packet.ID, out NetworkFireColumn netColumn)) { netColumn.Column.ActivateFire(); } @@ -321,9 +319,9 @@ namespace SRMultiplayer.Networking private static void OnOasis(PacketOasis packet) { - foreach(var oasisData in packet.Oasis) + foreach (var oasisData in packet.Oasis) { - if(SRSingleton.Instance.GameModel.AllOases().TryGetValue(oasisData.ID, out OasisModel model)) + if (SRSingleton.Instance.GameModel.AllOases().TryGetValue(oasisData.ID, out OasisModel model)) { model.isLive = oasisData.Model.isLive; @@ -337,30 +335,51 @@ namespace SRMultiplayer.Networking #region Exchanges private static void OnExchangeTryAccept(PacketExchangeTryAccept packet) { + //get the exchange type var type = (ExchangeDirector.OfferType)packet.Type; + //check if current scene (view) contains the item in question if (SRSingleton.Instance.ExchangeDirector.worldModel.currOffers.ContainsKey(type)) { + //handle the scene changes for the given offer var offer = SRSingleton.Instance.ExchangeDirector.worldModel.currOffers[type]; + //cycle through requested items foreach (ExchangeDirector.RequestedItemEntry requestedItemEntry in offer.requests) { + //check if the item can be accespted + //is on the board and not already completed if (requestedItemEntry.id == (Identifiable.Id)packet.ID && !requestedItemEntry.IsComplete()) { + //mark submit to log SRMP.Log($"Exchange TryAccept for {(Identifiable.Id)packet.ID} ({(ExchangeDirector.OfferType)packet.Type}", "SERVER"); + //mark progress requestedItemEntry.progress++; + + //if the given item completes the necesary quantity if (offer.IsComplete()) { - foreach(var rewarder in Resources.FindObjectsOfTypeAll()) + foreach (var rewarder in Resources.FindObjectsOfTypeAll()) { rewarder.AwardIfType(type); } - SRSingleton.Instance.ExchangeDirector.ClearOffer(type); + + //trigger fireworks + //get ExchangeEjector + foreach (var eject in Resources.FindObjectsOfTypeAll()) + { + //send off fireworks + SRBehaviour.InstantiateDynamic(eject.awardFX, eject.awardAt.position, eject.awardAt.rotation); + } + + //dont clear out the offer yet, we arent done with it + //SRSingleton.Instance.ExchangeDirector.ClearOffer(type); } + + //trigger offer status changed SRSingleton.Instance.ExchangeDirector.OfferDidChange(); } } } } - private static void OnExchangePrepareDaily(PacketExchangePrepareDaily packet) { SRSingleton.Instance.ExchangeDirector.worldModel.pendingOfferRancherIds = packet.pendingOfferRancherIds; @@ -414,7 +433,7 @@ namespace SRMultiplayer.Networking private static void OnTreasurePods(PacketTreasurePods packet) { - foreach(var pod in packet.TreasurePods) + foreach (var pod in packet.TreasurePods) { if (SRSingleton.Instance.GameModel.AllPods().TryGetValue(pod.ID, out TreasurePodModel model)) { @@ -446,7 +465,7 @@ namespace SRMultiplayer.Networking if (model.HasAttached()) { var netDrone = model.attached.transform.GetComponentInChildren(true); - if(netDrone != null) + if (netDrone != null) { netDrone.PositionRotationUpdate(packet.Position, packet.Rotation, false); } @@ -675,7 +694,7 @@ namespace SRMultiplayer.Networking extractor.nextProduceTime = packet.nextProduceTime; extractor.queuedToProduce = packet.queuedToProduce; - if(extractor.cyclesRemaining <= 0) + if (extractor.cyclesRemaining <= 0) { var extractorScript = extractor.transform.GetComponent(); if (extractorScript != null && extractorScript.gameObject.activeInHierarchy) @@ -770,7 +789,7 @@ namespace SRMultiplayer.Networking private static void OnGadgets(PacketGadgets packet) { List regions = new List(); - foreach(var gadgetData in packet.Gadgets) + foreach (var gadgetData in packet.Gadgets) { if (SRSingleton.Instance.GameModel.AllGadgetSites().TryGetValue(gadgetData.ID, out GadgetSiteModel model)) { @@ -823,7 +842,7 @@ namespace SRMultiplayer.Networking } } - foreach(var region in regions) + foreach (var region in regions) { if (Globals.Regions.TryGetValue(region, out NetworkRegion netRegion)) { @@ -881,7 +900,7 @@ namespace SRMultiplayer.Networking private static void OnPuzzleSlots(PacketPuzzleSlots packet) { - foreach(var puzzleSlotData in packet.PuzzleSlots) + foreach (var puzzleSlotData in packet.PuzzleSlots) { if (SRSingleton.Instance.GameModel.AllSlots().TryGetValue(puzzleSlotData.ID, out PuzzleSlotModel model)) { @@ -919,7 +938,7 @@ namespace SRMultiplayer.Networking private static void OnGordos(PacketGordos packet) { - foreach(var gordoData in packet.Gordos) + foreach (var gordoData in packet.Gordos) { if (SRSingleton.Instance.GameModel.AllGordos().TryGetValue(gordoData.ID, out GordoModel model)) { @@ -959,7 +978,7 @@ namespace SRMultiplayer.Networking private static void OnAccessDoors(PacketAccessDoors packet) { - foreach(var doorData in packet.Doors) + foreach (var doorData in packet.Doors) { if (SRSingleton.Instance.GameModel.AllDoors().TryGetValue(doorData.ID, out AccessDoorModel model)) { @@ -1216,7 +1235,7 @@ namespace SRMultiplayer.Networking } var phaseSiteDirector = GameObject.FindObjectOfType(); - if(phaseSiteDirector != null) + if (phaseSiteDirector != null) { phaseSiteDirector.ResetAllSites(); foreach (PhaseSite phaseSite in new List(phaseSiteDirector.availablePhaseSites)) @@ -1295,7 +1314,7 @@ namespace SRMultiplayer.Networking private static void OnLandPlotSiloAmmoAdd(PacketLandPlotSiloAmmoAdd packet) { - if(NetworkAmmo.All.TryGetValue(packet.ID, out NetworkAmmo ammo)) + if (NetworkAmmo.All.TryGetValue(packet.ID, out NetworkAmmo ammo)) { ammo.MaybeAddToSpecificSlot((Identifiable.Id)packet.Ident, null, packet.Slot, packet.Count, packet.Overflow); SRMP.Log($"NetworkAmmo add slot {packet.Slot} (Type: {(Identifiable.Id)packet.Ident} - Count: {packet.Count}) for {packet.ID}", "CLIENT"); @@ -1488,7 +1507,7 @@ namespace SRMultiplayer.Networking private static void OnLandPlots(PacketLandplots packet) { - foreach(var plotData in packet.LandPlots) + foreach (var plotData in packet.LandPlots) { if (SRSingleton.Instance.GameModel.AllLandPlots().TryGetValue(plotData.ID, out LandPlotModel model)) { @@ -1538,7 +1557,7 @@ namespace SRMultiplayer.Networking { var type = (PacketActorFX.FXType)packet.Type; var slimeEat = netActor.GetComponentInChildren(); - if(slimeEat != null) + if (slimeEat != null) { if (type == PacketActorFX.FXType.SlimeEatFavoriteFX) { @@ -1748,7 +1767,7 @@ namespace SRMultiplayer.Networking private static void OnActors(PacketActors packet) { - foreach(var actorData in packet.Actors) + foreach (var actorData in packet.Actors) { if (!Globals.Actors.ContainsKey(actorData.ID)) { @@ -1809,7 +1828,7 @@ namespace SRMultiplayer.Networking Globals.Actors.Add(netActor.ID, netActor); } - catch(Exception ex) + catch (Exception ex) { SRMP.Log($"Could not create actor {actorData.ID}: {ex}"); } @@ -1906,30 +1925,23 @@ namespace SRMultiplayer.Networking } } - private static void OnPlayerAnimationSpeed(NetIncomingMessage im) + private static void OnPlayerAnimation(PacketPlayerAnimation packet) { - byte id = im.ReadByte(); - if (Globals.Players.TryGetValue(id, out NetworkPlayer player) && player.HasLoaded) - { - player.ReadAnimatorSpeed(im); - } - } + //handle character animation triggers + PacketPlayerAnimation.AnimationType type = (PacketPlayerAnimation.AnimationType)packet.Type; - private static void OnPlayerAnimationParameters(NetIncomingMessage im) - { - byte id = im.ReadByte(); - if (Globals.Players.TryGetValue(id, out NetworkPlayer player) && player.HasLoaded) - { - player.ReadParameters(im); - } - } - private static void OnPlayerAnimationLayer(NetIncomingMessage im) - { - byte id = im.ReadByte(); - if (Globals.Players.TryGetValue(id, out NetworkPlayer player) && player.HasLoaded) + + if (Globals.Players.TryGetValue(packet.ID, out NetworkPlayer player) && player.HasLoaded) { - player.ReadAnimatorLayer(im); + if(type == PacketPlayerAnimation.AnimationType.Speed) + player.ReadAnimatorSpeed(packet.internalData); + else if (type == PacketPlayerAnimation.AnimationType.Parameters) + { + player.ReadParameters(packet.internalData); + } + else + player.ReadAnimatorLayer(packet.internalData); } } @@ -1941,57 +1953,74 @@ namespace SRMultiplayer.Networking { if (player.IsLocal) { - var euler = SRSingleton.Instance.player.GetComponentInChildren().transform.eulerAngles; - euler.x = packet.WeaponY; - SRSingleton.Instance.player.GetComponentInChildren().transform.eulerAngles = euler; - SRSingleton.Instance.player.transform.position = packet.Position; - SRSingleton.Instance.player.transform.eulerAngles = new Vector3(0, packet.Rotation, 0); - SRSingleton.Instance.PlayerState.model.SetCurrRegionSet((RegionRegistry.RegionSetId)packet.RegionSet); - - if (!Globals.IsServer) + if (packet.OnLoad) { - try + + var euler = SRSingleton.Instance.player.GetComponentInChildren().transform.eulerAngles; + euler.x = packet.WeaponY; + SRSingleton.Instance.player.GetComponentInChildren().transform.eulerAngles = euler; + SRSingleton.Instance.player.transform.position = packet.Position; + SRSingleton.Instance.player.transform.eulerAngles = new Vector3(0, packet.Rotation, 0); + SRSingleton.Instance.PlayerState.model.SetCurrRegionSet((RegionRegistry.RegionSetId)packet.RegionSet); + + + //only reload inventory if this is a load up packet and NOT a tp packet + if (!Globals.IsServer) { - using (FileStream file = new FileStream(Path.Combine(SRMP.ModDataPath, Globals.CurrentGameName + ".player"), FileMode.Open)) + try { - using (BinaryReader reader = new BinaryReader(file)) + using (FileStream file = new FileStream(Path.Combine(SRMP.ModDataPath, Globals.CurrentGameName + ".player"), FileMode.Open)) { - Debug.Log($"Loading {Path.Combine(SRMP.ModDataPath, Globals.CurrentGameName + ".player")}"); - var ammoCount = reader.ReadInt32(); - for (int i = 0; i < ammoCount; i++) + using (BinaryReader reader = new BinaryReader(file)) { - var state = (PlayerState.AmmoMode)reader.ReadByte(); - SRSingleton.Instance.PlayerState.model.ammoDict[state].usableSlots = reader.ReadInt32(); - var slotCount = reader.ReadInt32(); - SRSingleton.Instance.PlayerState.model.ammoDict[state].slots = new Ammo.Slot[slotCount]; - for (int j = 0; j < slotCount; j++) + Debug.Log($"Loading {Path.Combine(SRMP.ModDataPath, Globals.CurrentGameName + ".player")}"); + var ammoCount = reader.ReadInt32(); + for (int i = 0; i < ammoCount; i++) { - if(reader.ReadBoolean()) + var state = (PlayerState.AmmoMode)reader.ReadByte(); + SRSingleton.Instance.PlayerState.model.ammoDict[state].usableSlots = reader.ReadInt32(); + var slotCount = reader.ReadInt32(); + SRSingleton.Instance.PlayerState.model.ammoDict[state].slots = new Ammo.Slot[slotCount]; + for (int j = 0; j < slotCount; j++) { - SRSingleton.Instance.PlayerState.model.ammoDict[state].slots[j] = new Ammo.Slot((Identifiable.Id)reader.ReadUInt16(), reader.ReadInt32()); if (reader.ReadBoolean()) { - SRSingleton.Instance.PlayerState.model.ammoDict[state].slots[j].emotions = new SlimeEmotionData(); - var emotionCount = reader.ReadInt32(); - for (int k = 0; k < emotionCount; k++) + SRSingleton.Instance.PlayerState.model.ammoDict[state].slots[j] = new Ammo.Slot((Identifiable.Id)reader.ReadUInt16(), reader.ReadInt32()); + if (reader.ReadBoolean()) { - SRSingleton.Instance.PlayerState.model.ammoDict[state].slots[j].emotions.Add((SlimeEmotions.Emotion)reader.ReadUInt16(), reader.ReadSingle()); + SRSingleton.Instance.PlayerState.model.ammoDict[state].slots[j].emotions = new SlimeEmotionData(); + var emotionCount = reader.ReadInt32(); + for (int k = 0; k < emotionCount; k++) + { + SRSingleton.Instance.PlayerState.model.ammoDict[state].slots[j].emotions.Add((SlimeEmotions.Emotion)reader.ReadUInt16(), reader.ReadSingle()); + } } } - } - else - { - SRSingleton.Instance.PlayerState.model.ammoDict[state].slots[j] = null; + else + { + SRSingleton.Instance.PlayerState.model.ammoDict[state].slots[j] = null; + } } } } } } + catch (Exception ex) + { + Debug.Log($"No savefile for {Globals.CurrentGameName}: {ex.Message}"); + } } - catch (Exception ex) - { - Debug.Log($"No savefile for {Globals.CurrentGameName}: {ex.Message}"); - } + } + else + { + SRMP.Log("Player is being teleported", "CLIENT"); + + SRSingleton.Instance.player.transform.position = packet.Position; + SRSingleton.Instance.player.transform.eulerAngles = new Vector3(0, packet.Rotation, 0); + SRSingleton.Instance.PlayerState.model.SetCurrRegionSet((RegionRegistry.RegionSetId)packet.RegionSet); + + SRSingleton.Instance.PlayTeleport(); + } } else diff --git a/SRMP/Networking/NetworkHandlerServer.cs b/SRMP/Networking/Communication/NetworkHandlerServer.cs similarity index 94% rename from SRMP/Networking/NetworkHandlerServer.cs rename to SRMP/Networking/Communication/NetworkHandlerServer.cs index ee0c1d0..f84f831 100644 --- a/SRMP/Networking/NetworkHandlerServer.cs +++ b/SRMP/Networking/Communication/NetworkHandlerServer.cs @@ -2,6 +2,7 @@ using Lidgren.Network; using MonomiPark.SlimeRancher.DataModel; using MonomiPark.SlimeRancher.Regions; +using Newtonsoft.Json.Linq; using SRMultiplayer.Packets; using System; using System.Collections.Generic; @@ -19,14 +20,13 @@ namespace SRMultiplayer.Networking if (!Globals.PacketSize.ContainsKey(type)) Globals.PacketSize.Add(type, 0); Globals.PacketSize[type] += im.LengthBytes; - switch(type) + switch (type) { + //Player animation + case PacketType.PlayerAnimation: OnPlayerAnimation(new PacketPlayerAnimation(im), player); break; //Player case PacketType.PlayerLoaded: OnPlayerLoaded(new PacketPlayerLoaded(im), player); break; case PacketType.PlayerPosition: OnPlayerPosition(new PacketPlayerPosition(im), player); break; - case PacketType.PlayerAnimationLayer: OnPlayerAnimationLayer(im, player); break; - case PacketType.PlayerAnimationParameters: OnPlayerAnimationParameters(im, player); break; - case PacketType.PlayerAnimationSpeed: OnPlayerAnimationSpeed(im, player); break; case PacketType.PlayerCurrency: OnPlayerCurrency(new PacketPlayerCurrency(im), player); break; case PacketType.PlayerCurrencyDisplay: OnPlayerCurrencyDisplay(new PacketPlayerCurrencyDisplay(im), player); break; case PacketType.PlayerUpgrade: OnPlayerUpgrade(new PacketPlayerUpgrade(im), player); break; @@ -132,7 +132,7 @@ namespace SRMultiplayer.Networking case PacketType.RaceTime: OnRaceTime(new PacketRaceTime(im), player); break; case PacketType.RaceTrigger: OnRaceTrigger(new PacketRaceTrigger(im), player); break; default: - SRMP.Log($"Got unhandled packet from {player}: {type}"); + SRMP.Log($"Got unhandled packet from {player}: {type}" + Enum.GetName(typeof(PacketType), type)); break; } } @@ -140,7 +140,7 @@ namespace SRMultiplayer.Networking #region Race private static void OnRaceTrigger(PacketRaceTrigger packet, NetworkPlayer player) { - if(Globals.RaceTriggers.TryGetValue(packet.ID, out NetworkRaceTrigger trigger)) + if (Globals.RaceTriggers.TryGetValue(packet.ID, out NetworkRaceTrigger trigger)) { trigger.Activate(); } @@ -172,7 +172,7 @@ namespace SRMultiplayer.Networking var generator = QuicksilverEnergyGenerator.allGenerators.FirstOrDefault(g => g.id == packet.ID); if (generator) { - if(Globals.LocalPlayer.CurrentGenerator.id == generator.id) + if (Globals.LocalPlayer.CurrentGenerator.id == generator.id) { generator.Activate(); } @@ -242,9 +242,9 @@ namespace SRMultiplayer.Networking oasis.SetLive(!model.gameObj.activeInHierarchy); var oasisTriggers = GameObject.FindObjectsOfType(); - foreach(var trigger in oasisTriggers) + foreach (var trigger in oasisTriggers) { - if(trigger.oasisToScale == oasis && !trigger.hasAlreadyActivated) + if (trigger.oasisToScale == oasis && !trigger.hasAlreadyActivated) { if (trigger.scaleCue != null) { @@ -312,13 +312,23 @@ namespace SRMultiplayer.Networking { SRMP.Log($"Exchange TryAccept for {(Identifiable.Id)packet.ID} ({(ExchangeDirector.OfferType)packet.Type}", "SERVER"); requestedItemEntry.progress++; - if(offer.IsComplete()) + if (offer.IsComplete()) { foreach (var rewarder in Resources.FindObjectsOfTypeAll()) { rewarder.AwardIfType(type); } - SRSingleton.Instance.ExchangeDirector.ClearOffer(type); + + //trigger fireworks + //get ExchangeEjector + foreach (var eject in Resources.FindObjectsOfTypeAll()) + { + //send off fireworks + SRBehaviour.InstantiateDynamic(eject.awardFX, eject.awardAt.position, eject.awardAt.rotation); + } + + //dont clear out the offer yet, we arent done with it + //SRSingleton.Instance.ExchangeDirector.ClearOffer(type); } SRSingleton.Instance.ExchangeDirector.OfferDidChange(); } @@ -482,7 +492,7 @@ namespace SRMultiplayer.Networking { if (SRSingleton.Instance.GameModel.AllGadgetSites().TryGetValue(packet.ID, out GadgetSiteModel model)) { - if(model.HasAttached()) + if (model.HasAttached()) { model.attached.transform.GetComponent().drone.ammo.MaybeAddToSpecificSlot((Identifiable.Id)packet.Ident, null, 0, 1); } @@ -497,7 +507,7 @@ namespace SRMultiplayer.Networking if (Globals.GadgetSites.TryGetValue(packet.ID, out NetworkGadgetSite netSite)) { var echoNet = netSite.Site.GetComponentInChildren(true); - if(echoNet != null) + if (echoNet != null) { echoNet.ResetSpawnTime(echoNet.model); } @@ -510,7 +520,7 @@ namespace SRMultiplayer.Networking if (Globals.GadgetSites.TryGetValue(packet.ID, out NetworkGadgetSite netSite)) { var snare = netSite.Site.GetComponentInChildren(true); - if(snare != null) + if (snare != null) { if (!snare.IsBaited() || snare.HasSnaredGordo()) { @@ -579,7 +589,7 @@ namespace SRMultiplayer.Networking { Globals.GadgetSites.TryGetValue(packet.ID, out NetworkGadgetSite netSite); bool didUnproxy = false; - if(netSite != null) + if (netSite != null) { if (!netSite.Region.Region.root.activeSelf) { @@ -622,7 +632,7 @@ namespace SRMultiplayer.Networking foreach (var data in packet.Amounts) { SRSingleton.Instance.GameModel.GetGadgetsModel().craftMatCounts[(Identifiable.Id)data.Key] -= data.Value; - if(SRSingleton.Instance.GameModel.GetGadgetsModel().craftMatCounts[(Identifiable.Id)data.Key] < 0) + if (SRSingleton.Instance.GameModel.GetGadgetsModel().craftMatCounts[(Identifiable.Id)data.Key] < 0) { SRSingleton.Instance.GameModel.GetGadgetsModel().craftMatCounts[(Identifiable.Id)data.Key] = 0; } @@ -720,7 +730,7 @@ namespace SRMultiplayer.Networking if (attachFashions != null) { var component = SRSingleton.Instance.LookupDirector.GetPrefab((Identifiable.Id)packet.Fashion)?.GetComponent(); - if(component != null) + if (component != null) { attachFashions.Attach(component, !attachFashions.gameObject.activeInHierarchy); } @@ -821,17 +831,17 @@ namespace SRMultiplayer.Networking private static void OnWorldDecorizer(PacketWorldDecorizer packet, NetworkPlayer player) { - foreach(var c in packet.Contents) + foreach (var c in packet.Contents) { - for(int i = 0; i < c.Value; i++) + for (int i = 0; i < c.Value; i++) { SRSingleton.Instance.GameModel.decorizer.contents.Increment(c.Key); } } - foreach(var setting in packet.Settings) + foreach (var setting in packet.Settings) { var storage = SRSingleton.Instance.GameModel.decorizer.participants.FirstOrDefault(c => ((DecorizerStorage)c).id == setting.Key); - if(storage != null) + if (storage != null) { ((DecorizerStorage)storage).selected = (Identifiable.Id)setting.Value; } @@ -952,7 +962,7 @@ namespace SRMultiplayer.Networking if (SRSingleton.Instance.GameModel.AllLandPlots().TryGetValue(packet.ID, out LandPlotModel model)) { var incinerate = model.gameObj.GetComponentInChildren(); - if(incinerate != null) + if (incinerate != null) { SRBehaviour.SpawnAndPlayFX(incinerate.ExplosionFX, packet.Position, packet.Rotation); if (packet.Small) @@ -976,7 +986,7 @@ namespace SRMultiplayer.Networking private static void OnGlobalFX(PacketGlobalFX packet, NetworkPlayer player) { - if(Globals.FXPrefabs.TryGetValue(packet.Name, out GameObject prefabFX)) + if (Globals.FXPrefabs.TryGetValue(packet.Name, out GameObject prefabFX)) { SRBehaviour.SpawnAndPlayFX(prefabFX, packet.Position, Quaternion.identity); } @@ -1080,7 +1090,7 @@ namespace SRMultiplayer.Networking if (SRSingleton.Instance.GameModel.AllLandPlots().TryGetValue(packet.ID, out LandPlotModel model)) { var collector = model.gameObj.GetComponentInChildren(); - if(collector != null) + if (collector != null) { collector.StartCollection(); } @@ -1268,14 +1278,14 @@ namespace SRMultiplayer.Networking private static void OnRegionOwner(PacketRegionOwner packet, NetworkPlayer player) { - if(Globals.Regions.TryGetValue(packet.ID, out NetworkRegion netRegion)) + if (Globals.Regions.TryGetValue(packet.ID, out NetworkRegion netRegion)) { - if(packet.Owner == 0 && netRegion.Owner == player.ID) + if (packet.Owner == 0 && netRegion.Owner == player.ID) { netRegion.SetOwnership(0); packet.SendToAll(); } - else if(packet.Owner != 0 && netRegion.Owner == 0) + else if (packet.Owner != 0 && netRegion.Owner == 0) { netRegion.SetOwnership(packet.Owner); packet.SendToAll(); @@ -1338,7 +1348,7 @@ namespace SRMultiplayer.Networking var slimeFeral = netActor.GetComponentInChildren(true); if (slimeFeral != null) { - if(packet.Feral) + if (packet.Feral) { slimeFeral.MakeFeral(); } @@ -1384,7 +1394,7 @@ namespace SRMultiplayer.Networking if (Globals.Actors.TryGetValue(packet.ID, out NetworkActor netActor)) { var cycle = netActor.GetComponentInChildren(true); - if(cycle != null) + if (cycle != null) { var state = (ResourceCycle.State)packet.State; //SRMP.Log($"Resource state for {netActor.name} ({netActor.ID}): {state}", "SERVER"); @@ -1401,7 +1411,7 @@ namespace SRMultiplayer.Networking } TweenUtil.ScaleTo(cycle.gameObject, cycle.defaultScale, 4f, Ease.InOutQuad); } - else if(state == ResourceCycle.State.EDIBLE) + else if (state == ResourceCycle.State.EDIBLE) { cycle.MakeEdible(); cycle.additionalRipenessDelegate = null; @@ -1427,7 +1437,7 @@ namespace SRMultiplayer.Networking cycle.vacuumable.Pending = false; } } - else if(state == ResourceCycle.State.ROTTEN) + else if (state == ResourceCycle.State.ROTTEN) { cycle.Rot(); cycle.SetRotten(!cycle.gameObject.activeInHierarchy); @@ -1525,7 +1535,7 @@ namespace SRMultiplayer.Networking netActor.KnownPlayers.AddRange(Globals.Players.Values.Where(p => p.HasLoaded)); var resourceCycle = actorObj.GetComponentInChildren(true); - if(resourceCycle != null) + if (resourceCycle != null) { resourceCycle.SetInitState(ResourceCycle.State.UNRIPE, double.MaxValue); } @@ -1574,7 +1584,7 @@ namespace SRMultiplayer.Networking private static void OnPlayerCurrencyDisplay(PacketPlayerCurrencyDisplay packet, NetworkPlayer player) { SRSingleton.Instance.PlayerState.SetCurrencyDisplay(packet.IsNull ? null : new int?(packet.Currency)); - if(packet.IsNull) + if (packet.IsNull) { SRSingleton.Instance.CreateCoinsPopup(packet.Currency, PlayerState.CoinsType.DRONE); } @@ -1629,58 +1639,56 @@ namespace SRMultiplayer.Networking packet.SendToAllExcept(player); } - private static void OnPlayerAnimationSpeed(NetIncomingMessage im, NetworkPlayer player) + private static void OnPlayerAnimation(PacketPlayerAnimation packet, NetworkPlayer player) { if (player.HasLoaded) { - byte id = im.ReadByte(); - player.ReadAnimatorSpeed(im); + switch (packet.Type) + { + case (byte)PacketPlayerAnimation.AnimationType.Speed: + player.ReadAnimatorSpeed(packet.internalData); + break; + case (byte)PacketPlayerAnimation.AnimationType.Layer: + player.ReadAnimatorLayer(packet.internalData); + break; + case (byte)PacketPlayerAnimation.AnimationType.Parameters: + player.ReadParameters(packet.internalData); + break; + } - NetOutgoingMessage om = NetworkServer.Instance.CreateMessage(); - om.Write(im); - NetworkServer.Instance.SendToAll(om, player); - } - } - - private static void OnPlayerAnimationParameters(NetIncomingMessage im, NetworkPlayer player) - { - if (player.HasLoaded) - { - byte id = im.ReadByte(); - player.ReadParameters(im); - - NetOutgoingMessage om = NetworkServer.Instance.CreateMessage(); - om.Write(im); - NetworkServer.Instance.SendToAll(om, player); - } - } - - private static void OnPlayerAnimationLayer(NetIncomingMessage im, NetworkPlayer player) - { - if(player.HasLoaded) - { - byte id = im.ReadByte(); - player.ReadAnimatorLayer(im); - - NetOutgoingMessage om = NetworkServer.Instance.CreateMessage(); - om.Write(im); - NetworkServer.Instance.SendToAll(om, player); - } - } - - private static void OnPlayerPosition(PacketPlayerPosition packet, NetworkPlayer player) - { - if (player.HasLoaded) - { - player.PositionRotationUpdate(packet.Position, packet.Rotation, false); - player.UpdateWeaponRotation(packet.WeaponY); - player.CurrentRegionSet = (RegionRegistry.RegionSetId)packet.RegionSet; - - packet.ID = player.ID; + //make the incoming message an out going message packet.SendToAllExcept(player, NetDeliveryMethod.Unreliable); } } + private static void OnPlayerPosition(PacketPlayerPosition packet, NetworkPlayer netPlayer) + { + //get player id from packet in case of a teleport + NetworkPlayer player = Globals.Players.Values.FirstOrDefault(p => p.ID.Equals(packet.ID)); + + if (player.HasLoaded) + { + if (player.IsLocal) //if the server player is the one being moved, teleport them + { + SRSingleton.Instance.player.transform.position = packet.Position; + SRSingleton.Instance.player.transform.eulerAngles = new Vector3(0, packet.Rotation, 0); + SRSingleton.Instance.PlayerState.model.SetCurrRegionSet((RegionRegistry.RegionSetId)packet.RegionSet); + + SRSingleton.Instance.PlayTeleport(); + } + else //else process player movement + { + player.PositionRotationUpdate(packet.Position, packet.Rotation, false); + player.UpdateWeaponRotation(packet.WeaponY); + player.CurrentRegionSet = (RegionRegistry.RegionSetId)packet.RegionSet; + packet.ID = player.ID; + packet.SendToAllExcept(netPlayer, NetDeliveryMethod.Unreliable); + } + + + } + } + private static void OnPlayerLoaded(PacketPlayerLoaded packet, NetworkPlayer player) { new PacketWorldData() @@ -1707,7 +1715,7 @@ namespace SRMultiplayer.Networking Contents = SRSingleton.Instance.GameModel.decorizer.contents.ToDictionary(c => c.Key, v => v.Value), Settings = SRSingleton.Instance.GameModel.decorizer.settings.ToDictionary(s => s.Key, v => (ushort)v.Value.selected) }.Send(player, NetDeliveryMethod.ReliableOrdered); - + new PacketLandplots() { LandPlots = Globals.LandPlots.Values.Where(l => l.Plot.model != null).Select(l => new PacketLandplots.LandPlotData() { ID = l.Location.id, Model = l.Plot.model }).ToList() diff --git a/SRMP/Networking/NetworkServer.cs b/SRMP/Networking/Communication/NetworkServer.cs similarity index 99% rename from SRMP/Networking/NetworkServer.cs rename to SRMP/Networking/Communication/NetworkServer.cs index b0ffa74..fac69fa 100644 --- a/SRMP/Networking/NetworkServer.cs +++ b/SRMP/Networking/Communication/NetworkServer.cs @@ -340,6 +340,7 @@ namespace SRMultiplayer.Networking { Globals.HandlePacket = true; PacketType type = (PacketType)im.ReadUInt16(); + var player = Globals.Players.Values.FirstOrDefault(p => p.Connection != null && p.Connection.RemoteUniqueIdentifier == im.SenderConnection.RemoteUniqueIdentifier); if (player != null) { diff --git a/SRMP/Networking/NetworkActor.cs b/SRMP/Networking/NetworkActor.cs index f0a2feb..dcf6c10 100644 --- a/SRMP/Networking/NetworkActor.cs +++ b/SRMP/Networking/NetworkActor.cs @@ -1,8 +1,10 @@ -using MonomiPark.SlimeRancher.Regions; +using DG.Tweening; +using MonomiPark.SlimeRancher.Regions; using SRMultiplayer.Packets; using System; using System.Collections.Generic; using System.Linq; +using System.Net.Sockets; using System.Text; using System.Threading.Tasks; using UnityEngine; @@ -52,7 +54,7 @@ namespace SRMultiplayer.Networking private void OnEnable() { - if(Owner == 0) + if (Owner == 0) { TakeOwnership(); } @@ -68,7 +70,7 @@ namespace SRMultiplayer.Networking private void Update() { - if(IsLocal) + if (IsLocal) { m_MovementUpdateTimer -= Time.deltaTime; if (m_MovementUpdateTimer <= 0) @@ -92,7 +94,7 @@ namespace SRMultiplayer.Networking }.Send(Lidgren.Network.NetDeliveryMethod.Unreliable); } - if(SlimeEat != null && + if (SlimeEat != null && (!Utils.CloseEnoughForMe(SlimeEat.emotions.GetCurr(SlimeEmotions.Emotion.AGITATION), m_PreviousEmotions[SlimeEmotions.Emotion.AGITATION], 0.1f) || !Utils.CloseEnoughForMe(SlimeEat.emotions.GetCurr(SlimeEmotions.Emotion.FEAR), m_PreviousEmotions[SlimeEmotions.Emotion.FEAR], 0.1f) || !Utils.CloseEnoughForMe(SlimeEat.emotions.GetCurr(SlimeEmotions.Emotion.HUNGER), m_PreviousEmotions[SlimeEmotions.Emotion.HUNGER], 0.1f))) @@ -113,7 +115,7 @@ namespace SRMultiplayer.Networking } else { - if(m_Rigidbody != null) + if (m_Rigidbody != null) { m_Rigidbody.velocity = Vector3.zero; } @@ -227,7 +229,7 @@ namespace SRMultiplayer.Networking } } var destroyOnTouching = GetComponentInChildren(); - if(destroyOnTouching != null) + if (destroyOnTouching != null) { if (destroyOnTouching.destroyFX != null) { @@ -237,6 +239,7 @@ namespace SRMultiplayer.Networking var exchangeBreakOnImpact = GetComponentInChildren(); if (exchangeBreakOnImpact != null) { + SRMP.Log("Exchange Box Broke!", "ACTOR"); SRBehaviour.SpawnAndPlayFX(exchangeBreakOnImpact.breakFX, exchangeBreakOnImpact.gameObject.transform.position, exchangeBreakOnImpact.gameObject.transform.rotation); } var breakOnImpact = GetComponentInChildren(); @@ -245,7 +248,7 @@ namespace SRMultiplayer.Networking SRBehaviour.SpawnAndPlayFX(breakOnImpact.breakFX, breakOnImpact.gameObject.transform.position, breakOnImpact.gameObject.transform.rotation); } var quicksilver = GetComponentInChildren(); - if(quicksilver != null) + if (quicksilver != null) { if (quicksilver.destroyFX != null) { diff --git a/SRMP/Networking/NetworkGordo.cs b/SRMP/Networking/NetworkGordo.cs index 94685f0..9ddc3db 100644 --- a/SRMP/Networking/NetworkGordo.cs +++ b/SRMP/Networking/NetworkGordo.cs @@ -10,7 +10,7 @@ namespace SRMultiplayer.Networking { public class NetworkGordo : MonoBehaviour { - public string ID { get { return Gordo.id == null ? Gordo.GetComponentInParent(true).id : Gordo.id; } } + public string ID { get { return Gordo.id == null ? Gordo.GetComponentInParent(true).id : Gordo.id; } } public GordoEat Gordo; public NetworkRegion Region; @@ -33,36 +33,51 @@ namespace SRMultiplayer.Networking public void Burst() { + //if object is in active mark the reach target if (gameObject.activeInHierarchy) { StartCoroutine(ReachedTarget()); } else { + //if not just dismiss the gordo completely Gordo.gameObject.SetActive(false); Gordo.SetEatenCount(-1); } } + //process the gordo burst reaction private IEnumerator ReachedTarget() { + //start the burst and begin sounds and animations Gordo.WillStartBurst(); Gordo.GetComponent().SetTrigger("Strain"); SECTR_AudioSystem.Play(Gordo.strainCue, Gordo.transform.position, false); + //wait for amination/sounds to finish yield return new WaitForSeconds(2f); SECTR_AudioSystem.Play(Gordo.burstCue, Gordo.transform.position, false); + + //if the gordo has a destroy effect process it if (Gordo.destroyFX != null) { + //play the spawn behavior for destroy events for the gordo that is bursting GameObject gameObject = SRBehaviour.SpawnAndPlayFX(Gordo.destroyFX, Gordo.transform.position + Vector3.up * 2f, Gordo.transform.rotation); + //get the gordo slime type Identifiable component = Gordo.gameObject.GetComponent(); + //get the color of the current gordo Color[] colors = SlimeUtil.GetColors(Gordo.gameObject, (component != null) ? component.id : Identifiable.Id.NONE, true); + //get the slime children spawned by the gordo RecolorSlimeMaterial[] componentsInChildren = gameObject.GetComponentsInChildren(); for (int i = 0; i < componentsInChildren.Length; i++) { + //foreach slime in the count spawned by the gordo, set their coloring componentsInChildren[i].SetColors(colors[0], colors[1], colors[2]); } } + //trigger the burst completed event Gordo.DidCompleteBurst(); + + //despawn the bursted gordo from game Gordo.gameObject.SetActive(false); Gordo.SetEatenCount(-1); yield break; diff --git a/SRMP/Networking/NetworkPlayer.Animation.cs b/SRMP/Networking/NetworkPlayer.Animation.cs index 469f01a..0ea4470 100644 --- a/SRMP/Networking/NetworkPlayer.Animation.cs +++ b/SRMP/Networking/NetworkPlayer.Animation.cs @@ -1,12 +1,10 @@ using Lidgren.Network; using SRMultiplayer.Packets; -using System; using System.Collections; using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Threading.Tasks; using UnityEngine; +using static SRMultiplayer.Packets.PacketPlayerAnimation; namespace SRMultiplayer.Networking { @@ -62,33 +60,42 @@ namespace SRMultiplayer.Networking continue; } - NetOutgoingMessage writer = CreateMessage(); - writer.Write((ushort)PacketType.PlayerAnimationLayer); - writer.Write(Globals.LocalID); - WriteAnimatorLayer(writer, stateHash, normalizedTime, i, layerWeight[i]); - Send(writer); + //NetOutgoingMessage writer = CreateMessage(); + + //add the object to the writer but dont send it yet + var packet = new PacketPlayerAnimation() + { + Type = (byte)PacketPlayerAnimation.AnimationType.Layer, + ID = Globals.LocalID + }; + + //add extra parameters + WriteAnimatorLayer(packet, stateHash, normalizedTime, i, layerWeight[i]); + + //send the changes + packet.Send(); } CheckSpeed(); } - void WriteAnimatorLayer(NetOutgoingMessage writer, int stateHash, float normalizedTime, int layerNumber, float layerWeight) + void WriteAnimatorLayer(PacketPlayerAnimation writer, int stateHash, float normalizedTime, int layerNumber, float layerWeight) { - writer.Write(stateHash); - writer.Write(normalizedTime); - writer.Write(layerNumber); - writer.Write(layerWeight); + writer.Add(stateHash); + writer.Add(normalizedTime); + writer.Add(layerNumber); + writer.Add(layerWeight); WriteParameters(writer); } - public void ReadAnimatorLayer(NetIncomingMessage im) + public void ReadAnimatorLayer(Queue im) { if (m_Animator == null) return; - int stateHash = im.ReadInt32(); - float normalizedTime = im.ReadFloat(); - int layerNumber = im.ReadInt32(); - float layerWeight = im.ReadFloat(); + int stateHash = im.Dequeue().iData.Value; + float normalizedTime = im.Dequeue().fData.Value; + int layerNumber = im.Dequeue().iData.Value; + float layerWeight = im.Dequeue().fData.Value; if (stateHash != 0 && m_Animator.enabled) { @@ -106,24 +113,33 @@ namespace SRMultiplayer.Networking if (Mathf.Abs(previousSpeed - newSpeed) > 0.001f) { previousSpeed = newSpeed; - NetOutgoingMessage writer = CreateMessage(); - writer.Write((ushort)PacketType.PlayerAnimationSpeed); - writer.Write(Globals.LocalID); - WriteAnimatorSpeed(writer, newSpeed); - Send(writer); + //NetOutgoingMessage writer = CreateMessage(); + + //add the object to the writer but dont send it yet + var packet = new PacketPlayerAnimation() + { + Type = (byte)PacketPlayerAnimation.AnimationType.Speed, + ID = Globals.LocalID + }; + + //add extra parameters + WriteAnimatorSpeed(packet, newSpeed); + + //send the speed change + packet.Send(); } } - void WriteAnimatorSpeed(NetOutgoingMessage writer, float newSpeed) + void WriteAnimatorSpeed(PacketPlayerAnimation writer, float newSpeed) { - writer.Write(newSpeed); + writer.Add(newSpeed); } - public void ReadAnimatorSpeed(NetIncomingMessage im) + public void ReadAnimatorSpeed(Queue im) { if (m_Animator == null) return; - var newSpeed = im.ReadFloat(); + var newSpeed = im.Dequeue().fData.Value; // set m_Animator m_Animator.speed = newSpeed; m_AnimatorSpeed = newSpeed; @@ -179,12 +195,17 @@ namespace SRMultiplayer.Networking { nextSendTime = now + syncInterval; - NetOutgoingMessage writer = CreateMessage(); - writer.Write((ushort)PacketType.PlayerAnimationParameters); - writer.Write(Globals.LocalID); - if (WriteParameters(writer)) + //add the object to the writer but dont send it yet + var packet = new PacketPlayerAnimation() { - Send(writer); + Type = (byte)PacketPlayerAnimation.AnimationType.Parameters, + ID = Globals.LocalID + }; + + //add extra parameters + if (WriteParameters(packet)) + { + packet.Send(); } } } @@ -226,10 +247,10 @@ namespace SRMultiplayer.Networking return dirtyBits; } - bool WriteParameters(NetOutgoingMessage writer, bool forceAll = false) + bool WriteParameters(PacketPlayerAnimation writer, bool forceAll = false) { ulong dirtyBits = forceAll ? (~0ul) : NextDirtyBits(); - writer.Write(dirtyBits); + writer.Add(dirtyBits); for (int i = 0; i < parameters.Length; i++) { if ((dirtyBits & (1ul << i)) == 0) @@ -239,53 +260,55 @@ namespace SRMultiplayer.Networking if (par.type == AnimatorControllerParameterType.Int) { int newIntValue = m_Animator.GetInteger(par.nameHash); - writer.Write(newIntValue); + writer.Add(newIntValue); } else if (par.type == AnimatorControllerParameterType.Float) { float newFloatValue = m_Animator.GetFloat(par.nameHash); - writer.Write(newFloatValue); + writer.Add(newFloatValue); } else if (par.type == AnimatorControllerParameterType.Bool) { bool newBoolValue = m_Animator.GetBool(par.nameHash); - writer.Write(newBoolValue); + writer.Add(newBoolValue); } } return dirtyBits != 0; } - public void ReadParameters(NetIncomingMessage reader) - { + public void ReadParameters(Queue im) + { //make sure if (m_Animator == null) return; bool m_AnimatorEnabled = m_Animator.enabled; - // need to read values from NetworkReader even if m_Animator is disabled - ulong dirtyBits = reader.ReadUInt64(); + // need to read values from NetworkReader even if m_Animator is disabled + ulong dirtyBits = im.Dequeue().uData.Value; for (int i = 0; i < parameters.Length; i++) { if ((dirtyBits & (1ul << i)) == 0) continue; + AnimatorControllerParameter par = parameters[i]; + if (par.type == AnimatorControllerParameterType.Int) { - int newIntValue = reader.ReadInt32(); + int? newIntValue = im.Dequeue().iData; if (m_AnimatorEnabled) - m_Animator.SetInteger(par.nameHash, newIntValue); + m_Animator.SetInteger(par.nameHash, newIntValue.Value); } else if (par.type == AnimatorControllerParameterType.Float) { - float newFloatValue = reader.ReadSingle(); + float? newFloatValue = im.Dequeue().fData; if (m_AnimatorEnabled) - m_Animator.SetFloat(par.nameHash, newFloatValue); + m_Animator.SetFloat(par.nameHash, newFloatValue.Value); } else if (par.type == AnimatorControllerParameterType.Bool) { - bool newBoolValue = reader.ReadBoolean(); + bool? newBoolValue = im.Dequeue().bData; if (m_AnimatorEnabled) - m_Animator.SetBool(par.nameHash, newBoolValue); + m_Animator.SetBool(par.nameHash, newBoolValue.Value); } } } diff --git a/SRMP/Networking/NetworkPlayer.cs b/SRMP/Networking/NetworkPlayer.cs index aa4ff56..fb71921 100644 --- a/SRMP/Networking/NetworkPlayer.cs +++ b/SRMP/Networking/NetworkPlayer.cs @@ -150,6 +150,11 @@ namespace SRMultiplayer.Networking } } + public float GetWeaponLocation() + { + return m_ActualWeaponY; + } + private void OnAnimatorIK() { if(m_Animator != null && m_LeftHandTarget != null) diff --git a/SRMP/Packets/Actors/PacketPlayerAnimation.cs b/SRMP/Packets/Actors/PacketPlayerAnimation.cs new file mode 100644 index 0000000..35f18f9 --- /dev/null +++ b/SRMP/Packets/Actors/PacketPlayerAnimation.cs @@ -0,0 +1,133 @@ +using Lidgren.Network; +using MonomiPark.SlimeRancher.DataModel; +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using static SRMultiplayer.Packets.PacketAccessDoors; + +namespace SRMultiplayer.Packets +{ + [Packet(PacketType.PlayerAnimation)] + public class PacketPlayerAnimation : Packet + { + public enum AnimationType : int + { + Layer, + Speed, + Parameters + + } + + public byte ID; + public byte Type; + public struct animateData + { + public byte type + { + get + { + if (fData.HasValue) return 0; + if (bData.HasValue) return 1; + if (iData.HasValue) return 2; + if (uData.HasValue) return 3; + return 8; + } + } + public float? fData; + public bool? bData; + public int? iData; + public ulong? uData; + } + + public Queue internalData { get; set; } = new Queue(); + + public void Add(T obj) + { + switch (obj) + { + case float itm: + internalData.Enqueue(new animateData() { fData = itm }); + break; + case bool itm: + internalData.Enqueue(new animateData() { bData = itm }); + break; + case int itm: + internalData.Enqueue(new animateData() { iData = itm }); + break; + case ulong itm: + internalData.Enqueue(new animateData() { uData = itm }); + break; + } + } + + /// + /// mark construction inheritance incase we need it + /// + public PacketPlayerAnimation() : base() { } + /// + /// mark construction inheritance so the deserialization automatically happens for is + /// since the base decalres this + /// + public PacketPlayerAnimation(NetIncomingMessage im) : base(im) { } + + public override void Serialize(NetOutgoingMessage om) + { + base.Serialize(om); + + om.Write(internalData.Count); + foreach (var data in internalData) + { + om.Write(data.type); + switch (data.type) + { + case 0: + om.Write(data.fData.Value); + break; + case 1: + om.Write(data.bData.Value); + break; + case 2: + om.Write(data.iData.Value); + break; + case 3: + om.Write(data.uData.Value); + break; + } + } + } + + public override void Deserialize(NetIncomingMessage im) + { + base.Deserialize(im); + + internalData = new Queue(); + int Count = im.ReadInt32(); + for (int i = 0; i < Count; i++) + { + var data = new animateData(); + byte type = im.ReadByte(); + switch (type) + { + case 0: + data.fData = im.ReadFloat(); + break; + case 1: + data.bData = im.ReadBoolean(); + break; + case 2: + data.iData = im.ReadInt32(); + break; + case 3: + data.uData = im.ReadUInt64(); + break; + } + + internalData.Enqueue(data); + } + } + } + +} diff --git a/SRMP/Packets/Players/PacketPlayerPosition.cs b/SRMP/Packets/Players/PacketPlayerPosition.cs index 18398e4..0a4597e 100644 --- a/SRMP/Packets/Players/PacketPlayerPosition.cs +++ b/SRMP/Packets/Players/PacketPlayerPosition.cs @@ -15,6 +15,7 @@ namespace SRMultiplayer.Packets public float Rotation; public float WeaponY; public byte RegionSet; + public bool OnLoad = true; public PacketPlayerPosition() { } public PacketPlayerPosition(NetIncomingMessage im) { Deserialize(im); } diff --git a/SRMP/Packets/_Classes/IPacket.cs b/SRMP/Packets/_Classes/IPacket.cs index 6b1c3ed..3236699 100644 --- a/SRMP/Packets/_Classes/IPacket.cs +++ b/SRMP/Packets/_Classes/IPacket.cs @@ -1,4 +1,5 @@ using Lidgren.Network; +using SRMultiplayer.Networking; using System; using System.Collections.Generic; using System.Linq; @@ -9,7 +10,15 @@ namespace SRMultiplayer.Packets public interface IPacket { PacketType GetPacketType(); + /// + /// Searilizes the given packet item + /// + /// Outgoing Message that the packet should be added to void Serialize(NetOutgoingMessage om); - void Deserialize(NetIncomingMessage im); + /// + /// Deserializes the given packet item + /// + /// Incoming Message that the packet should be deserialized from + void Deserialize(NetIncomingMessage im); } } diff --git a/SRMP/Packets/_Classes/Packet.cs b/SRMP/Packets/_Classes/Packet.cs index 8b10008..9f77617 100644 --- a/SRMP/Packets/_Classes/Packet.cs +++ b/SRMP/Packets/_Classes/Packet.cs @@ -9,16 +9,42 @@ namespace SRMultiplayer.Packets { public abstract class Packet : IPacket { + /// + /// Parameterless constructor to be used through inheritance + /// + public Packet() { } + + /// + /// Incoming message based construtor that deserielizes the item for the message + /// + public Packet(NetIncomingMessage im) { Deserialize(im); } + + + /// + /// Searilizes the given packet item + /// + /// Outgoing Message that the packet should be added to + public virtual void Serialize(NetOutgoingMessage om) + { + om.Write((ushort)GetPacketType()); + //writes the object type using the gettype name + //this allows the object to assume its object packet type + //om.Write(this.GetType().AssemblyQualifiedName); + // + + om.WriteAllFields(this, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance); + } + + /// + /// Deserializes the given packet item + /// + /// Incoming Message that the packet should be deserialized from public virtual void Deserialize(NetIncomingMessage im) { im.ReadAllFields(this, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance); } - public virtual void Serialize(NetOutgoingMessage om) - { - om.Write((ushort)GetPacketType()); - om.WriteAllFields(this, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance); - } + public PacketType GetPacketType() { diff --git a/SRMP/Packets/_Classes/PacketType.cs b/SRMP/Packets/_Classes/PacketType.cs index a6ca38d..1f22782 100644 --- a/SRMP/Packets/_Classes/PacketType.cs +++ b/SRMP/Packets/_Classes/PacketType.cs @@ -7,9 +7,7 @@ PlayerLeft, PlayerPosition, PlayerLoaded, - PlayerAnimationLayer, - PlayerAnimationSpeed, - PlayerAnimationParameters, + PlayerAnimation, PlayerFX, PlayAudio, ActorSpawn, @@ -97,6 +95,7 @@ ExchangeTryAccept, ExchangeClear, ExchangeOffers, + ExchangeBreak, GordoEat, Oasis, OasisLive, diff --git a/SRMP/Patches/Patch_ExchangeBreakOnImpact.cs b/SRMP/Patches/Patch_ExchangeBreakOnImpact.cs index 219a384..1e29af0 100644 --- a/SRMP/Patches/Patch_ExchangeBreakOnImpact.cs +++ b/SRMP/Patches/Patch_ExchangeBreakOnImpact.cs @@ -1,9 +1,13 @@ using HarmonyLib; +using MonomiPark.SlimeRancher.Regions; using SRMultiplayer.Networking; +using SRMultiplayer.Packets; using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.InteropServices.WindowsRuntime; using System.Text; +using UnityEngine; namespace SRMultiplayer.Patches { @@ -11,11 +15,19 @@ namespace SRMultiplayer.Patches [HarmonyPatch("BreakOpen")] class ExchangeBreakOnImpact_BreakOpen { + static bool Prefix(ExchangeBreakOnImpact __instance) { - if (!Globals.IsMultiplayer) return true; + //if multiplayer, only the server can trigger the impact + if (!Globals.IsMultiplayer) return true; + + var entity = __instance.GetComponent(); + + SRMP.Log("Exchange Box Break: " + (entity != null && entity.IsLocal), "EXCHANGE"); + + //if the box exists and the entity is local process the break return (entity != null && entity.IsLocal); } } diff --git a/SRMP/Patches/Patch_Identifiable.cs b/SRMP/Patches/Patch_Identifiable.cs index d9bcd3c..ba109e3 100644 --- a/SRMP/Patches/Patch_Identifiable.cs +++ b/SRMP/Patches/Patch_Identifiable.cs @@ -22,7 +22,18 @@ namespace SRMultiplayer.Patches { if (Globals.Actors.ContainsKey(netActor.ID)) { + //check if this is an exchange box + var exchangeBreakOnImpact = netActor.GetComponentInChildren(); + if (exchangeBreakOnImpact != null) + { + //exchange box was found processing it with the ondestroy command instead of just removing it! + //netActor.OnDestroyEffect(); + //Destroyer.DestroyActor(netActor.gameObject, "NetworkHandlerServer.OnActorDestroy"); + } + + //make sure the actor still gets cleaned up Globals.Actors.Remove(netActor.ID); + new PacketActorDestroy() { ID = netActor.ID diff --git a/SRMP/Patches/Patch_PauseMenu.cs b/SRMP/Patches/Patch_PauseMenu.cs index 2003929..d34d87b 100644 --- a/SRMP/Patches/Patch_PauseMenu.cs +++ b/SRMP/Patches/Patch_PauseMenu.cs @@ -17,7 +17,9 @@ namespace SRMultiplayer.Patches { if (!Globals.IsMultiplayer) return; + //only handle the client if the client is the one disconnecting NetworkClient.Instance.Disconnect(); + //if server ahndle the shutdown NetworkServer.Instance.Disconnect(); } } diff --git a/SRMP/PauseState.cs b/SRMP/PauseState.cs deleted file mode 100644 index 416e527..0000000 --- a/SRMP/PauseState.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace SRMultiplayer -{ - public enum PauseState - { - Pause, - Playing - } -} diff --git a/SRMP/Properties/AssemblyInfo.cs b/SRMP/Properties/AssemblyInfo.cs index 4800f7c..00d781b 100644 --- a/SRMP/Properties/AssemblyInfo.cs +++ b/SRMP/Properties/AssemblyInfo.cs @@ -15,7 +15,7 @@ using System.Resources; [assembly: AssemblyCulture("")] // Version informationr( -[assembly: AssemblyVersion("0.0.0.1488")] -[assembly: AssemblyFileVersion("0.0.0.1488")] +[assembly: AssemblyVersion("0.0.0.1510")] +[assembly: AssemblyFileVersion("0.0.0.1510")] [assembly: NeutralResourcesLanguageAttribute( "en-US" )] diff --git a/SRMP/SRMP.cs b/SRMP/SRMP.cs index b474b26..7cb7b5c 100644 --- a/SRMP/SRMP.cs +++ b/SRMP/SRMP.cs @@ -20,26 +20,41 @@ namespace SRMultiplayer private float m_LastTimeSync; + /// + /// Acts as the initializer for the Mod + /// public override void Awake() { base.Awake(); + //attach scene manager to trigger event when in a menu or loading up a game SceneManager.activeSceneChanged += SceneManager_activeSceneChanged; + //attach log messager to log all game errors and exceptions into the SRMP Logs Application.logMessageReceived += Application_logMessageReceived; + //load up mod specific resources var myLoadedAssetBundle = AssetBundle.LoadFromMemory(Utils.ExtractResource("SRMultiplayer.srmultiplayer.dat")); if (myLoadedAssetBundle == null) { SRMP.Log("Failed to load AssetBundle!"); return; } + //load up the Player moment animator for the Beatrix model Globals.BeatrixController = myLoadedAssetBundle.LoadAsset("Controller"); - Globals.IngameMultiplayerMenuPrefab = myLoadedAssetBundle.LoadAsset("IngameMultiplayerMenu"); - Globals.MainMultiplayerMenuPrefab = myLoadedAssetBundle.LoadAsset("MainMultiplayerMenu"); - } + //unused prefab menus, these menus functions are handled in the floating gui + //Globals.IngameMultiplayerMenuPrefab = myLoadedAssetBundle.LoadAsset("IngameMultiplayerMenu"); + //Globals.MainMultiplayerMenuPrefab = myLoadedAssetBundle.LoadAsset("MainMultiplayerMenu"); + } + /// + /// Subscriber to the Applicaiton log and process it on to the Mods console + /// + /// Log condition + /// Stack trace of log strigger (if applicable) + /// Log Type private void Application_logMessageReceived(string condition, string stackTrace, LogType type) { + //if Error or Exception hand the error of to the Mods log/console to display if(type == LogType.Error || type == LogType.Exception) { SRMP.Log(condition); @@ -54,6 +69,10 @@ namespace SRMultiplayer //menuObj.AddComponent(); } + /// + /// After triggering base destroy + /// trigger disconnect and shut down the server + /// public override void OnDestroy() { base.OnDestroy(); @@ -62,18 +81,25 @@ namespace SRMultiplayer NetworkServer.Instance.Disconnect(); } + /// + /// On Game quit trigger disconnect and shut down the server + /// private void OnApplicationQuit() { NetworkClient.Instance.Disconnect(); NetworkServer.Instance.Disconnect(); } + /// + /// On Update triggered sync up game time + /// private void Update() { if(Globals.GameLoaded) { if(Globals.IsServer) { + //every 30 seconds send a time updater out to all clients if(Time.time - m_LastTimeSync > 30) { m_LastTimeSync = Time.time; @@ -98,17 +124,28 @@ namespace SRMultiplayer } } + /// + /// Handle scene changed events triggered by the game + /// + /// Scene previously + /// New Scene private void SceneManager_activeSceneChanged(Scene from, Scene to) { + //trigger handlers for returning or going to the main menu if (to.buildIndex == 2) OnMainMenuLoaded(); - if (to.buildIndex == 3) OnGameLoaded(); + //trigger handlers for loading the game + else if (to.buildIndex == 3) OnGameLoaded(); } + /// + /// Handle user changing to the main menu, whether it is start up or from saving/ being kicked out of the game + /// private void OnMainMenuLoaded() { //var menuObj = Instantiate(Globals.MainMultiplayerMenuPrefab, null, false); //menuObj.AddComponent(); + //innitialize all necessary global variables Globals.LocalID = 0; Globals.DisableAchievements = false; Globals.GameLoaded = false; @@ -135,6 +172,8 @@ namespace SRMultiplayer Globals.Nutcrackers.Clear(); Globals.RaceTriggers.Clear(); NetworkAmmo.All.Clear(); + + //clean up any lingering players in the global list foreach (var player in Globals.Players.Values.ToList()) { if(player != null && player.gameObject != null) @@ -144,9 +183,14 @@ namespace SRMultiplayer } Globals.Players.Clear(); + + //reset the chat ChatUI.Instance.Clear(); } + /// + /// Handle the user loading into the multiplayer game + /// private void OnGameLoaded() { System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch(); @@ -365,6 +409,12 @@ namespace SRMultiplayer private static FileStream m_LogFileStream; private static StreamWriter m_LogWriter; + /// + /// Custom message logging of a given message + /// + /// Main message to be logged + /// Prefix to be displayed before the message. Prefix will be after time marker and before the message + /// It will also be incapsulated in [] public static void Log(string msg, string prefix = null) { if(m_LogFileStream == null) diff --git a/SRMP/SRMP.csproj b/SRMP/SRMP.csproj index d8f208f..677c9da 100644 --- a/SRMP/SRMP.csproj +++ b/SRMP/SRMP.csproj @@ -9,14 +9,14 @@ Properties SRMultiplayer SRMP - v4.5 + v4.7.2 512 true true - full + portable false ..\Builds\SRMP\ __CONSTRAINED__;Standalone @@ -74,24 +74,25 @@ - C:\Program Files (x86)\Steam\steamapps\common\Slime Rancher\SlimeRancher_Data\Managed\0Harmony.dll + .\0Harmony.dll + False ..\Libs\Assembly-CSharp_publicized.dll + False - C:\Program Files (x86)\Steam\steamapps\common\Slime Rancher\SlimeRancher_Data\Managed\DOTween.dll + .\DOTween.dll + False - C:\Program Files (x86)\Steam\steamapps\common\Slime Rancher\SlimeRancher_Data\Managed\InControl.dll + .\InControl.dll + False - + False - C:\Program Files (x86)\Steam\steamapps\common\Slime Rancher\SlimeRancher_Data\Managed\Newtonsoft.Json.dll - - - False - ..\Libs\SRML.dll + ..\Libs\Newtonsoft.Json.dll + False @@ -103,54 +104,73 @@ - C:\Program Files (x86)\Steam\steamapps\common\Slime Rancher\SlimeRancher_Data\Managed\Unity.TextMeshPro.dll + .\Unity.TextMeshPro.dll + False False - C:\Program Files (x86)\Steam\steamapps\common\Slime Rancher\SlimeRancher_Data\Managed\UnityCoreMod.dll + .\UnityCoreMod.dll + False - C:\Program Files (x86)\Steam\steamapps\common\Slime Rancher\SlimeRancher_Data\Managed\UnityEngine.dll + .\UnityEngine.dll + False - C:\Program Files (x86)\Steam\steamapps\common\Slime Rancher\SlimeRancher_Data\Managed\UnityEngine.AnimationModule.dll + .\UnityEngine.AnimationModule.dll + False - C:\Program Files (x86)\Steam\steamapps\common\Slime Rancher\SlimeRancher_Data\Managed\UnityEngine.AssetBundleModule.dll + .\UnityEngine.AssetBundleModule.dll + False - C:\Program Files (x86)\Steam\steamapps\common\Slime Rancher\SlimeRancher_Data\Managed\UnityEngine.CoreModule.dll + .\UnityEngine.CoreModule.dll + False - C:\Program Files (x86)\Steam\steamapps\common\Slime Rancher\SlimeRancher_Data\Managed\UnityEngine.IMGUIModule.dll + .\UnityEngine.IMGUIModule.dll + False - C:\Program Files (x86)\Steam\steamapps\common\Slime Rancher\SlimeRancher_Data\Managed\UnityEngine.InputLegacyModule.dll + .\UnityEngine.InputLegacyModule.dll + False + + + .\UnityEngine.InputModule.dll + + + .\UnityEngine.JSONSerializeModule.dll - C:\Program Files (x86)\Steam\steamapps\common\Slime Rancher\SlimeRancher_Data\Managed\UnityEngine.PhysicsModule.dll + .\UnityEngine.PhysicsModule.dll + False False - C:\Program Files (x86)\Steam\steamapps\common\Slime Rancher\SlimeRancher_Data\Managed\UnityEngine.TextCoreModule.dll + .\UnityEngine.TextCoreModule.dll + False False - C:\Program Files (x86)\Steam\steamapps\common\Slime Rancher\SlimeRancher_Data\Managed\UnityEngine.TextRenderingModule.dll + .\UnityEngine.TextRenderingModule.dll + False - C:\Program Files (x86)\Steam\steamapps\common\Slime Rancher\SlimeRancher_Data\Managed\UnityEngine.UI.dll + .\UnityEngine.UI.dll + False - C:\Program Files (x86)\Steam\steamapps\common\Slime Rancher\SlimeRancher_Data\Managed\UnityEngine.UIModule.dll + .\UnityEngine.UIModule.dll + False - - - + + + @@ -228,11 +248,13 @@ - + + + + - @@ -241,8 +263,6 @@ - - @@ -256,11 +276,11 @@ - + @@ -462,19 +482,20 @@ - True True AssemblyInfo.tt - - - - + + + + + + TextTemplatingFileGenerator modinfo.json @@ -487,6 +508,11 @@ + + + ..\Libs\SRML.dll + + True diff --git a/SRMP/SRMPConsole.cs b/SRMP/SRMPConsole.cs deleted file mode 100644 index ea5d6d1..0000000 --- a/SRMP/SRMPConsole.cs +++ /dev/null @@ -1,238 +0,0 @@ -using MonomiPark.SlimeRancher.Regions; -using SRMultiplayer.Networking; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using UnityEngine; - -namespace SRMultiplayer -{ - public class SRMPConsole : MonoBehaviour - { - ConsoleWindow console = new ConsoleWindow(); - ConsoleInput input = new ConsoleInput(); - - // - // Create console window, register callbacks - // - void Awake() - { - DontDestroyOnLoad(gameObject); - - console.Initialize(); - console.SetTitle("Slime Rancher"); - - input.OnInputText += OnInputText; - - Application.logMessageReceived += Application_logMessageReceived; - - SRMP.Log("Console Started"); - } - - private void Application_logMessageReceived(string condition, string stackTrace, LogType type) - { - if (type == LogType.Warning) - Console.ForegroundColor = ConsoleColor.Yellow; - else if (type == LogType.Error) - Console.ForegroundColor = ConsoleColor.Red; - else - Console.ForegroundColor = ConsoleColor.White; - - // We're half way through typing something, so clear this line .. - if (Console.CursorLeft != 0) - input.ClearLine(); - - Console.WriteLine(condition); - if (!string.IsNullOrEmpty(stackTrace)) - Console.WriteLine(stackTrace); - - // If we were typing something re-add it. - input.RedrawInputLine(); - } - - // - // Text has been entered into the console - // Run it as a console command - // - void OnInputText(string obj) - { - var args = obj.Split(' '); - var cmd = args.FirstOrDefault(); - args = args.Skip(1).ToArray(); - - switch (cmd.ToLower()) - { - case "cheat": - { - if (args.Length > 0) - { - if (args[0].Equals("money")) - { - if (args.Length != 2 || !int.TryParse(args[1], out int money)) - { - SRMP.Log("Usage: cheat money "); - } - else - { - if(money > 0) - SRSingleton.Instance.PlayerState.AddCurrency(money); - else - SRSingleton.Instance.PlayerState.SpendCurrency(money); - } - } - else if(args[0].Equals("enable")) - { - //TestUI.Instance.cheat = !TestUI.Instance.cheat; - } - else if (args[0].Equals("keys")) - { - if (args.Length != 2 || !int.TryParse(args[1], out int value)) - { - SRMP.Log("Usage: cheat keys "); - } - else - { - SRSingleton.Instance.PlayerState.model.keys = value; - } - } - else if (args[0].Equals("allgadgets")) - { - foreach (var data in (Gadget.Id[])Enum.GetValues(typeof(Gadget.Id))) - { - SRSingleton.Instance.GadgetDirector.model.gadgets[data] = int.MaxValue; - } - foreach (var data in Identifiable.CRAFT_CLASS.Union(Identifiable.PLORT_CLASS)) - { - SRSingleton.Instance.GadgetDirector.model.craftMatCounts[data] = int.MaxValue; - } - } - else if (args[0].Equals("spawn")) - { - if (args.Length == 2) - { - if (Enum.TryParse(args[1].ToUpper(), out Identifiable.Id id)) - { - GameObject prefab = SRSingleton.Instance.LookupDirector.GetPrefab(id); - if (prefab != null) - { - SRBehaviour.InstantiateActor(prefab, SRSingleton.Instance.GameModel.player.currRegionSetId, SRSingleton.Instance.GameModel.player.GetPos() + new Vector3(0, 4, 0), Quaternion.identity, false); - } - else - { - SRMP.Log(id + " can not be spawned"); - } - } - else - { - var data = Enum.GetNames(typeof(Identifiable.Id)).Where(n => n.ToLower().Contains(args[1].ToLower())); - SRMP.Log(args[1] + " not found. " + (data.Count() > 0 ? " Did you mean one of these?" : "")); - foreach (var name in data) - { - SRMP.Log(name); - } - } - } - else if (args.Length == 3 && int.TryParse(args[2], out int amount)) - { - if (Enum.TryParse(args[1].ToUpper(), out Identifiable.Id id)) - { - GameObject prefab = SRSingleton.Instance.LookupDirector.GetPrefab(id); - if (prefab != null) - { - for (int i = 0; i < amount; i++) - { - SRBehaviour.InstantiateActor(prefab, SRSingleton.Instance.GameModel.player.currRegionSetId, SRSingleton.Instance.GameModel.player.GetPos() + new Vector3(0, 4, 0), Quaternion.identity, false); - } - } - else - { - SRMP.Log(id + " can not be spawned"); - } - } - else - { - var data = Enum.GetNames(typeof(Identifiable.Id)).Where(n => n.ToLower().Contains(args[1].ToLower())); - SRMP.Log(args[1] + " not found. " + (data.Count() > 0 ? " Did you mean one of these?" : "")); - foreach (var name in data) - { - SRMP.Log(name); - } - } - } - else - { - SRMP.Log("Usage: cheat spawn ()"); - } - } - } - else - { - SRMP.Log("Available sub commands:"); - SRMP.Log("cheat money "); - SRMP.Log("cheat keys "); - SRMP.Log("cheat spawn ()"); - SRMP.Log("cheat allgadgets"); - } - } - break; - case "tp": - { - if (args.Length == 1) - { - var player = Globals.Players.Values.FirstOrDefault(p => p.Username.Equals(args[0], StringComparison.CurrentCultureIgnoreCase)); - if (player != null) - { - SRSingleton.Instance.player.transform.position = player.transform.position; - } - else - { - SRMP.Log("Player not found"); - } - } - else - { - SRMP.Log("Usage: tp "); - } - } - break; - case "listplayers": - { - SRMP.Log("Players:"); - foreach (var player in Globals.Players.Values) - { - SRMP.Log(player.Username); - } - } - break; - case "sleep": - { - if (args.Length == 1) - { - SRSingleton.Instance.TimeDirector.FastForwardTo(SRSingleton.Instance.TimeDirector.HoursFromNow(float.Parse(args[0]))); - } - } - break; - } - } - - // - // Update the input every frame - // This gets new key input and calls the OnInputText callback - // - void Update() - { - input.Update(); - } - - // - // It's important to call console.ShutDown in OnDestroy - // because compiling will error out in the editor if you don't - // because we redirected output. This sets it back to normal. - // - void OnDestroy() - { - console.Shutdown(); - } - } -} \ No newline at end of file diff --git a/SRMP/UserData.cs b/SRMP/UserData.cs deleted file mode 100644 index c4f8959..0000000 --- a/SRMP/UserData.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace SRMultiplayer -{ - [Serializable] - public struct UserData - { - public Guid UUID; - public bool CheckDLC; - public List IgnoredMods; - } -} diff --git a/SRMP/Compression.cs b/SRMP/Utils/Compression.cs similarity index 100% rename from SRMP/Compression.cs rename to SRMP/Utils/Compression.cs diff --git a/SRMP/Extensions.cs b/SRMP/Utils/Extensions.cs similarity index 96% rename from SRMP/Extensions.cs rename to SRMP/Utils/Extensions.cs index 0dce3e1..b67946f 100644 --- a/SRMP/Extensions.cs +++ b/SRMP/Utils/Extensions.cs @@ -10,6 +10,10 @@ using UnityEngine; namespace SRMultiplayer { + /// + /// Extends multiple objects to add extras functionality + /// + /// public static class Extensions { public static void Rebuild(this RefineryUI ui) @@ -40,6 +44,7 @@ namespace SRMultiplayer } } + #region Ammo Slot Extensions public static void WriteAmmoSlot(this NetOutgoingMessage om, Ammo.Slot slot) { om.Write(slot != null); @@ -78,7 +83,9 @@ namespace SRMultiplayer } return null; } + #endregion + #region Packet Handling Extensions public static void Send(this Packet packet, NetDeliveryMethod method = NetDeliveryMethod.ReliableOrdered, int sequence = 0) { if(!Globals.IsClient) @@ -160,6 +167,10 @@ namespace SRMultiplayer NetworkServer.Instance.SendTo(packet, cons, method, sequence); } + #endregion + + #region Component Handling Extensions + public static T CopyComponent(this T original, GameObject destination) where T : Component { System.Type type = original.GetType(); @@ -245,5 +256,6 @@ namespace SRMultiplayer } return null; } + #endregion } } diff --git a/SRMP/Utils/Objects.cs b/SRMP/Utils/Objects.cs new file mode 100644 index 0000000..3c32ef3 --- /dev/null +++ b/SRMP/Utils/Objects.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SRMultiplayer +{ + /// + /// Used marking the game time movement status + /// + public enum PauseState + { + Pause, + Playing + } + + /// + /// Handles basic user data to be used for connection communication + /// Uesr ID, mod count and dlc checkers + /// + [Serializable] + public struct UserData + { + public Guid UUID; + public bool CheckDLC; + public List IgnoredMods; + } +} diff --git a/SRMP/Utils.cs b/SRMP/Utils/Utils.cs similarity index 81% rename from SRMP/Utils.cs rename to SRMP/Utils/Utils.cs index dc4f061..27d17ba 100644 --- a/SRMP/Utils.cs +++ b/SRMP/Utils/Utils.cs @@ -11,6 +11,11 @@ namespace SRMultiplayer { public static class Utils { + /// + /// Loads up any resources embedded in the mod + /// + /// Name of resource + /// Contents of resource public static byte[] ExtractResource(String filename) { System.Reflection.Assembly a = System.Reflection.Assembly.GetExecutingAssembly(); @@ -22,7 +27,9 @@ namespace SRMultiplayer return ba; } } - + /// + /// Sets what layer the given item is at + /// public static void SetLayer(GameObject obj, int layer) { obj.layer = layer; @@ -31,18 +38,27 @@ namespace SRMultiplayer SetLayer(child.gameObject, layer); } } - + /// + /// Check to see if the provided values are close enough to be the same + /// public static bool CloseEnoughForMe(double value1, double value2, double acceptableDifference) { return Math.Abs(value1 - value2) <= acceptableDifference; } - + /// + /// Check to see if the provided values are close enough to be the same + /// public static bool CloseEnoughForMe(float value1, float value2, float acceptableDifference) { return Mathf.Abs(value1 - value2) <= acceptableDifference; } private static System.Random m_Random = new System.Random(); + + /// + /// Gets a new random actor id for netowork actors + /// + /// Random integer between in Min and int max that is not in the current sessions of NetworkActors public static int GetRandomActorID() { int id = m_Random.Next(int.MinValue, int.MaxValue); @@ -55,6 +71,11 @@ namespace SRMultiplayer static readonly string[] SizeSuffixes = { "bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" }; const long byteConversion = 1000; + /// + /// Takes a count of bytes and turns it into a human readable version + /// + /// Count of Bytes as a long + /// String statement of the bytes public static string GetHumanReadableFileSize(long value) { diff --git a/SRMP/modinfo.json b/SRMP/modinfo.json index b836b8c..4ff9176 100644 --- a/SRMP/modinfo.json +++ b/SRMP/modinfo.json @@ -1,11 +1,9 @@ - { "id": "srmp", "name": "Slime Rancher Multiplayer", - "version": "0.0.1488", + "version": "0.0.1510", "author": "SatyPardus", "dependencies": [ ] -} - +}