diff --git a/VPet-Simulator.Windows/MainWindow.cs b/VPet-Simulator.Windows/MainWindow.cs
index a5b4a4d..892d8f1 100644
--- a/VPet-Simulator.Windows/MainWindow.cs
+++ b/VPet-Simulator.Windows/MainWindow.cs
@@ -1156,7 +1156,7 @@ namespace VPet_Simulator.Windows
Grid IMainWindow.MGHost => MGHost;
Grid IMainWindow.PetGrid => MGrid;
-
+ internal MWController MWController { get; set; }
///
/// 移除所有聊天对话框
///
@@ -1254,7 +1254,8 @@ namespace VPet_Simulator.Windows
Top = T;
// control position inside bounds
- Core.Controller = new MWController(this);
+ MWController = new MWController(this);
+ Core.Controller = MWController;
Task.Run(() =>
{
double dist;
@@ -1998,7 +1999,7 @@ namespace VPet_Simulator.Windows
}
-
+
#if NewYear
int newyearsay = 0;
diff --git a/VPet-Simulator.Windows/MainWindow.xaml.cs b/VPet-Simulator.Windows/MainWindow.xaml.cs
index e7d2291..a8f7f36 100644
--- a/VPet-Simulator.Windows/MainWindow.xaml.cs
+++ b/VPet-Simulator.Windows/MainWindow.xaml.cs
@@ -21,7 +21,6 @@ using static VPet_Simulator.Core.GraphInfo;
using System.Globalization;
using LinePutScript.Dictionary;
using Steamworks.Data;
-using VPet_Simulator.Windows.WinDesign;
namespace VPet_Simulator.Windows
{
@@ -221,7 +220,7 @@ namespace VPet_Simulator.Windows
if (IsSteamUser)
Dispatcher.Invoke(() =>
{
- Main.ToolBar.AddMenuButton(ToolBar.MenuType.Setting, "访客表".Translate(), () =>
+ Main.ToolBar.AddMenuButton(ToolBar.MenuType.Interact, "访客表".Translate(), () =>
{
if (winMutiPlayer == null)
{
@@ -233,6 +232,15 @@ namespace VPet_Simulator.Windows
winMutiPlayer.Focus();
}
});
+ int clid = Array.IndexOf(App.Args, "connect_lobby");
+ if (clid != -1)
+ {
+ if (ulong.TryParse(App.Args[clid + 1], out ulong lid))
+ {
+ winMutiPlayer = new winMutiPlayer(this, lid);
+ winMutiPlayer.Show();
+ }
+ }
});
});
diff --git a/VPet-Simulator.Windows/MutiPlayer/MPController.cs b/VPet-Simulator.Windows/MutiPlayer/MPController.cs
new file mode 100644
index 0000000..38e651e
--- /dev/null
+++ b/VPet-Simulator.Windows/MutiPlayer/MPController.cs
@@ -0,0 +1,116 @@
+using System.Windows.Forms;
+using System.Windows.Interop;
+using System.Drawing;
+using VPet_Simulator.Core;
+
+namespace VPet_Simulator.Windows
+{
+ ///
+ /// 窗体控制器实现
+ ///
+ public class MPController : IController
+ {
+ readonly MPFriends mp;
+ readonly MainWindow mw;
+ public MPController(MPFriends mp, MainWindow mw)
+ {
+ this.mp = mp;
+ this.mw = mw;
+ }
+
+ public double GetWindowsDistanceLeft()
+ {
+ return mp.Dispatcher.Invoke(() =>
+ {
+ if (mw.MWController.IsPrimaryScreen) return mp.Left;
+ return mp.Left - mw.MWController.ScreenBorder.X;
+ });
+ }
+
+ public double GetWindowsDistanceUp()
+ {
+ return mp.Dispatcher.Invoke(() =>
+ {
+ if (mw.MWController.IsPrimaryScreen) return mp.Top;
+ return mp.Top - mw.MWController.ScreenBorder.Y;
+ });
+ }
+
+ public double GetWindowsDistanceRight()
+ {
+ return mp.Dispatcher.Invoke(() =>
+ {
+ if (mw.MWController.IsPrimaryScreen) return System.Windows.SystemParameters.PrimaryScreenWidth - mp.Left - mp.ActualWidth;
+ return mw.MWController.ScreenBorder.Width + mw.MWController.ScreenBorder.X - mp.Left - mp.ActualWidth;
+ });
+ }
+
+ public double GetWindowsDistanceDown()
+ {
+ return mp.Dispatcher.Invoke(() =>
+ {
+ if (mw.MWController.IsPrimaryScreen) return System.Windows.SystemParameters.PrimaryScreenHeight - mp.Top - mp.ActualHeight;
+ return mw.MWController.ScreenBorder.Height + mw.MWController.ScreenBorder.Y - mp.Top - mp.ActualHeight;
+ });
+ }
+
+ public void MoveWindows(double X, double Y)
+ {
+ mp.Dispatcher.Invoke(() =>
+ {
+ mp.Left += X * ZoomRatio;
+ mp.Top += Y * ZoomRatio;
+ });
+ }
+
+ public void ShowSetting()
+ {
+
+ }
+
+ public void ShowPanel()
+ {
+
+ }
+
+ public void ResetPosition()
+ {
+ mp.Dispatcher.Invoke(() =>
+ {
+ if (GetWindowsDistanceUp() < -0.25 * mp.ActualHeight && GetWindowsDistanceDown() < System.Windows.SystemParameters.PrimaryScreenHeight)
+ {
+ MoveWindows(0, -GetWindowsDistanceUp() / ZoomRatio);
+ }
+ else if (GetWindowsDistanceDown() < -0.25 * mp.ActualHeight && GetWindowsDistanceUp() < System.Windows.SystemParameters.PrimaryScreenHeight)
+ {
+ MoveWindows(0, GetWindowsDistanceDown() / ZoomRatio);
+ }
+ if (GetWindowsDistanceLeft() < -0.25 * mp.ActualWidth && GetWindowsDistanceRight() < System.Windows.SystemParameters.PrimaryScreenWidth)
+ {
+ MoveWindows(-GetWindowsDistanceLeft() / ZoomRatio, 0);
+ }
+ else if (GetWindowsDistanceRight() < -0.25 * mp.ActualWidth && GetWindowsDistanceLeft() < System.Windows.SystemParameters.PrimaryScreenWidth)
+ {
+ MoveWindows(GetWindowsDistanceRight() / ZoomRatio, 0);
+ }
+ });
+ }
+ public bool CheckPosition() => mp.Dispatcher.Invoke(() =>
+ GetWindowsDistanceUp() < -0.25 * mp.ActualHeight && GetWindowsDistanceDown() < System.Windows.SystemParameters.PrimaryScreenHeight
+ || GetWindowsDistanceDown() < -0.25 * mp.ActualHeight && GetWindowsDistanceUp() < System.Windows.SystemParameters.PrimaryScreenHeight
+ || GetWindowsDistanceLeft() < -0.25 * mp.ActualWidth && GetWindowsDistanceRight() < System.Windows.SystemParameters.PrimaryScreenWidth
+ || GetWindowsDistanceRight() < -0.25 * mp.ActualWidth && GetWindowsDistanceLeft() < System.Windows.SystemParameters.PrimaryScreenWidth
+ );
+
+ public bool RePostionActive { get; set; } = true;
+
+ public double ZoomRatio => mw.Set.ZoomLevel;
+
+ public int PressLength => mw.Set.PressLength;
+
+ public bool EnableFunction => true;
+
+ public int InteractionCycle => mw.Set.InteractionCycle;
+
+ }
+}
diff --git a/VPet-Simulator.Windows/MWFriends.xaml b/VPet-Simulator.Windows/MutiPlayer/MPFriends.xaml
similarity index 62%
rename from VPet-Simulator.Windows/MWFriends.xaml
rename to VPet-Simulator.Windows/MutiPlayer/MPFriends.xaml
index 11bd576..b9d3a05 100644
--- a/VPet-Simulator.Windows/MWFriends.xaml
+++ b/VPet-Simulator.Windows/MutiPlayer/MPFriends.xaml
@@ -1,4 +1,4 @@
-
-
-
+
+
+
+
+
diff --git a/VPet-Simulator.Windows/MutiPlayer/MPFriends.xaml.cs b/VPet-Simulator.Windows/MutiPlayer/MPFriends.xaml.cs
new file mode 100644
index 0000000..962b31a
--- /dev/null
+++ b/VPet-Simulator.Windows/MutiPlayer/MPFriends.xaml.cs
@@ -0,0 +1,300 @@
+using LinePutScript.Dictionary;
+using LinePutScript;
+using Panuon.WPF.UI;
+using Steamworks;
+using Steamworks.Data;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using LinePutScript.Localization.WPF;
+using System.Threading;
+using VPet_Simulator.Windows.Interface;
+using VPet_Simulator.Core;
+using static VPet_Simulator.Core.GraphHelper;
+using System.Drawing;
+using Point = System.Windows.Point;
+using Size = System.Windows.Size;
+using static VPet_Simulator.Core.GraphInfo;
+
+namespace VPet_Simulator.Windows;
+///
+/// MPFriends.xaml 的交互逻辑
+///
+public partial class MPFriends : WindowX
+{
+ public Lobby lb;
+ MainWindow mw;
+ public Friend friend;
+ public GameCore Core { get; set; } = new GameCore();
+ public List Foods { get; } = new List();
+ public ImageResources ImageSources { get; }
+ public List Pets { get; set; } = new List();
+ public ILine OnMod { get; set; }
+
+ public string SetPetGraph;
+ public bool IsOnMod(string ModName)
+ {
+ if (CoreMOD.OnModDefList.Contains(ModName))
+ return true;
+ return OnMod.Find(ModName.ToLower()) != null;
+ }
+
+ public MPFriends(MainWindow mw, Lobby lb, Friend friend)
+ {
+ this.mw = mw;
+ this.lb = lb;
+ this.friend = friend;
+
+ mw.Windows.Add(this);
+ try
+ {
+
+ InitializeComponent();
+
+ //MGrid.Height = 500 * mw.Set.ZoomLevel;
+ MGrid.Width = 500 * mw.Set.ZoomLevel;
+
+ double L = 0, T = 0;
+ if (mw.Set.StartRecordLast)
+ {
+ var point = mw.Set.StartRecordLastPoint;
+ if (point.X != 0 || point.Y != 0)
+ {
+ L = point.X;
+ T = point.Y;
+ }
+ }
+ else
+ {
+ var point = mw.Set.StartRecordPoint;
+ L = point.X; T = point.Y;
+ }
+
+ Left = L;
+ Top = T;
+
+ // control position inside bounds
+ Core.Controller = new MPController(this, mw);
+ Task.Run(() =>
+ {
+ double dist;
+ if ((dist = Core.Controller.GetWindowsDistanceLeft()) < 0)
+ {
+ Thread.Sleep(100);
+ Dispatcher.Invoke(() => Left -= dist);
+ }
+ if ((dist = Core.Controller.GetWindowsDistanceRight()) < 0)
+ {
+ Thread.Sleep(100);
+ Dispatcher.Invoke(() => Left += dist);
+ }
+ if ((dist = Core.Controller.GetWindowsDistanceUp()) < 0)
+ {
+ Thread.Sleep(100);
+ Dispatcher.Invoke(() => Top -= dist);
+ }
+ if ((dist = Core.Controller.GetWindowsDistanceDown()) < 0)
+ {
+ Thread.Sleep(100);
+ Dispatcher.Invoke(() => Top += dist);
+ }
+ });
+ if (mw.Set.TopMost)
+ {
+ Topmost = true;
+ }
+
+ }
+ catch
+ {
+ Close();
+ return;
+ }
+
+
+ ImageSources.AddRange(mw.ImageSources);
+
+
+ //加载所有MOD
+ List Path = new List();
+ Path.AddRange(new DirectoryInfo(mw.ModPath).EnumerateDirectories());
+
+ var workshop = mw.Set["workshop"];
+ foreach (Sub ws in workshop)
+ {
+ Path.Add(new DirectoryInfo(ws.Name));
+ }
+
+ Task.Run(async () =>
+ {
+ //加载lobby传过来的数据
+ string tmp = lb.GetMemberData(friend, "save");
+ while (string.IsNullOrEmpty(tmp))
+ {
+ Thread.Sleep(500);
+ tmp = lb.GetMemberData(friend, "save");
+ }
+ Core.Save = GameSave_VPet.Load(new Line(tmp));
+ tmp = lb.GetMemberData(friend, "onmod");
+ while (string.IsNullOrEmpty(tmp))
+ {
+ Thread.Sleep(100);
+ tmp = lb.GetMemberData(friend, "onmod");
+ }
+ OnMod = new Line(tmp);
+
+ tmp = lb.GetMemberData(friend, "petgraph");
+ while (string.IsNullOrEmpty(tmp))
+ {
+ Thread.Sleep(100);
+ tmp = lb.GetMemberData(friend, "onmod");
+ }
+ SetPetGraph = tmp;
+
+ await GameLoad(Path);
+ });
+
+ }
+ public List MPMODs = new List();
+ public Main Main { get; set; }
+ ///
+ /// 加载游戏
+ ///
+ /// MOD地址
+ public async Task GameLoad(List Path)
+ {
+ Path = Path.Distinct().ToList();
+ await Dispatcher.InvokeAsync(new Action(() => LoadingText.Content = "Loading MOD"));
+ //加载mod
+ foreach (DirectoryInfo di in Path)
+ {
+ if (!File.Exists(di.FullName + @"\info.lps"))
+ continue;
+ await Dispatcher.InvokeAsync(new Action(() => LoadingText.Content = $"Loading MOD: {di.Name}"));
+ MPMODs.Add(new MPMOD(di, this));
+ }
+
+ await Dispatcher.InvokeAsync(new Action(() => LoadingText.Content = "尝试加载游戏MOD".Translate()));
+
+ //当前桌宠动画
+ var petloader = Pets.Find(x => x.Name == SetPetGraph);
+ petloader ??= Pets[0];
+
+
+ //加载数据合理化:食物
+ foreach (Food f in Foods)
+ {
+ if (f.IsOverLoad())
+ {
+ f.Price = Math.Max((int)f.RealPrice, 1);
+ f.isoverload = false;
+ }
+ }
+ await Dispatcher.InvokeAsync(new Action(() =>
+ {
+ LoadingText.Content = "尝试加载动画和生成缓存\n该步骤可能会耗时比较长\n请耐心等待".Translate();
+
+ Core.Graph = petloader.Graph(mw.Set.Resolution);
+ Main = new Main(Core);
+
+ //清空资源
+ Main.Resources = Application.Current.Resources;
+ Main.MsgBar.This.Resources = Application.Current.Resources;
+ Main.ToolBar.Resources = Application.Current.Resources;
+ Main.ToolBar.LoadClean();
+
+ LoadingText.Content = "正在加载游戏\n该步骤可能会耗时比较长\n请耐心等待".Translate();
+
+ Main.PlayVoiceVolume = mw.Set.VoiceVolume;
+
+ DisplayGrid.Child = Main;
+ Task.Run(async () =>
+ {
+ while (Main.IsWorking)
+ {
+ Thread.Sleep(100);
+ }
+ await Dispatcher.InvokeAsync(() => LoadingText.Visibility = Visibility.Collapsed);
+ });
+
+
+ Main.SetMoveMode(mw.Set.AllowMove, mw.Set.SmartMove, mw.Set.SmartMoveInterval * 1000);
+ Main.SetLogicInterval(1500);
+ if (mw.Set.MessageBarOutside)
+ Main.MsgBar.SetPlaceOUT();
+
+ Main.WorkCheck = mw.WorkCheck;
+
+
+ //添加捏脸动画(若有)
+ if (Core.Graph.GraphConfig.Data.ContainsLine("pinch"))
+ {
+ var pin = Core.Graph.GraphConfig.Data["pinch"];
+ Main.Core.TouchEvent.Insert(0, new TouchArea(
+ new Point(pin[(gdbe)"px"], pin[(gdbe)"py"]), new Size(pin[(gdbe)"sw"], pin[(gdbe)"sh"])
+ , DisplayPinch, true));
+ }
+ }));
+ }
+ ///
+ /// 显示捏脸情况
+ ///
+ public bool DisplayPinch()
+ {
+ if (Core.Graph.FindGraphs("pinch", AnimatType.A_Start, Core.Save.Mode) == null)
+ {
+ return false;
+ }
+ Main.CountNomal = 0;
+
+ if (Core.Controller.EnableFunction && Core.Save.Strength >= 10 && Core.Save.Feeling < 100)
+ {
+ Core.Save.StrengthChange(-2);
+ Core.Save.FeelingChange(1);
+ Core.Save.Mode = Core.Save.CalMode();
+ Main.LabelDisplayShowChangeNumber(LocalizeCore.Translate("体力-{0:f0} 心情+{1:f0}"), 2, 1);
+ }
+ if (Main.DisplayType.Name == "pinch")
+ {
+ if (Main.DisplayType.Animat == AnimatType.A_Start)
+ return false;
+ else if (Main.DisplayType.Animat == AnimatType.B_Loop)
+ if (Dispatcher.Invoke(() => Main.PetGrid.Tag) is IGraph ig && ig.GraphInfo.Name == "pinch" && ig.GraphInfo.Animat == AnimatType.B_Loop)
+ {
+ ig.IsContinue = true;
+ return true;
+ }
+ else if (Dispatcher.Invoke(() => Main.PetGrid2.Tag) is IGraph ig2 && ig2.GraphInfo.Name == "pinch" && ig2.GraphInfo.Animat == AnimatType.B_Loop)
+ {
+ ig2.IsContinue = true;
+ return true;
+ }
+ }
+ Main.Display("pinch", AnimatType.A_Start, () =>
+ Main.Display("pinch", AnimatType.B_Loop, DisplayPinch_loop));
+ return true;
+ }
+ private void DisplayPinch_loop()
+ {
+ if (Main.isPress && Main.DisplayType.Name == "pinch" && Main.DisplayType.Animat == AnimatType.B_Loop)
+ {
+ if (Core.Controller.EnableFunction && Core.Save.Strength >= 10 && Core.Save.Feeling < 100)
+ {
+ Core.Save.StrengthChange(-2);
+ Core.Save.FeelingChange(1);
+ Core.Save.Mode = Core.Save.CalMode();
+ Main.LabelDisplayShowChangeNumber(LocalizeCore.Translate("体力-{0:f0} 心情+{1:f0}"), 2, 1);
+ }
+ Main.Display("pinch", AnimatType.B_Loop, DisplayPinch_loop);
+ }
+ else
+ {
+ Main.DisplayCEndtoNomal("pinch");
+ }
+ }
+}
diff --git a/VPet-Simulator.Windows/MutiPlayer/MPMOD.cs b/VPet-Simulator.Windows/MutiPlayer/MPMOD.cs
new file mode 100644
index 0000000..6a170a3
--- /dev/null
+++ b/VPet-Simulator.Windows/MutiPlayer/MPMOD.cs
@@ -0,0 +1,129 @@
+using LinePutScript.Converter;
+using LinePutScript.Dictionary;
+using LinePutScript.Localization.WPF;
+using LinePutScript;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Security.Cryptography.X509Certificates;
+using System.Text;
+using System.Threading.Tasks;
+using VPet_Simulator.Core;
+using VPet_Simulator.Windows.Interface;
+
+namespace VPet_Simulator.Windows;
+public class MPMOD
+{
+ public static void LoadImage(MPFriends mw, DirectoryInfo di, string pre = "")
+ {
+ //加载其他放在文件夹的图片
+ foreach (FileInfo fi in di.EnumerateFiles("*.png"))
+ {
+ mw.ImageSources.AddSource(pre + fi.Name.ToLower().Substring(0, fi.Name.Length - 4), fi.FullName);
+ }
+ //加载其他放在文件夹中文件夹的图片
+ foreach (DirectoryInfo fordi in di.EnumerateDirectories())
+ {
+ LoadImage(mw, fordi, pre + fordi.Name + "_");
+ }
+ //加载标志好的图片和图片设置
+ foreach (FileInfo fi in di.EnumerateFiles("*.lps"))
+ {
+ var tmp = new LpsDocument(File.ReadAllText(fi.FullName));
+ if (fi.Name.ToLower().StartsWith("set_"))
+ foreach (var line in tmp)
+ mw.ImageSources.ImageSetting.AddorReplaceLine(line);
+ else
+ mw.ImageSources.AddImages(tmp, di.FullName);
+ }
+ }
+ public string Name { get; set; }
+ public MPMOD(DirectoryInfo directory, MPFriends mw)
+ {
+#if !DEBUG
+ try
+ {
+#endif
+ var Path = directory;
+ LpsDocument modlps = new LpsDocument(File.ReadAllText(directory.FullName + @"\info.lps"));
+ Name = modlps.FindLine("vupmod").Info;
+
+ //MOD未加载时支持翻译
+ foreach (var line in modlps.FindAllLine("lang"))
+ {
+ List ls = new List();
+ foreach (var sub in line)
+ {
+ ls.Add(new Line(sub.Name, sub.info));
+ }
+ LocalizeCore.AddCulture(line.info, ls);
+ }
+ if (!IsOnMOD(mw))
+ {
+ return;
+ }
+
+ foreach (DirectoryInfo di in Path.EnumerateDirectories())
+ {
+ switch (di.Name.ToLower())
+ {
+ case "pet":
+ //宠物模型
+ foreach (FileInfo fi in di.EnumerateFiles("*.lps"))
+ {
+ LpsDocument lps = new LpsDocument(File.ReadAllText(fi.FullName));
+ if (lps.First().Name.ToLower() == "pet")
+ {
+ var name = lps.First().Info;
+ var p = mw.Pets.FirstOrDefault(x => x.Name == name);
+ if (p == null)
+ {
+ p = new PetLoader(lps, di);
+ mw.Pets.Add(p);
+ }
+ else
+ {
+ var dis = new DirectoryInfo(di.FullName + "\\" + lps.First()["path"].Info);
+ p.path.Add(di.FullName + "\\" + lps.First()["path"].Info);
+ p.Config.Set(lps);
+ }
+ }
+ }
+ break;
+ case "food":
+ foreach (FileInfo fi in di.EnumerateFiles("*.lps"))
+ {
+ var tmp = new LpsDocument(File.ReadAllText(fi.FullName));
+ foreach (ILine li in tmp)
+ {
+ if (li.Name != "food")
+ continue;
+ string tmps = li.Find("name").info;
+ mw.Foods.RemoveAll(x => x.Name == tmps);
+ mw.Foods.Add(LPSConvert.DeserializeObject(li));
+ }
+ }
+ break;
+ case "image":
+ LoadImage(mw, di);
+ break;
+ case "lang":
+ foreach (FileInfo fi in di.EnumerateFiles("*.lps"))
+ {
+ LocalizeCore.AddCulture(fi.Name.Substring(0, fi.Name.Length - fi.Extension.Length), new LPS_D(File.ReadAllText(fi.FullName)));
+ }
+ foreach (DirectoryInfo dis in di.EnumerateDirectories())
+ {
+ foreach (FileInfo fi in dis.EnumerateFiles("*.lps"))
+ {
+ LocalizeCore.AddCulture(dis.Name, new LPS_D(File.ReadAllText(fi.FullName)));
+ }
+ }
+ break;
+ }
+ }
+ }
+ public bool IsOnMOD(MPFriends mw) => mw.IsOnMod(Name);
+}
\ No newline at end of file
diff --git a/VPet-Simulator.Windows/MutiPlayer/MPUserControl.xaml b/VPet-Simulator.Windows/MutiPlayer/MPUserControl.xaml
new file mode 100644
index 0000000..b4c8ebb
--- /dev/null
+++ b/VPet-Simulator.Windows/MutiPlayer/MPUserControl.xaml
@@ -0,0 +1,11 @@
+
+
+
+
+
diff --git a/VPet-Simulator.Windows/MWFriends.xaml.cs b/VPet-Simulator.Windows/MutiPlayer/MPUserControl.xaml.cs
similarity index 72%
rename from VPet-Simulator.Windows/MWFriends.xaml.cs
rename to VPet-Simulator.Windows/MutiPlayer/MPUserControl.xaml.cs
index ca0d782..23e6da4 100644
--- a/VPet-Simulator.Windows/MWFriends.xaml.cs
+++ b/VPet-Simulator.Windows/MutiPlayer/MPUserControl.xaml.cs
@@ -1,5 +1,4 @@
-using Panuon.WPF.UI;
-using System;
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -11,16 +10,16 @@ using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
using System.Windows.Shapes;
namespace VPet_Simulator.Windows;
///
-/// MWFriends.xaml 的交互逻辑
+/// MPUserControl.xaml 的交互逻辑
///
-public partial class MWFriends : WindowX
+public partial class MPUserControl : UserControl
{
-
- public MWFriends()
+ public MPUserControl()
{
InitializeComponent();
}
diff --git a/VPet-Simulator.Windows/MutiPlayer/winMutiPlayer.xaml b/VPet-Simulator.Windows/MutiPlayer/winMutiPlayer.xaml
new file mode 100644
index 0000000..2d40a65
--- /dev/null
+++ b/VPet-Simulator.Windows/MutiPlayer/winMutiPlayer.xaml
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+ :
+ :
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/VPet-Simulator.Windows/MutiPlayer/winMutiPlayer.xaml.cs b/VPet-Simulator.Windows/MutiPlayer/winMutiPlayer.xaml.cs
new file mode 100644
index 0000000..5357465
--- /dev/null
+++ b/VPet-Simulator.Windows/MutiPlayer/winMutiPlayer.xaml.cs
@@ -0,0 +1,161 @@
+using LinePutScript;
+using LinePutScript.Localization.WPF;
+using Panuon.WPF.UI;
+using Steamworks;
+using Steamworks.Data;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Shapes;
+
+namespace VPet_Simulator.Windows;
+///
+/// winMutiPlayer.xaml 的交互逻辑
+///
+public partial class winMutiPlayer : Window
+{
+ Steamworks.Data.Lobby lb;
+ MainWindow mw;
+ ///
+ /// 好友宠物模块
+ ///
+ List mFriends = new List();
+ public winMutiPlayer(MainWindow mw, ulong? lobbyid = null)
+ {
+ InitializeComponent();
+ this.mw = mw;
+ if (lobbyid == null)
+ CreateLobby();
+ else
+ JoinLobby(lobbyid);
+ }
+ public async void JoinLobby(ulong? lobbyid)
+ {
+ lb = (await SteamMatchmaking.JoinLobbyAsync((SteamId)lobbyid)).Value;
+ ShowLobbyInfo();
+ }
+ public async void CreateLobby()
+ {
+ lb = (await SteamMatchmaking.CreateLobbyAsync()).Value;
+ lb.SetJoinable(true);
+ lb.SetPublic();
+ swAllowJoin.Visibility = Visibility.Visible;
+ ShowLobbyInfo();
+ }
+ public static BitmapFrame ConvertToImageSource(Steamworks.Data.Image image)
+ {
+ int stride = (int)((image.Width * 32 + 7) / 8); // 32 bits per pixel
+ // Convert RGBA to BGRA
+ for (int i = 0; i < image.Data.Length; i += 4)
+ {
+ byte r = image.Data[i];
+ image.Data[i] = image.Data[i + 2];
+ image.Data[i + 2] = r;
+ }
+ var bitmap = BitmapSource.Create(
+ (int)image.Width,
+ (int)image.Height,
+ 96, 96, // dpi x, dpi y
+ PixelFormats.Bgra32, // Pixel format
+ null, // Bitmap palette
+ image.Data, // Pixel data
+ stride // Stride
+ );
+
+ // Convert to ImageSource
+ var stream = new MemoryStream();
+ var encoder = new PngBitmapEncoder(); // or use another encoder if you want
+ encoder.Frames.Add(BitmapFrame.Create(bitmap));
+ encoder.Save(stream);
+ stream.Seek(0, SeekOrigin.Begin);
+
+ BitmapFrame result = BitmapFrame.Create(stream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad);
+ return result;
+ }
+ public async void ShowLobbyInfo()
+ {
+ lb.SetMemberData("save", mw.GameSavesData.GameSave.ToLine().ToString());
+ lb.SetMemberData("onmod", mw.Set.FindLine("onmod").ToString());
+ lb.SetMemberData("petgraph", mw.Set.PetGraph);
+
+ SteamMatchmaking.OnLobbyDataChanged += SteamMatchmaking_OnLobbyDataChanged;
+ SteamMatchmaking.OnLobbyMemberDataChanged += SteamMatchmaking_OnLobbyMemberDataChanged;
+ SteamMatchmaking.OnLobbyMemberJoined += SteamMatchmaking_OnLobbyMemberJoined;
+ hostName.Text = lb.Owner.Name;
+ lbLid.Text = lb.Id.Value.ToString("x");
+ Steamworks.Data.Image? img = (await lb.Owner.GetMediumAvatarAsync());
+ if (img.HasValue)
+ {
+ HostHead.Source = ConvertToImageSource(img.Value);
+ }
+ else
+ {
+ HostHead.Source = new BitmapImage(new Uri("pack://application:,,,/Res/vpeticon.png"));
+ }
+ }
+
+ private void SteamMatchmaking_OnLobbyMemberJoined(Lobby lobby, Friend friend)
+ {
+ if (lobby.Id == lb.Id)
+ {
+
+ }
+ }
+
+ private void SteamMatchmaking_OnLobbyMemberDataChanged(Lobby lobby, Friend friend)
+ {
+ if (lobby.Id == lb.Id)
+ {
+
+ }
+ }
+
+ private void SteamMatchmaking_OnLobbyDataChanged(Lobby lobby)
+ {
+ if (lobby.Id == lb.Id)
+ {
+
+ }
+ }
+
+ private void Window_Closed(object sender, EventArgs e)
+ {
+ SteamMatchmaking.OnLobbyDataChanged -= SteamMatchmaking_OnLobbyDataChanged;
+ SteamMatchmaking.OnLobbyMemberDataChanged -= SteamMatchmaking_OnLobbyMemberDataChanged;
+ lb.SetMemberData("leave", DateTime.Now.ToString());
+ lb.Leave();
+ foreach (var item in mFriends)
+ {
+ item.Close();
+ }
+ mw.winMutiPlayer = null;
+ }
+
+ private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
+ {
+ if (MessageBoxX.Show("确定要关闭访客表吗?".Translate(), "离开游戏", MessageBoxButton.YesNo) != MessageBoxResult.Yes)
+ {
+ e.Cancel = true;
+ }
+ }
+
+ private void swAllowJoin_Checked(object sender, RoutedEventArgs e)
+ {
+ lb.SetJoinable(true);
+ }
+
+ private void swAllowJoin_Unchecked(object sender, RoutedEventArgs e)
+ {
+ lb.SetJoinable(false);
+ }
+}
diff --git a/VPet-Simulator.Windows/WinDesign/winMutiPlayer.xaml b/VPet-Simulator.Windows/WinDesign/winMutiPlayer.xaml
deleted file mode 100644
index e0bdda9..0000000
--- a/VPet-Simulator.Windows/WinDesign/winMutiPlayer.xaml
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
- :
-
-
-
-
diff --git a/VPet-Simulator.Windows/WinDesign/winMutiPlayer.xaml.cs b/VPet-Simulator.Windows/WinDesign/winMutiPlayer.xaml.cs
deleted file mode 100644
index 3523d96..0000000
--- a/VPet-Simulator.Windows/WinDesign/winMutiPlayer.xaml.cs
+++ /dev/null
@@ -1,54 +0,0 @@
-using Steamworks;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows;
-using System.Windows.Controls;
-using System.Windows.Data;
-using System.Windows.Documents;
-using System.Windows.Input;
-using System.Windows.Media;
-using System.Windows.Media.Imaging;
-using System.Windows.Shapes;
-
-namespace VPet_Simulator.Windows.WinDesign;
-///
-/// winMutiPlayer.xaml 的交互逻辑
-///
-public partial class winMutiPlayer : Window
-{
- Steamworks.Data.Lobby lb;
- MainWindow mw;
- public winMutiPlayer(MainWindow mw, ulong? lobbyid = null)
- {
- InitializeComponent();
- this.mw = mw;
- if (lobbyid == null)
- CreateLobby();
- else
- JoinLobby(lobbyid);
- }
- public async void JoinLobby(ulong? lobbyid)
- {
- lb = (await SteamMatchmaking.JoinLobbyAsync((SteamId)lobbyid)).Value;
- }
- public async void CreateLobby()
- {
- lb = (await SteamMatchmaking.CreateLobbyAsync()).Value;
- lb.SetJoinable(true);
- lb.SetPublic();
-
- }
- public void ShowLobbyInfo()
- {
- hostName.Text = lb.Owner.Name;
- }
-
- private void Window_Closed(object sender, EventArgs e)
- {
- lb.Leave();
- mw.winMutiPlayer = null;
- }
-}