using System;
using System.Collections.Generic;
using System.Linq;
using Lidgren.Network;
using StardewValley.Network;
namespace StardewModdingAPI.Framework.Networking
{
/// Metadata about a connected player.
internal class MultiplayerPeer : IMultiplayerPeer
{
/*********
** Properties
*********/
/// The server through which to send messages, if this is an incoming farmhand.
private readonly SLidgrenServer Server;
/// The client through which to send messages, if this is the host player.
private readonly SLidgrenClient Client;
/// The network connection to the player.
private readonly NetConnection ServerConnection;
/*********
** Accessors
*********/
/// The player's unique ID.
public long PlayerID { get; }
/// Whether this is a connection to the host player.
public bool IsHost { get; }
/// Whether the player has SMAPI installed.
public bool HasSmapi => this.ApiVersion != null;
/// The player's OS platform, if is true.
public GamePlatform? Platform { get; }
/// The installed version of Stardew Valley, if is true.
public ISemanticVersion GameVersion { get; }
/// The installed version of SMAPI, if is true.
public ISemanticVersion ApiVersion { get; }
/// The installed mods, if is true.
public IEnumerable Mods { get; }
/*********
** Public methods
*********/
/// Construct an instance.
/// The player's unique ID.
/// The metadata to copy.
/// The server through which to send messages.
/// The server connection through which to send messages.
/// The client through which to send messages.
/// Whether this is a connection to the host player.
public MultiplayerPeer(long playerID, RemoteContextModel model, SLidgrenServer server, NetConnection serverConnection, SLidgrenClient client, bool isHost)
{
this.PlayerID = playerID;
this.IsHost = isHost;
if (model != null)
{
this.Platform = model.Platform;
this.GameVersion = model.GameVersion;
this.ApiVersion = model.ApiVersion;
this.Mods = model.Mods.Select(mod => new MultiplayerPeerMod(mod)).ToArray();
}
this.Server = server;
this.ServerConnection = serverConnection;
this.Client = client;
}
/// Construct an instance for a connection to an incoming farmhand.
/// The player's unique ID.
/// The metadata to copy, if available.
/// The server through which to send messages.
/// The server connection through which to send messages.
public static MultiplayerPeer ForConnectionToFarmhand(long playerID, RemoteContextModel model, SLidgrenServer server, NetConnection serverConnection)
{
return new MultiplayerPeer(
playerID: playerID,
model: model,
server: server,
serverConnection: serverConnection,
client: null,
isHost: false
);
}
/// Construct an instance for a connection to the host player.
/// The player's unique ID.
/// The metadata to copy.
/// The client through which to send messages.
/// Whether this connection is for the host player.
public static MultiplayerPeer ForConnectionToHost(long playerID, RemoteContextModel model, SLidgrenClient client, bool isHost)
{
return new MultiplayerPeer(
playerID: playerID,
model: model,
server: null,
serverConnection: null,
client: client,
isHost: isHost
);
}
/// Get metadata for a mod installed by the player.
/// The unique mod ID.
/// Returns the mod info, or null if the player doesn't have that mod.
public IMultiplayerPeerMod GetMod(string id)
{
if (string.IsNullOrWhiteSpace(id))
return null;
id = id.Trim();
return this.Mods.FirstOrDefault(mod => mod.ID != null && mod.ID.Equals(id, StringComparison.InvariantCultureIgnoreCase));
}
/// Send a message to the given peer, bypassing the game's normal validation to allow messages before the connection is approved.
/// The message to send.
public void SendMessage(OutgoingMessage message)
{
if (this.IsHost)
this.Client.sendMessage(message);
else
this.Server.SendMessage(this.ServerConnection, message);
}
}
}