Exemplo n.º 1
0
        public void sendAvailableFarmhands(string userID, Action <OutgoingMessage> sendMessage)
        {
            List <NetRef <Farmer> > availableFarmhands = new List <NetRef <Farmer> >();

            Game1.getFarm();
            foreach (Cabin cabin in cabins())
            {
                NetRef <Farmer> farmhand2 = cabin.getFarmhand();
                if ((!farmhand2.Value.isActive() || Game1.multiplayer.isDisconnecting(farmhand2.Value.UniqueMultiplayerID)) && !cabin.isInventoryOpen())
                {
                    availableFarmhands.Add(farmhand2);
                }
            }
            using MemoryStream stream = new MemoryStream();
            using BinaryWriter writer = new BinaryWriter(stream);
            writer.Write(Game1.year);
            writer.Write(Utility.getSeasonNumber(Game1.currentSeason));
            writer.Write(Game1.dayOfMonth);
            writer.Write((byte)availableFarmhands.Count);
            foreach (NetRef <Farmer> farmhand in availableFarmhands)
            {
                try
                {
                    farmhand.Serializer = SaveGame.farmerSerializer;
                    farmhand.WriteFull(writer);
                }
                finally
                {
                    farmhand.Serializer = null;
                }
            }
            stream.Seek(0L, SeekOrigin.Begin);
            sendMessage(new OutgoingMessage(9, Game1.player, stream.ToArray()));
        }
