using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using BarrageGrab.Forms; using BarrageGrab.Forms.Models; using BarrageGrab.Modles.JsonEntity; using BarrageGrab.Proxy; using Newtonsoft.Json; namespace BarrageGrab { public partial class FormView : Form { static int printCount = 0; WsBarrageServer barServer = AppRuntime.WsServer; WssBarrageGrab grab = AppRuntime.WsServer.Grab; ISystemProxy proxy = AppRuntime.WsServer.Grab.Proxy; private Panel testPanel; private ComboBox cmbPlayers; private ComboBox cmbEventType; private PictureBox picAvatar; private TextBox txtPlayerName; private Label lblPlayerid; private Button btnGeneratePlayers; private Panel inputPanel; private Label lblDynamic1, lblDynamic2; private TextBox txtDynamic1, txtDynamic2; private Button btnSendTest; private Label lblStatus; public FormView() { InitializeComponent(); barServer.OnPrint += WssService_OnPrint; barServer.Grab.Proxy.OnProxyStatus += Proxy_OnProxyStatus; AppRuntime.RoomCaches.OnCache += RoomCaches_OnCache; // 扩大form和panel2高度 this.ClientSize = new Size(687, 650); this.panel2.Height = 390; this.panel1.Top = 392; this.panel1.Height = this.ClientSize.Height - this.panel1.Top - 20; // 固定panel3高度,不让它随panel2拉伸 this.panel3.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right; this.panel3.Height = 159; BuildTestPanel(); // 游戏配置按钮 var btnConfig = new Button { Text = "游戏配置", Width = 100, Left = 10, Top = 90 }; btnConfig.Click += (s, e) => { using (var f = new Forms.ConfigEditorForm()) f.ShowDialog(this); }; this.panel3.Controls.Add(btnConfig); // Settings button var btnSettings = new Button { Text = "设置", Width = 60, Left = 120, Top = 90 }; btnSettings.Click += (s, e) => { using (var f = new Forms.SettingsForm()) f.ShowDialog(this); }; this.panel3.Controls.Add(btnSettings); // 打开游戏按钮 var btnLaunchGame = new Button { Text = "打开游戏", Width = 80, Left = 190, Top = 90 }; btnLaunchGame.Click += (s, e) => { Program.LaunchGame(); }; this.panel3.Controls.Add(btnLaunchGame); // 重新打开游戏按钮 var btnRestartGame = new Button { Text = "重启游戏", Width = 80, Left = 280, Top = 90 }; btnRestartGame.Click += (s, e) => { Program.RestartGame(); }; this.panel3.Controls.Add(btnRestartGame); } private void InitTabPages() { var msgTypes = GetMsgTypes(); foreach (TabPage page in this.tab_filters.TabPages) { page.Padding = new Padding(0) { Left = 5 }; page.Margin = new Padding(0); foreach (Control control in page.Controls) { var panel = control as FlowLayoutPanel; if (panel == null) continue; panel.Padding = new Padding(0); panel.Margin = new Padding(0); foreach (var label in msgTypes) { var ck = new CheckBox() { Text = label.Value, Tag = label.Key, Parent = panel, Padding = new Padding(0), Margin = new Padding(0) }; string type = "console"; if (page == this.tabPage_Ws) { type = "ws"; ck.Checked = AppSetting.Current.PushFilter.Contains(label.Key); } if (page == this.tabPage_Console) { type = "console"; ck.Checked = AppSetting.Current.PrintFilter.Contains(label.Key); } if (page == this.tabPage_Log) { type = "log"; ck.Checked = AppSetting.Current.LogFilter.Contains(label.Key); } ck.Name = $"cbx_bartype_{type}_{label.Key}"; ck.CheckedChanged += Ck_CheckedChanged; panel.Controls.Add(ck); } } } } private void Ck_CheckedChanged(object sender, EventArgs e) { CheckBox cbx = sender as CheckBox; if (cbx == null) return; var selected = GetCheckedBarTypes((FlowLayoutPanel)cbx.Parent); if (cbx.Parent.Parent == this.tabPage_Console) { AppSetting.Current.PrintFilter = selected; } if (cbx.Parent.Parent == this.tabPage_Ws) { AppSetting.Current.PushFilter = selected; } if (cbx.Parent.Parent == this.tabPage_Log) { AppSetting.Current.LogFilter = selected; } AppSetting.Current.Save(); } private int[] GetCheckedBarTypes(FlowLayoutPanel panel) { List list = new List(); foreach (Control ctr in panel.Controls) { var cbk = ctr as CheckBox; if (cbk == null) continue; if (cbk.Checked && cbk.Name.StartsWith("cbx_bartype_")) { list.Add((int)cbk.Tag); } } return list.OrderBy(o => o).ToArray(); } private Dictionary GetMsgTypes() { var dic = new Dictionary(); Type enumType = typeof(PackMsgType); FieldInfo[] fields = enumType.GetFields(BindingFlags.Public | BindingFlags.Static); foreach (var field in fields) { DescriptionAttribute attribute = (DescriptionAttribute)field.GetCustomAttribute(typeof(DescriptionAttribute), false); int value = (int)field.GetValue(null); if (attribute != null && value > 0) { dic.Add(value, attribute.Description); } } return dic; } private void RoomCaches_OnCache(object sender, AppRuntime.RoomCacheManager.RoomCacheEventArgs e) { this.Invoke(new Action(() => { if (e.Model == 0) { var item = new RoomCacheItem(e.RoomInfo); this.label3.Text = $"房间缓存列表({AppRuntime.RoomCaches.RoomInfoCache.Count})"; list_roomCaches.Items.Add(item); } })); } private void FormView_Load(object sender, EventArgs e) { this.txb_wsaddr.Text = barServer.ServerLocation; this.txb_upstreamProxy.Text = proxy.HttpUpstreamProxy; this.cbx_barrageLog.Checked = AppSetting.Current.BarrageLog; InitTabPages(); this.cbx_enableProxy.Checked = SystemProxy.ProxyIsOpen(); } private void Proxy_OnProxyStatus(object sender, Proxy.ProxyEventArgs.SystemProxyChangeEventArgs e) { if (this.Disposing || this.IsDisposed) return; this.Invoke(new Action(() => { this.cbx_enableProxy.Checked = e.Open; })); } private void WssService_OnPrint(object sender, WsBarrageServer.PrintEventArgs e) { //将弹幕输出到richTextBox //颜色转换 Color color = AppSetting.Current.ColorMap[e.MsgType].Item2; string msg = e.Message; this.Invoke(new Action(() => { //输出到richTextBox this.rich_output.SelectionColor = color; this.rich_output.AppendText(msg + "\n"); this.rich_output.ScrollToCaret(); if (++printCount > 10000) { this.rich_output.Clear(); printCount = 0; } })); } private void cbx_enableProxy_CheckedChanged(object sender, EventArgs e) { var checker = (CheckBox)sender; if (checker.Checked) { barServer.Grab.Proxy.RegisterSystemProxy(); } else { barServer.Grab.Proxy.CloseSystemProxy(); } } private void list_roomCaches_DoubleClick(object sender, EventArgs e) { // 获取双击的 ListBox 中的选中项 var selectedItem = list_roomCaches.SelectedItem as RoomCacheItem; if (selectedItem == null) return; var form = new RoomDetail(selectedItem.RoomInfo); form.ShowDialog(); } private void btn_updateUpProxy_Click(object sender, EventArgs e) { var text = this.txb_upstreamProxy.Text; try { proxy.SetUpstreamProxy(text); AppSetting.Current.UpstreamProxy = text; AppSetting.Current.Save(); } catch (Exception ex) { //弹窗提示错误 MessageBox.Show(ex.Message, "设置失败"); } } private void cbx_barrageLog_CheckedChanged(object sender, EventArgs e) { var checker = (CheckBox)sender; AppSetting.Current.BarrageLog = checker.Checked; AppSetting.Current.Save(); } // ==================== 测试面板 ==================== private readonly string DefaultAvatarUrl = "https://aliyun_id_photo_bucket.oss.aliyuncs.com/default_handsome_intl.jpg"; private readonly List<(long Id, string Name)> _testPlayers = new List<(long Id, string Name)>(); private static readonly string[] SampleNames = { "小明", "小红", "玩家001", "铁柱", "翠花", "老六", "大佬666", "战神", "小可爱", "路人甲", "氪金玩家", "欧皇", "非酋", "主播铁粉", "水友123", "弹幕刷屏王", "白嫖党", "榜一大哥", "守塔小兵", "运营总监" }; private void BuildTestPanel() { // 测试面板标题 int yBase = 195; var lblTitle = new Label { Text = "📡 WebSocket 模拟测试", Location = new Point(250, yBase), Size = new Size(200, 18), Font = new Font("微软雅黑", 10, FontStyle.Bold), ForeColor = Color.DarkBlue }; panel2.Controls.Add(lblTitle); // ── 生成按钮 ── btnGeneratePlayers = new Button { Text = "随机生成玩家", Location = new Point(250, yBase + 20), Size = new Size(130, 24), BackColor = Color.LightSteelBlue, UseVisualStyleBackColor = true }; btnGeneratePlayers.Click += BtnGeneratePlayers_Click; panel2.Controls.Add(btnGeneratePlayers); // ── 玩家下拉(含头像) ── cmbPlayers = new ComboBox { Location = new Point(250, yBase + 46), Size = new Size(310, 22), DropDownStyle = ComboBoxStyle.DropDownList, DropDownWidth = 400 }; cmbPlayers.SelectedIndexChanged += CmbPlayers_SelectedIndexChanged; panel2.Controls.Add(cmbPlayers); lblPlayerid = new Label { Text = "ID: --", Location = new Point(565, yBase + 48), Size = new Size(110, 18), ForeColor = Color.Gray }; panel2.Controls.Add(lblPlayerid); // ── 事件类型下拉 ── var lblEvent = new Label { Text = "事件:", Location = new Point(250, yBase + 74), Size = new Size(40, 20) }; panel2.Controls.Add(lblEvent); cmbEventType = new ComboBox { Location = new Point(290, yBase + 72), Size = new Size(130, 22), DropDownStyle = ComboBoxStyle.DropDownList }; cmbEventType.Items.AddRange(new object[] { "弹幕消息", "点赞消息", "礼物消息", "关注消息", "进直播间", "直播间分享", "粉丝团消息" }); cmbEventType.SelectedIndex = 0; cmbEventType.SelectedIndexChanged += CmbEventType_SelectedIndexChanged; panel2.Controls.Add(cmbEventType); // ── 发送按钮 ── btnSendTest = new Button { Text = "发送", Location = new Point(430, yBase + 70), Size = new Size(130, 26), BackColor = Color.Orange, Font = new Font("微软雅黑", 9, FontStyle.Bold), UseVisualStyleBackColor = true }; btnSendTest.Click += BtnSendTest_Click; panel2.Controls.Add(btnSendTest); // ── 动态输入面板 ── inputPanel = new Panel { Location = new Point(248, yBase + 100), Size = new Size(430, 50), BorderStyle = BorderStyle.FixedSingle }; panel2.Controls.Add(inputPanel); lblDynamic1 = new Label { Location = new Point(8, 8), Size = new Size(50, 18), Text = "内容:" }; inputPanel.Controls.Add(lblDynamic1); txtDynamic1 = new TextBox { Location = new Point(60, 6), Size = new Size(200, 21), Text = "测试弹幕666" }; inputPanel.Controls.Add(txtDynamic1); lblDynamic2 = new Label { Location = new Point(8, 30), Size = new Size(50, 18), Text = "" }; inputPanel.Controls.Add(lblDynamic2); txtDynamic2 = new TextBox { Location = new Point(60, 28), Size = new Size(80, 21), Text = "", Visible = false }; inputPanel.Controls.Add(txtDynamic2); // ── 状态 ── lblStatus = new Label { Location = new Point(250, yBase + 155), Size = new Size(425, 18), ForeColor = Color.DimGray }; panel2.Controls.Add(lblStatus); // 初始刷新 RefreshInputPanel(); } private void BtnGeneratePlayers_Click(object sender, EventArgs e) { _testPlayers.Clear(); cmbPlayers.Items.Clear(); var rnd = new Random(); // 生成28个完全随机玩家 for (int i = 0; i < 28; i++) { long id = 10000 + rnd.Next(1, 99999); string name = SampleNames[rnd.Next(SampleNames.Length)]; if (rnd.Next(2) == 0) name += rnd.Next(10, 999).ToString(); _testPlayers.Add((id, name)); cmbPlayers.Items.Add($"{name} (ID:{id})"); } cmbPlayers.SelectedIndex = 0; lblStatus.Text = $"已生成 {_testPlayers.Count} 个测试玩家"; } private void CmbPlayers_SelectedIndexChanged(object sender, EventArgs e) { if (cmbPlayers.SelectedIndex >= 0 && cmbPlayers.SelectedIndex < _testPlayers.Count) { var (id, name) = _testPlayers[cmbPlayers.SelectedIndex]; lblPlayerid.Text = $"ID: {id}"; } } private void CmbEventType_SelectedIndexChanged(object sender, EventArgs e) { RefreshInputPanel(); } private void RefreshInputPanel() { string evt = cmbEventType.SelectedItem?.ToString() ?? ""; switch (evt) { case "弹幕消息": lblDynamic1.Text = "内容:"; txtDynamic1.Visible = true; txtDynamic1.Text = "测试弹幕666"; lblDynamic2.Text = ""; txtDynamic2.Visible = false; break; case "点赞消息": lblDynamic1.Text = "点赞数:"; txtDynamic1.Visible = true; txtDynamic1.Text = "10"; lblDynamic2.Text = ""; txtDynamic2.Visible = false; break; case "礼物消息": lblDynamic1.Text = "礼物名:"; txtDynamic1.Visible = true; txtDynamic1.Text = "小心心"; lblDynamic2.Text = "数量:"; txtDynamic2.Visible = true; txtDynamic2.Text = "1"; break; case "直播间分享": lblDynamic1.Text = "次数:"; txtDynamic1.Visible = true; txtDynamic1.Text = "1"; lblDynamic2.Text = ""; txtDynamic2.Visible = false; break; default: // 关注/进房/粉丝团 lblDynamic1.Text = "无额外参数"; txtDynamic1.Visible = false; lblDynamic2.Text = ""; txtDynamic2.Visible = false; break; } } private void BtnSendTest_Click(object sender, EventArgs e) { try { if (cmbPlayers.SelectedIndex < 0 || cmbPlayers.SelectedIndex >= _testPlayers.Count) { lblStatus.Text = "❌ 请先选择玩家"; return; } var (pid, pname) = _testPlayers[cmbPlayers.SelectedIndex]; string evt = cmbEventType.SelectedItem?.ToString() ?? "弹幕消息"; MsgUser user = new MsgUser { Id = pid, Nickname = pname, HeadImgUrl = DefaultAvatarUrl, DisplayId = pid.ToString(), Level = 10, Gender = 1 }; BarrageMsgPack pack = null; string desc = ""; switch (evt) { case "弹幕消息": { var msg = new Msg { MsgId = DateTime.Now.Ticks, User = user, Content = txtDynamic1.Text, RoomId = "123456" }; pack = new BarrageMsgPack(JsonConvert.SerializeObject(msg), PackMsgType.弹幕消息, "test"); desc = $"弹幕: {txtDynamic1.Text}"; } break; case "点赞消息": { long cnt = long.TryParse(txtDynamic1.Text, out var c) ? c : 1; var msg = new LikeMsg { MsgId = DateTime.Now.Ticks, User = user, Count = cnt, Total = cnt + 100, RoomId = "123456" }; pack = new BarrageMsgPack(JsonConvert.SerializeObject(msg), PackMsgType.点赞消息, "test"); desc = $"点赞 x{cnt}"; } break; case "礼物消息": { long cnt = long.TryParse(txtDynamic2.Text, out var gc) ? gc : 1; var msg = new GiftMsg { MsgId = DateTime.Now.Ticks, User = user, GiftName = txtDynamic1.Text, GiftCount = cnt, GiftId = 100, DiamondCount = 1, RoomId = "123456" }; pack = new BarrageMsgPack(JsonConvert.SerializeObject(msg), PackMsgType.礼物消息, "test"); desc = $"礼物: {txtDynamic1.Text} x{cnt}"; } break; case "关注消息": { var msg = new Msg { MsgId = DateTime.Now.Ticks, User = user, Content = "关注了主播", RoomId = "123456" }; pack = new BarrageMsgPack(JsonConvert.SerializeObject(msg), PackMsgType.关注消息, "test"); desc = "关注主播"; } break; case "进直播间": { var msg = new MemberMessage { MsgId = DateTime.Now.Ticks, User = user, CurrentCount = 999, RoomId = "123456" }; pack = new BarrageMsgPack(JsonConvert.SerializeObject(msg), PackMsgType.进直播间, "test"); desc = "进入直播间"; } break; case "直播间分享": { long cnt = long.TryParse(txtDynamic1.Text, out var sc) ? sc : 1; var msg = new ShareMessage { MsgId = DateTime.Now.Ticks, User = user, ShareType = BarrageGrab.Modles.JsonEntity.ShareType.微信, RoomId = "123456" }; desc = $"分享 x{cnt}"; // 分享用次数送多次 for (int i = 0; i < cnt; i++) { pack = new BarrageMsgPack(JsonConvert.SerializeObject(msg), PackMsgType.直播间分享, "test"); barServer.Broadcast(pack); } lblStatus.Text = $"✅ 已发送: {pname}(ID:{pid}) → {desc}"; return; } case "粉丝团消息": { var msg = new FansclubMsg { MsgId = DateTime.Now.Ticks, User = user, Type = 2, // 加入 Level = 1, RoomId = "123456" }; pack = new BarrageMsgPack(JsonConvert.SerializeObject(msg), PackMsgType.粉丝团消息, "test"); desc = "加入粉丝团"; } break; } if (pack != null) { barServer.Broadcast(pack); lblStatus.Text = $"✅ 已发送: {pname}(ID:{pid}) → {desc}"; } } catch (Exception ex) { lblStatus.Text = $"❌ 发送失败: {ex.Message}"; } } } }