Debug_interface - success Server Communicate

This commit is contained in:
JackPWY 2025-04-03 12:19:36 +08:00
parent fdefca0555
commit ccc933d4f5
13 changed files with 743 additions and 446 deletions

View File

@ -1,4 +1,6 @@
//using installer.ViewModel;
//ConfigDataFile.cs
//using installer.ViewModel;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;

View File

@ -1,4 +1,5 @@
using System.Collections.Concurrent;
//Logger.cs
using System.Collections.Concurrent;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.IO;

View File

@ -0,0 +1,327 @@
//using System;
//using System.Threading.Tasks;
//using intaller.Data;
//using installer.Utils;
//using debug_interface.Utils;
//using THUAI8.Proto; // 确保这是你实际的Proto命名空间
//namespace debug_interface.Services
//{
// public class ServerCommunicationService
// {
// private readonly DebugConfig _config;
// private readonly Logger _logger;
// private Channel _channel;
// private DebugInterface.DebugInterfaceClient _client; // 使用你的Proto定义的客户端类
// private AsyncServerStreamingCall<MessageToClient> _responseStream;
// private bool _isConnected = false;
// private bool _isSpectatorMode = false;
// public ServerCommunicationService(
// IConfiguration configuration,
// Logger logger)
// {
// _config = configuration.GetSection("DebugConfig").Get<DebugConfig>();
// _logger = logger;
// }
// public bool IsConnected => _isConnected;
// public async Task ConnectToServer()
// {
// try
// {
// string ip = _config.Commands.IP;
// string port = _config.Commands.Port;
// long playerID = long.Parse(_config.Commands.PlayerID);
// long teamID = long.Parse(_config.Commands.TeamID);
// _logger.LogInfo($"正在连接到服务器 {ip}:{port}");
// _logger.LogInfo($"玩家ID: {playerID}, 队伍ID: {teamID}");
// if (playerID > 2023)
// {
// _isSpectatorMode = true;
// _logger.LogInfo("启用观察者模式");
// }
// // 创建连接地址
// string connect = $"{ip}:{port}";
// _logger.LogInfo($"创建gRPC通道: {connect}");
// // 创建Channel
// _channel = new Channel(connect, ChannelCredentials.Insecure);
// // 创建客户端
// _client = new DebugInterface.DebugInterfaceClient(_channel);
// _logger.LogInfo("创建gRPC客户端成功");
// // 创建玩家消息
// PlayerMsg playerMsg = new PlayerMsg();
// playerMsg.PlayerId = playerID;
// playerMsg.TeamId = teamID;
// // 如果不是观察者模式,设置附加信息
// if (!_isSpectatorMode)
// {
// // 设置Ship类型等信息
// int shipTypeID = int.Parse(_config.Commands.ShipType);
// ShipType shipType = (ShipType)shipTypeID;
// playerMsg.ShipType = shipType;
// _logger.LogInfo($"玩家舰船类型: {shipType}");
// }
// // 连接到服务器
// _logger.LogInfo("尝试连接服务器...");
// _responseStream = _client.AddPlayer(playerMsg);
// _logger.LogInfo("成功获取服务器响应流");
// _isConnected = true;
// _logger.LogInfo("成功连接到服务器!");
// // 开始接收服务器消息
// StartReceivingMessages();
// }
// catch (RpcException ex)
// {
// _isConnected = false;
// _logger.LogError($"gRPC连接错误: {ex.Status.Detail}");
// _logger.LogError($"错误状态码: {ex.Status.StatusCode}");
// }
// catch (Exception ex)
// {
// _isConnected = false;
// _logger.LogError($"连接失败: {ex.Message}");
// _logger.LogError($"异常类型: {ex.GetType().FullName}");
// if (ex.InnerException != null)
// {
// _logger.LogError($"内部异常: {ex.InnerException.Message}");
// }
// }
// }
// private async void StartReceivingMessages()
// {
// try
// {
// _logger.LogInfo("开始接收服务器消息...");
// while (_responseStream != null && await _responseStream.ResponseStream.MoveNext())
// {
// _logger.LogInfo("收到服务器消息");
// // 获取当前消息
// MessageToClient message = _responseStream.ResponseStream.Current;
// // 处理游戏状态
// switch (message.GameState)
// {
// case GameState.GameStart:
// _logger.LogInfo("游戏开始");
// ProcessGameStart(message);
// break;
// case GameState.GameRunning:
// _logger.LogInfo("游戏运行中");
// ProcessGameRunning(message);
// break;
// case GameState.GameEnd:
// _logger.LogInfo("游戏结束");
// ProcessGameEnd(message);
// break;
// }
// }
// _logger.LogInfo("服务器消息流结束");
// }
// catch (Exception ex)
// {
// _logger.LogError($"接收消息时发生错误: {ex.Message}");
// _isConnected = false;
// }
// }
// private void ProcessGameStart(MessageToClient message)
// {
// try
// {
// _logger.LogInfo("处理游戏开始消息");
// // 处理对象消息
// foreach (var obj in message.ObjMessage)
// {
// ProcessObjectMessage(obj);
// }
// // 处理全局消息
// _logger.LogInfo($"红方能量: {message.AllMessage.RedTeamEnergy}, 蓝方能量: {message.AllMessage.BlueTeamEnergy}");
// _logger.LogInfo($"红方血量: {message.AllMessage.RedHomeHp}, 蓝方血量: {message.AllMessage.BlueHomeHp}");
// _logger.LogInfo($"红方分数: {message.AllMessage.RedTeamScore}, 蓝方分数: {message.AllMessage.BlueTeamScore}");
// }
// catch (Exception ex)
// {
// _logger.LogError($"处理游戏开始消息时发生错误: {ex.Message}");
// }
// }
// private void ProcessGameRunning(MessageToClient message)
// {
// try
// {
// _logger.LogInfo("处理游戏运行消息");
// // 处理对象消息
// foreach (var obj in message.ObjMessage)
// {
// ProcessObjectMessage(obj);
// }
// // 处理全局消息
// _logger.LogInfo($"红方能量: {message.AllMessage.RedTeamEnergy}, 蓝方能量: {message.AllMessage.BlueTeamEnergy}");
// }
// catch (Exception ex)
// {
// _logger.LogError($"处理游戏运行消息时发生错误: {ex.Message}");
// }
// }
// private void ProcessGameEnd(MessageToClient message)
// {
// try
// {
// _logger.LogInfo("处理游戏结束消息");
// // 处理对象消息
// foreach (var obj in message.ObjMessage)
// {
// ProcessObjectMessage(obj);
// }
// // 处理全局消息
// _logger.LogInfo($"红方最终分数: {message.AllMessage.RedTeamScore}, 蓝方最终分数: {message.AllMessage.BlueTeamScore}");
// }
// catch (Exception ex)
// {
// _logger.LogError($"处理游戏结束消息时发生错误: {ex.Message}");
// }
// }
// private void ProcessObjectMessage(MessageOfObj obj)
// {
// try
// {
// switch (obj.MessageOfObjCase)
// {
// case MessageOfObj.MessageOfObjOneofCase.ShipMessage:
// _logger.LogInfo($"舰船位置: ({obj.ShipMessage.X}, {obj.ShipMessage.Y})");
// break;
// case MessageOfObj.MessageOfObjOneofCase.MapMessage:
// _logger.LogInfo("收到地图信息");
// break;
// case MessageOfObj.MessageOfObjOneofCase.BulletMessage:
// _logger.LogInfo($"子弹位置: ({obj.BulletMessage.X}, {obj.BulletMessage.Y})");
// break;
// // 可以添加其他消息类型的处理
// }
// }
// catch (Exception ex)
// {
// _logger.LogError($"处理对象消息时发生错误: {ex.Message}");
// }
// }
// public async Task DisconnectFromServer()
// {
// if (!_isConnected) return;
// try
// {
// _logger.LogInfo("正在断开服务器连接...");
// // 关闭响应流
// _responseStream?.Dispose();
// // 关闭通道
// if (_channel != null)
// {
// await _channel.ShutdownAsync();
// }
// _isConnected = false;
// _logger.LogInfo("已断开服务器连接");
// }
// catch (Exception ex)
// {
// _logger.LogError($"断开连接时发生错误: {ex.Message}");
// }
// }
// public async Task SendCommand(string command)
// {
// if (!_isConnected || _client == null)
// {
// _logger.LogWarning("无法发送命令:未连接到服务器");
// return;
// }
// try
// {
// _logger.LogInfo($"发送命令: {command}");
// // 这里需要根据实际的Proto定义来实现命令发送
// // 以下代码仅作为示例
// if (command.StartsWith("move"))
// {
// string direction = command.Substring(5);
// double angle = 0;
// switch (direction.ToLower())
// {
// case "up": angle = Math.PI; break;
// case "down": angle = 0; break;
// case "left": angle = Math.PI * 3 / 2; break;
// case "right": angle = Math.PI / 2; break;
// }
// MoveMsg moveMsg = new MoveMsg
// {
// PlayerId = long.Parse(_config.Commands.PlayerID),
// TeamId = long.Parse(_config.Commands.TeamID),
// Angle = angle,
// TimeInMilliseconds = 100
// };
// await _client.MoveAsync(moveMsg);
// _logger.LogInfo("移动命令已发送");
// }
// else if (command.StartsWith("attack"))
// {
// AttackMsg attackMsg = new AttackMsg
// {
// PlayerId = long.Parse(_config.Commands.PlayerID),
// TeamId = long.Parse(_config.Commands.TeamID),
// Angle = 0 // 或者根据需要设置角度
// };
// await _client.AttackAsync(attackMsg);
// _logger.LogInfo("攻击命令已发送");
// }
// // 添加其他命令的处理
// }
// catch (Exception ex)
// {
// _logger.LogError($"发送命令时发生错误: {ex.Message}");
// }
// }
// public void CleanUp()
// {
// _responseStream?.Dispose();
// _channel?.Dispose();
// }
// }
//}

