支持联机接口 代码插件现在可以制作联机功能

This commit is contained in:
ZouJin
2024-03-19 23:14:19 +08:00
parent e3f2c51c4d
commit 7907dd5f9a
7 changed files with 179 additions and 27 deletions

View File

@ -1,5 +1,6 @@
using LinePutScript;
using LinePutScript.Dictionary;
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
@ -164,6 +165,10 @@ namespace VPet_Simulator.Windows.Interface
/// 主窗体 Pet Grid
/// </summary>
Grid PetGrid { get; }
/// <summary>
/// 当创建/加入新的多人联机窗口(访客表)时触发
/// </summary>
event Action<IMPWindows> MutiPlayerHandle;
}
}

View File

@ -0,0 +1,56 @@
using LinePutScript;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VPet_Simulator.Core;
using static VPet_Simulator.Windows.Interface.MPMessage;
namespace VPet_Simulator.Windows.Interface;
/// <summary>
/// 好友的宠物(图形)模块接口
/// </summary>
public interface IMPFriend
{
/// <summary>
/// 访客表id
/// </summary>
ulong LobbyID { get; }
/// <summary>
/// 好友id
/// </summary>
ulong FriendID { get; }
/// <summary>
/// 桌宠数据核心
/// </summary>
GameCore Core { get; }
/// <summary>
/// 图像资源集
/// </summary>
ImageResources ImageSources { get; }
/// <summary>
/// 当前宠物图形名称
/// </summary>
string SetPetGraph { get; }
/// <summary>
/// 桌宠主要部件
/// </summary>
Main Main { get; }
/// <summary>
/// 智能化显示后续过度动画
/// </summary>
void DisplayAuto(GraphInfo gi);
/// <summary>
/// 根据好友数据显示动画
/// </summary>
bool DisplayGraph(GraphInfo gi);
/// <summary>
/// 显示好友之间聊天消息
/// </summary>
/// <param name="msg">聊天内容</param>
void DisplayMessage(Chat msg);
}

View File

@ -0,0 +1,61 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VPet_Simulator.Windows.Interface;
/// <summary>
/// 多人联机窗口接口 (访客表)
/// </summary>
public interface IMPWindows
{
/// <summary>
/// 访客表id
/// </summary>
ulong LobbyID { get; }
/// <summary>
/// 所有好友(不包括自己)
/// </summary>
IEnumerable<IMPFriend> Friends { get; }
/// <summary>
/// 主持人SteamID
/// </summary>
ulong OwnerID { get; }
/// <summary>
/// 事件:成员退出
/// </summary>
event Action<ulong> OnMemberLeave;
/// <summary>
/// 事件:成员加入
/// </summary>
event Action<ulong> OnMemberJoined;
/// <summary>
/// 给指定好友发送消息(数据包)
/// </summary>
/// <param name="friendid">好友id</param>
/// <param name="msg">消息内容(数据包)</param>
void SendMessage(ulong friendid, MPMessage msg);
/// <summary>
/// 给所有人发送消息
/// </summary>
void SendMessageALL(MPMessage msg);
/// <summary>
/// 发送日志消息
/// </summary>
/// <param name="message">日志</param>
void Log(string message);
/// <summary>
/// 收到消息日志 发送人id, 消息内容
/// </summary>
event Action<ulong, MPMessage> ReceivedMessage;
/// <summary>
/// 事件: 结束访客表, 窗口关闭
/// </summary>
event Action ClosingMutiPlayer;
}

View File

@ -48,7 +48,7 @@ public struct MPMessage
/// <summary>
/// 消息类型
/// </summary>
[Line] public MSGType Type { get; set; }
[Line] public int Type { get; set; }
/// <summary>
/// 消息内容

View File

