private void SendModMessage(string messageText, string messageType, string receiverModID, long receiverID) { AuthDewMessage message = new AuthDewMessage(); message.messageSenderId = senderId; message.messageBody = messageText; this.Helper.Multiplayer.SendMessage <AuthDewMessage>(message, messageType, modIDs: new[] { receiverModID }, playerIDs: new[] { receiverID }); this.Monitor.Log($"sent message of type {messageType}, with senderID {message.messageSenderId}" + $"and text |{message.messageBody}| to player {receiverID}"); }
private bool IsApiCompatible(AuthDewMessage message) { if (message.messageApiMajor >= 1 && message.messageApiMinor >= 0 && message.messageApiPatch >= 0) { return(true); } else { return(false); } }
private void OnModMessageReceived(object sender, ModMessageReceivedEventArgs e) { // if player isn't host, just return // TODO: uncomment or implement otherwise if (!CheckIfServer()) { return; } // HOST: receive authCode, inviteCode, confirmation of received authCode // DEBUG/DEVELOPMENT STUFF - TODO: remove when testing done. this.Monitor.Log($"received message of type {e.Type} by mod {e.FromModID} from " + $"player {e.FromPlayerID}, is the player host? " + $"{this.Helper.Multiplayer.GetConnectedPlayer(e.FromPlayerID).IsHost}"); this.Monitor.Log($"comparing remote mod ID {e.FromModID} to this.ModManifest.UniqueID " + $"{this.ModManifest.UniqueID}"); AuthDewMessage message = e.ReadAs <AuthDewMessage>(); // TODO: make this check optional to allow other server software to interact with the API if (e.FromModID != "thfr.AuthDew") { this.Monitor.Log($"received message from a mod that's not thfr.AuthDew: {e.FromModID}"); return; } if (!IsApiCompatible(message)) { if (ApiCompatibleBool) { this.Monitor.Log($"ERROR: received message with incompatible API version " + $"{message.messageApiMajor}." + $"{message.messageApiMinor}." + $"{message.messageApiPatch}"); ApiCompatibleBool = false; } // send message to sending player indicating API incompatibility SendModMessage("", "ApiIncompatible", "thfr.AuthDew", e.FromPlayerID); return; } isServer = true; // this one may be redundant ApiCompatibleBool = true; string farmerName = Game1.getFarmer(e.FromPlayerID).Name; PlayerSlot slotToRemove = null; switch (e.Type) { case "authResponse": this.Monitor.Log($"received authResponse from {e.FromPlayerID} " + $"(Farmer {farmerName} " + $"with text {message.messageBody}"); // player should exist in serverAuthTable // compare message.messageBody to entry in serverAuthTable // if correct, remove e.FromPlayerID from the needAuthList // if incorrect, kick player foreach (PlayerSlot slot in PlayersNeedInvite) { if (slot.Peer.PlayerID == e.FromPlayerID) { slotToRemove = slot; } } if (serverAuthTable[farmerName] == message.messageBody) { // nothing } else { SendDirectMessage(e.FromPlayerID, "Authentication response did not match. Disconnecting..."); //KickPlayer(e.FromPlayerID); this.PlayersToKick.Add(new PlayerSlot { Peer = slotToRemove.Peer, CountDownSeconds = this.SecondsUntilKick }); } this.Monitor.Log($"removing player {e.FromPlayerID} " + $"(Farmer {farmerName} from the PlayersNeedAuth list"); PlayersNeedAuth.Remove(slotToRemove); break; case "inviteCodeResponse": this.Monitor.Log($"received inviteCodeResponse from {e.FromPlayerID} " + $"with text {message.messageBody}"); // player should exist in inviteCodeTable // if exists, compare e.ReadAs<MPAuthModMessage>().messageBody to entry in inviteCodeTable // if correct, remove e.FromPlayerID from the needInviteCodeList // if incorrect, kick player foreach (PlayerSlot slot in PlayersNeedInvite) { if (slot.Peer.PlayerID == e.FromPlayerID) { slotToRemove = slot; } } if (this.Config.serverInviteCode == message.messageBody) { //nothing } else { SendDirectMessage(e.FromPlayerID, "Invite Code did not match. Disconnecting..."); this.PlayersToKick.Add(new PlayerSlot { Peer = slotToRemove.Peer, CountDownSeconds = this.SecondsUntilKick }); } this.Monitor.Log($"removing player {e.FromPlayerID} " + $"(Farmer {farmerName} from the PlayersNeedInvite list"); PlayersNeedInvite.Remove(slotToRemove); break; case "confirmNewAuth": this.Monitor.Log($"received confirmNewAuth from {e.FromPlayerID} " + $"with text {message.messageBody}"); // Check #1: is e.FromPlayerID in the the unconfirmedAuths? if (!unconfirmedNewAuths.ContainsKey(e.FromPlayerID)) { this.Monitor.Log($"ERROR: received confirmNewAuth message from player {e.FromPlayerID} " + "who is not in unconfirmedNewAuths"); break; } // TODO: This should only be done if the farmerName has been finalized. The onus for this // may need to be on the client mod. // Check #2: Does the name provided in messageBody match the entry in unconfirmedAuths? if (!(unconfirmedNewAuths[e.FromPlayerID].Key == message.messageBody)) { this.Monitor.Log($"ERROR: received confirmNewAuth message from player " + $"{e.FromPlayerID} with name mismatch (" + $"server: {unconfirmedNewAuths[e.FromPlayerID].Key}, " + $"client message: {message.messageBody}"); break; } // If checks #1 and #2 pass, add to serverAuthTable serverAuthTable.Add(unconfirmedNewAuths[e.FromPlayerID].Key, unconfirmedNewAuths[e.FromPlayerID].Value); unconfirmedNewAuths.Remove(e.FromPlayerID); break; case "ApiIncompatible": this.Monitor.Log($"WARNING: received ApiIncompatible message from {e.FromPlayerID} with " + $"message body {message.messageBody}"); // TODO: add handler for "ApiIncompatible" message type break; default: this.Monitor.Log($"received message of unknown type from {e.FromPlayerID}"); break; } }