Exemplo n.º 2
0
        public void drawItem(NetRef <Item> i, float x, float y, SpriteBatch spriteBatch, float layerDepth)
        {
            if (i.Value != null)
            {
                //this.monitor.Log($"draw [ {i.Get().Name}, {x}, {y} LD: {layerDepth}]");
                switch (this.displayType.Value)
                {
                case 1:
                    i.Value.drawInMenu(spriteBatch, Game1.GlobalToLocal(Game1.viewport, new Vector2(x + 2f, (float)(y + 8 - 1))), 0.75f, 0.45f, layerDepth, false, Color.Black, false);
                    i.Value.drawInMenu(spriteBatch, Game1.GlobalToLocal(Game1.viewport, new Vector2(x + 2f, (float)(y + 4 - 1))), 0.75f, 1f, layerDepth + 1E-05f, false, Color.White, false);
                    break;

                case 3:
                    i.Value.drawInMenu(spriteBatch, Game1.GlobalToLocal(Game1.viewport, new Vector2(x, (float)(y + 4 - 1))), 0.75f, 1f, layerDepth, false, Color.White, false);
                    break;

                case 2:
                    i.Value.drawInMenu(spriteBatch, Game1.GlobalToLocal(Game1.viewport, new Vector2(x + 6f, (float)(y + 16 - 1))), 0.75f, 0.45f, layerDepth, false, Color.Black, false);
                    i.Value.drawInMenu(spriteBatch, Game1.GlobalToLocal(Game1.viewport, new Vector2(x + 6f, (float)(y + 12 - 1))), 0.75f, 1f, layerDepth + 1E-05f, false, Color.White, false);
                    break;

                case 4:
                    i.Value.drawInMenu(spriteBatch, Game1.GlobalToLocal(Game1.viewport, new Vector2(x - 1f, (float)(y + 8 - 1))), 0.75f, 0.45f, layerDepth, false, Color.Black, false);
                    i.Value.drawInMenu(spriteBatch, Game1.GlobalToLocal(Game1.viewport, new Vector2(x - 1f, (float)(y + 4 - 1))), 0.75f, 1f, layerDepth + 1E-05f, false, Color.White, false);
                    break;

                case 5:
                    i.Value.drawInMenu(spriteBatch, Game1.GlobalToLocal(Game1.viewport, new Vector2(x, (float)(y + 8 - 1))), 0.75f, 0.45f, layerDepth, false, Color.Black, false);
                    i.Value.drawInMenu(spriteBatch, Game1.GlobalToLocal(Game1.viewport, new Vector2(x, (float)(y + 4 - 1))), 0.75f, 1f, layerDepth + 1E-05f, false, Color.White, false);
                    break;
                }
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Sets up listeners on NetRef values for when a waterable item changes
        /// </summary>
        /// <param name="tilledDirt">Tilled dirt plot to listen for changes to</param>
        /// <param name="indoorPot">Garden pot to listen for changes to</param>
        private void SetupWaterableLocationListener(HoeDirt tilledDirt, IndoorPot indoorPot = null)
        {
            try
            {
                NetRef <Crop> netRefCrop = Helper.Reflection.GetField <NetRef <Crop> >(tilledDirt, "netCrop", true).GetValue();

                if (netRefCrop.Value != null)
                {
                    TrackAndWater(tilledDirt, indoorPot);
                }

                netRefCrop.fieldChangeVisibleEvent += (_, __, crop) =>
                {
                    if (crop != null)
                    {
                        TrackAndWater(tilledDirt, indoorPot);
                    }
                    else
                    {
                        RemoveTrack(tilledDirt, indoorPot);
                    }
                };
            }
            catch (Exception ex)
            {
                Monitor.Log($"Could not read crop data on dirt; possible new game version?\n{ex}", LogLevel.Error);
            }
        }
Exemplo n.º 4
0
 public void OnDepositedItemChange(NetRef <Object> field, Object old_value, Object new_value)
 {
     if (Game1.gameMode != 6 && new_value != null)
     {
         shakeTimer       = 1000;
         _isAnimatingChip = true;
     }
 }
Exemplo n.º 5
0
 public ItemFrame(ItemFrameData itemFrameData, Vector2 tile, IMonitor monitor, Item dispItem = null) : base(itemFrameData.id, tile)
 {
     this.monitor = monitor;
     if (dispItem != null)
     {
         this.displayItem = new NetRef <Item>(dispItem.getOne());
         this.setDisplayType();
     }
     this.setDataFromJson();
 }
Exemplo n.º 6
0
 private void hookField(int index, NetRef <TValue> field)
 {
     if (field == default)
     {
         return;
     }
     field.fieldChangeVisibleEvent += (f, oldValue, newValue) =>
     {
         this.OnElementChanged(this.Field, index, oldValue, newValue);
     };
 }
Exemplo n.º 7
0
        internal static NetRef <Farmer> getNewFarmHand()
        {
            NetRef <Farmer> farmhand = new NetRef <Farmer>();

            farmhand.Value = new Farmer(new FarmerSprite((string)null), new Vector2(0.0f, 0.0f), 1, "", Farmer.initialTools(), true);
            farmhand.Value.UniqueMultiplayerID = Utility.RandomLong(rnd);
            farmhand.Value.questLog.Add((Quest)(Quest.getQuestFromId(9) as SocializeQuest));
            farmhand.Value.farmName.Value     = Game1.MasterPlayer.farmName.Value;
            farmhand.Value.homeLocation.Value = "FarmHouse";
            farmhand.Value.currentLocation    = Game1.getLocationFromName("FarmHouse");
            farmhand.Value.Position           = new Vector2(640f, 320f);
            return(farmhand);
        }
Exemplo n.º 8
0
        /// <summary>
        /// Checks to see if the Farmer is wearing the Leprechaun boots
        /// </summary>
        /// <returns></returns>
        public static bool IsWearingLeprechaunBoots()
        {
            NetRef <Boots> currentBootsRef = Game1.player.boots;

            // If the Farmer has no boots on, or they aren't the Leprechaun Boots their luck isn't increased
            if (currentBootsRef == null || currentBootsRef.Value == null || currentBootsRef.Value.indexInTileSheet.Value != 806)
            {
                return(false);
            }
            else
            {
                return(true);
            }
        }
Exemplo n.º 9
0
        private void TemporarilyFakeInteraction(Action action)
        {
            // get references
            // (Note: change net values directly to avoid sync bugs, since the value will be reset when we're done.)
            Farmer                    player             = Game1.player;
            NetRef <Horse>            mountField         = this.Reflection.GetField <NetRef <Horse> >(Game1.player, "netMount").GetValue();
            IReflectedField <Horse>   mountFieldValue    = this.Reflection.GetField <Horse>(mountField, "value");
            IReflectedField <Vector2> mountPositionValue = this.Reflection.GetField <Vector2>(player.mount.position.Field, "value");

            // save current state
            Horse       mount            = mountField.Value;
            Vector2     mountPosition    = mount.Position;
            WateringCan wateringCan      = player.CurrentTool as WateringCan;
            int         waterInCan       = wateringCan?.WaterLeft ?? 0;
            float       stamina          = player.stamina;
            Vector2     position         = player.Position;
            int         facingDirection  = player.FacingDirection;
            int         currentToolIndex = player.CurrentToolIndex;
            bool        canMove          = player.canMove; // fix player frozen due to animations when performing an action

            // move mount out of the way
            mountFieldValue.SetValue(null);
            mountPositionValue.SetValue(new Vector2(-5, -5));

            // perform action
            try
            {
                action();
            }
            finally
            {
                // move mount back
                mountPositionValue.SetValue(mountPosition);
                mountFieldValue.SetValue(mount);

                // restore previous state
                if (wateringCan != null)
                {
                    wateringCan.WaterLeft = waterInCan;
                }
                player.stamina          = stamina;
                player.Position         = position;
                player.FacingDirection  = facingDirection;
                player.CurrentToolIndex = currentToolIndex;
                player.canMove          = canMove;
            }
        }
Exemplo n.º 10
0
        public ItemFrame(int which, Vector2 tile, IMonitor monitor, Item dispItem = null) : base(which, tile)
        {
            this.monitor = monitor;

            this.monitor.Log($"Creating new itemFrame with id {which}", LogLevel.Trace);
            if (dispItem != null && dispItem is Item item)
            {
                this.monitor.Log($"displayItem set to {dispItem.Name}", LogLevel.Trace);
                this.displayItem = new NetRef <Item>(item.getOne());
                this.setDisplayType();
            }
            else
            {
                this.monitor.Log($"displayItem not set.", LogLevel.Trace);
            }
            this.setDataFromJson();
        }
Exemplo n.º 11
0
        /// <summary>Temporarily dismount and set up the player to interact with a tile, then return it to the previous state afterwards.</summary>
        /// <param name="action">The action to perform.</param>
        private void TemporarilyFakeInteraction(Action action)
        {
            // get references
            SFarmer        player     = Game1.player;
            NetRef <Horse> mountField = this.Reflection.GetField <NetRef <Horse> >(Game1.player, "netMount").GetValue(); // change value directly to bypass the game's on-dismount logic

            // save current state
            Horse       mount            = mountField.Value;
            Vector2     mountPosition    = this.Position;
            WateringCan wateringCan      = player.CurrentTool as WateringCan;
            int         waterInCan       = wateringCan?.WaterLeft ?? 0;
            float       stamina          = player.stamina;
            Vector2     position         = player.Position;
            int         facingDirection  = player.FacingDirection;
            int         currentToolIndex = player.CurrentToolIndex;
            bool        canMove          = Game1.player.canMove; // fix player frozen due to animations when performing an action

            // move mount out of the way
            mountField.Value = null;
            this.Position    = new Vector2(-5, -5);

            // perform action
            try
            {
                action();
            }
            finally
            {
                // move mount back
                this.Position    = mountPosition;
                mountField.Value = mount;

                // restore previous state
                if (wateringCan != null)
                {
                    wateringCan.WaterLeft = waterInCan;
                }
                player.stamina          = stamina;
                player.Position         = position;
                player.FacingDirection  = facingDirection;
                player.CurrentToolIndex = currentToolIndex;
                Game1.player.canMove    = canMove;
            }
        }
Exemplo n.º 12
0
        /*********
        ** Public methods
        *********/
        /// <summary>Construct an instance.</summary>
        /// <param name="field">The field to watch.</param>
        public NetListWatcher(NetList <TValue, NetRef <TValue> > field)
        {
            this.Field = field;
#if SMAPI_FOR_MOBILE
            this.innerArray = (NetRef <NetArray <TValue, NetRef <TValue> > >) this.Field.GetType().GetField("array", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).GetValue(this.Field);
            this.hookArray(this.innerArray.Value);
            this.innerArray.fieldChangeVisibleEvent += (arrayRef, oldArray, newArray) =>
            {
                if (newArray != null)
                {
                    this.hookArray(newArray);
                }
                this.OnArrayReplaced(this.Field, oldArray, newArray);
            };
#else
            field.OnElementChanged += this.OnElementChanged;
            field.OnArrayReplaced  += this.OnArrayReplaced;
#endif
        }
        public void sendAvailableFarmhands(string userID, Action <OutgoingMessage> sendMessage)
        {
            List <NetRef <Farmer> > list = new List <NetRef <Farmer> >();

            Game1.getFarm();
            foreach (Cabin cabin in this.cabins())
            {
                NetRef <Farmer> farmhand = cabin.getFarmhand();
                if ((!farmhand.Value.isActive() || ModCore.multiplayer.isDisconnecting(farmhand.Value.UniqueMultiplayerID)) && this.authCheck(userID, farmhand.Value))
                {
                    list.Add(farmhand);
                }
            }
            using (MemoryStream memoryStream = new MemoryStream())
            {
                using (BinaryWriter writer = new BinaryWriter((Stream)memoryStream))
                {
                    writer.Write(Game1.year);
                    writer.Write(Utility.getSeasonNumber(Game1.currentSeason));
                    writer.Write(Game1.dayOfMonth);
                    writer.Write((byte)list.Count);
                    foreach (NetRef <Farmer> netRef in list)
                    {
                        try
                        {
                            netRef.Serializer = SaveGame.farmerSerializer;
                            netRef.WriteFull(writer);
                        }
                        finally
                        {
                            netRef.Serializer = (XmlSerializer)null;
                        }
                    }
                    memoryStream.Seek(0L, SeekOrigin.Begin);
                    sendMessage(new OutgoingMessage((byte)9, Game1.player, new object[1]
                    {
                        (object)memoryStream.ToArray()
                    }));
                }
            }
        }
		private void UpdateRemoteNetRef(NetRef<object> obj)
		{
			valueGetter = obj.Value;

			bool finalize = false;

			if (valueGetter is float)
			{
				obj.Value = (float)Mathf.Lerp((float)valueGetter, (float)obj.LerpTo, lerpT);

				if (Math.Abs((float)obj.LerpTo - (float)valueGetter) <= lerpStopOffset)
					finalize = true;
			}
			else if (valueGetter is double)
			{
				obj.Value = BeardedMath.Lerp((double)valueGetter, (double)obj.LerpTo, lerpT);

				if (Math.Abs((double)obj.LerpTo - (double)valueGetter) <= lerpStopOffset)
					finalize = true;
			}
			else if (valueGetter is Vector2)
			{
				obj.Value = Vector2.Lerp((Vector2)valueGetter, (Vector2)obj.LerpTo, lerpT);

				if (Vector2.Distance((Vector2)valueGetter, (Vector2)obj.LerpTo) <= lerpStopOffset)
					finalize = true;
			}
			else if (valueGetter is Vector3)
			{
				obj.Value = Vector3.Lerp((Vector3)valueGetter, (Vector3)obj.LerpTo, lerpT);

				if (Vector3.Distance((Vector3)valueGetter, (Vector3)obj.LerpTo) <= lerpStopOffset)
					finalize = true;
			}
			else if (valueGetter is Vector4)
			{
				obj.Value = Vector4.Lerp((Vector4)valueGetter, (Vector4)obj.LerpTo, lerpT);

				if (Vector4.Distance((Vector4)valueGetter, (Vector4)obj.LerpTo) <= lerpStopOffset)
					finalize = true;
			}
			else if (valueGetter is Quaternion)
			{
				obj.Value = Quaternion.Slerp((Quaternion)valueGetter, (Quaternion)obj.LerpTo, lerpT);

				if (Quaternion.Angle((Quaternion)valueGetter, (Quaternion)obj.LerpTo) <= lerpAngleStopOffset)
					finalize = true;
			}
			else
				finalize = true;

			if (finalize)
			{
				obj.AssignToLerp();
				obj.Callback(this, true);
			}
		}
Exemplo n.º 15
0
        internal static bool sendAvailableFarmhands(string userID, Action <OutgoingMessage> sendMessage)
        {
            Multiplayer             multiplayer = (Multiplayer)typeof(Game1).GetField("multiplayer", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null);
            List <NetRef <Farmer> > netRefList  = new List <NetRef <Farmer> >();

            foreach (Cabin cabin in cabins())
            {
                if (cabin.getFarmhand() is NetRef <Farmer> farmhand && ((!farmhand.Value.isActive() || multiplayer.isDisconnecting(farmhand.Value.UniqueMultiplayerID)) && authCheck(userID, farmhand.Value)))
                {
                    netRefList.Add(farmhand);
                }
            }

            if (netRefList.Count > 0)
            {
                return(true);
            }

            foreach (NetRef <Farmer> f in farmers)
            {
                if ((!f.Value.isActive() || multiplayer.isDisconnecting(f.Value.UniqueMultiplayerID)) && authCheck(userID, f.Value))
                {
                    f.Value.currentLocation    = Game1.getLocationFromName("FarmHouse");
                    f.Value.homeLocation.Value = "FarmHouse";
                    f.Value.Position           = new Vector2(640f, 320f);
                    netRefList.Add(f);
                }
            }

            if (netRefList.Count < 1)
            {
                NetRef <Farmer> newF = getNewFarmHand();
                farmers.Add(newF);
                netRefList.Add(newF);
            }

            using (MemoryStream memoryStream = new MemoryStream())
            {
                using (BinaryWriter writer = new BinaryWriter((Stream)memoryStream))
                {
                    writer.Write(Game1.year);
                    writer.Write(Utility.getSeasonNumber(Game1.currentSeason));
                    writer.Write(Game1.dayOfMonth);
                    writer.Write((byte)netRefList.Count);
                    foreach (NetRef <Farmer> netRef in netRefList)
                    {
                        try
                        {
                            netRef.Serializer = SaveGame.farmerSerializer;
                            netRef.WriteFull(writer);
                        }
                        catch (Exception e)
                        {
                            mon.Log(e.Message + ":" + e.StackTrace);
                        }
                        finally
                        {
                            netRef.Serializer = (XmlSerializer)null;
                        }
                    }
                    memoryStream.Seek(0L, SeekOrigin.Begin);
                    sendMessage(new OutgoingMessage((byte)9, Game1.player, new object[1]
                    {
                        (object)memoryStream.ToArray()
                    }));
                }
            }

            return(false);
        }
Exemplo n.º 16
0
        public string Generate(bool indent)
        {
            var i  = indent ? "    " : "";
            var sb = new StringBuilder();

            sb.Append($"{i}nuget_package(\n");
            if (Variable == null)
            {
                sb.Append($"{i}    name = \"{PackageIdentity.Id.ToLower()}\",\n");
            }
            else
            {
                sb.Append($"{i}    name = {Variable},\n");
            }

            sb.Append($"{i}    package = \"{PackageIdentity.Id.ToLower()}\",\n");
            sb.Append($"{i}    version = \"{PackageIdentity.Version}\",\n");
            if (!String.IsNullOrEmpty(Sha256))
            {
                sb.Append($"{i}    sha256 = \"{Sha256}\",\n");
            }
            if (NugetSourceCustom)
            {
                sb.Append($"{i}    source = source,\n");
            }
            if (CoreLib != null && CoreLib.Any())
            {
                sb.Append($"{i}    core_lib = {{\n");
                foreach (var pair in CoreLib)
                {
                    sb.Append($"{i}        \"{pair.Key}\": \"{pair.Value}\",\n");
                }
                sb.Append($"{i}    }},\n");
            }
            if (CoreRef != null && CoreRef.Any())
            {
                sb.Append($"{i}    core_ref = {{\n");
                foreach (var pair in CoreRef)
                {
                    sb.Append($"{i}        \"{pair.Key}\": \"{pair.Value}\",\n");
                }
                sb.Append($"{i}    }},\n");
            }
            if (NetLib != null && NetLib.Any())
            {
                sb.Append($"{i}    net_lib = {{\n");
                foreach (var pair in NetLib)
                {
                    sb.Append($"{i}        \"{pair.Key}\": \"{pair.Value}\",\n");
                }
                sb.Append($"{i}    }},\n");
            }
            if (NetRef != null && NetRef.Any())
            {
                sb.Append($"{i}    net_ref = {{\n");
                foreach (var pair in NetRef)
                {
                    sb.Append($"{i}        \"{pair.Key}\": \"{pair.Value}\",\n");
                }
                sb.Append($"{i}    }},\n");
            }
            if (!String.IsNullOrEmpty(MonoLib))
            {
                sb.Append($"{i}    mono_lib = \"{MonoLib}\",\n");
            }
            if (!String.IsNullOrEmpty(MonoRef))
            {
                sb.Append($"{i}    mono_ref = \"{MonoRef}\",\n");
            }
            if (CoreTool != null && CoreTool.Sum(x => x.Value.Count()) > 0)
            {
                sb.Append($"{i}   core_tool = {{\n");
                foreach (var pair in CoreTool)
                {
                    sb.Append($"{i}       \"{pair.Key}\": \"{pair.Value}\",\n");
                }
                sb.Append($"{i}   }},\n");
            }
            if (NetTool != null && NetTool.Sum(x => x.Value.Count()) > 0)
            {
                sb.Append($"{i}   net_tool = {{\n");
                foreach (var pair in NetTool)
                {
                    sb.Append($"{i}       \"{pair.Key}\": \"{pair.Value}\",\n");
                }
                sb.Append($"{i}   }},\n");
            }
            if (!String.IsNullOrEmpty(MonoTool))
            {
                sb.Append($"{i}    mono_tool = \"{MonoTool}\",\n");
            }

            if (Core_Deps != null && Core_Deps.Sum(x => x.Value.Count()) > 0)
            {
                sb.Append($"{i}    core_deps = {{\n");
                foreach (var pair in Core_Deps)
                {
                    if (!pair.Value.Any())
                    {
                        continue;
                    }

                    sb.Append($"{i}        \"{pair.Key}\": [\n");
                    foreach (var s in pair.Value)
                    {
                        sb.Append($"{i}           \"{s}\",\n");
                    }
                    sb.Append($"{i}        ],\n");
                }
                sb.Append($"{i}    }},\n");
            }

            if (Net_Deps != null && Net_Deps.Sum(x => x.Value.Count()) > 0)
            {
                sb.Append($"{i}    net_deps = {{\n");
                foreach (var pair in Net_Deps)
                {
                    if (!pair.Value.Any())
                    {
                        continue;
                    }

                    sb.Append($"{i}        \"{pair.Key}\": [\n");
                    foreach (var s in pair.Value)
                    {
                        sb.Append($"{i}           \"{s}\",\n");
                    }
                    sb.Append($"{i}        ],\n");
                }
                sb.Append($"{i}    }},\n");
            }

            if (Mono_Deps != null && Mono_Deps.Any())
            {
                sb.Append($"{i}    mono_deps = [\n");
                foreach (var s in Mono_Deps)
                {
                    sb.Append($"{i}        \"{s}\",\n");
                }
                sb.Append($"{i}    ],\n");
            }

            if (Core_Files != null && Core_Files.Sum(x => x.Value.Count()) > 0)
            {
                sb.Append($"{i}    core_files = {{\n");
                foreach (var pair in Core_Files)
                {
                    if (!pair.Value.Any())
                    {
                        continue;
                    }

                    sb.Append($"{i}        \"{pair.Key}\": [\n");
                    foreach (var s in pair.Value)
                    {
                        sb.Append($"{i}           \"{s}\",\n");
                    }
                    sb.Append($"{i}        ],\n");
                }
                sb.Append($"{i}    }},\n");
            }

            if (Net_Files != null && Net_Files.Sum(x => x.Value.Count()) > 0)
            {
                sb.Append($"{i}    net_files = {{\n");
                foreach (var pair in Net_Files)
                {
                    if (!pair.Value.Any())
                    {
                        continue;
                    }

                    sb.Append($"{i}        \"{pair.Key}\": [\n");
                    foreach (var s in pair.Value)
                    {
                        sb.Append($"{i}           \"{s}\",\n");
                    }
                    sb.Append($"{i}        ],\n");
                }
                sb.Append($"{i}    }},\n");
            }

            if (Mono_Files != null && Mono_Files.Any())
            {
                sb.Append($"{i}    mono_files = [\n");
                foreach (var s in Mono_Files)
                {
                    sb.Append($"{i}        \"{s}\",\n");
                }
                sb.Append($"{i}    ],\n");
            }
            sb.Append($"{i})\n");
            return(sb.ToString());
        }
        public static global::StardewValley.AnimalHouse GetIndoors(Building building)
        {
            NetRef <GameLocation> indoors = Utilities.Reflection.GetFieldValue <NetRef <GameLocation> >(building, "indoors");

            return(indoors.Value as global::StardewValley.AnimalHouse);
        }
        /// <summary>Opens the kitchen menu using any available containers. Imitates <see cref="GameLocation.ActivateKitchen"/> but avoids issues with a null "fridge" parameter.</summary>
        /// <param name="location">The location of the kitchen.</param>
        /// <returns>True if the menu successfully opened. False otherwise, e.g. if no storage containers exist or one is currently in use.</returns>
        private static void ActivateKitchen(GameLocation location)
        {
            //get the current location's static fridge if applicable
            NetRef <Chest> fridge = null;

            if (location is FarmHouse farmhouse)
            {
                fridge = farmhouse.fridge;
            }
            else if (location is IslandFarmHouse islandfarmhouse)
            {
                fridge = islandfarmhouse.fridge;
            }

            //imitate GameLocation.ActivateKitchen except where otherwise noted
            List <NetMutex> muticies     = new List <NetMutex>();
            List <Chest>    mini_fridges = new List <Chest>();

            foreach (StardewValley.Object item in location.objects.Values)
            {
                if (item != null && item is Chest chest)
                {
                    if ((chest.bigCraftable.Value && chest.ParentSheetIndex == 216) || chest.fridge.Value) //if this chest is a Mini-Fridge OR has "fridge" set to true (the original method only checks for Mini-Fridge)
                    {
                        mini_fridges.Add(chest);
                        muticies.Add(chest.mutex);
                    }
                }
            }
            if (fridge != null && fridge.Value.mutex.IsLocked())
            {
                Game1.showRedMessage(Game1.content.LoadString("Strings\\UI:Kitchen_InUse"));
                return;
            }
            MultipleMutexRequest multiple_mutex_request = null;

            multiple_mutex_request = new MultipleMutexRequest(muticies, delegate
            {
                if (fridge != null) //if this location has a fridge, use the original code
                {
                    fridge.Value.mutex.RequestLock(delegate
                    {
                        List <Chest> list = new List <Chest>();
                        //skip redundant null check on the fridge
                        list.Add(fridge);
                        list.AddRange(mini_fridges);
                        Vector2 topLeftPositionForCenteringOnScreen = Utility.getTopLeftPositionForCenteringOnScreen(800 + IClickableMenu.borderWidth * 2, 600 + IClickableMenu.borderWidth * 2);
                        Game1.activeClickableMenu = new CraftingPage((int)topLeftPositionForCenteringOnScreen.X, (int)topLeftPositionForCenteringOnScreen.Y, 800 + IClickableMenu.borderWidth * 2, 600 + IClickableMenu.borderWidth * 2, cooking: true, standalone_menu: true, list);
                        Game1.activeClickableMenu.exitFunction = delegate
                        {
                            fridge.Value.mutex.ReleaseLock();
                            multiple_mutex_request.ReleaseLocks();
                        };
                    }, delegate
                    {
                        Game1.showRedMessage(Game1.content.LoadString("Strings\\UI:Kitchen_InUse"));
                        multiple_mutex_request.ReleaseLocks();
                    });
                }
                else //if this location does NOT have a fridge, only use mini-fridges
                {
                    //don't RequestLock the fridge mutex
                    List <Chest> list = new List <Chest>();
                    //don't add the fridge to this list
                    list.AddRange(mini_fridges);
                    Vector2 topLeftPositionForCenteringOnScreen = Utility.getTopLeftPositionForCenteringOnScreen(800 + IClickableMenu.borderWidth * 2, 600 + IClickableMenu.borderWidth * 2);
                    Game1.activeClickableMenu = new CraftingPage((int)topLeftPositionForCenteringOnScreen.X, (int)topLeftPositionForCenteringOnScreen.Y, 800 + IClickableMenu.borderWidth * 2, 600 + IClickableMenu.borderWidth * 2, cooking: true, standalone_menu: true, mini_fridges);
                    Game1.activeClickableMenu.exitFunction = delegate
                    {
                        //don't ReleaseLock the fridge mutex
                        multiple_mutex_request.ReleaseLocks();
                    };
                }
            }, delegate
            {
                Game1.showRedMessage(Game1.content.LoadString("Strings\\UI:Kitchen_InUse"));
            });
        }