private void OnModMessageReceived(object sender, ModMessageReceivedEventArgs e) { if (e.FromModID != this.ModManifest.UniqueID) { return; } ModEntry.Log($"[{(Context.IsMainPlayer ? "host" : "farmhand")}] Received {e.Type} from {e.FromPlayerID}.", LogLevel.Trace); switch (e.Type) { // farmhand requested metadata case MessageId.RequestMetadata: if (Context.IsMainPlayer) { // client requests settings and state, send it: InitResponseMessage response = new InitResponseMessage { Settings = DeepWoodsSettings.Settings, State = DeepWoodsSettings.DeepWoodsState, LevelNames = Game1.locations.OfType <DeepWoods>().Select(p => p.Name).ToArray() }; ModEntry.SendMessage(response, MessageId.Metadata, e.FromPlayerID); } break; // host sent metadata case MessageId.Metadata: if (!Context.IsMainPlayer) { InitResponseMessage response = e.ReadAs <InitResponseMessage>(); DeepWoodsSettings.Settings = response.Settings; DeepWoodsSettings.DeepWoodsState = response.State; ModEntry.DeepWoodsInitServerAnswerReceived(response.LevelNames); } break; // farmhand requested that we load and activate a DeepWoods level case MessageId.RequestWarp: if (Context.IsMainPlayer) { // load level int level = e.ReadAs <int>(); DeepWoods deepWoods = DeepWoodsManager.AddDeepWoodsFromObelisk(level); // send response WarpMessage response = new WarpMessage { Level = deepWoods.Level, Name = deepWoods.Name, EnterLocation = new Vector2(deepWoods.enterLocation.Value.X, deepWoods.enterLocation.Value.Y) }; ModEntry.SendMessage(response, MessageId.Warp, e.FromPlayerID); } break; // host loaded area for warp case MessageId.Warp: if (!Context.IsMainPlayer) { WarpMessage data = e.ReadAs <WarpMessage>(); DeepWoodsManager.AddBlankDeepWoodsToGameLocations(data.Name); DeepWoodsManager.WarpFarmerIntoDeepWoodsFromServerObelisk(data.Name, data.EnterLocation); } break; // host sent 'lowest level reached' update case MessageId.SetLowestLevelReached: if (!Context.IsMainPlayer) { DeepWoodsState.LowestLevelReached = e.ReadAs <int>(); } break; // host sent 'received stardrop from unicorn' update case MessageId.SetUnicornStardropReceived: if (Context.IsMainPlayer) { DeepWoodsState.PlayersWhoGotStardropFromUnicorn.Add(e.FromPlayerID); } break; // host added/removed location case MessageId.AddLocation: if (!Context.IsMainPlayer) { string name = e.ReadAs <string>(); DeepWoodsManager.AddBlankDeepWoodsToGameLocations(name); } break; case MessageId.RemoveLocation: if (!Context.IsMainPlayer) { string name = e.ReadAs <string>(); DeepWoodsManager.RemoveDeepWoodsFromGameLocations(name); } break; default: ModEntry.Log(" ignored unknown type.", LogLevel.Trace); break; } }
// This method is also called by the patch in DeepWoodsMTNCompatibilityMod. // We return false when we handled this message, so Harmony will cancel the original MTN handler. private static bool InternalProcessIncomingMessage(IncomingMessage msg) { if (msg.MessageType == Settings.Network.DeepWoodsMessageId) { int deepwoodsMessageType = msg.Reader.ReadInt32(); int randId = Game1.random.Next(); ModEntry.Log("InterceptProcessIncomingMessage[" + randId + "], master id: " + Game1.MasterPlayer.UniqueMultiplayerID + ", local id: " + Game1.player.UniqueMultiplayerID + ", msg.FarmerID: " + msg.FarmerID + ", deepwoodsMessageType: " + deepwoodsMessageType, StardewModdingAPI.LogLevel.Debug); Farmer who = Game1.getFarmer(msg.FarmerID); if (who == null || who == Game1.player) { ModEntry.Log(" who is null or local!", StardewModdingAPI.LogLevel.Warn); return(true); // execute original } if (deepwoodsMessageType == NETWORK_MESSAGE_DEEPWOODS_INIT) { ModEntry.Log(" [" + randId + "] deepwoodsMessageType == NETWORK_MESSAGE_DEEPWOODS_INIT", StardewModdingAPI.LogLevel.Debug); if (Game1.IsMasterGame) { // Client requests settings and state, send it: List <string> deepWoodsLevelNames = new List <string>(); foreach (var location in Game1.locations) { if (location is DeepWoods deepWoods) { deepWoodsLevelNames.Add(deepWoods.Name); } } object[] data = new object[deepWoodsLevelNames.Count + 4]; data[0] = NETWORK_MESSAGE_DEEPWOODS_INIT; data[1] = JsonConvert.SerializeObject(Settings); data[2] = JsonConvert.SerializeObject(DeepWoodsState); data[3] = (int)deepWoodsLevelNames.Count; for (int i = 0; i < deepWoodsLevelNames.Count; i++) { data[i + 4] = deepWoodsLevelNames[i]; } ModEntry.Log(" [" + randId + "] Client requests settings and state, deepWoodsLevelNames.Count: " + deepWoodsLevelNames.Count + ", deepWoodsLevelNames: " + String.Join(", ", deepWoodsLevelNames.ToArray()), StardewModdingAPI.LogLevel.Debug); who.queueMessage(Settings.Network.DeepWoodsMessageId, Game1.MasterPlayer, data); } else { // Server sent us settings and state! Settings = JsonConvert.DeserializeObject <DeepWoodsSettings>(msg.Reader.ReadString()); DeepWoodsState = JsonConvert.DeserializeObject <DeepWoodsStateData>(msg.Reader.ReadString()); int numDeepWoodsLevelNames = msg.Reader.ReadInt32(); List <string> deepWoodsLevelNames = new List <string>(); for (int i = 0; i < numDeepWoodsLevelNames; i++) { deepWoodsLevelNames.Add(msg.Reader.ReadString()); } ModEntry.Log(" [" + randId + "] Server sent us settings and state, deepWoodsLevelNames.Count: " + deepWoodsLevelNames.Count + ", deepWoodsLevelNames: " + String.Join(", ", deepWoodsLevelNames.ToArray()), StardewModdingAPI.LogLevel.Debug); ModEntry.DeepWoodsInitServerAnswerReceived(deepWoodsLevelNames); } } else { if (!Game1.IsMasterGame && !ModEntry.IsDeepWoodsGameRunning) { if (ModEntry.HasRequestedInitMessageFromServer) { ModEntry.Log("Got message from server before init message!", StardewModdingAPI.LogLevel.Warn); } else { ModEntry.Log("Got message from server before init message, never sent init message request!", StardewModdingAPI.LogLevel.Warn); } } if (deepwoodsMessageType == NETWORK_MESSAGE_DEEPWOODS_WARP) { ModEntry.Log(" [" + randId + "] deepwoodsMessageType == NETWORK_MESSAGE_DEEPWOODS_WARP", StardewModdingAPI.LogLevel.Debug); DeepWoodsWarpMessageData data = ReadDeepWoodsWarpMessage(msg.Reader); if (Game1.IsMasterGame) { // Client requests that we load and activate a specific DeepWoods level they want to warp into. DeepWoods deepWoods = DeepWoodsManager.AddDeepWoodsFromObelisk(data.Level); // Send message to client telling them we have the level ready. ModEntry.Log(" [" + randId + "] Client requests that we load and activate a specific DeepWoods level they want to warp into: data.Level:" + data.Level, StardewModdingAPI.LogLevel.Debug); who.queueMessage(Settings.Network.DeepWoodsMessageId, Game1.MasterPlayer, new object[] { NETWORK_MESSAGE_DEEPWOODS_WARP, deepWoods.level.Value, deepWoods.Name, new Vector2(deepWoods.enterLocation.Value.X, deepWoods.enterLocation.Value.Y) }); } else { // Server informs us that we can warp now! ModEntry.Log(" [" + randId + "] Server informs us that we can warp now: data.Level:" + data.Level + ", data.Name:" + data.Name, StardewModdingAPI.LogLevel.Debug); DeepWoodsManager.AddBlankDeepWoodsToGameLocations(data.Name); DeepWoodsManager.WarpFarmerIntoDeepWoodsFromServerObelisk(data.Name, data.EnterLocation); } } else if (deepwoodsMessageType == NETWORK_MESSAGE_DEEPWOODS_LEVEL) { ModEntry.Log(" [" + randId + "] deepwoodsMessageType == NETWORK_MESSAGE_DEEPWOODS_LEVEL", StardewModdingAPI.LogLevel.Debug); if (!Game1.IsMasterGame && who == Game1.MasterPlayer) { DeepWoodsState.LowestLevelReached = msg.Reader.ReadInt32(); ModEntry.Log(" [" + randId + "] DeepWoodsState.LowestLevelReached: " + DeepWoodsState.LowestLevelReached, StardewModdingAPI.LogLevel.Debug); } } else if (deepwoodsMessageType == NETWORK_MESSAGE_RCVD_STARDROP_FROM_UNICORN) { ModEntry.Log(" [" + randId + "] deepwoodsMessageType == NETWORK_MESSAGE_RCVD_STARDROP_FROM_UNICORN", StardewModdingAPI.LogLevel.Debug); if (Game1.IsMasterGame) { DeepWoodsState.PlayersWhoGotStardropFromUnicorn.Add(who.UniqueMultiplayerID); } } else if (deepwoodsMessageType == NETWORK_MESSAGE_DEEPWOODS_ADDREMOVE) { ModEntry.Log(" [" + randId + "] deepwoodsMessageType == NETWORK_MESSAGE_DEEPWOODS_ADDREMOVE", StardewModdingAPI.LogLevel.Debug); if (!Game1.IsMasterGame) { bool added = msg.Reader.ReadByte() != 0; string name = msg.Reader.ReadString(); ModEntry.Log(" [" + randId + "] added: " + added + ", name: " + name, StardewModdingAPI.LogLevel.Debug); if (added) { DeepWoodsManager.AddBlankDeepWoodsToGameLocations(name); } else { DeepWoodsManager.RemoveDeepWoodsFromGameLocations(name); } } } else { ModEntry.Log(" [" + randId + "] unknown deepwoodsMessageType: " + deepwoodsMessageType + "!", StardewModdingAPI.LogLevel.Warn); return(true); // execute original } } return(false); // don't execute original } return(true); // execute original }