@ -2003,6 +2003,13 @@ namespace VPet_Simulator.Windows
}
TextBlock tlvplus;
public event Action<IMPWindows> MutiPlayerHandle;
internal void MutiPlayerStart(IMPWindows mp)
{
MutiPlayerHandle?.Invoke(mp);
}
private void MWUIHandle(Main main)
{
if (Main.ToolBar.BdrPanel.Visibility == Visibility.Visible)

View File

@ -30,7 +30,7 @@ namespace VPet_Simulator.Windows;
/// <summary>
/// MPFriends.xaml 的交互逻辑
/// </summary>
public partial class MPFriends : WindowX
public partial class MPFriends : WindowX, IMPFriend
{
public Lobby lb;
MainWindow mw;
@ -42,7 +42,7 @@ public partial class MPFriends : WindowX
public List<PetLoader> Pets { get; set; } = new List<PetLoader>();
public ILine OnMod { get; set; }
public string SetPetGraph;
public string SetPetGraph { get; set; }
public bool IsOnMod(string ModName)
{
if (CoreMOD.OnModDefList.Contains(ModName))
@ -166,6 +166,11 @@ public partial class MPFriends : WindowX
}
public List<MPMOD> MPMODs = new List<MPMOD>();
public Main Main { get; set; }
public ulong LobbyID => lb.Id;
public ulong FriendID => friend.Id;
/// <summary>
/// 加载游戏
/// </summary>
@ -446,7 +451,7 @@ public partial class MPFriends : WindowX
Task.Run(() =>
{
MPMessage msg = new MPMessage();
msg.Type = MSGType.Chat;
msg.Type = (int)MSGType.Chat;
msg.SetContent(new Chat() { Content = cont, ChatType = (Chat.Type)talktype, SendName = SteamClient.Name });
msg.To = SteamClient.SteamId;

View File

@ -9,6 +9,7 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
@ -28,7 +29,7 @@ namespace VPet_Simulator.Windows;
/// <summary>
/// winMutiPlayer.xaml 的交互逻辑
/// </summary>
public partial class winMutiPlayer : Window
public partial class winMutiPlayer : Window, IMPWindows
{
Steamworks.Data.Lobby lb;
MainWindow mw;
@ -108,7 +109,12 @@ public partial class winMutiPlayer : Window
BitmapFrame result = BitmapFrame.Create(stream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad);
return result;
}
ulong owner;
public ulong OwnerID { get; set; }
public ulong LobbyID => lb.Id.Value;
public IEnumerable<IMPFriend> Friends => MPFriends;
public void ShowLobbyInfo()
{
_ = Task.Run(async () =>
@ -117,7 +123,6 @@ public partial class winMutiPlayer : Window
lb.SetMemberData("onmod", mw.Set.FindLine("onmod")?.ToString() ?? "onmod");
lb.SetMemberData("petgraph", mw.Set.PetGraph);
SteamMatchmaking.OnLobbyDataChanged += SteamMatchmaking_OnLobbyDataChanged;
SteamMatchmaking.OnLobbyMemberJoined += SteamMatchmaking_OnLobbyMemberJoined;
SteamMatchmaking.OnLobbyMemberLeave += SteamMatchmaking_OnLobbyMemberLeave;
Steamworks.Data.Image? img = await lb.Owner.GetMediumAvatarAsync();
@ -125,7 +130,7 @@ public partial class winMutiPlayer : Window
Dispatcher.Invoke(() =>
{
hostName.Text = lb.Owner.Name;
owner = lb.Owner.Id.Value;
OwnerID = lb.Owner.Id.Value;
lbLid.Text = lb.Id.Value.ToString("x");
HostHead.Source = ConvertToImageSource(img.Value);
});
@ -175,13 +180,16 @@ public partial class winMutiPlayer : Window
});
});
}
mw.MutiPlayerStart(this);
LoopP2PPacket();
});
}
public event Action<ulong> OnMemberLeave;
private void SteamMatchmaking_OnLobbyMemberLeave(Lobby lobby, Friend friend)
{
if (friend.Id == owner)
if (lobby.Id != lb.Id) return;
OnMemberLeave?.Invoke(friend.Id);
if (friend.Id == OwnerID)
{
Task.Run(() => MessageBox.Show("访客表已被房主{0}关闭".Translate(friend.Name)));
lb = default(Lobby);
@ -212,7 +220,7 @@ public partial class winMutiPlayer : Window
return;
lastgraph = info;
MPMessage msg = new MPMessage();
msg.Type = MSGType.DispayGraph;
msg.Type = (int)MSGType.DispayGraph;
msg.SetContent(info);
msg.To = SteamClient.SteamId.Value;
SendMessageALL(msg);
@ -220,8 +228,6 @@ public partial class winMutiPlayer : Window
/// <summary>
/// 给指定好友发送消息
/// </summary>
/// <param name="mpf"></param>
/// <param name="msg"></param>
public void SendMessage(ulong friendid, MPMessage msg)
{
byte[] data = ConverTo(msg);
@ -240,7 +246,19 @@ public partial class winMutiPlayer : Window
}
}
/// <summary>
/// 发送日志消息
/// </summary>
/// <param name="message">日志</param>
public void Log(string message)
{
Dispatcher.Invoke(() => tbLog.AppendText($"[{DateTime.Now.ToShortTimeString()}]{message}\n"));
}
/// <summary>
/// 事件:成员加入
/// </summary>
public event Action<ulong> OnMemberJoined;
private void SteamMatchmaking_OnLobbyMemberJoined(Lobby lobby, Friend friend)
{
if (lobby.Id == lb.Id)
@ -251,15 +269,7 @@ public partial class winMutiPlayer : Window
var mpuc = new MPUserControl(this, mpf);
MUUCList.Children.Add(mpuc);
MPUserControls.Add(mpuc);
}
}
private void SteamMatchmaking_OnLobbyDataChanged(Lobby lobby)
{
if (lobby.Id == lb.Id)
{
OnMemberJoined?.Invoke(friend.Id);
}
}
private void LoopP2PPacket()
@ -272,15 +282,17 @@ public partial class winMutiPlayer : Window
var packet = SteamNetworking.ReadP2PPacket();
if (packet.HasValue)
{
var From = packet.Value.SteamId;
SteamId From = packet.Value.SteamId;
var MSG = ConverTo(packet.Value.Data);
var To = MPFriends.Find(x => x.friend.Id == MSG.To);
ReceivedMessage?.Invoke(From.Value, MSG);
switch (MSG.Type)
{
case MSGType.DispayGraph:
case (int)MSGType.DispayGraph:
var To = MPFriends.Find(x => x.friend.Id == MSG.To);
To.DisplayGraph(MSG.GetContent<GraphInfo>());
break;
case MSGType.Chat:
case (int)MSGType.Chat:
To = MPFriends.Find(x => x.friend.Id == MSG.To);
To.DisplayMessage(MSG.GetContent<Chat>());
break;
}
@ -294,9 +306,10 @@ public partial class winMutiPlayer : Window
}
}
public event Action<ulong, MPMessage> ReceivedMessage;
private void Window_Closed(object sender, EventArgs e)
{
SteamMatchmaking.OnLobbyDataChanged -= SteamMatchmaking_OnLobbyDataChanged;
mw.Main.GraphDisplayHandler -= Main_GraphDisplayHandler;
SteamMatchmaking.OnLobbyMemberJoined -= SteamMatchmaking_OnLobbyMemberJoined;
lb.Leave();
@ -307,6 +320,10 @@ public partial class winMutiPlayer : Window
mw.winMutiPlayer = null;
}
bool isOPEN = true;
/// <summary>
/// 事件: 结束访客表, 窗口关闭
/// </summary>
public event Action ClosingMutiPlayer;
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
if (!lb.Equals(default(Lobby)))
@ -315,6 +332,7 @@ public partial class winMutiPlayer : Window
e.Cancel = true;
return;
}
ClosingMutiPlayer?.Invoke();
isOPEN = false;
}