295 lines
12 KiB
C#
295 lines
12 KiB
C#
using Lidgren.Network;
|
|
using ModdedUtilitiesNetworking.Framework.Network;
|
|
using StardewValley;
|
|
using StardewValley.Network;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using Netcode;
|
|
using ModdedUtilitiesNetworking.Framework.Extentions;
|
|
using ModdedUtilitiesNetworking.Framework.Messages;
|
|
|
|
namespace ModdedUtilitiesNetworking.Framework.Clients
|
|
{
|
|
class CustomLidgrenClient : LidgrenClient
|
|
{
|
|
private string address;
|
|
private NetClient client;
|
|
private bool serverDiscovered;
|
|
|
|
public CustomLidgrenClient(string address) : base(address)
|
|
{
|
|
this.address = address;
|
|
}
|
|
|
|
|
|
|
|
public override string getUserID()
|
|
{
|
|
|
|
return "";
|
|
}
|
|
|
|
public virtual NetClient getClient()
|
|
{
|
|
return this.client;
|
|
}
|
|
|
|
protected override string getHostUserName()
|
|
{
|
|
return this.client.ServerConnection.RemoteEndPoint.Address.ToString();
|
|
}
|
|
|
|
protected override void connectImpl()
|
|
{
|
|
NetPeerConfiguration config = new NetPeerConfiguration("StardewValley");
|
|
config.EnableMessageType(NetIncomingMessageType.DiscoveryResponse);
|
|
config.EnableMessageType(NetIncomingMessageType.Data);
|
|
config.ConnectionTimeout = 30f;
|
|
config.PingInterval = 5f;
|
|
config.MaximumTransmissionUnit = 1200;
|
|
this.client = new NetClient(config);
|
|
this.client.Start();
|
|
int serverPort = 24642;
|
|
if (this.address.Contains(":"))
|
|
{
|
|
string[] strArray = this.address.Split(':');
|
|
this.address = strArray[0];
|
|
serverPort = Convert.ToInt32(strArray[1]);
|
|
}
|
|
this.client.DiscoverKnownPeer(this.address, serverPort);
|
|
ModCore.monitor.Log("Success on generating modded lidgren client.");
|
|
}
|
|
|
|
public override void disconnect(bool neatly = true)
|
|
{
|
|
if (this.client.ConnectionStatus != NetConnectionStatus.Disconnected && this.client.ConnectionStatus != NetConnectionStatus.Disconnecting)
|
|
{
|
|
if (neatly)
|
|
this.sendMessage(new OutgoingMessage((byte)19, Game1.player, new object[0]));
|
|
this.client.FlushSendQueue();
|
|
this.client.Disconnect("");
|
|
this.client.FlushSendQueue();
|
|
}
|
|
this.connectionMessage = (string)null;
|
|
}
|
|
|
|
public void disconnect(string leaveMeNULL,bool neatly = true)
|
|
{
|
|
if (this.client.ConnectionStatus != NetConnectionStatus.Disconnected && this.client.ConnectionStatus != NetConnectionStatus.Disconnecting)
|
|
{
|
|
if (neatly)
|
|
this.sendMessage(new OutgoingMessage((byte)19, Game1.player, new object[0]));
|
|
this.client.FlushSendQueue();
|
|
this.client.Disconnect("");
|
|
this.client.FlushSendQueue();
|
|
}
|
|
this.connectionMessage = (string)null;
|
|
}
|
|
|
|
protected virtual bool validateProtocol(string version)
|
|
{
|
|
return version == ModCore.multiplayer.protocolVersion;
|
|
}
|
|
|
|
protected override void receiveMessagesImpl()
|
|
{
|
|
NetIncomingMessage netIncomingMessage;
|
|
while ((netIncomingMessage = this.client.ReadMessage()) != null)
|
|
{
|
|
switch (netIncomingMessage.MessageType)
|
|
{
|
|
case NetIncomingMessageType.ErrorMessage:
|
|
case NetIncomingMessageType.DebugMessage:
|
|
case NetIncomingMessageType.WarningMessage:
|
|
string str = netIncomingMessage.ReadString();
|
|
Console.WriteLine("{0}: {1}", (object)netIncomingMessage.MessageType, (object)str);
|
|
Game1.debugOutput = str;
|
|
continue;
|
|
case NetIncomingMessageType.StatusChanged:
|
|
this.statusChanged(netIncomingMessage);
|
|
continue;
|
|
case NetIncomingMessageType.Data:
|
|
this.parseDataMessageFromServer(netIncomingMessage);
|
|
continue;
|
|
case NetIncomingMessageType.DiscoveryResponse:
|
|
ModCore.monitor.Log("Found server at " + (object)netIncomingMessage.SenderEndPoint);
|
|
if (this.validateProtocol(netIncomingMessage.ReadString()))
|
|
{
|
|
this.serverName = netIncomingMessage.ReadString();
|
|
this.receiveHandshake(netIncomingMessage);
|
|
this.serverDiscovered = true;
|
|
continue;
|
|
}
|
|
this.connectionMessage = "Strings\\UI:CoopMenu_FailedProtocolVersion";
|
|
this.client.Disconnect("");
|
|
continue;
|
|
default:
|
|
continue;
|
|
}
|
|
}
|
|
if (this.client.ServerConnection == null || DateTime.Now.Second % 2 != 0)
|
|
return;
|
|
Game1.debugOutput = "Ping: " + (object)(float)((double)this.client.ServerConnection.AverageRoundtripTime * 1000.0) + "ms";
|
|
}
|
|
|
|
private void receiveHandshake(NetIncomingMessage msg)
|
|
{
|
|
this.client.Connect(msg.SenderEndPoint.Address.ToString(), msg.SenderEndPoint.Port);
|
|
}
|
|
|
|
private void statusChanged(NetIncomingMessage message)
|
|
{
|
|
switch ((NetConnectionStatus)message.ReadByte())
|
|
{
|
|
case NetConnectionStatus.Disconnected:
|
|
case NetConnectionStatus.Disconnecting:
|
|
this.clientRemotelyDisconnected();
|
|
break;
|
|
}
|
|
}
|
|
|
|
private void clientRemotelyDisconnected()
|
|
{
|
|
this.timedOut = true;
|
|
}
|
|
|
|
public override void sendMessage(OutgoingMessage message)
|
|
{
|
|
NetOutgoingMessage message1 = this.client.CreateMessage();
|
|
|
|
using (NetBufferWriteStream bufferWriteStream = new NetBufferWriteStream((NetBuffer)message1))
|
|
{
|
|
using (BinaryWriter writer = new BinaryWriter((Stream)bufferWriteStream))
|
|
{
|
|
if (message.MessageType <20)
|
|
{
|
|
message.Write(writer);
|
|
}
|
|
else
|
|
{
|
|
OutgoingMessageBase.WriteFromMessage(message, writer);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
int num = (int)this.client.SendMessage(message1, NetDeliveryMethod.ReliableOrdered);
|
|
}
|
|
|
|
private void parseDataMessageFromServer(NetIncomingMessage dataMsg)
|
|
{
|
|
using (IncomingMessage message = new IncomingMessage())
|
|
{
|
|
using (NetBufferReadStream bufferReadStream = new NetBufferReadStream((NetBuffer)dataMsg))
|
|
{
|
|
using (BinaryReader reader = new BinaryReader((Stream)bufferReadStream))
|
|
{
|
|
while ((long)dataMsg.LengthBits - dataMsg.Position >= 8L)
|
|
{
|
|
message.Read(reader);
|
|
this.processIncomingMessage(message);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
protected override void processIncomingMessage(IncomingMessage message)
|
|
{
|
|
|
|
byte messageType = message.MessageType;
|
|
if ((uint)messageType <= 9U)
|
|
{
|
|
switch (messageType)
|
|
{
|
|
case 1:
|
|
this.receiveServerIntroduction(message.Reader);
|
|
return;
|
|
case 2:
|
|
this.userNames[message.FarmerID] = message.Reader.ReadString();
|
|
ModCore.multiplayer.processIncomingMessage(message);
|
|
return;
|
|
case 3:
|
|
ModCore.multiplayer.processIncomingMessage(message);
|
|
return;
|
|
case 9:
|
|
this.receiveAvailableFarmhands(message.Reader);
|
|
return;
|
|
}
|
|
}
|
|
else if ((int)messageType != 11)
|
|
{
|
|
if ((int)messageType == 16)
|
|
{
|
|
if (message.FarmerID != Game1.serverHost.Value.UniqueMultiplayerID)
|
|
return;
|
|
this.receiveUserNameUpdate(message.Reader);
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
this.connectionMessage = message.Reader.ReadString();
|
|
return;
|
|
}
|
|
ModCore.multiplayer.processIncomingMessage(message);
|
|
|
|
|
|
//Packet signiture for functions that return nothing.
|
|
if (message.MessageType == Enums.MessageTypes.SendOneWay || message.MessageType == Enums.MessageTypes.SendToAll)
|
|
{
|
|
object[] obj = message.Reader.ReadModdedInfoPacket();
|
|
string functionName = (string)obj[0];
|
|
string classType = (string)obj[1];
|
|
object actualObject = ModCore.processTypesToRead(message.Reader, classType);
|
|
ModCore.processVoidFunction(functionName, actualObject);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
if(message.MessageType == Enums.MessageTypes.SendToSpecific)
|
|
{
|
|
object[] obj = message.Reader.ReadModdedInfoPacket();
|
|
string functionName = (string)obj[0];
|
|
string classType = (string)obj[1];
|
|
object actualObject = ModCore.processTypesToRead(message.Reader, classType);
|
|
DataInfo info = (DataInfo)actualObject;
|
|
|
|
if (info.recipientID == Game1.player.UniqueMultiplayerID.ToString())
|
|
{
|
|
ModCore.processVoidFunction(functionName, actualObject);
|
|
}
|
|
}
|
|
}
|
|
|
|
//message.Reader.ReadChar();
|
|
//Write Binary ententions reader
|
|
|
|
//ModCore.multiplayer.processIncomingMessage(message); //If we don't know how to initially process the message, send it to the multiplayer function.
|
|
}
|
|
|
|
protected override void receiveServerIntroduction(BinaryReader msg)
|
|
{
|
|
Game1.otherFarmers.Roots[Game1.player.UniqueMultiplayerID] = (NetRoot<Farmer>)(Game1.player.NetFields.Root as NetFarmerRoot);
|
|
NetFarmerRoot netFarmerRoot = ModCore.multiplayer.readFarmer(msg);
|
|
long uniqueMultiplayerId = netFarmerRoot.Value.UniqueMultiplayerID;
|
|
Game1.serverHost = netFarmerRoot;
|
|
Game1.serverHost.Value.teamRoot = ModCore.multiplayer.readObjectFull<FarmerTeam>(msg);
|
|
Game1.otherFarmers.Roots.Remove(uniqueMultiplayerId);
|
|
Game1.otherFarmers.Roots.Add(uniqueMultiplayerId, (NetRoot<Farmer>)netFarmerRoot);
|
|
Game1.player.teamRoot = Game1.serverHost.Value.teamRoot;
|
|
Game1.netWorldState = ModCore.multiplayer.readObjectFull<IWorldState>(msg);
|
|
Game1.netWorldState.Clock.InterpolationTicks = 0;
|
|
Game1.netWorldState.Value.WriteToGame1();
|
|
this.setUpGame();
|
|
if (Game1.chatBox == null)
|
|
return;
|
|
//Game1.chatBox.listPlayers();
|
|
}
|
|
}
|
|
}
|