好友联机相关(未完成)

This commit is contained in:
ZouJin 2024-03-16 01:33:56 +08:00
parent d2d977b858
commit 71e1e73d61
12 changed files with 785 additions and 89 deletions

View File

@ -1156,7 +1156,7 @@ namespace VPet_Simulator.Windows
Grid IMainWindow.MGHost => MGHost;
Grid IMainWindow.PetGrid => MGrid;
internal MWController MWController { get; set; }
/// <summary>
/// 移除所有聊天对话框
/// </summary>
@ -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;

View File

@ -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();
}
}
});
});

View File

@ -0,0 +1,116 @@
using System.Windows.Forms;
using System.Windows.Interop;
using System.Drawing;
using VPet_Simulator.Core;
namespace VPet_Simulator.Windows
{
/// <summary>
/// 窗体控制器实现
/// </summary>
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;
}
}

View File

@ -1,4 +1,4 @@
<pu:WindowX x:Class="VPet_Simulator.Windows.MWFriends" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
<pu:WindowX x:Class="VPet_Simulator.Windows.MPFriends" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
@ -9,7 +9,12 @@
<WindowChrome.WindowChrome>
<WindowChrome GlassFrameThickness="-1" />
</WindowChrome.WindowChrome>
<Grid>
<Grid x:Name="MGHost" x:FieldModifier="public">
<Grid x:Name="MGrid" Width="250" Height="Auto" x:FieldModifier="public">
<Label x:Name="LoadingText" HorizontalAlignment="Center" VerticalAlignment="Center"
Background="{DynamicResource DARKPrimaryLight}" Foreground="{DynamicResource DARKPrimaryText}"
Content="Loading" />
<Border x:Name="DisplayGrid" />
</Grid>
</Grid>
</pu:WindowX>

View File

@ -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;
/// <summary>
/// MPFriends.xaml 的交互逻辑
/// </summary>
public partial class MPFriends : WindowX
{
public Lobby lb;
MainWindow mw;
public Friend friend;
public GameCore Core { get; set; } = new GameCore();
public List<Food> Foods { get; } = new List<Food>();
public ImageResources ImageSources { get; }
public List<PetLoader> Pets { get; set; } = new List<PetLoader>();
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<DirectoryInfo> Path = new List<DirectoryInfo>();
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<MPMOD> MPMODs = new List<MPMOD>();
public Main Main { get; set; }
/// <summary>
/// 加载游戏
/// </summary>
/// <param name="Path">MOD地址</param>
public async Task GameLoad(List<DirectoryInfo> 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));
}
}));
}
/// <summary>
/// 显示捏脸情况
/// </summary>
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");
}
}
}

View File

@ -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<ILine> ls = new List<ILine>();
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<Food>(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);
}

View File

@ -0,0 +1,11 @@
<UserControl x:Class="VPet_Simulator.Windows.MPUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:VPet_Simulator.Windows"
mc:Ignorable="d" Margin="5" Width="360" Height="200" >
<Grid>
</Grid>
</UserControl>

View File

