Debug_interface - old Server Communicate

This commit is contained in:
JackPWY 2025-04-03 16:07:12 +08:00
commit d54b51538d
17 changed files with 1405 additions and 372 deletions

View File

@ -168,7 +168,7 @@ namespace Constants
SCCI int32_t time_cost = 10;
};
struct Trap
struct Hole
{
SCCI int32_t cost = 1000;
SCCI int32_t time = 5;

View File

@ -8,19 +8,22 @@
// 为假则play()期间确保游戏状态不更新,为真则只保证游戏状态在调用相关方法时不更新,大致一帧更新一次
extern const bool asynchronous = false;
// 选手需要依次将player1到player4的角色类型在这里定义
extern const std::array<THUAI8::CharacterType, 12> CharacterTypeDict = {
// 选手需要依次将player1到player5的角色类型在这里定义
extern const std::array<THUAI8::CharacterType, 5> BuddhistsCharacterTypeDict = {
THUAI8::CharacterType::Monk,
THUAI8::CharacterType::MonkeyKing,
THUAI8::CharacterType::Pigsy,
THUAI8::CharacterType::ShaWujing,
THUAI8::CharacterType::Whitedragonhorse,
};
extern const std::array<THUAI8::CharacterType, 5> MonstersCharacterTypeDict = {
THUAI8::CharacterType::JiuTouYuanSheng,
THUAI8::CharacterType::Honghaier,
THUAI8::CharacterType::Gyuumao,
THUAI8::CharacterType::Princess_Iron_Fan,
THUAI8::CharacterType::Spider,
};
}
// 可以在AI.cpp内部声明变量与函数

View File

@ -27,9 +27,9 @@ Logic::Logic(int32_t pID, int32_t tID, THUAI8::PlayerType pType, THUAI8::Charact
bufferState->gameInfo = std::make_shared<THUAI8::GameInfo>();
bufferState->mapInfo = std::make_shared<THUAI8::GameMap>();
if (teamID == 0)
playerTeam = THUAI8::PlayerTeam::Red;
playerTeam = THUAI8::PlayerTeam::BuddhistsTeam;
else if (teamID == 1)
playerTeam = THUAI8::PlayerTeam::Blue;
playerTeam = THUAI8::PlayerTeam::MonstersTeam;
else
playerTeam = THUAI8::PlayerTeam::NullTeam;
}
@ -42,7 +42,7 @@ std::vector<std::shared_ptr<const THUAI8::Character>> Logic::GetCharacters() con
return temp;
}
std::vector<std::shared_ptr<const THUAI8::Character>> Logic::GetEnemySCharacters() const
std::vector<std::shared_ptr<const THUAI8::Character>> Logic::GetEnemyCharacters() const
{
std::unique_lock<std::mutex> lock(mtxState);
std::vector<std::shared_ptr<const THUAI8::Character>> temp(currentState->enemyCharacters.begin(), currentState->enemyCharacters.end());

View File

@ -1,10 +1,12 @@
import PyAPI.structures as THUAI8
from PyAPI.Interface import ICharacterAPI, ITeamAPI, IAI
from PyAPI.utils import AssistFunction
from typing import Union, Final, cast, List
from PyAPI.constants import Constants
import queue
import time
from typing import Final, List, Union, cast
import PyAPI.structures as THUAI8
from PyAPI.constants import Constants
from PyAPI.Interface import IAI, ICharacterAPI, ITeamAPI
from PyAPI.utils import AssistFunction
class Setting:
# 为假则play()期间确保游戏状态不更新,为真则只保证游戏状态在调用相关方法时不更新,大致一帧更新一次
@ -13,6 +15,22 @@ class Setting:
return False
@staticmethod
<<<<<<< HEAD
def BuddhistsCharacterTypes() -> List[THUAI8.CharacterType]:
return [
THUAI8.CharacterType.Monk,
THUAI8.CharacterType.MonkyKing,
THUAI8.CharacterType.Pigsy,
THUAI8.CharacterType.ShaWujing,
THUAI8.CharacterType.Whitedragonhorse,
]
@staticmethod
def MonsterCharacterTypes() -> List[THUAI8.CharacterType]:
return [
THUAI8.CharacterType.JiuTouYuanSheng,
THUAI8.CharacterType.HongHaier,
=======
def ShipTypes() -> List[THUAI8.CharacterType]:
return [
THUAI8.CharacterType.Monk,
@ -22,17 +40,30 @@ class Setting:
THUAI8.CharacterType.Whitedragonhorse,
THUAI8.CharacterType.JiuTouYuanSheng,
THUAI8.CharacterType.Honghaier,
>>>>>>> 5a1751dc64f09ba19aaa818e5dc99172d15f4c69
THUAI8.CharacterType.Gyuumao,
THUAI8.CharacterType.Princess_Iron_Fan,
THUAI8.CharacterType.Spider,
]
<<<<<<< HEAD
numOfGridPerCell: Final[int] = 1000
=======
numOfGridPerCell: Final[int] = 1000
>>>>>>> 5a1751dc64f09ba19aaa818e5dc99172d15f4c69
class AI(IAI):
def __init__(self, pID: int):
self.__playerID = pID
<<<<<<< HEAD
def CharacterPlay(self, api: ICharacterAPI) -> None:
=======
def ShipPlay(self, api: IShipAPI) -> None:
>>>>>>> 5a1751dc64f09ba19aaa818e5dc99172d15f4c69
# 公共操作
if self.__playerID == 1:
# player1的操作
@ -46,9 +77,13 @@ class AI(IAI):
elif self.__playerID == 4:
# player4的操作
return
<<<<<<< HEAD
return
=======
elif self.__playerID == 5:
# player4的操作
return
>>>>>>> 5a1751dc64f09ba19aaa818e5dc99172d15f4c69
def TeamPlay(self, api: ITeamAPI) -> None:
# player0的操作

199
CAPI/python/constants.py Normal file
View File

@ -0,0 +1,199 @@
class Constants:
frameDuration = 50
numofGridPerCell = 1000
rows = 50
cols = 50
destroyBarracksBonus = 6000
destroySpringBonus = 3000
destroyFarmBonus = 4000
sizeofCharacter = 800
speed = 2500
class Monk:
maxHp = 1000
class MonkyKing:
maxHp = 200
commonAttackPower = 30
attackRange = 1
cost = 5000
class Pigsy:
maxHp = 300
commonAttackPower = 20
attackRange = 2
cost = 4000
class ShaWujing:
maxHp = 150
commonAttackPower = 10
attackRange = 5
cost = 3000
class Whitedragonhorse:
maxHp = 150
commonAttackPower = 10
attackRange = 5
cost = 4000
class JiuTouYuanSheng:
maxHp = 1000
class HongHaier:
maxHp = 200
commonAttackPower = 25
attackRange = 1
cost = 5000
class Gyuumao:
maxHp = 300
commonAttackPower = 20
attackRange = 2
cost = 4000
class Princess_Iron_Fan:
maxHp = 150
commonAttackPower = 10
attackRange = 5
cost = 3000
class Spider:
maxHp = 150
commonAttackPower = 10
attackRange = 5
cost = 3000
class resumption:
recovery1 = 50
recovery2 = 100
recovery3 = 150
score1 = 2000
score2 = 3000
score3 = 4000
maxHp1 = 200
maxHp2 = 300
maxHp3 = 400
attack = 10
class Attack_Boost:
attackBoost1 = 10
attackBoost2 = 15
attackBoost3 = 20
time1 = 30
time2 = 45
time3 = 60
score1 = 4000
score2 = 5000
score3 = 6000
maxHp1 = 400
maxHp2 = 500
maxHp3 = 600
attack1 = 10
attack2 = 15
attack3 = 20
class Speed_Boost:
speedBoost1 = 500
time = 60
score = 3000
maxHp = 300
attack = 10
class View_Boost:
time = 60
score = 3000
maxHp = 300
attack = 10
class Barracks:
maxHp = 600
cost = 10000
sabotage_score = 6000
time_cost = 15
class Spring:
maxHp = 300
cost = 8000
sabotage_score = 3000
time_cost = 10
class Farm:
maxHp = 400
cost = 8000
sabotage_score = 3000
time_cost = 10
class Hole:
cost = 1000
time = 5
attack = 20
continous_time = 5
class Cage:
cost = 1000
time = 5
continueous_time = 30
class blood_vial:
cost1 = 1500
cost2 = 3000
cost3 = 4500
recovery1 = 50
recovery2 = 100
recovery3 = 150
class Shield:
cost1 = 2000
cost2 = 3500
cost3 = 5000
defence1 = 50
defence2 = 100
defence3 = 150
class Speed_shoes:
speedBoost = 500
time = 60
cost = 1500
class purification_medicine:
cost = 2000
time = 30
class invisibility:
cost = 4000
time = 10
class berserk:
cost = 10000
time = 30
attack_boost = 1.2 # 注意这是提升的倍数
speed_boost = 300 # 注意这是直接叠加
attack_freq_boost = 1.25 # 注意这是提升的倍数

View File

@ -1,20 +1,18 @@
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Data.Core;
using Avalonia.Data.Core.Plugins;
using Avalonia.Markup.Xaml;
using debug_interface.Services;
using debug_interface.ViewModels;
using debug_interface.Views;
using System.Linq;
using System;
using System.IO;
using installer.Model;
using installer.Data;
namespace debug_interface
{
/// <summary>
/// 应用程序的后置代码,负责初始化和启动主窗口。
/// </summary>
public partial class App : Application
{
public override void Initialize()
{
AvaloniaXamlLoader.Load(this);
@ -24,34 +22,43 @@ namespace debug_interface
{
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
// Avoid duplicate validations from both Avalonia and the CommunityToolkit.
// More info: https://docs.avaloniaui.net/docs/guides/development-guides/data-validation#manage-validationplugins
DisableAvaloniaDataAnnotationValidation();
// 加载配置
var config = new ConfigData();
var mainWindowViewModel = new MainWindowViewModel();
// 设置日志目录
string logDir = Path.Combine(config.InstallPath, "Logs");
Directory.CreateDirectory(logDir);
// 创建日志记录器
var logFilePath = Path.Combine(logDir, $"debug_interface_{DateTime.Now:yyyyMMdd_HHmmss}.log");
var logger = new FileLogger(logFilePath);
// 创建主窗口视图模型
var mainWindowViewModel = new MainWindowViewModel(logger, config);
// 创建服务器通信服务
var serverCommunicationService = new ServerCommunicationService(mainWindowViewModel, logger, config);
// 设置主窗口
desktop.MainWindow = new MainWindow
{
DataContext = new MainWindowViewModel(),
DataContext = mainWindowViewModel
};
// 尝试连接服务器或启动回放
if (string.IsNullOrEmpty(config.Commands.PlaybackFile))
{
// 连接到服务器
_ = serverCommunicationService.ConnectToServer();
}
else
{
// 启动回放模式
serverCommunicationService.StartPlaybackMode();
}
}
base.OnFrameworkInitializationCompleted();
}
private void DisableAvaloniaDataAnnotationValidation()
{
// Get an array of plugins to remove
var dataValidationPluginsToRemove =
BindingPlugins.DataValidators.OfType<DataAnnotationsValidationPlugin>().ToArray();
// remove each entry found
foreach (var plugin in dataValidationPluginsToRemove)
{
BindingPlugins.DataValidators.Remove(plugin);
}
}
}
}

View File

@ -1,6 +1,7 @@
//MapCell.cs
using Avalonia.Media;
using CommunityToolkit.Mvvm.ComponentModel;
using debug_interface.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;

View File

@ -0,0 +1,776 @@
using System;
using System.Threading.Tasks;
using Avalonia.Threading;
using debug_interface.ViewModels;
using Grpc.Core;
using installer.Model;
using installer.Data;
namespace debug_interface.Services
{
public class ServerCommunicationService
{
private readonly MainWindowViewModel _viewModel;
private readonly Logger _logger;
private readonly ConfigData _config;
private bool _isConnected = false;
private bool _isPlaybackMode = false;
public ServerCommunicationService(MainWindowViewModel viewModel, Logger logger, ConfigData config)
{
_viewModel = viewModel;
_logger = logger;
_config = config;
}
public async Task ConnectToServer()
{
try
{
string ip = _config.Commands.IP;
string port = _config.Commands.Port;
_logger.LogInfo($"尝试连接服务器 {ip}:{port}");
// 由于没有正确的Proto引用这里暂时只模拟连接行为
await Task.Delay(1000); // 模拟连接延迟
await Dispatcher.UIThread.InvokeAsync(() => {
_viewModel.GameLog = $"已连接到服务器 {ip}:{port}";
});
_isConnected = true;
_logger.LogInfo("已模拟连接到服务器");
}
catch (Exception ex)
{
_logger.LogError($"连接失败: {ex.Message}");
await Dispatcher.UIThread.InvokeAsync(() => {
_viewModel.GameLog = $"连接失败: {ex.Message}";
});
}
}
public void StartPlaybackMode()
{
try
{
_isPlaybackMode = true;
string playbackFile = _config.Commands.PlaybackFile ?? "";
_logger.LogInfo($"模拟回放: {playbackFile}");
Dispatcher.UIThread.InvokeAsync(() => {
_viewModel.GameLog = $"模拟回放: {playbackFile}";
});
}
catch (Exception ex)
{
_logger.LogError($"回放错误: {ex.Message}");
Dispatcher.UIThread.InvokeAsync(() => {
_viewModel.GameLog = $"回放错误: {ex.Message}";
});
}
}
}
}
//using System;
//using System.Linq;
//using System.Threading.Tasks;
//using Avalonia.Threading;
//using debug_interface.ViewModels;
//using Grpc.Core;
//using Google.Protobuf; // 假设这是proto文件生成的命名空间
//using installer.Model; // Logger的命名空间
//using installer.Data; // ConfigData的命名空间
//using System.Collections.Generic;
//using Avalonia.Data;
//using System.Threading.Channels;
//namespace debug_interface.Services
//{
// public class ServerCommunicationService
// {
// private readonly MainWindowViewModel _viewModel;
// private readonly Logger _logger;
// private readonly ConfigData _config;
// private AvailableService.AvailableServiceClient? _client;
// private AsyncServerStreamingCall<MessageToClient>? _responseStream;
// private bool _isConnected = false;
// private bool _isPlaybackMode = false;
// public ServerCommunicationService(MainWindowViewModel viewModel, Logger logger, ConfigData config)
// {
// _viewModel = viewModel;
// _logger = logger;
// _config = config;
// }
// public async Task ConnectToServer()
// {
// try
// {
// if (_isPlaybackMode)
// return;
// string ip = _config.Commands.IP;
// string port = _config.Commands.Port;
// long playerId = _config.Commands.PlayerID;
// long teamId = _config.Commands.TeamID;
// int characterType = _config.Commands.CharacterType;
// string connectionString = $"{ip}:{port}";
// _logger.LogInfo($"正在连接到服务器 {connectionString}");
// // 创建gRPC通道和客户端
// var channel = new Channel(connectionString, ChannelCredentials.Insecure);
// _client = new AvailableService.AvailableServiceClient(channel);
// // 创建连接消息
// var characterMsg = new CharacterMsg
// {
// CharacterId = playerId,
// TeamId = teamId,
// CharacterType = (CharacterType)characterType
// };
// // 连接到服务器
// _responseStream = _client.AddCharacter(characterMsg);
// _isConnected = true;
// // 开始接收消息
// _ = StartReceivingMessagesAsync();
// _logger.LogInfo("成功连接到服务器");
// }
// catch (Exception ex)
// {
// _isConnected = false;
// _logger.LogError($"连接服务器失败: {ex.Message}");
// // 在UI中显示错误
// await Dispatcher.UIThread.InvokeAsync(() => {
// _viewModel.GameLog = $"连接服务器错误: {ex.Message}";
// });
// throw;
// }
// }
// public void StartPlaybackMode()
// {
// _isPlaybackMode = true;
// string playbackFile = _config.Commands.PlaybackFile ?? "";
// double playbackSpeed = _config.Commands.PlaybackSpeed;
// _logger.LogInfo($"正在从{playbackFile}以{playbackSpeed}倍速开始回放模式");
// // 这里可以实现回放逻辑,读取文件并模拟服务器消息
// // 例如启动一个单独的任务来读取和处理文件
// _ = Task.Run(async () => {
// try
// {
// // 简单的回放逻辑示例
// if (System.IO.File.Exists(playbackFile))
// {
// // 读取文件内容...
// _logger.LogInfo("回放文件存在,开始读取数据");
// // 这里是简化实现,实际应根据文件格式处理
// var fileBytes = System.IO.File.ReadAllBytes(playbackFile);
// // 通知UI
// await Dispatcher.UIThread.InvokeAsync(() => {
// _viewModel.GameLog = "正在回放...";
// });
// }
// else
// {
// _logger.LogError($"回放文件不存在: {playbackFile}");
// await Dispatcher.UIThread.InvokeAsync(() => {
// _viewModel.GameLog = "回放文件不存在!";
// });
// }
// }
// catch (Exception ex)
// {
// _logger.LogError($"回放过程中出错: {ex.Message}");
// await Dispatcher.UIThread.InvokeAsync(() => {
// _viewModel.GameLog = $"回放错误: {ex.Message}";
// });
// }
// });
// }
// private async Task StartReceivingMessagesAsync()
// {
// if (_responseStream == null)
// return;
// try
// {
// _logger.LogInfo("开始接收服务器消息");
// while (await _responseStream.ResponseStream.MoveNext(default))
// {
// var message = _responseStream.ResponseStream.Current;
// // 在UI线程上处理消息以安全地更新UI
// await Dispatcher.UIThread.InvokeAsync(() => {
// ProcessServerMessage(message);
// });
// }
// }
// catch (RpcException ex) when (ex.StatusCode == StatusCode.Cancelled)
// {
// _logger.LogInfo("服务器流已取消");
// }
// catch (Exception ex)
// {
// _logger.LogError($"接收服务器消息错误: {ex.Message}");
// await Dispatcher.UIThread.InvokeAsync(() => {
// _viewModel.GameLog = $"连接错误: {ex.Message}";
// });
// // 尝试重新连接
// await TryReconnectAsync();
// }
// finally
// {
// _isConnected = false;
// }
// }
// private async Task TryReconnectAsync()
// {
// _logger.LogInfo("尝试重新连接服务器...");
// // 等待一段时间后重试
// await Task.Delay(5000);
// if (!_isConnected && !_isPlaybackMode)
// {
// try
// {
// await ConnectToServer();
// }
// catch
// {
// // 重连失败,等待更长时间后再次尝试
// await Task.Delay(10000);
// _ = TryReconnectAsync();
// }
// }
// }
// private void ProcessServerMessage(MessageToClient message)
// {
// try
// {
// // 更新游戏状态
// switch (message.GameState)
// {
// case GameState.GameStart:
// _logger.LogInfo("游戏开始");
// _viewModel.GameLog = "游戏开始...";
// break;
// case GameState.GameRunning:
// // 处理运行中的游戏数据
// _viewModel.GameLog = "游戏运行中...";
// break;
// case GameState.GameEnd:
// _logger.LogInfo("游戏结束");
// _viewModel.GameLog = "游戏结束";
// break;
// }
// // 更新全局游戏信息
// if (message.AllMessage != null)
// {
// UpdateGlobalGameInfo(message.AllMessage);
// }
// // 处理单个对象消息
// foreach (var obj in message.ObjMessage)
// {
// ProcessObjectMessage(obj);
// }
// }
// catch (Exception ex)
// {
// _logger.LogError($"处理服务器消息错误: {ex.Message}");
// }
// }
// private void UpdateGlobalGameInfo(MessageOfAll allMessage)
// {
// try
// {
// // 更新游戏时间
// _viewModel.CurrentTime = FormatGameTime(allMessage.GameTime);
// // 更新队伍得分
// _viewModel.RedScore = allMessage.BuddhistsTeamScore;
// _viewModel.BlueScore = allMessage.MonstersTeamScore;
// // 更新队伍经济/资源
// _viewModel.BuddhistTeamEconomy = allMessage.BuddhistsTeamEconomy;
// _viewModel.MonstersTeamEconomy = allMessage.MonstersTeamEconomy;
// // 更新英雄HP (如果ViewModel中有对应属性)
// if (typeof(MainWindowViewModel).GetProperty("BuddhistHeroHp") != null)
// {
// _viewModel.BuddhistHeroHp = allMessage.BuddhistsHeroHp;
// _viewModel.MonstersHeroHp = allMessage.MonstersHeroHp;
// }
// }
// catch (Exception ex)
// {
// _logger.LogError($"更新全局游戏信息失败: {ex.Message}");
// }
// }
// private void ProcessObjectMessage(MessageOfObj objMessage)
// {
// try
// {
// switch (objMessage.MessageOfObjCase)
// {
// case MessageOfObj.MessageOfObjOneofCase.CharacterMessage:
// UpdateCharacter(objMessage.CharacterMessage);
// break;
// case MessageOfObj.MessageOfObjOneofCase.BarracksMessage:
// UpdateBuilding(objMessage.BarracksMessage, "兵营");
// break;
// case MessageOfObj.MessageOfObjOneofCase.SpringMessage:
// UpdateBuilding(objMessage.SpringMessage, "泉水");
// break;
// case MessageOfObj.MessageOfObjOneofCase.FarmMessage:
// UpdateBuilding(objMessage.FarmMessage, "农场");
// break;
// case MessageOfObj.MessageOfObjOneofCase.TrapMessage:
// UpdateTrap(objMessage.TrapMessage);
// break;
// case MessageOfObj.MessageOfObjOneofCase.EconomyResourceMessage:
// UpdateResource(objMessage.EconomyResourceMessage);
// break;
// case MessageOfObj.MessageOfObjOneofCase.AdditionResourceMessage:
// UpdateAdditionResource(objMessage.AdditionResourceMessage);
// break;
// case MessageOfObj.MessageOfObjOneofCase.MapMessage:
// UpdateMap(objMessage.MapMessage);
// break;
// }
// }
// catch (Exception ex)
// {
// _logger.LogError($"处理对象消息失败: {ex.Message} (类型: {objMessage.MessageOfObjCase})");
// }
// }
// private void UpdateCharacter(MessageOfCharacter character)
// {
// try
// {
// // 在适当的团队集合中查找角色
// var isRedTeam = character.TeamId == 1; // 1表示取经队
// var collection = isRedTeam
// ? _viewModel.RedTeamCharacters
// : _viewModel.BlueTeamCharacters;
// // 计算网格坐标
// int gridX = character.X / 1000;
// int gridY = character.Y / 1000;
// // 尝试查找现有角色
// var existingCharacter = collection.FirstOrDefault(c => c.CharacterId == character.PlayerId);
// if (existingCharacter != null)
// {
// // 更新现有角色
// existingCharacter.Name = GetCharacterTypeName(character.CharacterType);
// existingCharacter.Hp = character.Hp;
// existingCharacter.PosX = gridX;
// existingCharacter.PosY = gridY;
// // 更新主动状态
// existingCharacter.ActiveState = GetCharacterStateText(character.CharacterActiveState);
// // 更新被动状态
// existingCharacter.PassiveStates.Clear();
// // 根据需要添加被动状态
// if (character.BlindState != CharacterState.NullCharacterState)
// existingCharacter.PassiveStates.Add("致盲");
// if (character.StunnedState != CharacterState.NullCharacterState)
// existingCharacter.PassiveStates.Add("定身");
// if (character.InvisibleState != CharacterState.NullCharacterState)
// existingCharacter.PassiveStates.Add("隐身");
// if (character.BurnedState != CharacterState.NullCharacterState)
// existingCharacter.PassiveStates.Add("灼烧");
// // 更新装备
// existingCharacter.EquipmentInventory.Clear();
// if (character.ShieldEquipment > 0)
// existingCharacter.EquipmentInventory.Add(new EquipmentItem("护盾", character.ShieldEquipment));
// if (character.ShoesEquipment > 0)
// existingCharacter.EquipmentInventory.Add(new EquipmentItem("鞋子", 1));
// if (character.PurificationEquipmentTime > 0)
// existingCharacter.EquipmentInventory.Add(new EquipmentItem("净化药水", 1));
// // 通知UI更新显示的状态和装备文本
// existingCharacter.OnPropertyChanged(nameof(CharacterViewModel.DisplayStates));
// existingCharacter.OnPropertyChanged(nameof(CharacterViewModel.DisplayEquipments));
// }
// else
// {
// // 创建新角色
// var newCharacter = new CharacterViewModel
// {
// CharacterId = character.PlayerId,
// Name = GetCharacterTypeName(character.CharacterType),
// Hp = character.Hp,
// PosX = gridX,
// PosY = gridY,
// ActiveState = GetCharacterStateText(character.CharacterActiveState)
// };
// // 添加被动状态
// if (character.BlindState != CharacterState.NullCharacterState)
// newCharacter.PassiveStates.Add("致盲");
// if (character.StunnedState != CharacterState.NullCharacterState)
// newCharacter.PassiveStates.Add("定身");
// if (character.InvisibleState != CharacterState.NullCharacterState)
// newCharacter.PassiveStates.Add("隐身");
// if (character.BurnedState != CharacterState.NullCharacterState)
// newCharacter.PassiveStates.Add("灼烧");
// // 添加装备
// if (character.ShieldEquipment > 0)
// newCharacter.EquipmentInventory.Add(new EquipmentItem("护盾", character.ShieldEquipment));
// if (character.ShoesEquipment > 0)
// newCharacter.EquipmentInventory.Add(new EquipmentItem("鞋子", 1));
// if (character.PurificationEquipmentTime > 0)
// newCharacter.EquipmentInventory.Add(new EquipmentItem("净化药水", 1));
// // 添加到集合
// collection.Add(newCharacter);
// }
// // 更新地图上的角色位置
// _viewModel.MapVM.UpdateCharacterPosition(
// character.PlayerId,
// character.TeamId,
// gridX,
// gridY,
// GetCharacterTypeName(character.CharacterType)
// );
// }
// catch (Exception ex)
// {
// _logger.LogError($"更新角色失败: {ex.Message}");
// }
// }
// private string GetCharacterTypeName(CharacterType type)
// {
// return type switch
// {
// CharacterType.TangSeng => "唐僧",
// CharacterType.SunWukong => "孙悟空",
// CharacterType.ZhuBajie => "猪八戒",
// CharacterType.ShaWujing => "沙悟净",
// CharacterType.BaiLongma => "白龙马",
// CharacterType.Monkid => "小和尚",
// CharacterType.JiuLing => "九灵元圣",
// CharacterType.HongHaier => "红孩儿",
// CharacterType.NiuMowang => "牛魔王",
// CharacterType.TieShan => "铁扇公主",
// CharacterType.ZhiZhujing => "蜘蛛精",
// CharacterType.Pawn => "小妖",
// _ => "未知角色"
// };
// }
// private string GetCharacterStateText(CharacterState state)
// {
// return state switch
// {
// CharacterState.Idle => "空置",
// CharacterState.Harvesting => "开采",
// CharacterState.Attacking => "攻击",
// CharacterState.SkillCasting => "释放技能",
// CharacterState.Constructing => "建造",
// CharacterState.Moving => "移动",
// _ => "未知状态"
// };
// }
// private void UpdateBuilding(MessageOfBarracks building, string buildingType)
// {
// try
// {
// // 转换为网格坐标
// int gridX = building.X / 1000;
// int gridY = building.Y / 1000;
// // 确保坐标在有效范围内
// if (gridX >= 0 && gridX < 50 && gridY >= 0 && gridY < 50)
// {
// // 在地图上更新建筑
// _viewModel.MapVM.UpdateBuildingCell(
// gridX,
// gridY,
// building.TeamId == 1 ? "取经队" : "妖怪队",
// buildingType,
// building.Hp
// );
// // 更新建筑信息文本 (假设ViewModel有这些属性)
// string buildingInfo = $"{buildingType} 位置:({gridX},{gridY}) 血量:{building.Hp}";
// if (building.TeamId == 1) // 取经队
// {
// // 尝试更新建筑信息,如果属性存在的话
// if (typeof(MainWindowViewModel).GetProperty("SomeBuildingInfo") != null)
// {
// _viewModel.SomeBuildingInfo = buildingInfo;
// }
// }
// else // 妖怪队
// {
// if (typeof(MainWindowViewModel).GetProperty("AnotherBuildingInfo") != null)
// {
// _viewModel.AnotherBuildingInfo = buildingInfo;
// }
// }
// }
// }
// catch (Exception ex)
// {
// _logger.LogError($"更新建筑(兵营)失败: {ex.Message}");
// }
// }
// private void UpdateBuilding(MessageOfSpring building, string buildingType)
// {
// try
// {
// // 类似于UpdateBuilding(MessageOfBarracks...)的实现
// int gridX = building.X / 1000;
// int gridY = building.Y / 1000;
// if (gridX >= 0 && gridX < 50 && gridY >= 0 && gridY < 50)
// {
// _viewModel.MapVM.UpdateBuildingCell(
// gridX,
// gridY,
// building.TeamId == 1 ? "取经队" : "妖怪队",
// buildingType,
// building.Hp
// );
// string buildingInfo = $"{buildingType} 位置:({gridX},{gridY}) 血量:{building.Hp}";
// if (building.TeamId == 1 &&
// typeof(MainWindowViewModel).GetProperty("SomeBuildingInfo") != null)
// {
// _viewModel.SomeBuildingInfo += "\n" + buildingInfo;
// }
// else if (building.TeamId != 1 &&
// typeof(MainWindowViewModel).GetProperty("AnotherBuildingInfo") != null)
// {
// _viewModel.AnotherBuildingInfo += "\n" + buildingInfo;
// }
// }
// }
// catch (Exception ex)
// {
// _logger.LogError($"更新建筑(泉水)失败: {ex.Message}");
// }
// }
// private void UpdateBuilding(MessageOfFarm building, string buildingType)
// {
// try
// {
// // 类似于其他建筑更新方法
// int gridX = building.X / 1000;
// int gridY = building.Y / 1000;
// if (gridX >= 0 && gridX < 50 && gridY >= 0 && gridY < 50)
// {
// _viewModel.MapVM.UpdateBuildingCell(
// gridX,
// gridY,
// building.TeamId == 1 ? "取经队" : "妖怪队",
// buildingType,
// building.Hp
// );
// string buildingInfo = $"{buildingType} 位置:({gridX},{gridY}) 血量:{building.Hp}";
// if (building.TeamId == 1 &&
// typeof(MainWindowViewModel).GetProperty("SomeBuildingInfo") != null)
// {
// _viewModel.SomeBuildingInfo += "\n" + buildingInfo;
// }
// else if (building.TeamId != 1 &&
// typeof(MainWindowViewModel).GetProperty("AnotherBuildingInfo") != null)
// {
// _viewModel.AnotherBuildingInfo += "\n" + buildingInfo;
// }
// }
// }
// catch (Exception ex)
// {
// _logger.LogError($"更新建筑(农场)失败: {ex.Message}");
// }
// }
// private void UpdateTrap(MessageOfTrap trap)
// {
// try
// {
// int gridX = trap.X / 1000;
// int gridY = trap.Y / 1000;
// if (gridX >= 0 && gridX < 50 && gridY >= 0 && gridY < 50)
// {
// string trapTypeName = trap.TrapType switch
// {
// TrapType.Hole => "陷阱坑",
// TrapType.Cage => "牢笼",
// _ => "未知陷阱"
// };
// _viewModel.MapVM.UpdateTrapCell(
// gridX,
// gridY,
// trap.TeamId == 1 ? "取经队" : "妖怪队",
// trapTypeName
// );
// }
// }
// catch (Exception ex)
// {
// _logger.LogError($"更新陷阱失败: {ex.Message}");
// }
// }
// private void UpdateResource(MessageOfEconomyResource resource)
// {
// try
// {
// int gridX = resource.X / 1000;
// int gridY = resource.Y / 1000;
// if (gridX >= 0 && gridX < 50 && gridY >= 0 && gridY < 50)
// {
// string resourceTypeName = resource.EconomyResourceType switch
// {
// EconomyResourceType.SmallEconomyResource => "小经济资源",
// EconomyResourceType.MediumEconomyResource => "中经济资源",
// EconomyResourceType.LargeEconomyResource => "大经济资源",
// _ => "未知资源"
// };
// _viewModel.MapVM.UpdateResourceCell(
// gridX,
// gridY,
// resourceTypeName,
// resource.Process
// );
// }
// }
// catch (Exception ex)
// {
// _logger.LogError($"更新经济资源失败: {ex.Message}");
// }
// }
// private void UpdateAdditionResource(MessageOfAdditionResource resource)
// {
// try
// {
// int gridX = resource.X / 1000;
// int gridY = resource.Y / 1000;
// if (gridX >= 0 && gridX < 50 && gridY >= 0 && gridY < 50)
// {
// string resourceName = GetAdditionResourceName(resource.AdditionResourceType);
// _viewModel.MapVM.UpdateAdditionResourceCell(
// gridX,
// gridY,
// resourceName,
// resource.Hp
// );
// }
// }
// catch (Exception ex)
// {
// _logger.LogError($"更新附加资源失败: {ex.Message}");
// }
// }
// private string GetAdditionResourceName(AdditionResourceType type)
// {
// return type switch
// {
// AdditionResourceType.LifePool1 => "生命池(小)",
// AdditionResourceType.LifePool2 => "生命池(中)",
// AdditionResourceType.LifePool3 => "生命池(大)",
// AdditionResourceType.CrazyMan1 => "疯人(小)",
// AdditionResourceType.CrazyMan2 => "疯人(中)",
// AdditionResourceType.CrazyMan3 => "疯人(大)",
// AdditionResourceType.QuickStep => "神行步",
// AdditionResourceType.WideView => "千里眼",
// _ => "未知加成资源"
// };
// }
// private void UpdateMap(MessageOfMap map)
// {
// try
// {
// // 将地图数据转换为二维数组
// int[,] mapData = new int[50, 50];
// for (int i = 0; i < map.Rows.Count && i < 50; i++)
// {
// for (int j = 0; j < map.Rows[i].Cols.Count && j < 50; j++)
// {
// mapData[i, j] = (int)map.Rows[i].Cols[j];
// }
// }
// // 更新地图视图模型
// _viewModel.MapVM.UpdateMap(mapData);
// _logger.LogInfo("地图数据已更新");
// }
// catch (Exception ex)
// {
// _logger.LogError($"更新地图数据时出错: {ex.Message}");
// }
// }
// private string FormatGameTime(int milliseconds)
// {
// TimeSpan time = TimeSpan.FromMilliseconds(milliseconds);
// return $"{time.Minutes:00}:{time.Seconds:00}";
// }
// }
//}

View File

@ -1,102 +1,55 @@
//CharacterViewModel.cs
using System.Collections.ObjectModel;
using CommunityToolkit.Mvvm.ComponentModel;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
namespace debug_interface.ViewModels
{
public partial class CharacterViewModel : ViewModelBase
{
[ObservableProperty]
private string name = "角色"; // 默认角色名,可由服务器更新
private long characterId;
[ObservableProperty]
private int hp = 1000; // 血量,可由服务器动态更新
private string name = "";
[ObservableProperty]
private int posX = 0;
private int hp;
[ObservableProperty]
private int posY = 0;
private int posX;
// 主动状态(单一)
// 可能值: "空置","开采","攻击","释放技能","建造","移动"
[ObservableProperty]
private string activeState = "空置";
private int posY;
// 被动状态(可叠加)
// 可能值: "致盲","击退","定身","隐身" 等,可由服务器控制增减
public ObservableCollection<string> PassiveStates { get; } = new ObservableCollection<string>();
[ObservableProperty]
private string activeState = "";
// 装备清单:用名称+数量表示。如 {"小血瓶":2, "鞋子":1, "大护盾":1, "净化药水":3}
// 为了方便绑定,用 ObservableCollection 来存储装备条目每个条目包含Name和Count
public ObservableCollection<EquipmentItem> EquipmentInventory { get; } = new ObservableCollection<EquipmentItem>();
public ObservableCollection<string> PassiveStates { get; } = new();
// 状态选项列表和装备选项列表已不再使用ComboBox选择而是纯展示。
// 如果需要仍保留可由服务器更新,但这里不会再用于交互。
public ObservableCollection<EquipmentItem> EquipmentInventory { get; } = new();
// 构造函数
public CharacterViewModel()
{
PassiveStates = new ObservableCollection<string>();
EquipmentInventory = new ObservableCollection<EquipmentItem>();
// 格式化状态文本的属性
public string DisplayStates =>
$"{ActiveState} {(PassiveStates.Count > 0 ? $"[{string.Join(", ", PassiveStates)}]" : "")}";
// 格式化装备文本的属性
public string DisplayEquipments =>
EquipmentInventory.Count > 0 ? string.Join(", ", EquipmentInventory) : "无";
}
// 用于UI展示状态字符串
// 格式: 主动xx 被动xx yy zz
public string DisplayStates
{
get
{
var sb = new StringBuilder();
sb.Append("(主动:").Append(ActiveState).Append(" 被动:");
if (PassiveStates.Count > 0)
sb.Append(string.Join(" ", PassiveStates));
else
sb.Append("无");
sb.Append("");
return sb.ToString();
}
}
// 用于UI展示装备字符串
// 格式: 装备: 小血瓶x2 鞋子x1 大护盾x1 净化药水x3
public string DisplayEquipments
{
get
{
if (EquipmentInventory.Count == 0)
{
return "装备:无";
}
return "装备: " + string.Join(", ",
EquipmentInventory.Select(e => $"{e.Name}×{e.Count}"));
}
}
// 当ActiveState或PassiveStates变化后通知UI更新 DisplayStates
partial void OnActiveStateChanged(string oldValue, string newValue)
{
OnPropertyChanged(nameof(DisplayStates));
}
// 如果被动状态列表更新需要调用OnPropertyChanged(nameof(DisplayStates))
// 可以在服务器更新逻辑中调用。
// 同理当EquipmentInventory变化时需要更新DisplayEquipments
// 可以在添加/移除装备后调用OnPropertyChanged(nameof(DisplayEquipments))
}
// 定义装备类
public class EquipmentItem
{
public string Name { get; set; }
public int Count { get; set; }
public string Name { get; }
public int Count { get; }
public EquipmentItem(string name, int count)
{
Name = name;
Count = count;
}
public override string ToString()
{
return Count > 1 ? $"{Name}x{Count}" : Name;
}
}
}

View File

@ -1,29 +1,19 @@
// ViewModels/MainWindowViewModel.cs
using CommunityToolkit.Mvvm.ComponentModel;
using System;
using System.Collections.ObjectModel;
using System;
using System.Timers;
using debug_interface.ViewModels;
using CommunityToolkit.Mvvm.ComponentModel;
using installer.Model;
using installer.Data;
namespace debug_interface.ViewModels
{
public partial class MainWindowViewModel : ViewModelBase
{
// Keep only one definition of MapVM
// 属性定义
[ObservableProperty]
private MapViewModel mapVM;
public ObservableCollection<CharacterViewModel> RedTeamCharacters { get; }
public ObservableCollection<CharacterViewModel> BlueTeamCharacters { get; }
private string gameLog = "等待连接...";
[ObservableProperty]
private string someBuildingInfo = "红方建筑信息...";
[ObservableProperty]
private string anotherBuildingInfo = "蓝方建筑信息...";
[ObservableProperty]
private string currentTime = DateTime.Now.ToString("HH:mm:ss");
private string currentTime = "00:00";
[ObservableProperty]
private int redScore = 0;
@ -32,85 +22,74 @@ namespace debug_interface.ViewModels
private int blueScore = 0;
[ObservableProperty]
private bool isBlueView = true;
public bool IsRedView
{
get => !IsBlueView;
set => IsBlueView = !value;
}
private string someBuildingInfo = "";
[ObservableProperty]
private string gameLog = "地图...";
private string anotherBuildingInfo = "";
private Timer _timer;
[ObservableProperty]
private int buddhistTeamEconomy = 0;
public MainWindowViewModel()
[ObservableProperty]
private int monstersTeamEconomy = 0;
[ObservableProperty]
private MapViewModel mapVM;
// 团队角色集合
public ObservableCollection<CharacterViewModel> RedTeamCharacters { get; } = new();
public ObservableCollection<CharacterViewModel> BlueTeamCharacters { get; } = new();
// 构造函数
public MainWindowViewModel(Logger logger, ConfigData config) : base(logger)
{
// Initialize collections first
RedTeamCharacters = new ObservableCollection<CharacterViewModel>();
BlueTeamCharacters = new ObservableCollection<CharacterViewModel>();
// Initialize characters
for (int i = 0; i < 6; i++)
{
var redChar = new CharacterViewModel()
{
Name = "红方角色" + (i + 1),
Hp = 1000 * (i + 1),
ActiveState = i % 2 == 0 ? "攻击" : "移动",
};
redChar.PassiveStates.Add("致盲");
if (i % 3 == 0) redChar.PassiveStates.Add("定身");
redChar.EquipmentInventory.Add(new EquipmentItem("小血瓶", 2));
if (i % 2 == 0)
redChar.EquipmentInventory.Add(new EquipmentItem("大护盾", 1));
RedTeamCharacters.Add(redChar);
var blueChar = new CharacterViewModel()
{
Name = "蓝方角色" + (i + 1),
Hp = 1500 + i * 500,
ActiveState = "空置",
};
blueChar.PassiveStates.Add("隐身");
blueChar.EquipmentInventory.Add(new EquipmentItem("净化药水", 3));
if (i % 2 == 1)
blueChar.EquipmentInventory.Add(new EquipmentItem("鞋子", 1));
BlueTeamCharacters.Add(blueChar);
}
// Initialize MapViewModel
// 初始化MapViewModel
MapVM = new MapViewModel();
// Assign random initial positions to characters
Random rnd = new Random();
foreach (var character in RedTeamCharacters)
// 如果在设计模式下,可以添加一些测试数据
if (Avalonia.Controls.Design.IsDesignMode)
{
character.PosX = rnd.Next(10, 40);
character.PosY = rnd.Next(10, 40);
InitializeDesignTimeData();
}
foreach (var character in BlueTeamCharacters)
{
character.PosX = rnd.Next(10, 40);
character.PosY = rnd.Next(10, 40);
// 启动UI更新定时器
StartUiUpdateTimer();
}
_timer = new Timer(1000);
_timer.Elapsed += Timer_Elapsed;
_timer.Start();
}
// 设计时数据
private void InitializeDesignTimeData()
{
GameLog = "设计模式 - 模拟数据";
CurrentTime = "12:34";
RedScore = 50;
BlueScore = 30;
private void Timer_Elapsed(object? sender, ElapsedEventArgs e)
// 添加一些测试角色
for (int i = 0; i < 3; i++)
{
CurrentTime = DateTime.Now.ToString("HH:mm:ss");
Avalonia.Threading.Dispatcher.UIThread.Post(() =>
RedTeamCharacters.Add(new CharacterViewModel
{
OnPropertyChanged(nameof(CurrentTime));
CharacterId = i + 1,
Name = $"取经队角色{i + 1}",
Hp = 1000,
ActiveState = "空置"
});
BlueTeamCharacters.Add(new CharacterViewModel
{
CharacterId = i + 101,
Name = $"妖怪队角色{i + 1}",
Hp = 1200,
ActiveState = "移动"
});
}
}
// 定时器更新方法
protected override void OnTimerTick(object? sender, EventArgs e)
{
// 更新当前时间显示
CurrentTime = DateTime.Now.ToString("HH:mm:ss");
}
}
}

View File

@ -1,137 +1,201 @@
//MapViewModel.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections.ObjectModel;
using CommunityToolkit.Mvvm.ComponentModel;
using System.Collections.ObjectModel;
using debug_interface.Models;
using Avalonia.Media;
using debug_interface.Models;
namespace debug_interface.ViewModels
{
// 地图视图模型,管理整个 50×50 的地图数据
public partial class MapViewModel : ObservableObject
public partial class MapViewModel : ViewModelBase
{
// 定义地图网格大小为 50× 50
public const int GridSize = 50;
private const int GridSize = 50;
// ObservableCollection 存放 2500 个 MapCell 对象,每个对象代表一个地图格子
// 数据绑定到视图后,界面会显示出整个地图
public ObservableCollection<MapCell> MapCells { get; }
public ObservableCollection<CharacterViewModel> RedTeamCharacters { get; }
public ObservableCollection<CharacterViewModel> BlueTeamCharacters { get; }
[ObservableProperty]
private ObservableCollection<MapCell> mapCells = new();
public MapViewModel(ObservableCollection<CharacterViewModel> redTeam, ObservableCollection<CharacterViewModel> blueTeam)
{
MapCells = new ObservableCollection<MapCell>();
RedTeamCharacters = redTeam;
BlueTeamCharacters = blueTeam;
InitializeDefaultMap();
}
// 构造函数,用于测试
public MapViewModel()
{
MapCells = new ObservableCollection<MapCell>();
InitializeDefaultMap();
// 初始化地图单元格
InitializeMapCells();
}
// 初始化默认地图数据,用于测试效果
private void InitializeDefaultMap()
private void InitializeMapCells()
{
// 遍历所有行和列
for (int i = 0; i < GridSize; i++)
MapCells.Clear();
for (int i = 0; i < GridSize * GridSize; i++)
{
for (int j = 0; j < GridSize; j++)
MapCells.Add(new MapCell
{
// 创建一个 MapCell 对象,并设置行列信息
var cell = new MapCell
{
CellX = i,
CellY = j,
// 根据坐标决定默认单元格类型
CellType = GetDefaultCellType(i, j),
DisplayText = "" // 默认无文本显示,可后续根据需要设置
};
// 设置显示颜色,根据单元格类型获取颜色
cell.DisplayColor = new SolidColorBrush(GetColorForCellType(cell.CellType));
MapCells.Add(cell);
}
Row = i / GridSize,
Col = i % GridSize,
CellType = MapCellType.Empty,
DisplayText = "",
DisplayColor = new SolidColorBrush(Colors.White),
BackgroundColor = new SolidColorBrush(Colors.LightGray)
});
}
}
// 根据单元格在地图中的坐标决定默认类型
private MapCellType GetDefaultCellType(int i, int j)
// 更新整个地图
public void UpdateMap(int[,] mapData)
{
// 1. 边界(第一行、最后一行、第一列、最后一列)均设为障碍物
if (i == 0 || i == GridSize - 1 || j == 0 || j == GridSize - 1)
{
return MapCellType.Obstacle;
}
// 2. 在特定位置放置资源点(测试用)
if ((i == 10 && j == 10) || (i == 20 && j == 20) || (i == 30 && j == 30))
{
return MapCellType.Resource;
}
// 3. 在特定位置放置草丛(测试用)
if ((i == 15 && j == 35) || (i == 35 && j == 15))
{
return MapCellType.Grass;
}
// 4. 可预留一个建筑点,例如 (25,25)
if (i == 25 && j == 25)
{
return MapCellType.Building;
}
// 5. 其他区域默认为空地
return MapCellType.OpenLand;
}
// 根据单元格类型返回对应的颜色(可根据需要调整颜色)
private Color GetColorForCellType(MapCellType type)
{
switch (type)
{
case MapCellType.Obstacle:
return Colors.DarkGray;
case MapCellType.OpenLand:
return Colors.LightGreen;
case MapCellType.Grass:
return Colors.Green;
case MapCellType.Resource:
return Colors.Yellow;
case MapCellType.Building:
return Colors.Orange;
default:
return Colors.Black;
}
}
// 用于更新地图数据的方法,
// newMapData 是一个 50x50 的二维整型数组,数值应能映射为 MapCellType 枚举值
public void UpdateMap(int[,] newMapData)
{
if (newMapData.GetLength(0) != GridSize || newMapData.GetLength(1) != GridSize)
throw new ArgumentException("地图数据尺寸不正确");
// 遍历二维数组更新每个 MapCell 对象
for (int i = 0; i < GridSize; i++)
{
for (int j = 0; j < GridSize; j++)
{
int index = i * GridSize + j;
// 将整型转换为 MapCellType 枚举
MapCellType newType = (MapCellType)newMapData[i, j];
var cell = MapCells[index];
cell.CellType = newType;
// 更新颜色
cell.DisplayColor = new SolidColorBrush(GetColorForCellType(newType));
// 如果需要,可以根据新数据更新文本(例如建筑血量、资源剩余)
cell.DisplayText = "123"; // 这里留空,可扩展
if (index < MapCells.Count)
{
int cellType = mapData[i, j];
UpdateCellType(MapCells[index], cellType);
}
}
}
OnPropertyChanged(nameof(MapCells));
}
private void UpdateCellType(MapCell cell, int cellType)
{
// 根据cellType设置单元格属性
// 这里简化处理
switch (cellType)
{
case 0: // 空地
cell.CellType = MapCellType.Empty;
cell.BackgroundColor = new SolidColorBrush(Colors.White);
break;
case 1: // 障碍物
cell.CellType = MapCellType.Obstacle;
cell.BackgroundColor = new SolidColorBrush(Colors.DarkGray);
break;
case 2: // 资源
cell.CellType = MapCellType.Resource;
cell.BackgroundColor = new SolidColorBrush(Colors.Green);
break;
default:
cell.CellType = MapCellType.Empty;
cell.BackgroundColor = new SolidColorBrush(Colors.LightGray);
break;
}
}
// 更新角色位置
public void UpdateCharacterPosition(long characterId, long teamId, int x, int y, string name)
{
// 简化实现
int index = x * GridSize + y;
if (index >= 0 && index < MapCells.Count)
{
MapCells[index].DisplayText = name.Substring(0, 1);
MapCells[index].DisplayColor = teamId == 1
? new SolidColorBrush(Colors.Red)
: new SolidColorBrush(Colors.Blue);
OnPropertyChanged(nameof(MapCells));
}
}
// 更新建筑
public void UpdateBuildingCell(int x, int y, string team, string buildingType, int hp)
{
int index = x * GridSize + y;
if (index >= 0 && index < MapCells.Count)
{
MapCells[index].CellType = MapCellType.Building;
MapCells[index].DisplayText = buildingType.Substring(0, 1);
MapCells[index].DisplayColor = team == "取经队"
? new SolidColorBrush(Colors.DarkRed)
: new SolidColorBrush(Colors.DarkBlue);
OnPropertyChanged(nameof(MapCells));
}
}
// 更新陷阱
public void UpdateTrapCell(int x, int y, string team, string trapType)
{
int index = x * GridSize + y;
if (index >= 0 && index < MapCells.Count)
{
MapCells[index].CellType = MapCellType.Obstacle;
MapCells[index].DisplayText = trapType.Substring(0, 1);
MapCells[index].DisplayColor = team == "取经队"
? new SolidColorBrush(Colors.IndianRed)
: new SolidColorBrush(Colors.CornflowerBlue);
OnPropertyChanged(nameof(MapCells));
}
}
// 更新资源
public void UpdateResourceCell(int x, int y, string resourceType, int process)
{
int index = x * GridSize + y;
if (index >= 0 && index < MapCells.Count)
{
MapCells[index].CellType = MapCellType.Resource;
MapCells[index].DisplayText = process.ToString();
MapCells[index].DisplayColor = new SolidColorBrush(Colors.DarkGreen);
OnPropertyChanged(nameof(MapCells));
}
}
// 更新额外资源
public void UpdateAdditionResourceCell(int x, int y, string resourceName, int value)
{
int index = x * GridSize + y;
if (index >= 0 && index < MapCells.Count)
{
MapCells[index].CellType = MapCellType.Resource;
MapCells[index].DisplayText = value.ToString();
// 根据资源类型选择颜色
if (resourceName.Contains("生命池"))
{
MapCells[index].DisplayColor = new SolidColorBrush(Colors.LightGreen);
}
else if (resourceName.Contains("疯人"))
{
MapCells[index].DisplayColor = new SolidColorBrush(Colors.OrangeRed);
}
else
{
MapCells[index].DisplayColor = new SolidColorBrush(Colors.Purple);
}
OnPropertyChanged(nameof(MapCells));
}
}
}
//public enum MapCellType
//{
// Empty,
// Obstacle,
// Building,
// Resource,
// Character
//}
//public partial class MapCell : ViewModelBase
//{
// [ObservableProperty]
// private int row;
// [ObservableProperty]
// private int col;
// [ObservableProperty]
// private MapCellType cellType;
// [ObservableProperty]
// private string displayText = "";
// [ObservableProperty]
// private IBrush displayColor = new SolidColorBrush(Colors.Black);
// [ObservableProperty]
// private IBrush backgroundColor = new SolidColorBrush(Colors.White);
//}
}

View File

@ -1,4 +1,3 @@
//ViewModeBase.cs
using System;
using Avalonia.Threading;

View File

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

View File

@ -253,6 +253,7 @@ public class Character : Movable, ICharacter
Shield = new(0);
NiuShield = new(0);
AttackSize = new(Occupation.BaseAttackSize);
HP = new(Occupation.MaxHp);
AttackPower = new(Occupation.AttackPower);
MoneyPool = pool;
Init();
@ -340,10 +341,6 @@ public class Character : Movable, ICharacter
}
case EquipmentType.BERSERK_POTION:
{
if (IsBerserk)
{
return false;
}
IsBerserk = true;
BerserkTime = Environment.TickCount64;
SetCharacterState(CharacterState1, CharacterState.BERSERK);//此处缺少时间限制

View File

@ -299,6 +299,7 @@ namespace Gaming
character.Shoes.SubPositiveV(GameData.CrazySpeed);
character.ATKFrequency = GameData.ATKFreq;
character.BerserkTime = long.MaxValue;
character.IsBerserk = false;
}
}
}
@ -314,7 +315,15 @@ namespace Gaming
character.IsShoes = false;
}
}
}
public void CheckInvisibility(Character character)
{
int nowtime = gameMap.Timer.NowTime();
if (nowtime >= GameData.SevenMinutes
)
{
character.visible = true;
}
}
}
}

View File

@ -35,7 +35,7 @@ namespace Gaming
return GameObj.invalidID;
}
teamList[(int)playerInitInfo.teamID].CharacterNum.Add(1);
if (gameMap.TeamExists(playerInitInfo.teamID))
if (!gameMap.TeamExists(playerInitInfo.teamID))
{
return GameObj.invalidID;
}
@ -423,6 +423,18 @@ namespace Gaming
{
if (!gameMap.Timer.IsGaming)
return false;
int nowtime = gameMap.Timer.NowTime();
if (nowtime >= GameData.SevenMinutes)
{
if (equiptype == EquipmentType.INVISIBILITY_POTION)
{
return false;
}
}
else if (equiptype == EquipmentType.BERSERK_POTION)
{
return false;
}
Character? character = gameMap.FindCharacterInPlayerID(teamID, characterID);
if (character != null && character.IsRemoved == false)
return equipManager.GetEquipment(character, equiptype);

View File

@ -214,5 +214,6 @@ namespace Preparation.Utility
public const int InitialMoney = 5000;
public const int CharacterTotalNumMax = 6;
public const double RecycleRate = 0.5;
public const int SevenMinutes = 420000;
}
}