private void OnMenuChanged(object sender, MenuChangedEventArgs e) { if (!DeliveryEnabled()) { return; } // remove old overlay if (this.CurrentOverlay != null) { this.CurrentOverlay?.Dispose(); this.CurrentOverlay = null; } this.Monitor.Log("New menu: " + e.NewMenu?.GetType(), LogLevel.Trace); if (e.NewMenu is ItemGrabMenu igm && igm.context is Chest container) { DeliveryChest chest; if (!this.DeliveryChests.TryGetValue(container, out chest)) { chest = new DeliveryChest(container); if (chest.Location == null) { Monitor.Log($"Failed to find chest location. Can't deliver to chest {container.Name}", LogLevel.Warn); return; } DeliveryChests[container] = chest; Monitor.Log($"Creating DeliveryChest {chest.Location}", LogLevel.Trace); } this.Monitor.Log($"Applying DeliveryOverlay to {chest.Location}", LogLevel.Trace); this.Monitor.Log($"Send: {string.Join(", ", chest.DeliveryOptions.Send)} Receive: {string.Join(", ", chest.DeliveryOptions.Receive)}", LogLevel.Trace); this.CurrentOverlay = new DeliveryOverlay(this.Monitor, igm, chest, this.Helper, this.ModManifest.UniqueID, this.HostID); } }
private DeliveryChest GetDeliveryChestFromMessage(SerializableChestLocation message) { foreach (GameLocation location in LocationHelper.GetAccessibleLocations()) { if (location.NameOrUniqueName == message.Location) { Item item; if (message.isFridge) { if (location is FarmHouse house && Game1.player.HouseUpgradeLevel > 0) { item = house.fridge.Value; } else { break; } } else { item = location.getObjectAtTile(message.X, message.Y); } if (item != null && item is Chest chest) { DeliveryChest dchest; if (DeliveryChests.TryGetValue(chest, out dchest)) { return(dchest); } dchest = new DeliveryChest(chest); DeliveryChests[chest] = dchest; return(dchest); } } }
private void MoveItems(DeliveryChest from, DeliveryChest to, Tuple <DeliveryCategories, int>[] filter) { // Store items because removing items aborts foreach() Item[] items = from.Chest.items.ToArray(); foreach (Item item in items) { string type = ""; int quality = 1; if (item is SObject obj) { type = obj.Type; quality = 1 << obj.Quality; } DeliveryCategories cat = item.getDeliveryCategory(); this.Monitor.Log($"Found existing item {item.Name} Type: {type} Category: {item.getCategoryName()} cat: {cat.Name()}", LogLevel.Trace); if (!filter.Any(x => x.Item1 == cat && (x.Item2 & quality) > 0)) { continue; } Item chest_full = to.Chest.addItem(item); if (chest_full != null) { this.Monitor.Log($"Item {item.Name} will not fit in chest at {to.Location}", LogLevel.Info); continue; } //this.Monitor.Log($"Removing item", LogLevel.Trace); from.Chest.items.Remove(item); } }
private void OnModMessageReceived(object sender, ModMessageReceivedEventArgs e) { //Monitor.Log($"Got message: {e.Type}", LogLevel.Debug); if (e.FromModID != this.ModManifest.UniqueID) { return; } if (e.Type == "UpdateDeliveryOptions") { SyncDataModel message = e.ReadAs <SyncDataModel>(); DeliveryChest dchest = GetDeliveryChestFromMessage(message); if (dchest != null) { //Monitor.Log($"Send:{string.Join(", ", message.DeliveryOptions.Send)}", LogLevel.Debug); dchest.DeliveryOptions.Set(message.DeliveryOptions); if (this.CurrentOverlay != null) { this.CurrentOverlay.ResetEdit(); } } } else if (e.Type == "RequestDeliveryOptions") { SerializableChestLocation message = e.ReadAs <SerializableChestLocation>(); DeliveryChest dchest = GetDeliveryChestFromMessage(message); if (dchest != null) { Helper.Multiplayer.SendMessage(new SyncDataModel(dchest), "UpdateDeliveryOptions", modIDs: new[] { e.FromModID }, playerIDs: new[] { e.FromPlayerID }); } } }
private void Load(object sender, SaveLoadedEventArgs e) { CurrentOverlay = null; DeliveryChests = new Dictionary <Chest, DeliveryChest>(); HostID = 0; if (DeliveryEnabled() && Config.WaitForWizardShop) { Game1.addMailForTomorrow("DeliveryServiceWizardMail"); } if (!Context.IsMainPlayer) { // Farmhands don't maintain state foreach (IMultiplayerPeer peer in this.Helper.Multiplayer.GetConnectedPlayers()) { if (peer.HasSmapi && peer.IsHost) { HostID = peer.PlayerID; break; } } return; } List <SaveDataModel> save = Helper.Data.ReadSaveData <List <SaveDataModel> >("delivery-service"); if (save == null) { return; } foreach (SaveDataModel data in save) { DeliveryChest dchest = GetDeliveryChestFromMessage(data); if (dchest != null) { int[] send = new int[Enum.GetValues(typeof(DeliveryCategories)).Length]; int[] receive = new int[Enum.GetValues(typeof(DeliveryCategories)).Length]; foreach (DeliveryCategories cat in Enum.GetValues(typeof(DeliveryCategories))) { send[(int)cat] = CheckCategoryEnabledInSave(cat, data.Send); receive[(int)cat] = CheckCategoryEnabledInSave(cat, data.Receive); } dchest.DeliveryOptions.Set(send, receive, data.MatchColor); } } }
/********* ** Accessors *********/ /// <summary>The menu instance for which the overlay was created.</summary> public DeliveryOverlay(IMonitor monitor, ItemGrabMenu menu, DeliveryChest chest, IModHelper helper, string modid, long hostid) : base(helper.Events, helper.Input, keepAlive: () => Game1.activeClickableMenu is ItemGrabMenu) { this.Menu = menu; this.Chest = chest; this.Monitor = monitor; this.Multiplayer = helper.Multiplayer; this.ModID = modid; this.HostID = hostid; this.origInventoryHighlighter = this.Menu.inventory.highlightMethod; this.origChestHighlighter = this.Menu.ItemsToGrabMenu.highlightMethod; this.EditSaveButtonArea = new ClickableComponent(new Rectangle(0, 0, Game1.tileSize, Game1.tileSize), "save-delivery"); this.SendCategories = Category.CategoryList(chest.DeliveryOptions.Send); this.ReceiveCategories = Category.CategoryList(chest.DeliveryOptions.Receive); this.MatchColor = new Checkbox(chest.DeliveryOptions.MatchColor); //this.bounds = new Rectangle(this.Menu.xPositionOnScreen, this.Menu.yPositionOnScreen, this.Menu.width, this.Menu.Height); this.LabelHeight = (int)Game1.smallFont.MeasureString("ABC").Y + 2; this.maxLabelWidth = 24 + 10 + (int)this.SendCategories.Select(p => Game1.smallFont.MeasureString(p.Name()).X).Max(); int width = 100 + // border this.maxLabelWidth + // label 40 + 10 * 26 + // checkbox 11 * Game1.pixelZoom; //scrollbar this.bounds = new Rectangle((Game1.viewport.Width - width) / 2, 10, width, Game1.viewport.Height - 20); this.scrollbar = new ScrollBar(helper.Events, helper.Input, new Rectangle( this.bounds.X + 10 * Game1.pixelZoom, this.bounds.Y + 10 * Game1.pixelZoom + 3 * LabelHeight, this.bounds.Width - 20 * Game1.pixelZoom, this.bounds.Height - 20 * Game1.pixelZoom - 5 * LabelHeight), this.SendCategories.Count, LabelHeight); if (!Context.IsMainPlayer) { this.Multiplayer.SendMessage(new SerializableChestLocation(chest), "RequestDeliveryOptions", modIDs: new[] { this.ModID }, playerIDs: new[] { this.HostID }); } }
private void DoDelivery() { List <DeliveryChest> toChests = new List <DeliveryChest>(); List <DeliveryChest> fromChests = new List <DeliveryChest>(); // ignore if player hasn't loaded a save yet if (!Context.IsWorldReady) { return; } Chest[] containers = DeliveryChests.Keys.ToArray(); foreach (Chest container in containers) { DeliveryChest chest = DeliveryChests[container]; Monitor.Log($"chest:{chest} container:{container}, Chest:{chest.Chest} location:{chest.Location}", LogLevel.Trace); if (chest == null || !chest.Exists()) { this.Monitor.Log($"Chest {chest.Location} no longer exists", LogLevel.Trace); DeliveryChests.Remove(container); continue; } if (chest.DeliveryOptions.Send.Any(x => x > 0)) { fromChests.Add(chest); } if (chest.DeliveryOptions.Receive.Any(x => x > 0)) { toChests.Add(chest); } } foreach (DeliveryChest fromChest in fromChests) { bool match_color = fromChest.DeliveryOptions.MatchColor; foreach (DeliveryChest toChest in toChests) { List <Tuple <DeliveryCategories, int> > categories = new List <Tuple <DeliveryCategories, int> >(); if (fromChest == toChest || (match_color && fromChest.Chest.playerChoiceColor != toChest.Chest.playerChoiceColor)) { continue; } foreach (DeliveryCategories category in Enum.GetValues(typeof(DeliveryCategories))) { int mask = (fromChest.DeliveryOptions.Send[(int)category] & toChest.DeliveryOptions.Receive[(int)category]); if (mask > 0) { // There is overlap between these chests categories.Add(new Tuple <DeliveryCategories, int>(category, mask)); } } if (categories.Count == 0 || (fromChest.DeliveryOptions.MatchColor && fromChest.Chest.playerChoiceColor != toChest.Chest.playerChoiceColor)) { continue; } this.Monitor.Log($"Moving {string.Join(", ", categories)} items from {fromChest.Location} -> {toChest.Location}", LogLevel.Trace); MoveItems( from: fromChest, to: toChest, filter: categories.ToArray()); } } }