Debug_interface - old Server Communicate
This commit is contained in:
commit
d54b51538d
|
@ -22,7 +22,7 @@ namespace Constants
|
|||
SCCI int32_t DestroyFarmBonus = 4000;
|
||||
// SCCI double recoverMultiplier = 1.2;
|
||||
// SCCI double recycleMultiplier = 0.5;
|
||||
//角色
|
||||
// 角色
|
||||
SCCI int32_t sizeofCharacter = 800;
|
||||
SCCI int32_t Speed = 2500;
|
||||
struct Monk
|
||||
|
@ -92,39 +92,39 @@ namespace Constants
|
|||
SCCI int32_t attackRange = 5;
|
||||
SCCI int32_t Cost = 3000;
|
||||
};
|
||||
//模块
|
||||
// 模块
|
||||
|
||||
struct resumption //生命之泉
|
||||
struct resumption // 生命之泉
|
||||
{
|
||||
SCCI int32_t recovery1 = 50;
|
||||
SCCI int32_t recovery2 = 100;
|
||||
SCCI int32_t recovery3 = 150;
|
||||
SCCI int32_t score1 = 2000; //一级生命之泉分数
|
||||
SCCI int32_t score2 = 3000; //二级生命之泉分数
|
||||
SCCI int32_t score3 = 4000; //三级生命之泉分数
|
||||
SCCI int32_t maxHp1 = 200; //一级生命之泉守关怪物血量
|
||||
SCCI int32_t maxHp2 = 300; //二级生命之泉守关怪物血量
|
||||
SCCI int32_t maxHp3 = 400; //三级生命之泉守关怪物血量
|
||||
SCCI int32_t attack = 10; //生命之泉守关怪物攻击力
|
||||
SCCI int32_t score1 = 2000; // 一级生命之泉分数
|
||||
SCCI int32_t score2 = 3000; // 二级生命之泉分数
|
||||
SCCI int32_t score3 = 4000; // 三级生命之泉分数
|
||||
SCCI int32_t maxHp1 = 200; // 一级生命之泉守关怪物血量
|
||||
SCCI int32_t maxHp2 = 300; // 二级生命之泉守关怪物血量
|
||||
SCCI int32_t maxHp3 = 400; // 三级生命之泉守关怪物血量
|
||||
SCCI int32_t attack = 10; // 生命之泉守关怪物攻击力
|
||||
};
|
||||
|
||||
struct Attack_Boost //狂战士之力
|
||||
struct Attack_Boost // 狂战士之力
|
||||
{
|
||||
SCCI int32_t attack_boost1 = 10;
|
||||
SCCI int32_t attack_boost2 = 15;
|
||||
SCCI int32_t attack_boost3 = 20;
|
||||
SCCI int32_t time1 = 30; //一级狂战士之力持续时间
|
||||
SCCI int32_t time2 = 45; //二级狂战士之力持续时间
|
||||
SCCI int32_t time3 = 60; //三级狂战士之力持续时间
|
||||
SCCI int32_t score1 = 4000; //一级狂战士之力分数
|
||||
SCCI int32_t score2 = 5000; //二级狂战士之力分数
|
||||
SCCI int32_t score3 = 6000; //三级狂战士之力分数
|
||||
SCCI int32_t maxHp1 = 400; //一级狂战士之力守关怪物血量
|
||||
SCCI int32_t maxHp2 = 500; //二级狂战士之力守关怪物血量
|
||||
SCCI int32_t maxHp3 = 600; //三级狂战士之力守关怪物血量
|
||||
SCCI int32_t attack1 = 10; //一级狂战士之力守关怪物攻击力
|
||||
SCCI int32_t attack2 = 15; //二级狂战士之力守关怪物攻击力
|
||||
SCCI int32_t attack3 = 20; //三级狂战士之力守关怪物攻击力
|
||||
SCCI int32_t time1 = 30; // 一级狂战士之力持续时间
|
||||
SCCI int32_t time2 = 45; // 二级狂战士之力持续时间
|
||||
SCCI int32_t time3 = 60; // 三级狂战士之力持续时间
|
||||
SCCI int32_t score1 = 4000; // 一级狂战士之力分数
|
||||
SCCI int32_t score2 = 5000; // 二级狂战士之力分数
|
||||
SCCI int32_t score3 = 6000; // 三级狂战士之力分数
|
||||
SCCI int32_t maxHp1 = 400; // 一级狂战士之力守关怪物血量
|
||||
SCCI int32_t maxHp2 = 500; // 二级狂战士之力守关怪物血量
|
||||
SCCI int32_t maxHp3 = 600; // 三级狂战士之力守关怪物血量
|
||||
SCCI int32_t attack1 = 10; // 一级狂战士之力守关怪物攻击力
|
||||
SCCI int32_t attack2 = 15; // 二级狂战士之力守关怪物攻击力
|
||||
SCCI int32_t attack3 = 20; // 三级狂战士之力守关怪物攻击力
|
||||
};
|
||||
|
||||
struct Speed_Boost
|
||||
|
@ -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;
|
||||
|
@ -182,7 +182,7 @@ namespace Constants
|
|||
SCCI int32_t time = 5;
|
||||
SCCI int32_t continous_time = 30;
|
||||
};
|
||||
//商店商品
|
||||
// 商店商品
|
||||
struct blood_vial
|
||||
{
|
||||
SCCI int32_t cost1 = 1500;
|
||||
|
@ -226,9 +226,9 @@ namespace Constants
|
|||
{
|
||||
SCCI int32_t cost = 10000;
|
||||
SCCI int32_t time = 30;
|
||||
SCCI int32_t attack_boost = 1.2; //注意这是提升的倍数
|
||||
SCCI int32_t speed_boost = 300; //注意这是直接叠加
|
||||
SCCI int32_t attack_freq_boost = 1.25; //注意这是提升的倍数
|
||||
SCCI int32_t attack_boost = 1.2; // 注意这是提升的倍数
|
||||
SCCI int32_t speed_boost = 300; // 注意这是直接叠加
|
||||
SCCI int32_t attack_freq_boost = 1.25; // 注意这是提升的倍数
|
||||
};
|
||||
} // namespace Constants
|
||||
#endif
|
|
@ -8,23 +8,26 @@
|
|||
// 为假则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内部声明变量与函数
|
||||
|
||||
void AI::play(ICharacterAPI& api)
|
||||
void AI::play(ICharacterAPI & api)
|
||||
{
|
||||
if (this->playerID == 1)
|
||||
{
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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的操作
|
||||
|
|
|
@ -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 # 注意这是提升的倍数
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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}";
|
||||
// }
|
||||
// }
|
||||
//}
|
|
@ -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)}]" : "")}";
|
||||
|
||||
// 用于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 string DisplayEquipments =>
|
||||
EquipmentInventory.Count > 0 ? string.Join(", ", EquipmentInventory) : "无";
|
||||
}
|
||||
|
||||
// 定义装备类
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
_timer = new Timer(1000);
|
||||
_timer.Elapsed += Timer_Elapsed;
|
||||
_timer.Start();
|
||||
// 启动UI更新定时器
|
||||
StartUiUpdateTimer();
|
||||
}
|
||||
|
||||
private void Timer_Elapsed(object? sender, ElapsedEventArgs e)
|
||||
// 设计时数据
|
||||
private void InitializeDesignTimeData()
|
||||
{
|
||||
CurrentTime = DateTime.Now.ToString("HH:mm:ss");
|
||||
Avalonia.Threading.Dispatcher.UIThread.Post(() =>
|
||||
GameLog = "设计模式 - 模拟数据";
|
||||
CurrentTime = "12:34";
|
||||
RedScore = 50;
|
||||
BlueScore = 30;
|
||||
|
||||
// 添加一些测试角色
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
OnPropertyChanged(nameof(CurrentTime));
|
||||
});
|
||||
RedTeamCharacters.Add(new CharacterViewModel
|
||||
{
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
//}
|
||||
}
|
|
@ -1,4 +1,3 @@
|
|||
//ViewModeBase.cs
|
||||
using System;
|
||||
|
||||
using Avalonia.Threading;
|
||||
|
|
|
@ -1,24 +1,22 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net8.0-windows</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<BuiltInComInteropSupport>true</BuiltInComInteropSupport>
|
||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
|
||||
<AssemblyName>debug_interface</AssemblyName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net8.0-windows</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<BuiltInComInteropSupport>true</BuiltInComInteropSupport>
|
||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
|
||||
<AssemblyName>debug_interface</AssemblyName>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<AvaloniaResource Include="Assets\**" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<AvaloniaResource Include="Assets\**" />
|
||||
<ProjectReference Include="..\..\..\logic\proto\proto.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!-- 相对路径 -->
|
||||
<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">
|
||||
|
@ -30,26 +28,26 @@
|
|||
<Error Condition="!Exists('../../installer/Model/Logger.cs')" />
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Avalonia" Version="11.2.5" />
|
||||
<PackageReference Include="Avalonia.Desktop" Version="11.2.5" />
|
||||
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.2.5" />
|
||||
<PackageReference Include="Avalonia.Fonts.Inter" Version="11.2.5" />
|
||||
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
|
||||
<PackageReference Include="Avalonia.Diagnostics" Version="11.2.5">
|
||||
<IncludeAssets Condition="'$(Configuration)' != 'Debug'">None</IncludeAssets>
|
||||
<PrivateAssets Condition="'$(Configuration)' != 'Debug'">All</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
|
||||
<PackageReference Include="Google.Protobuf" Version="3.30.2" />
|
||||
<PackageReference Include="Grpc.Net.Client" Version="2.70.0" />
|
||||
<PackageReference Include="Grpc.Tools" Version="2.71.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Avalonia" Version="11.2.5" />
|
||||
<PackageReference Include="Avalonia.Desktop" Version="11.2.5" />
|
||||
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.2.5" />
|
||||
<PackageReference Include="Avalonia.Fonts.Inter" Version="11.2.5" />
|
||||
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
|
||||
<PackageReference Include="Avalonia.Diagnostics" Version="11.2.5">
|
||||
<IncludeAssets Condition="'$(Configuration)' != 'Debug'">None</IncludeAssets>
|
||||
<PrivateAssets Condition="'$(Configuration)' != 'Debug'">All</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
|
||||
<PackageReference Include="Google.Protobuf" Version="3.30.2" />
|
||||
<PackageReference Include="Grpc.Net.Client" Version="2.70.0" />
|
||||
<PackageReference Include="Grpc.Tools" Version="2.71.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Utili\" />
|
||||
|
|
|
@ -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);//此处缺少时间限制
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue