refactor: update TrainParty system

This commit is contained in:
letheriver2007
2025-01-28 08:14:54 +08:00
committed by EggLink
parent 2b8b269a1d
commit f4f3fa42b9
16 changed files with 131 additions and 391 deletions

View File

@@ -1,9 +1,9 @@
using EggLink.DanhengServer.Data;
using EggLink.DanhengServer.Database.Avatar;
using EggLink.DanhengServer.Database.Inventory;
using EggLink.DanhengServer.Database.TrainParty;
using EggLink.DanhengServer.Enums.Item;
using EggLink.DanhengServer.GameServer.Server.Packet.Send.PlayerSync;
using EggLink.DanhengServer.GameServer.Server.Packet.Send.Scene;
using EggLink.DanhengServer.Internationalization;
namespace EggLink.DanhengServer.Command.Command.Cmd;
@@ -252,34 +252,44 @@ public class CommandGiveall : ICommand
return;
}
foreach (var grid in GameData.TrainPartyGridConfigData.Keys) await player.TrainPartyManager!.AddGrid(grid);
// Reset
player.TrainPartyManager!.Data.Fund = 1000000;
player.TrainPartyManager!.Data.Areas.Clear();
foreach (var card in GameData.TrainPartyCardConfigData.Keys) await player.TrainPartyManager!.AddCard(card);
foreach (var area in player.TrainPartyManager!.TrainPartyData.Areas)
foreach (var step in GameData.TrainPartyStepConfigData.Values.Where(stepExcel => GameData
.TrainPartyAreaGoalConfigData.First(x => x.Value.AreaID == area.Value.AreaId).Value
.StepGroupList.Contains(stepExcel.GroupID)))
area.Value.StepList.Add(step.ID);
Dictionary<string, int> update = [];
player.SceneData!.FloorSavedData[player.SceneInstance!.FloorId] = [];
foreach (var savedValue in player.SceneInstance!.FloorInfo!.FloorSavedValue)
if (savedValue.Name.StartsWith("Build_") || savedValue.Name == "Onboarded")
foreach (var excel in GameData.TrainPartyAreaConfigData.Where(excel =>
!player.TrainPartyManager!.Data.Areas.ContainsKey(excel.Key)))
player.TrainPartyManager!.Data.Areas[excel.Key] = new TrainAreaInfo
{
player.SceneData!.FloorSavedData[player.SceneInstance!.FloorId][savedValue.Name] = 1;
update.TryAdd(savedValue.Name, 1);
}
else if (savedValue.Name.StartsWith("Progress_"))
AreaId = excel.Key,
StepList = []
};
foreach (var area in player.TrainPartyManager!.Data.Areas)
foreach (var step in GameData.TrainPartyStepConfigData.Values.Where(stepExcel =>
GameData.TrainPartyAreaGoalConfigData.FirstOrDefault(x =>
x.Value.AreaID == area.Value.AreaId).Value.StepGroupList.Contains(stepExcel.GroupID)))
area.Value.StepList.Add(step.ID);
foreach (var floorInfo in GameData.FloorInfoData.Values)
{
var savedData = new Dictionary<string, int>();
foreach (var floorSavedValue in floorInfo.FloorSavedValue)
{
player.SceneData!.FloorSavedData[player.SceneInstance!.FloorId][savedValue.Name] = 100;
update.TryAdd(savedValue.Name, 100);
if (floorSavedValue.Name.StartsWith("Build_") || floorSavedValue.Name == "Onboarded")
savedData[floorSavedValue.Name] = 1;
else if (floorSavedValue.Name.StartsWith("Progress_"))
savedData[floorSavedValue.Name] = 100;
else if (floorSavedValue.Name.StartsWith("Connection_") || floorSavedValue.Name.StartsWith("Utility_"))
savedData[floorSavedValue.Name] = 0;
}
await player.SendPacket(new PacketUpdateFloorSavedValueNotify(update, player));
if (savedData.Count > 0)
player.SceneData!.FloorSavedData[floorInfo.FloorID] = savedData;
}
await arg.SendMsg(I18NManager.Translate("Game.Command.GiveAll.GiveAllItems",
I18NManager.Translate("Word.TrainItem"), "1"));
I18NManager.Translate("Word.TrainParty"), "1"));
}
[CommandMethod("0 path")]