View File

@ -1,30 +1,31 @@
//ViewModeBase.cs
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using debug_interface.Models;
using Google.Protobuf;
using Protobuf;
using Grpc.Core;
//using installer;
//using installer.Model;
using installer.Model;
using installer.Data;
using Avalonia.Controls.Shapes;
using Avalonia.Logging;
using System.Threading.Channels;
namespace debug_interface.ViewModels
{
public class ViewModelBase : ObservableObject
public partial class ViewModelBase : ObservableObject
{
// 用于 UI 刷新的定时器Avalonia 的 DispatcherTimer
private DispatcherTimer timerViewModel;
private int counterViewModelTest = 0;
// 使用 CommunityToolkit 的 ObservableProperty 自动实现 INotifyPropertyChanged
//[ObservableProperty]
//private string title;
[ObservableProperty]
private string title;
//private MapPatch testPatch;
//public MapPatch TestPatch
@ -48,261 +49,38 @@ namespace debug_interface.ViewModels
private long teamID;
//private ShipType shipType;
//private AvailableService.AvailableServiceClient? client;
//private AsyncServerStreamingCall<MessageToClient>? responseStream;
private AvailableService.AvailableServiceClient? client;
private AsyncServerStreamingCall<MessageToClient>? responseStream;
private bool isSpectatorMode = false;
private bool isPlaybackMode = false;
// 用于存储上次移动角度(示例,仅作为参考)
private double lastMoveAngle;
// 日志记录(保持你原来的 Logger 类)
// 日志记录
//public Logger myLogger;
//public Logger lockGenerator;
// 以下定义各个操作的命令(基于 CommunityToolkit.Mvvm.Input 的 RelayCommand
public RelayCommand MoveUpCommand { get; }
public RelayCommand MoveDownCommand { get; }
public RelayCommand MoveLeftCommand { get; }
public RelayCommand MoveRightCommand { get; }
public RelayCommand MoveLeftUpCommand { get; }
public RelayCommand MoveRightUpCommand { get; }
public RelayCommand MoveLeftDownCommand { get; }
public RelayCommand MoveRightDownCommand { get; }
public RelayCommand AttackCommand { get; }
public RelayCommand RecoverCommand { get; }
public RelayCommand ProduceCommand { get; }
public RelayCommand ConstructCommand { get; }
public ViewModelBase()
{
//Title = "THUAI8;
title = "THUAI8";
// 读取配置(假设 ConfigData 类来自 installer.Data 命名空间)
//var d = new installer.Data.ConfigData();
//ip = d.Commands.IP;
//port = d.Commands.Port;
//playerID = Convert.ToInt64(d.Commands.PlayerID);
//teamID = Convert.ToInt64(d.Commands.TeamID);
var d = new installer.Data.ConfigData();
ip = d.Commands.IP;
port = d.Commands.Port;
playerID = Convert.ToInt64(d.Commands.PlayerID);
teamID = Convert.ToInt64(d.Commands.TeamID);
//shipTypeID = Convert.ToInt32(d.Commands.ShipType);
//string playbackFile = d.Commands.PlaybackFile;
//double playbackSpeed = d.Commands.PlaybackSpeed;
string playbackFile = d.Commands.PlaybackFile;
double playbackSpeed = d.Commands.PlaybackSpeed;
//初始化日志记录器
//myLogger = LoggerProvider.FromFile(System.IO.Path.Combine(d.InstallPath, "Logs", $"Client.{teamID}.{playerID}.log"));
//lockGenerator = LoggerProvider.FromFile(System.IO.Path.Combine(d.InstallPath, "Logs", $"lock.{teamID}.{playerID}.log"));
// 初始化命令:这里仅示例了部分命令,其他命令同理
MoveUpCommand = new RelayCommand(() =>
{
//if (client == null || isSpectatorMode || isPlaybackMode)
//{
// myLogger.LogInfo("Client is null or in Spectator/Playback mode");
// return;
//}
//// 构造移动消息,这里采用 gRPC 的消息格式(注意:根据你的 proto 定义,字段名称可能有所不同)
//MoveMsg movemsg = new MoveMsg
//{
// character_id = playerID,
// team_id = teamID,
// angle = Math.PI,
// time_in_milliseconds = 50
//};
//lastMoveAngle = movemsg.angle;
//client.Move(movemsg);
});
MoveDownCommand = new RelayCommand(() =>
{
//if (client == null || isSpectatorMode || isPlaybackMode)
//{
// myLogger.LogInfo("Client is null or in Spectator/Playback mode");
// return;
//}
//MoveMsg movemsg = new MoveMsg
//{
// character_id = playerID,
// team_id = teamID,
// // 这里使用 0 表示“负零”
// angle = 0,
// time_in_milliseconds = 100
//};
//lastMoveAngle = movemsg.angle;
//client.Move(movemsg);
});
MoveLeftCommand = new RelayCommand(() =>
{
//if (client == null || isSpectatorMode || isPlaybackMode)
//{
// myLogger.LogInfo("Client is null or in Spectator/Playback mode");
// return;
//}
//MoveMsg movemsg = new MoveMsg
//{
// character_id = playerID,
// team_id = teamID,
// angle = Math.PI * 3 / 2,
// time_in_milliseconds = 100
//};
//lastMoveAngle = movemsg.angle;
//client.Move(movemsg);
});
MoveRightCommand = new RelayCommand(() =>
{
//if (client == null || isSpectatorMode || isPlaybackMode)
//{
// myLogger.LogInfo("Client is null or in Spectator/Playback mode");
// return;
//}
//MoveMsg movemsg = new MoveMsg
//{
// character_id = playerID,
// team_id = teamID,
// angle = Math.PI / 2,
// time_in_milliseconds = 100
//};
//lastMoveAngle = movemsg.angle;
//client.Move(movemsg);
});
MoveLeftUpCommand = new RelayCommand(() =>
{
//if (client == null || isSpectatorMode || isPlaybackMode)
//{
// myLogger.LogInfo("Client is null or in Spectator/Playback mode");
// return;
//}
//MoveMsg movemsg = new MoveMsg
//{
// character_id = playerID,
// team_id = teamID,
// angle = Math.PI * 5 / 4,
// time_in_milliseconds = 100
//};
//lastMoveAngle = movemsg.angle;
//client.Move(movemsg);
});
MoveRightUpCommand = new RelayCommand(() =>
{
//if (client == null || isSpectatorMode || isPlaybackMode)
//{
// myLogger.LogInfo("Client is null or in Spectator/Playback mode");
// return;
//}
//MoveMsg movemsg = new MoveMsg
//{
// character_id = playerID,
// team_id = teamID,
// angle = Math.PI * 3 / 4,
// time_in_milliseconds = 100
//};
//lastMoveAngle = movemsg.angle;
//client.Move(movemsg);
});
MoveLeftDownCommand = new RelayCommand(() =>
{
//if (client == null || isSpectatorMode || isPlaybackMode)
//{
// myLogger.LogInfo("Client is null or in Spectator/Playback mode");
// return;
//}
//MoveMsg movemsg = new MoveMsg
//{
// character_id = playerID,
// team_id = teamID,
// angle = Math.PI * 7 / 4,
// time_in_milliseconds = 100
//};
//lastMoveAngle = movemsg.angle;
//client.Move(movemsg);
});
MoveRightDownCommand = new RelayCommand(() =>
{
//if (client == null || isSpectatorMode || isPlaybackMode)
//{
// myLogger.LogInfo("Client is null or in Spectator/Playback mode");
// return;
//}
//MoveMsg movemsg = new MoveMsg
//{
// character_id = playerID,
// team_id = teamID,
// angle = Math.PI / 4,
// time_in_milliseconds = 100
//};
//lastMoveAngle = movemsg.angle;
//client.Move(movemsg);
});
AttackCommand = new RelayCommand(() =>
{
//if (client == null || isSpectatorMode || isPlaybackMode)
//{
// myLogger.LogInfo("Client is null or in Spectator/Playback mode");
// return;
//}
//AttackMsg attackMsg = new AttackMsg
//{
// character_id = playerID,
// team_id = teamID,
// attack_range = 50, // 示例值,根据实际情况修改
// attacked_character_id = 0 // 示例目标ID
//};
//client.Attack(attackMsg);
});
RecoverCommand = new RelayCommand(() =>
{
//if (client == null || isSpectatorMode || isPlaybackMode)
//{
// myLogger.LogInfo("Client is null or in Spectator/Playback mode");
// return;
//}
//RecoverMsg recoverMsg = new RecoverMsg
//{
// character_id = playerID,
// recovered_hp = 10, // 示例数值
// team_id = teamID
//};
//client.Recover(recoverMsg);
});
ProduceCommand = new RelayCommand(() =>
{
//if (client == null || isSpectatorMode || isPlaybackMode)
//{
// myLogger.LogInfo("Client is null or in Spectator/Playback mode");
// return;
//}
//// 此处 Produce 可使用对应的 gRPC 方法(例如 Equip 或其他你定义的生产逻辑)
//IDMsg idMsg = new IDMsg
//{
// character_id = playerID,
// team_id = teamID
//};
//client.Equip(idMsg);
});
ConstructCommand = new RelayCommand(() =>
{
//if (client == null || isSpectatorMode || isPlaybackMode)
//{
// myLogger.LogInfo("Client is null or in Spectator/Playback mode");
// return;
//}
//ConstructMsg constructMsg = new ConstructMsg
//{
// character_id = playerID,
// team_id = teamID,
// construction_type = ConstructionType.BARRACKS // 示例建筑类型
//};
//client.Construct(constructMsg);
});
// 使用 Avalonia 的 DispatcherTimer 定时刷新 UI
timerViewModel = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(50) };
@ -310,24 +88,25 @@ namespace debug_interface.ViewModels
timerViewModel.Start();
//判断是否走回放模式
//if (string.IsNullOrEmpty(d.Commands.PlaybackFile))
//{
// string[] comInfo = new string[]
// {
// ip,
// port,
// Convert.ToString(playerID),
// Convert.ToString(teamID),
// Convert.ToString(shipTypeID),
// };
// ConnectToServer(comInfo);
// OnReceive();
//}
//else
//{
if (string.IsNullOrEmpty(d.Commands.PlaybackFile))
{
string[] comInfo = new string[]
{
ip,
port,
Convert.ToString(playerID),
Convert.ToString(teamID),
Convert.ToString(0),
};
ConnectToServer(comInfo);
OnReceive();
}
else
{
//myLogger.LogInfo($"PlaybackFile: {d.Commands.PlaybackFile}");
//Playback(d.Commands.PlaybackFile, playbackSpeed);
//}
}
}
/// <summary>
@ -336,27 +115,27 @@ namespace debug_interface.ViewModels
/// <param name="comInfo">包含 ip、port、playerID、teamID、shipTypeID 的数组</param>
public void ConnectToServer(string[] comInfo)
{
//if (isPlaybackMode) return;
//if (Convert.ToInt64(comInfo[2]) > 2023)
//{
// isSpectatorMode = true;
if (isPlaybackMode) return;
if (Convert.ToInt64(comInfo[2]) > 2023)
{
isSpectatorMode = true;
//myLogger.LogInfo("isSpectatorMode = true");
//}
//if (comInfo.Length != 5)
//{
// throw new Exception("Error Registration Information");
//}
}
if (comInfo.Length != 5)
{
throw new Exception("Error Registration Information");
}
//string connect = $"{comInfo[0]}:{comInfo[1]}";
//Channel channel = new Channel(connect, ChannelCredentials.Insecure);
//client = new AvailableService.AvailableServiceClient(channel);
//PlayerMsg playerMsg = new PlayerMsg();
//playerID = Convert.ToInt64(comInfo[2]);
//playerMsg.PlayerId = playerID;
//if (!isSpectatorMode)
//{
// teamID = Convert.ToInt64(comInfo[3]);
// playerMsg.TeamId = teamID;
string connect = $"{comInfo[0]}:{comInfo[1]}";
Channel channel = new Channel(connect, ChannelCredentials.Insecure);
client = new AvailableService.AvailableServiceClient(channel);
CharacterMsg playerMsg = new CharacterMsg();
playerID = Convert.ToInt64(comInfo[2]);
playerMsg.CharacterId = playerID;
if (!isSpectatorMode)
{
teamID = Convert.ToInt64(comInfo[3]);
playerMsg.TeamId = teamID;
//shipType = Convert.ToInt64(comInfo[4]) switch
//{
// 0 => ShipType.NullShipType,
@ -365,9 +144,9 @@ namespace debug_interface.ViewModels
// 3 => ShipType.FlagShip,
// _ => ShipType.NullShipType
//};
// playerMsg.ShipType = shipType;
//}
//responseStream = client.AddPlayer(playerMsg);
playerMsg.CharacterType = CharacterType.TangSeng;
}
responseStream = client.AddCharacter(playerMsg);
}
/// <summary>

View File

@ -4,8 +4,8 @@
xmlns="https://github.com/avaloniaui"
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:debug_interface.Views"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="using:debug_interface.ViewModels"
x:Name="MainWindowElement"
Title="THUAI8 调试界面"
@ -207,10 +207,7 @@
</Grid>
<!-- 右侧区域 -->
<Grid
Grid.Column="1"
Margin="2"
>
<Grid Grid.Column="1" Margin="2">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />

View File

@ -144,7 +144,100 @@ namespace debug_interface.Views
{
if (characterCanvas == null) return;
//bool isRedTeam = color.Equals(Colors.Red);
//// 形状选择 - 红队使用圆形,蓝队使用正方形
//for (int i = 0; i < characters.Count; i++)
//{
// var character = characters[i];
// // 创建容器 - 用于定位
// var container = new Canvas
// {
// Width = 16,
// Height = 16,
// Tag = character
// };
// Control characterShape;
// if (isRedTeam)
// {
// // 红队使用圆形
// characterShape = new Ellipse
// {
// Width = 14,
// Height = 14,
// Fill = new SolidColorBrush(color) { Opacity = 0.7 },
// Stroke = Brushes.White,
// StrokeThickness = 1
// };
// }
// else
// {
// // 蓝队使用正方形
// characterShape = new Rectangle
// {
// Width = 14,
// Height = 14,
// Fill = new SolidColorBrush(color) { Opacity = 0.7 },
// Stroke = Brushes.White,
// StrokeThickness = 1
// };
// }
// // 添加形状到容器
// Canvas.SetLeft(characterShape, 1);
// Canvas.SetTop(characterShape, 1);
// container.Children.Add(characterShape);
// // 添加标识符 - 使用不同的方式标识队伍内部的角色
// var identifier = new TextBlock
// {
// Text = (i + 1).ToString(),
// FontSize = 8,
// Foreground = Brushes.White,
// HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center,
// VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center
// };
// // 为标识符添加背景以增强可读性
// var textContainer = new Border
// {
// Child = identifier,
// Width = 14,
// Height = 14,
// Background = Brushes.Transparent,
// HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center,
// VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center
// };
// Canvas.SetLeft(textContainer, 1);
// Canvas.SetTop(textContainer, 1);
// container.Children.Add(textContainer);
// // 添加工具提示,显示详细信息
// var tooltip = new ToolTip
// {
// // 使用角色的泛型属性,确保可以访问
// Content = new TextBlock { Text = $"{(isRedTeam ? "红队" : "蓝队")} 角色 {i + 1}" }
// };
// ToolTip.SetTip(container, tooltip);
// // 将容器添加到画布
// characterCanvas.Children.Add(container);
// characterElements[character.Name] = container;
// // 初始定位 - 稍后会更新
// Canvas.SetLeft(container, i*i * i*i);
// Canvas.SetTop(container, i*i * i * i );
//}
/////////////////////////////////////
/////////////////////////////////////
////////////////////////////////////
for (int i = 0; i < characters.Count; i++)
{
{
var character = characters[i];
var id = color == Colors.Red ? $"red_{i}" : $"blue_{i}";
@ -171,15 +264,15 @@ namespace debug_interface.Views
// ===== 选项1: 显示数字编号 =====
// 如果不需要数字编号,注释掉下面这段代码
//var textBlock = new TextBlock
//{
// Text = (i + 1).ToString(), // 使用编号(从1开始)
// HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center,
// VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center,
// FontSize = 8,
// Foreground = new SolidColorBrush(color), // 文本颜色与队伍颜色一致
// FontWeight = FontWeight.Bold,
//};
var textBlock = new TextBlock
{
Text = (i + 1).ToString(), // 使用编号(从1开始)
HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center,
VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center,
FontSize = 8,
Foreground = new SolidColorBrush(color), // 文本颜色与队伍颜色一致
FontWeight = FontWeight.Bold,
};
//grid.Children.Add(textBlock);
// 设置提示信息
@ -205,6 +298,7 @@ namespace debug_interface.Views
};
}
}
}
// 修改位置更新方法接受任何UIElement
private void UpdateCharacterPosition(Control element, int x, int y)
@ -226,5 +320,77 @@ namespace debug_interface.Views
// When collection changes, refresh all characters for simplicity
RefreshCharacters();
}
public void UpdateCharacterPosition(long characterId, int x, int y, bool isRedTeam, string name)
{
// 查找现有角色标记或创建新标记
var marker = FindCharacterMarker(characterId);
if (marker == null)
{
// 创建新角色标记
marker = new Ellipse
{
Width = 10,
Height = 10,
Fill = new SolidColorBrush(isRedTeam ? Colors.Red : Colors.Blue),
Tag = characterId
};
// 添加文本标签
var label1 = new TextBlock
{
Text = name,
FontSize = 8,
Foreground = new SolidColorBrush(Colors.White)
};
// 添加到画布
CharacterCanvas.Children.Add(marker);
CharacterCanvas.Children.Add(label1);
}
// 更新位置
double cellWidth = CharacterCanvas.Bounds.Width / 50;
double cellHeight = CharacterCanvas.Bounds.Height / 50;
Canvas.SetLeft(marker, y * cellWidth + cellWidth / 2 - marker.Width / 2);
Canvas.SetTop(marker, x * cellHeight + cellHeight / 2 - marker.Height / 2);
// 更新标签位置
var label = FindCharacterLabel(characterId);
if (label != null)
{
Canvas.SetLeft(label, y * cellWidth + cellWidth / 2 - label.Bounds.Width / 2);
Canvas.SetTop(label, x * cellHeight + cellHeight / 2 + marker.Height);
}
}
private Ellipse FindCharacterMarker(long characterId)
{
foreach (var child in CharacterCanvas.Children)
{
if (child is Ellipse ellipse && (long?)ellipse.Tag == characterId)
{
return ellipse;
}
}
return null;
}
private TextBlock FindCharacterLabel(long characterId)
{
var marker = FindCharacterMarker(characterId);
if (marker == null) return null;
int index = CharacterCanvas.Children.IndexOf(marker);
if (index >= 0 && index + 1 < CharacterCanvas.Children.Count &&
CharacterCanvas.Children[index + 1] is TextBlock label)
{
return label;
}
return null;
}
}
}