@ -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;
/// <summary>
/// MWFriends.xaml 的交互逻辑
/// MPUserControl.xaml 的交互逻辑
/// </summary>
public partial class MWFriends : WindowX
public partial class MPUserControl : UserControl
{
public MWFriends()
public MPUserControl()
{
InitializeComponent();
}

View File

@ -0,0 +1,41 @@
<Window x:Class="VPet_Simulator.Windows.winMutiPlayer" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:VPet_Simulator.Windows" mc:Ignorable="d"
xmlns:pu="https://opensource.panuon.com/wpf-ui"
xmlns:ll="clr-namespace:LinePutScript.Localization.WPF;assembly=LinePutScript.Localization.WPF" Title="xxx的访客表"
MinHeight="400" Width="400" Closed="Window_Closed" FontSize="16" SizeToContent="Height" MaxHeight="800"
ResizeMode="CanMinimize" Closing="Window_Closing">
<Grid>
<Image x:Name="HostHead" Margin="20" Width="80" Height="80" HorizontalAlignment="Left" VerticalAlignment="Top"
Source="/Res/TopLogo2019.PNG" />
<TextBlock HorizontalAlignment="Left" VerticalAlignment="Top" Margin="120,20,0,0"
Foreground="{DynamicResource DARKPrimaryDarker}">
<Run Text="萝莉斯" FontSize="24" FontWeight="Bold" /> <Run Text="{ll:Str 的访客表}" />
<LineBreak />
<Run Text="{ll:Str 主持人}" />: <Run x:Name="hostName" Text="XXX" /><LineBreak />
<Run Text="{ll:Str 访客表ID}" />:
</TextBlock>
<TextBox x:Name="lbLid" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="200,70,0,0"
BorderThickness="0" IsReadOnly="True" Text="1145141919" Background="{DynamicResource DARKPrimaryTrans4}"
Foreground="{DynamicResource DARKPrimaryDarker}" Padding="0" />
<TabControl x:Name="tabControl" HorizontalAlignment="Left" Margin="15,115,15,15">
<TabItem Header="{ll:Str 访客列表}">
<StackPanel Background="{DynamicResource SecondaryLighter}" />
</TabItem>
<TabItem Header="{ll:Str 消息日志}">
<TextBox x:Name="tbLog" Margin="0" BorderThickness="0" Background="{DynamicResource DARKPrimaryTrans4}"
Foreground="{DynamicResource DARKPrimaryDarker}" IsReadOnly="True" VerticalScrollBarVisibility="Visible" />
</TabItem>
</TabControl>
<pu:Switch x:Name="swAllowJoin" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="120,92,20,0"
Background="Transparent" BorderBrush="{DynamicResource PrimaryDark}" BoxHeight="16" BoxWidth="35"
Foreground="{DynamicResource DARKPrimaryDarker}" CheckedBackground="{DynamicResource Primary}"
CheckedBorderBrush="{DynamicResource Primary}" CheckedToggleBrush="{DynamicResource DARKPrimaryText}"
Content="{ll:Str 允许好友加入}" ToggleBrush="{DynamicResource PrimaryDark}" ToggleShadowColor="{x:Null}"
ToggleSize="14" IsChecked="True" Visibility="Collapsed" Checked="swAllowJoin_Checked"
Unchecked="swAllowJoin_Unchecked" />
</Grid>
</Window>

View File

@ -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;
/// <summary>
/// winMutiPlayer.xaml 的交互逻辑
/// </summary>
public partial class winMutiPlayer : Window
{
Steamworks.Data.Lobby lb;
MainWindow mw;
/// <summary>
/// 好友宠物模块
/// </summary>
List<MPFriends> mFriends = new List<MPFriends>();
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);
}
}

View File

@ -1,21 +0,0 @@
<Window x:Class="VPet_Simulator.Windows.WinDesign.winMutiPlayer"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:VPet_Simulator.Windows.WinDesign" mc:Ignorable="d"
xmlns:pu="https://opensource.panuon.com/wpf-ui"
xmlns:ll="clr-namespace:LinePutScript.Localization.WPF;assembly=LinePutScript.Localization.WPF" Title="xxx的访客表"
Height="600" Width="400" Closed="Window_Closed" FontSize="16">
<Grid>
<Image Margin="20" Width="80" Height="80" HorizontalAlignment="Left" VerticalAlignment="Top"
Source="/Res/TopLogo2019.PNG" />
<TextBlock HorizontalAlignment="Left" VerticalAlignment="Top" Margin="120,20,0,0"
Foreground="{DynamicResource DARKPrimaryDarker}">
<Run Text="萝莉斯" FontSize="24" FontWeight="Bold" /> <Run Text="{ll:Str 的访客表}" />
<LineBreak />
<Run Text="{ll:Str 主持人}" />: <Run x:Name="hostName" Text="XXX" />
</TextBlock>
<StackPanel />
</Grid>
</Window>

View File

@ -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;
/// <summary>
/// winMutiPlayer.xaml 的交互逻辑
/// </summary>
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;
}
}