View File

@@ -7,28 +7,23 @@ namespace EggLink.DanhengServer.Data.Config.Scene;
public class FloorInfo
{
public int FloorID { get; set; }
public int StartGroupIndex { get; set; }
public int StartAnchorID { get; set; }
public List<FloorGroupInfo> GroupInstanceList { get; set; } = [];
public List<FloorDimensionInfo> DimensionList { get; set; } = [];
[JsonConverter(typeof(ConcurrentDictionaryConverter<int, PropInfo>))]
public ConcurrentDictionary<int, PropInfo> CachedTeleports = [];
[JsonConverter(typeof(ConcurrentDictionaryConverter<int, GroupInfo>))]
public ConcurrentDictionary<int, GroupInfo> Groups = [];
[JsonIgnore] public bool Loaded;
[JsonConverter(typeof(ConcurrentBagConverter<PropInfo>))]
public ConcurrentBag<PropInfo> UnlockedCheckpoints = [];
public int FloorID { get; set; }
public int StartGroupIndex { get; set; }
public int StartAnchorID { get; set; }
public List<FloorGroupInfo> GroupInstanceList { get; set; } = [];
public List<FloorSavedValueInfo> SavedValues { get; set; } = [];
public List<FloorCustomValueInfo> CustomValues { get; set; } = [];
public List<FloorDimensionInfo> DimensionList { get; set; } = [];
[JsonIgnore] public bool Loaded;
[JsonIgnore] public int StartGroupID { get; set; }
[JsonIgnore] public List<FloorSavedValueInfo> FloorSavedValue { get; set; } = [];
public AnchorInfo? GetAnchorInfo(int groupId, int anchorId)
@@ -39,6 +34,7 @@ public class FloorInfo
return group.AnchorList.Find(info => info.ID == anchorId);
}
public void OnLoad()
{
if (Loaded) return;
@@ -47,19 +43,9 @@ public class FloorInfo
foreach (var dimension in DimensionList) dimension.OnLoad(this);
FloorSavedValue.AddRange(SavedValues);
// Cache anchors
foreach (var group in Groups.Values)
{
foreach (var condition in group.SavedValueCondition.Conditions.Where(x =>
SavedValues.Find(s => s.Name == x.SavedValueName) == null))
FloorSavedValue.Add(new FloorSavedValueInfo
{
DefaultValue = 0,
ID = -1,
Name = condition.SavedValueName
});
foreach (var prop in group.PropList)
// Check if prop can be teleported to
if (prop.AnchorID > 0)
@@ -110,22 +96,33 @@ public class FloorSavedValueInfo
public int DefaultValue { get; set; }
}
public class FloorCustomValueInfo
{
public int ID { get; set; }
public string Name { get; set; } = string.Empty;
public string DefaultValue { get; set; } = string.Empty;
}
public class FloorDimensionInfo
{
public int ID { get; set; }
public List<DimensionSavedValues> SavedValues { get; set; } = [];
public List<int> GroupIndexList { get; set; } = [];
[JsonIgnore] public List<int> GroupIDList { get; set; } = [];
public void OnLoad(FloorInfo floor)
{
foreach (var data in SavedValues)
{
floor.FloorSavedValue.Add(new FloorSavedValueInfo
{
ID = data.ID,
Name = data.Name,
DefaultValue = data.MaxValue
});
}
foreach (var index in GroupIndexList) GroupIDList.Add(floor.GroupInstanceList[index].ID);
}
}
public class DimensionSavedValues
{
public int ID { get; set; }
public string Name { get; set; } = string.Empty;
public int MaxValue { get; set; }
}

View File

@@ -6,7 +6,8 @@ namespace EggLink.DanhengServer.Data.Excel;
[ResourceEntity("ItemConfig.json,ItemConfigAvatar.json,ItemConfigAvatarPlayerIcon.json," +
"ItemConfigAvatarRank.json,ItemConfigBook.json,ItemConfigDisk.json," +
"ItemConfigEquipment.json,ItemConfigRelic.json,ItemPlayerCard.json", true)]
"ItemConfigEquipment.json,ItemConfigRelic.json,ItemPlayerCard.json," +
"ItemConfigTrainDynamic.json", true)]
public class ItemConfigExcel : ExcelResource
{
// General item data

View File

@@ -1,19 +0,0 @@
namespace EggLink.DanhengServer.Data.Excel;
[ResourceEntity("TrainPartyCardConfig.json")]
public class TrainPartyCardConfigExcel : ExcelResource
{
public int CardID { get; set; }
public int UpgradeLevel { get; set; }
public int Rarity { get; set; }
public override int GetId()
{
return CardID;
}
public override void Loaded()
{
GameData.TrainPartyCardConfigData[CardID] = this;
}
}

View File

@@ -1,18 +0,0 @@
namespace EggLink.DanhengServer.Data.Excel;
[ResourceEntity("TrainPartyGridConfig.json")]
public class TrainPartyGridConfigExcel : ExcelResource
{
public int GridID { get; set; }
public List<int> ParamList { get; set; } = [];
public override int GetId()
{
return GridID;
}
public override void Loaded()
{
GameData.TrainPartyGridConfigData.Add(GridID, this);
}
}

View File

@@ -4,7 +4,6 @@
public class TrainPartyPassengerConfigExcel : ExcelResource
{
public int PassengerID { get; set; }
public int PassengerQuest { get; set; }
public override int GetId()
{

View File

@@ -1,21 +0,0 @@
namespace EggLink.DanhengServer.Data.Excel;
[ResourceEntity("TrainPartyTeam.json")]
public class TrainPartyTeamExcel : ExcelResource
{
public int TeamID { get; set; }
public int InitialMeetingSkill { get; set; }
public int LeaderWorkingBuffID { get; set; }
public int GridNum { get; set; }
public List<int> PassengerList { get; set; } = [];
public override int GetId()
{
return TeamID;
}
public override void Loaded()
{
GameData.TrainPartyTeamData.Add(TeamID, this);
}
}

View File

@@ -157,11 +157,8 @@ public static class GameData
public static Dictionary<int, TrainPartyAreaGoalConfigExcel> TrainPartyAreaGoalConfigData { get; private set; } =
[];
public static Dictionary<int, TrainPartyTeamExcel> TrainPartyTeamData { get; private set; } = [];
public static Dictionary<int, TrainPartyStepConfigExcel> TrainPartyStepConfigData { get; private set; } = [];
public static Dictionary<int, TrainPartyDynamicConfigExcel> TrainPartyDynamicConfigData { get; private set; } = [];
public static Dictionary<int, TrainPartyGridConfigExcel> TrainPartyGridConfigData { get; private set; } = [];
public static Dictionary<int, TrainPartyCardConfigExcel> TrainPartyCardConfigData { get; private set; } = [];
#endregion

View File

@@ -1,113 +0,0 @@
using EggLink.DanhengServer.Data;
using EggLink.DanhengServer.Proto;
using SqlSugar;
namespace EggLink.DanhengServer.Database.TrainParty;
[SugarTable("train_party_data")]
public class GameTrainPartyData : BaseDatabaseDataHelper
{
[SugarColumn(IsJson = true, ColumnDataType = "TEXT")]
public Dictionary<int, GameTrainPartyAreaInfo> Areas { get; set; } = [];
[SugarColumn(IsJson = true, ColumnDataType = "TEXT")]
public Dictionary<int, GameTrainPartyGridInfo> Grids { get; set; } = [];
[SugarColumn(IsJson = true, ColumnDataType = "TEXT")]
public Dictionary<int, GameTrainPartyCardInfo> Cards { get; set; } = [];
public int UniqueId { get; set; } = 1;
}
public class GameTrainPartyGridInfo
{
public int GridId { get; set; }
public int UniqueId { get; set; }
public TrainPartyGameGrid ToProto()
{
return new TrainPartyGameGrid
{
GridId = (uint)GridId,
UniqueId = (uint)UniqueId,
GHFAIHLCELN = (uint)UniqueId
};
}
}
public class GameTrainPartyCardInfo
{
public int CardId { get; set; }
public int UniqueId { get; set; }
public TrainPartyGameCard ToProto()
{
return new TrainPartyGameCard
{
CardId = (uint)CardId,
UniqueId = (uint)UniqueId
};
}
}
public class GameTrainPartyAreaInfo
{
public int AreaId { get; set; }
public List<int> StepList { get; set; } = [];
public Dictionary<int, int> DynamicInfo { get; set; } = [];
public TrainPartyArea ToProto()
{
var info = new TrainPartyArea
{
AreaId = (uint)AreaId,
StepIdList = { StepList.Select(x => (uint)x) },
AreaStepInfo = new AreaStepInfo
{
AreaGlobalId = (uint)GameData.TrainPartyAreaGoalConfigData.First(x => x.Value.AreaID == AreaId).Key,
AreaStepList =
{
StepList.Select(x => new BuildAreaStep
{
StepId = (uint)x,
Status = BuildGoalStep.Finish
})
}
},
Progress = 100,
DynamicInfo =
{
DynamicInfo.Select(x => new AreaDynamicInfo
{
DiceSlotId = (uint)x.Key,
DiyDynamicId = (uint)x.Value
})
}
};
foreach (var step in StepList)
{
GameData.TrainPartyStepConfigData.TryGetValue(step, out var stepExcel);
if (stepExcel == null) continue;
info.StaticPropIdList.AddRange(stepExcel.StaticPropIDList.Select(x => (uint)x));
}
return info;
}
public int GetCoinCost()
{
var cost = 0;
foreach (var step in StepList)
{
GameData.TrainPartyStepConfigData.TryGetValue(step, out var stepExcel);
if (stepExcel == null) continue;
cost += stepExcel.CoinCost;
}
return cost;
}
}

View File

@@ -0,0 +1,46 @@
using EggLink.DanhengServer.Data;
using EggLink.DanhengServer.Proto;
using SqlSugar;
namespace EggLink.DanhengServer.Database.TrainParty;
[SugarTable("TrainParty")]
public class TrainData : BaseDatabaseDataHelper
{
public int Fund { get; set; }
[SugarColumn(IsJson = true)] public Dictionary<int, TrainAreaInfo> Areas { get; set; } = [];
}
public class TrainAreaInfo
{
public int AreaId { get; set; }
public List<int> StepList { get; set; } = [];
public Dictionary<int, int> DynamicInfo { get; set; } = [];
public TrainPartyArea ToProto()
{
var info = new TrainPartyArea
{
AreaId = (uint)AreaId,
AreaStepInfo = new AreaStepInfo(),
StepIdList = { StepList.Select(x => (uint)x) },
VerifyStepIdList = { StepList.Select(x => (uint)x) },
Progress = 100,
DynamicInfo = { DynamicInfo.Select(x => new AreaDynamicInfo
{
DiceSlotId = (uint)x.Key,
DiyDynamicId = (uint)x.Value
}) }
};
foreach (var step in StepList)
{
GameData.TrainPartyStepConfigData.TryGetValue(step, out var stepExcel);
if (stepExcel == null) continue;
info.StaticPropIdList.AddRange(stepExcel.StaticPropIDList.Select(x => (uint)x));
}
return info;
}
}

View File

@@ -22,5 +22,6 @@ public enum GameModeTypeEnum
TournRogue = 17,
RelicRogue = 18,
ArcadeRogue = 19,
MagicRogue = 20
MagicRogue = 20,
TrainParty = 21
}

View File

@@ -51,7 +51,7 @@ public class SceneInstance
{
SceneInfo sceneInfo = new()
{
WorldId = (uint)(Excel.WorldID == 100 ? Player.LastWorldId : Excel.WorldID),
WorldId = (uint)(Excel.WorldID == 100 ? GameConstants.LAST_TRAIN_WORLD_ID : Excel.WorldID),
GameModeType = (uint)GameModeType,
PlaneId = (uint)PlaneId,
FloorId = (uint)FloorId,
@@ -125,17 +125,6 @@ public class SceneInstance
foreach (var value in floorData ?? [])
sceneInfo.FloorSavedData[value.Key] = value.Value;
foreach (var value in FloorInfo?.CustomValues ?? [])
if (floorData != null && floorData.TryGetValue(value.Name, out var v))
{
sceneInfo.FloorSavedData[value.Name] = v;
}
else
{
_ = int.TryParse(value.DefaultValue, out var x);
sceneInfo.FloorSavedData[value.Name] = x;
}
// mission
Player.MissionManager!.OnLoadScene(sceneInfo);

View File

@@ -1,64 +1,19 @@
using EggLink.DanhengServer.Data;
using EggLink.DanhengServer.Data.Excel;
using EggLink.DanhengServer.Database;
using EggLink.DanhengServer.Database.TrainParty;
using EggLink.DanhengServer.GameServer.Game.Player;
using EggLink.DanhengServer.Proto;
using EggLink.DanhengServer.Util;
using GameTrainPartyCardInfo = EggLink.DanhengServer.Database.TrainParty.GameTrainPartyCardInfo;
namespace EggLink.DanhengServer.GameServer.Game.TrainParty;
public class TrainPartyManager : BasePlayerManager
public class TrainPartyManager(PlayerInstance player) : BasePlayerManager(player)
{
public TrainPartyManager(PlayerInstance player) : base(player)
public TrainData Data { get; } =
DatabaseHelper.Instance!.GetInstanceOrCreateNew<TrainData>(player.Uid);
public TrainAreaInfo? SetDynamicId(int areaId, int slotId, int dynamicId)
{
TrainPartyData =
DatabaseHelper.Instance!.GetInstanceOrCreateNew<GameTrainPartyData>(player.Uid);
foreach (var excel in GameData.TrainPartyAreaConfigData.Where(excel =>
!TrainPartyData.Areas.ContainsKey(excel.Key)))
TrainPartyData.Areas[excel.Key] = new GameTrainPartyAreaInfo
{
AreaId = excel.Key,
StepList = [excel.Value.FirstStep]
};
TeamExcel = GameData.TrainPartyTeamData.Values.ToList().RandomElement();
}
public GameTrainPartyData TrainPartyData { get; }
public TrainPartyTeamExcel TeamExcel { get; }
public async ValueTask AddCard(int cardId)
{
if (TrainPartyData.Cards.Values.FirstOrDefault(x => x.CardId == cardId) != null) return;
var uniqueId = TrainPartyData.UniqueId++;
TrainPartyData.Cards.Add(uniqueId, new GameTrainPartyCardInfo
{
CardId = cardId,
UniqueId = uniqueId
});
await ValueTask.CompletedTask;
}
public async ValueTask AddGrid(int gridId)
{
var uniqueId = TrainPartyData.UniqueId++;
TrainPartyData.Grids.Add(uniqueId, new GameTrainPartyGridInfo
{
GridId = gridId,
UniqueId = uniqueId
});
await ValueTask.CompletedTask;
}
public GameTrainPartyAreaInfo? SetDynamicId(int areaId, int slotId, int dynamicId)
{
if (!TrainPartyData.Areas.TryGetValue(areaId, out var area)) return null;
if (!Data.Areas.TryGetValue(areaId, out var area)) return null;
area.DynamicInfo[slotId] = dynamicId;
@@ -70,9 +25,8 @@ public class TrainPartyManager : BasePlayerManager
var proto = new TrainPartyData
{
TrainPartyInfo = ToPartyInfo(),
PassengerInfo = ToPassengerInfo(),
TrainPartyGameInfo = ToGameInfo(),
AIANOFKNLHG = 6
PassengerInfo = ToPassenger(),
UnlockAreaNum = 6
};
return proto;
@@ -82,72 +36,27 @@ public class TrainPartyManager : BasePlayerManager
{
var proto = new TrainPartyInfo
{
AreaList = { TrainPartyData.Areas.Values.Select(x => x.ToProto()) },
CoinCost = (uint)TrainPartyData.Areas.Values.Sum(x => x.GetCoinCost()),
DynamicIdList = { GameData.TrainPartyDynamicConfigData.Select(x => (uint)x.Key) }
EEBNAAPBKCN = 30,
CoinCost = (uint)Data.Fund,
AreaList = { Data.Areas.Values.Select(x => x.ToProto()) },
DynamicIdList = { GameData.TrainPartyDynamicConfigData.Select(x => (uint)x.Key) },
};
return proto;
}
public TrainPartyPassengerInfo ToPassengerInfo()
public static TrainPartyPassengerInfo ToPassenger()
{
return new TrainPartyPassengerInfo
{
PassengerInfoList =
var info = new TrainPartyPassengerInfo();
info.PassengerInfoList.AddRange(
GameData.TrainPartyPassengerConfigData.Select(x =>
{
GameData.TrainPartyPassengerConfigData.Select(x => new TrainPartyPassenger
return new TrainPartyPassenger
{
PassengerId = (uint)x.Key
})
}
};
}
public TrainPartyGameInfo ToGameInfo()
{
return new TrainPartyGameInfo
{
TeamId = (uint)TeamExcel.TeamID,
TrainActionInfo = new TrainPartyActionInfo(),
TrainPassengerInfo = ToGamePassengerInfo(),
TrainPartyGridInfo = ToGameGridInfo(),
TrainPartyItemInfo = ToGameItemInfo()
};
}
public TrainPartyGamePassengerInfo ToGamePassengerInfo()
{
return new TrainPartyGamePassengerInfo
{
PassengerList =
{
TeamExcel.PassengerList.Select(x => new TrainPartyGamePassenger
{
PassengerId = (uint)x
})
},
CurPassengerId = (uint)TeamExcel.PassengerList.RandomElement(),
MtRankId = 104
};
}
public TrainPartyGameGridInfo ToGameGridInfo()
{
return new TrainPartyGameGridInfo
{
GridList = { TrainPartyData.Grids.Values.Select(x => x.ToProto()) }
};
}
public TrainPartyGameItemInfo ToGameItemInfo()
{
return new TrainPartyGameItemInfo
{
TrainPartyCardInfo = new TrainPartyGameCardInfo
{
TrainPartyCardInfo = { TrainPartyData.Cards.Values.Select(x => x.ToProto()) }
}
};
};
})
);
return info;
}
}

View File

@@ -1,13 +0,0 @@
using EggLink.DanhengServer.GameServer.Server.Packet.Send.TrainParty;
using EggLink.DanhengServer.Kcp;
namespace EggLink.DanhengServer.GameServer.Server.Packet.Recv.TrainParty;
[Opcode(CmdIds.TrainPartyAddBuildDynamicBuffCsReq)]
public class HandlerTrainPartyAddBuildDynamicBuffCsReq : Handler
{
public override async Task OnHandle(Connection connection, byte[] header, byte[] data)
{
await connection.SendPacket(new PacketTrainPartyAddBuildDynamicBuffScRsp());
}
}

View File

@@ -1,17 +0,0 @@
using EggLink.DanhengServer.Kcp;
using EggLink.DanhengServer.Proto;
namespace EggLink.DanhengServer.GameServer.Server.Packet.Send.TrainParty;
public class PacketTrainPartyAddBuildDynamicBuffScRsp : BasePacket
{
public PacketTrainPartyAddBuildDynamicBuffScRsp() : base(CmdIds.TrainPartyAddBuildDynamicBuffScRsp)
{
var proto = new TrainPartyAddBuildDynamicBuffScRsp
{
BuffId = 102
};
SetData(proto);
}
}

View File

@@ -6,7 +6,7 @@ namespace EggLink.DanhengServer.GameServer.Server.Packet.Send.TrainParty;
public class PacketTrainPartyBuildDiyScRsp : BasePacket
{
public PacketTrainPartyBuildDiyScRsp(GameTrainPartyAreaInfo? area) : base(CmdIds.TrainPartyBuildDiyScRsp)
public PacketTrainPartyBuildDiyScRsp(TrainAreaInfo? area) : base(CmdIds.TrainPartyBuildDiyScRsp)
{
var proto = area == null
? new TrainPartyBuildDiyScRsp
@@ -16,14 +16,6 @@ public class PacketTrainPartyBuildDiyScRsp : BasePacket
: new TrainPartyBuildDiyScRsp
{
AreaId = (uint)area.AreaId,
DynamicInfo =
{
area.DynamicInfo.Select(x => new AreaDynamicInfo
{
DiceSlotId = (uint)x.Key,
DiyDynamicId = (uint)x.Value
})
}
};
SetData(proto);