View File

@ -14,9 +14,11 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\logic\proto\proto.csproj" />
<!-- 相对路径 -->
<Protobuf Include="..\..\..\dependency\proto\*.proto" GrpcServices="Client">
<Link>Protos\%(RecursiveDir)%(Filename)%(Extension)</Link>
</Protobuf>
</ItemGroup>
<ItemGroup>
<!-- 使用正斜杠 / 确保跨平台兼容 -->
<Compile Include="..\..\..\installer\Data\ConfigFileData.cs" Link="Interact/ConfigFileData.cs">
@ -52,4 +54,8 @@
<ItemGroup>
<Folder Include="Utili\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\dependency\proto\Proto.csproj" />
</ItemGroup>
</Project>

View File

@ -5,6 +5,8 @@ VisualStudioVersion = 17.11.35219.272
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "debug_interface", "debug_interface.csproj", "{4F12E13F-A324-4E71-8003-DB2D5C8C4643}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Proto", "..\..\..\dependency\proto\Proto.csproj", "{B6C305C4-ACFA-467E-9408-9617886B7D4D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -15,6 +17,10 @@ Global
{4F12E13F-A324-4E71-8003-DB2D5C8C4643}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4F12E13F-A324-4E71-8003-DB2D5C8C4643}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4F12E13F-A324-4E71-8003-DB2D5C8C4643}.Release|Any CPU.Build.0 = Release|Any CPU
{B6C305C4-ACFA-467E-9408-9617886B7D4D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B6C305C4-ACFA-467E-9408-9617886B7D4D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B6C305C4-ACFA-467E-9408-9617886B7D4D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B6C305C4-ACFA-467E-9408-9617886B7D4D}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -7,14 +7,26 @@ namespace ClientTest
{
public static Task Main(string[] args)
{
if (!int.TryParse(args[0], out int characterId))
{
Console.WriteLine("Invalid CharacterId. Please provide a valid integer.");
return Task.CompletedTask;
}
if (!int.TryParse(args[1], out int teamId))
{
Console.WriteLine("Invalid TeamId. Please provide a valid integer.");
return Task.CompletedTask;
}
Thread.Sleep(3000);
Channel channel = new("127.0.0.1:8888", ChannelCredentials.Insecure);
var client = new AvailableService.AvailableServiceClient(channel);
CharacterMsg playerInfo = new()
{
CharacterId = 0,
TeamId = 0,
CharacterType = CharacterType.TangSeng
CharacterId = characterId,
TeamId = teamId,
CharacterType = teamId == 0 ? CharacterType.JiuLing : CharacterType.TangSeng,
SideFlag = 1 - teamId
};
var call = client.AddCharacter(playerInfo);
MoveMsg moveMsg = new()

View File

@ -0,0 +1 @@