public static object SerializeMenu(IClickableMenu menu, Point mousePosition) { dynamic serialized = Menus.SerializeMenu(menu, mousePosition); if (serialized != null) { return(serialized); } if (menu == null) { return(null); } Rectangle menuRect = new Rectangle(menu.xPositionOnScreen, menu.yPositionOnScreen, menu.width, menu.height); bool containsMouse = menu.isWithinBounds(mousePosition.X, mousePosition.Y); var menuBarObj = new { menu.xPositionOnScreen, menu.yPositionOnScreen, upperRightCloseButton = Utils.SerializeClickableCmp(menu.upperRightCloseButton, mousePosition), containsMouse, menuType = "unknown", classType = menu.GetType().ToString(), }; dynamic menuTypeObj = new { }; if (menu is ShopMenu) { var sm = menu as ShopMenu; var forSale = sm.forSale.Select(x => Utils.SerializeItem((Item)x)); var forSaleButtons = Utils.SerializeComponentList(sm.forSaleButtons, mousePosition); menuTypeObj = new { menuType = "shopMenu", forSale, forSaleButtons, sm.currentItemIndex, inventory = SerializeMenu(sm.inventory), upArrow = SerializeClickableCmp(sm.upArrow, mousePosition), downArrow = SerializeClickableCmp(sm.downArrow, mousePosition), scrollBar = SerializeClickableCmp(sm.scrollBar, mousePosition), }; } else if (menu is ProfileMenu) { var pm = menu as ProfileMenu; var clickableProfileItems = Utils.SerializeComponentList(pm.clickableProfileItems, mousePosition); menuTypeObj = new { menuType = "profileMenu", backButton = Utils.SerializeClickableCmp(pm.backButton, mousePosition), forwardButton = Utils.SerializeClickableCmp(pm.forwardButton, mousePosition), previousCharacterButton = Utils.SerializeClickableCmp(pm.previousCharacterButton, mousePosition), nextCharacterButton = Utils.SerializeClickableCmp(pm.nextCharacterButton, mousePosition), clickableProfileItems, upArrow = SerializeClickableCmp(pm.upArrow, mousePosition), downArrow = SerializeClickableCmp(pm.downArrow, mousePosition), }; } else if (menu is DialogueBox) { var db = menu as DialogueBox; var responseCC = SerializeComponentList(db.responseCC, mousePosition); var responses = db.responses.Select(x => new { x.responseKey, x.responseText, x.hotkey }).ToList(); menuTypeObj = new { menuType = "dialogueBox", responseCC, responses, }; } else if (menu is CoopMenu) { var cb = menu as CoopMenu; var slotButtons = SerializeComponentList(cb.slotButtons, mousePosition); String currentTab = Utils.GetPrivateField(cb, "currentTab").ToString(); menuTypeObj = new { menuType = "coopMenu", downArrow = SerializeClickableCmp(cb.downArrow, mousePosition), hostTab = SerializeClickableCmp(cb.hostTab, mousePosition), joinTab = SerializeClickableCmp(cb.joinTab, mousePosition), refreshButton = SerializeClickableCmp(cb.refreshButton, mousePosition), upArrow = SerializeClickableCmp(cb.upArrow, mousePosition), slotButtons, currentTab, }; if (currentTab == "JOIN_TAB") { } else if (currentTab == "HOST_TAB") { } } else if (menu is TitleTextInputMenu) { var ttim = menu as TitleTextInputMenu; menuTypeObj = new { menuType = "titleTextInputMenu", doneNamingButton = SerializeClickableCmp(ttim.doneNamingButton, mousePosition), pasteButton = SerializeClickableCmp(ttim.pasteButton, mousePosition), textBoxCC = SerializeClickableCmp(ttim.textBoxCC, mousePosition), }; } else if (menu is AnimalQueryMenu) { var aqm = menu as AnimalQueryMenu; bool movingAnimal = (bool)Utils.GetPrivateField(aqm, "movingAnimal"); menuTypeObj = new { menuType = "animalQueryMenu", movingAnimal, }; if (movingAnimal) { var vt = VisibleTiles(Game1.getFarm()); var tileComponents = vt.Select(t => TileToClickableComponent(t[0], t[1], mousePosition)).ToList(); var okButton = SerializeClickableCmp(aqm.okButton, mousePosition); menuTypeObj = Merge(menuTypeObj, new { tileComponents, okButton }); } else { bool confirmingSell = (bool)Utils.GetPrivateField(aqm, "confirmingSell"); if (confirmingSell) { var noButton = SerializeClickableCmp(aqm.noButton, mousePosition); var yesButton = SerializeClickableCmp(aqm.yesButton, mousePosition); menuTypeObj = Merge(menuTypeObj, new { yesButton, noButton }); } else { menuTypeObj = Merge(menuTypeObj, new { allowReproductionButton = SerializeClickableCmp(aqm.allowReproductionButton, mousePosition), sellButton = SerializeClickableCmp(aqm.sellButton, mousePosition), textBoxCC = SerializeClickableCmp(aqm.textBoxCC, mousePosition), moveHomeButton = SerializeClickableCmp(aqm.moveHomeButton, mousePosition), okButton = SerializeClickableCmp(aqm.okButton, mousePosition), }); } } } else if (menu is MineElevatorMenu) { var mem = menu as MineElevatorMenu; var elevators = SerializeComponentList(mem.elevators, mousePosition); menuTypeObj = new { menuType = "mineElevatorMenu", elevators, }; } else if (menu is LetterViewerMenu) { var lvm = menu as LetterViewerMenu; var itemsToGrab = SerializeComponentList(lvm.itemsToGrab, mousePosition); var acceptQuestButton = SerializeClickableCmp(lvm.acceptQuestButton, mousePosition); var backButton = SerializeClickableCmp(lvm.backButton, mousePosition); var forwardButton = SerializeClickableCmp(lvm.forwardButton, mousePosition); menuTypeObj = new { menuType = "letterViewerMenu", acceptQuestButton, backButton, forwardButton, itemsToGrab, }; } else if (menu is InventoryMenu) { var im = menu as InventoryMenu; menuTypeObj = new { menuType = "inventoryMenu", inventory = SerializeComponentList(im.inventory, mousePosition), im.rows, im.capacity, }; } else if (menu is CarpenterMenu) { var cm = menu as CarpenterMenu; bool onFarm = (bool)Utils.GetPrivateField(cm, "onFarm"); menuTypeObj = new { menuType = "carpenterMenu", cancelButton = SerializeClickableCmp(cm.cancelButton, mousePosition), onFarm, }; if (onFarm) { var vt = VisibleTiles(Game1.getFarm()); var tileComponents = vt.Select(t => TileToClickableComponent(t[0], t[1], mousePosition)).ToList(); menuTypeObj = Merge(menuTypeObj, new { tileComponents }); } else { menuTypeObj = Merge(menuTypeObj, new { backButton = SerializeClickableCmp(cm.backButton, mousePosition), demolishButton = SerializeClickableCmp(cm.demolishButton, mousePosition), forwardButton = SerializeClickableCmp(cm.forwardButton, mousePosition), moveButton = SerializeClickableCmp(cm.moveButton, mousePosition), okButton = SerializeClickableCmp(cm.okButton, mousePosition), paintButton = SerializeClickableCmp(cm.paintButton, mousePosition), upgradeIcon = SerializeClickableCmp(cm.upgradeIcon, mousePosition), }); } } else if (menu is TitleMenu) { var tm = menu as TitleMenu; menuTypeObj = new { menuType = "titleMenu", windowedButton = SerializeClickableCmp(tm.windowedButton, mousePosition), }; if (TitleMenu.subMenu != null) { bool addBackButton = tm.backButton != null && !(TitleMenu.subMenu is CharacterCustomization && !TitleMenu.subMenu.readyToClose()); dynamic backButton = addBackButton ? SerializeClickableCmp(tm.backButton, mousePosition) : null; var subMenu = Merge(SerializeMenu(TitleMenu.subMenu), new { backButton }); menuTypeObj = Merge(menuTypeObj, new { subMenu }); } else { dynamic subMenu = null; menuTypeObj = Merge(menuTypeObj, new { subMenu, buttons = SerializeComponentList(tm.buttons, mousePosition), languageButton = SerializeClickableCmp(tm.languageButton, mousePosition), aboutButton = SerializeClickableCmp(tm.aboutButton, mousePosition), muteMusicButton = SerializeClickableCmp(tm.muteMusicButton, mousePosition), }); } } else if (menu is CharacterCustomization) { var ccm = menu as CharacterCustomization; menuTypeObj = new { menuType = "characterCustomizationMenu", }; if (ccm.showingCoopHelp) { menuTypeObj = Merge(menuTypeObj, new { okButton = SerializeClickableCmp(ccm.coopHelpOkButton, mousePosition), coopHelpLeftButton = SerializeClickableCmp(ccm.coopHelpLeftButton, mousePosition), coopHelpRightButton = SerializeClickableCmp(ccm.coopHelpRightButton, mousePosition), }); } else { menuTypeObj = Merge(menuTypeObj, new { advancedOptionsButton = SerializeClickableCmp(ccm.advancedOptionsButton, mousePosition), backButton = SerializeClickableCmp(ccm.backButton, mousePosition), cabinLayoutButtons = SerializeComponentList(ccm.cabinLayoutButtons, mousePosition), coopHelpButton = SerializeClickableCmp(ccm.coopHelpButton, mousePosition), farmTypeButtons = SerializeComponentList(ccm.farmTypeButtons, mousePosition), favThingBoxCC = SerializeClickableCmp(ccm.favThingBoxCC, mousePosition), farmnameBoxCC = SerializeClickableCmp(ccm.farmnameBoxCC, mousePosition), genderButtons = SerializeComponentList(ccm.genderButtons, mousePosition), leftSelectionButtons = SerializeComponentList(ccm.leftSelectionButtons, mousePosition), nameBoxCC = SerializeClickableCmp(ccm.nameBoxCC, mousePosition), okButton = SerializeClickableCmp(ccm.okButton, mousePosition), petButtons = SerializeComponentList(ccm.petButtons, mousePosition), randomButton = SerializeClickableCmp(ccm.randomButton, mousePosition), rightSelectionButtons = SerializeComponentList(ccm.rightSelectionButtons, mousePosition), skipIntroButton = SerializeClickableCmp(ccm.skipIntroButton, mousePosition), }); } } else if (menu is QuestLog) { var qlm = menu as QuestLog; StardewValley.Quests.IQuest shownQuest = GetPrivateField(qlm, "_shownQuest"); int currentPage = GetPrivateField(qlm, "currentPage"); int questPage = GetPrivateField(qlm, "questPage"); float contentHeight = GetPrivateField(qlm, "_contentHeight"); float scissorRectHeight = GetPrivateField(qlm, "_scissorRectHeight"); float scrollAmount = GetPrivateField(qlm, "scrollAmount"); List <List <StardewValley.Quests.IQuest> > pages = GetPrivateField(qlm, "pages"); menuTypeObj = new { menuType = "questLogMenu" }; if (questPage == -1) { if (pages.Count > 0 && pages[currentPage].Count > 0) { menuTypeObj = Merge(menuTypeObj, new { questLogButtons = SerializeComponentList(qlm.questLogButtons, mousePosition) }); } if (currentPage < pages.Count - 1) { menuTypeObj = Merge(menuTypeObj, new { forwardButton = SerializeClickableCmp(qlm.forwardButton, mousePosition) }); } if (currentPage > 0) { menuTypeObj = Merge(menuTypeObj, new { backButton = SerializeClickableCmp(qlm.backButton, mousePosition) }); } } else { var quest = shownQuest as StardewValley.Quests.Quest; bool needsScroll = qlm.NeedsScroll(); if (questPage != -1 && shownQuest.ShouldDisplayAsComplete() && shownQuest.HasMoneyReward()) { menuTypeObj = Merge(menuTypeObj, new { rewardBox = SerializeClickableCmp(qlm.rewardBox, mousePosition) }); } if (questPage != -1 && quest != null && !quest.completed && (bool)quest.canBeCancelled) { menuTypeObj = Merge(menuTypeObj, new { cancelQuestButton = SerializeClickableCmp(qlm.cancelQuestButton, mousePosition) }); } if (needsScroll) { if (scrollAmount < contentHeight - scissorRectHeight) { menuTypeObj = Merge(menuTypeObj, new { downArrow = SerializeClickableCmp(qlm.downArrow, mousePosition) }); } else if (scrollAmount > 0f) { menuTypeObj = Merge(menuTypeObj, new { upArrow = SerializeClickableCmp(qlm.upArrow, mousePosition) }); } } else { menuTypeObj = Merge(menuTypeObj, new { backButton = SerializeClickableCmp(qlm.backButton, mousePosition) }); } } //backButton = SerializeClickableCmp(qlm.backButton, mousePosition), //downArrow = SerializeClickableCmp(qlm.downArrow, mousePosition), //forwardButton = SerializeClickableCmp(qlm.forwardButton, mousePosition), //questLogButtons = SerializeComponentList(qlm.questLogButtons, mousePosition), //upArrow = SerializeClickableCmp(qlm.upArrow, mousePosition), //rewardBox = SerializeClickableCmp(qlm.rewardBox, mousePosition), } else if (menu is LanguageSelectionMenu) { var lsm = menu as LanguageSelectionMenu; menuTypeObj = new { menuType = "languageSelectionMenu", languages = SerializeComponentList(lsm.languages, mousePosition), }; } else if (menu is LevelUpMenu) { var lum = menu as LevelUpMenu; menuTypeObj = new { menuType = "levelUpMenu", }; if (lum.isProfessionChooser) { menuTypeObj = Merge(menuTypeObj, new { leftProfession = SerializeClickableCmp(lum.leftProfession, mousePosition), rightProfession = SerializeClickableCmp(lum.rightProfession, mousePosition), }); } else { menuTypeObj = Merge(menuTypeObj, new { okButton = SerializeClickableCmp(lum.okButton, mousePosition) }); } } else if (menu is LoadGameMenu) { var lgm = menu as LoadGameMenu; int currentItemIndex = (int)GetPrivateField(lgm, "currentItemIndex"); menuTypeObj = new { menuType = "loadGameMenu", currentItemIndex, lgm.deleteConfirmationScreen, }; if (lgm.deleteConfirmationScreen) { menuTypeObj = Utils.Merge(menuTypeObj, new { cancelDeleteButton = SerializeClickableCmp(lgm.cancelDeleteButton, mousePosition), okDeleteButton = SerializeClickableCmp(lgm.okDeleteButton, mousePosition), }); } else { menuTypeObj = Utils.Merge(menuTypeObj, new { deleteButtons = SerializeComponentList(lgm.deleteButtons, mousePosition), slotButtons = SerializeComponentList(lgm.slotButtons, mousePosition), upArrow = SerializeClickableCmp(lgm.upArrow, mousePosition), downArrow = SerializeClickableCmp(lgm.downArrow, mousePosition), }); } } else if (menu is Billboard) { var bb = menu as Billboard; bool dailyQuestBoard = Utils.GetPrivateField(bb, "dailyQuestBoard"); menuTypeObj = new { menuType = "billboard" }; if (dailyQuestBoard) { menuTypeObj = Merge(menuTypeObj, new { acceptQuestButton = SerializeClickableCmp(bb.acceptQuestButton, mousePosition) }); } else { menuTypeObj = Merge(menuTypeObj, new { calendarDays = SerializeComponentList(bb.calendarDays, mousePosition) }); } } else if (menu is LevelUpMenu) { var lum = menu as LevelUpMenu; menuTypeObj = new { menuType = "levelUpMenu", okButton = SerializeClickableCmp(lum.okButton, mousePosition), rightProfession = SerializeClickableCmp(lum.rightProfession, mousePosition), leftProfession = SerializeClickableCmp(lum.leftProfession, mousePosition), lum.isProfessionChooser }; } else if (menu is MuseumMenu) { var mm = menu as MuseumMenu; var location = Game1.currentLocation as StardewValley.Locations.LibraryMuseum; var museumPieceTileComponents = from t in VisibleTiles(location) where location.museumPieces.ContainsKey(new Vector2(t[0], t[1])) || location.isTileSuitableForMuseumPiece(t[0], t[1]) select TileToClickableComponent(t[0], t[1], mousePosition); var inventoryRect = new Rectangle(mm.inventory.xPositionOnScreen, mm.inventory.yPositionOnScreen, mm.inventory.width, mm.inventory.height); var clickableTileComponents = museumPieceTileComponents.Where(x => !x.rect.Intersects(inventoryRect)).ToList(); menuTypeObj = new { menuType = "museumMenu", okButton = SerializeClickableCmp(mm.okButton, mousePosition), clickableTileComponents, inventory = SerializeMenu(mm.inventory), trashCan = SerializeClickableCmp(mm.trashCan, mousePosition), }; } else if (menu is GeodeMenu) { var gm = menu as GeodeMenu; menuTypeObj = new { menuType = "geodeMenu", okButton = SerializeClickableCmp(gm.okButton, mousePosition), geodeSpot = SerializeClickableCmp(gm.geodeSpot, mousePosition), inventory = SerializeMenu(gm.inventory), trashCan = SerializeClickableCmp(gm.trashCan, mousePosition), }; } return(Utils.Merge(menuBarObj, menuTypeObj)); }