fix trial avatar battle

This commit is contained in:
Somebody
2024-06-01 22:36:32 +08:00
parent 065c24f488
commit 6b08b9c591
18 changed files with 380 additions and 51 deletions

View File

@@ -46,6 +46,7 @@ namespace EggLink.DanhengServer.Configuration
public string ConfigPath { get; set; } = "Config";
public string DatabasePath { get; set; } = "Config/Database";
public string LogPath { get; set; } = "Logs";
public string PluginPath { get; set; } = "Plugins";
}
public class DatabaseConfig

View File

@@ -9,6 +9,7 @@ namespace EggLink.DanhengServer.Data.Excel
public int StageID { get; set; } = 0;
public HashName StageName { get; set; } = new HashName();
public List<StageMonsterList> MonsterList { get; set; } = [];
public List<int> TrialAvatarList { get; set; } = [];
public override int GetId()

View File

@@ -4,7 +4,7 @@ namespace EggLink.DanhengServer.Data
{
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
internal class ResourceEntity : Attribute
public class ResourceEntity : Attribute
{
public List<string> FileName { get; private set; }

View File

@@ -278,7 +278,8 @@ namespace EggLink.DanhengServer.Database
try
{
var prev = DateTime.Now;
foreach (var uid in ToSaveUidList)
var list = ToSaveUidList.ToList(); // copy the list to avoid the exception
foreach (var uid in list)
{
var value = UidInstanceMap[uid];
var baseType = typeof(BaseDatabaseDataHelper);

View File

@@ -176,7 +176,7 @@ namespace EggLink.DanhengServer.Command.Cmd
var level = arg.GetInt(1);
if (level < 1 || level > 80)
{
arg.SendMsg(I18nManager.Translate("Game.Command.Avatar.InvalidLevel", I18nManager.Translate("Word.Level")));
arg.SendMsg(I18nManager.Translate("Game.Command.Avatar.InvalidLevel", I18nManager.Translate("Word.Avatar")));
return;
}
@@ -187,7 +187,7 @@ namespace EggLink.DanhengServer.Command.Cmd
avatar.Level = Math.Min(level, 80);
avatar.Promotion = GameData.GetMinPromotionForLevel(avatar.Level);
});
arg.SendMsg(I18nManager.Translate("Game.Command.Avatar.AllAvatarsLevelSet", I18nManager.Translate("Word.Level"), level.ToString()));
arg.SendMsg(I18nManager.Translate("Game.Command.Avatar.AllAvatarsLevelSet", I18nManager.Translate("Word.Avatar"), level.ToString()));
// sync
arg.Target.SendPacket(new PacketPlayerSyncScNotify(arg.Target.Player!.AvatarManager.AvatarData.Avatars));
@@ -206,7 +206,7 @@ namespace EggLink.DanhengServer.Command.Cmd
// sync
arg.Target.SendPacket(new PacketPlayerSyncScNotify(avatar));
arg.SendMsg(I18nManager.Translate("Game.Command.Avatar.AvatarLevelSet", avatar.Excel?.Name ?? id.ToString(), I18nManager.Translate("Word.Level"), level.ToString()));
arg.SendMsg(I18nManager.Translate("Game.Command.Avatar.AvatarLevelSet", avatar.Excel?.Name ?? id.ToString(), I18nManager.Translate("Word.Avatar"), level.ToString()));
}
}
}

View File

@@ -84,6 +84,101 @@ namespace EggLink.DanhengServer.Game.Battle
BattleTargets[key].BGNPEBHGELB.Add(battleTarget);
}
public Dictionary<AvatarInfo, AvatarType> GetBattleAvatars()
{
var excel = GameData.StageConfigData[StageId];
if (excel.TrialAvatarList.Count > 0)
{
var list = new List<int>();
list.AddRange(excel.TrialAvatarList);
if (Player.Data.CurrentGender == Gender.Man)
{
foreach (var avatar in excel.TrialAvatarList)
{
if (avatar.ToString().EndsWith("8002"))
{
list.Remove(avatar);
}
if (avatar.ToString().EndsWith("8004"))
{
list.Remove(avatar);
}
if (avatar.ToString().EndsWith("8006"))
{
list.Remove(avatar);
}
}
} else
{
foreach (var avatar in excel.TrialAvatarList)
{
if (avatar.ToString().EndsWith("8001"))
{
list.Remove(avatar);
}
if (avatar.ToString().EndsWith("8003"))
{
list.Remove(avatar);
}
if (avatar.ToString().EndsWith("8005"))
{
list.Remove(avatar);
}
}
}
Dictionary<AvatarInfo, AvatarType> dict = [];
foreach (var avatar in list)
{
GameData.SpecialAvatarData.TryGetValue(avatar * 10 + Player.Data.WorldLevel, out var specialAvatar);
if (specialAvatar != null)
{
dict.Add(specialAvatar.ToAvatarData(Player.Uid), AvatarType.AvatarTrialType);
}
}
return dict;
}
else
{
Dictionary<AvatarInfo, AvatarType> dict = [];
foreach (var avatar in Lineup.BaseAvatars!)
{
AvatarInfo? avatarInstance = null;
AvatarType avatarType = AvatarType.AvatarFormalType;
if (avatar.AssistUid != 0)
{
var player = DatabaseHelper.Instance!.GetInstance<AvatarData>(avatar.AssistUid);
if (player != null)
{
avatarInstance = player.Avatars!.Find(item => item.GetAvatarId() == avatar.BaseAvatarId);
avatarType = AvatarType.AvatarAssistType;
}
}
else if (avatar.SpecialAvatarId != 0)
{
GameData.SpecialAvatarData.TryGetValue(avatar.SpecialAvatarId, out var specialAvatar);
if (specialAvatar != null)
{
avatarInstance = specialAvatar.ToAvatarData(Player.Uid);
avatarType = AvatarType.AvatarTrialType;
}
}
else
{
avatarInstance = Player.AvatarManager!.GetAvatar(avatar.BaseAvatarId);
}
if (avatarInstance == null) continue;
dict.Add(avatarInstance, avatarType);
}
return dict;
}
}
public SceneBattleInfo ToProto()
{
var proto = new SceneBattleInfo()
@@ -108,33 +203,9 @@ namespace EggLink.DanhengServer.Game.Battle
proto.MonsterWaveList.AddRange(protoWave);
}
foreach (var avatar in Lineup.BaseAvatars!)
foreach (var avatar in GetBattleAvatars())
{
AvatarInfo? avatarInstance = null;
var avatarType = AvatarType.AvatarFormalType;
if (avatar.AssistUid != 0)
{
var player = DatabaseHelper.Instance!.GetInstance<AvatarData>(avatar.AssistUid);
if (player != null)
{
avatarInstance = player.Avatars!.Find(item => item.GetAvatarId() == avatar.BaseAvatarId);
avatarType = AvatarType.AvatarAssistType;
}
} else if (avatar.SpecialAvatarId != 0)
{
GameData.SpecialAvatarData.TryGetValue(avatar.SpecialAvatarId, out var specialAvatar);
if (specialAvatar != null)
{
avatarInstance = specialAvatar.ToAvatarData(Player.Uid);
avatarType = AvatarType.AvatarTrialType;
}
} else
{
avatarInstance = Player.AvatarManager!.GetAvatar(avatar.BaseAvatarId);
}
if (avatarInstance == null) continue;
proto.BattleAvatarList.Add(avatarInstance.ToBattleProto(Player.LineupManager!.GetCurLineup()!, Player.InventoryManager!.Data, avatarType));
proto.BattleAvatarList.Add(avatar.Key.ToBattleProto(Player.LineupManager!.GetCurLineup()!, Player.InventoryManager!.Data, avatar.Value));
}
foreach (var monster in EntityMonsters)

View File

@@ -13,7 +13,15 @@ namespace EggLink.DanhengServer.Game.Mission.FinishAction.Handler
{
public override void OnHandle(List<int> Params, List<string> ParamString, PlayerInstance Player)
{
// TODO
_ = int.TryParse(ParamString[1], out var floor);
Player.SceneData!.FloorSavedData.TryGetValue(floor, out var value);
if (value == null)
{
value = [];
Player.SceneData.FloorSavedData[floor] = value;
}
value[ParamString[2]] = Params[3]; // ParamString[2] is the key
}
}
}

View File

@@ -6,6 +6,8 @@ using EggLink.DanhengServer.Enums;
using EggLink.DanhengServer.Game.Mission.FinishAction;
using EggLink.DanhengServer.Game.Mission.FinishType;
using EggLink.DanhengServer.Game.Player;
using EggLink.DanhengServer.Plugin.Event;
using EggLink.DanhengServer.Server.Packet.Send.Lineup;
using EggLink.DanhengServer.Server.Packet.Send.Mission;
using EggLink.DanhengServer.Server.Packet.Send.Player;
using EggLink.DanhengServer.Server.Packet.Send.Scene;
@@ -129,6 +131,29 @@ namespace EggLink.DanhengServer.Game.Mission
return AcceptMainMission(missionId, sendPacket);
}
public void RemoveMainMission(int missionId)
{
if (!ConfigManager.Config.ServerOption.EnableMission) return;
Data.SetMainMissionStatus(missionId, MissionPhaseEnum.None);
GameData.MainMissionData.TryGetValue(missionId, out var mission);
if (mission == null) return;
Proto.MissionSync sync = new();
foreach (var subMission in mission.SubMissionIds)
{
Data.SetSubMissionStatus(subMission, MissionPhaseEnum.None);
sync.MissionList.Add(new Proto.Mission()
{
Id = (uint)subMission,
Status = Proto.MissionStatus.MissionNone,
});
}
Player.SendPacket(new PacketPlayerSyncScNotify(sync));
}
public void AcceptSubMission(int missionId)
{
if (!ConfigManager.Config.ServerOption.EnableMission) return;
@@ -156,10 +181,15 @@ namespace EggLink.DanhengServer.Game.Mission
Player.SceneInstance!.SyncGroupInfo();
if (mission.SubMissionInfo != null)
{
FinishTypeHandlers.TryGetValue(mission.SubMissionInfo.FinishType, out var handler);
handler?.Init(Player, mission.SubMissionInfo, null);
if (doFinishTypeAction)
handler?.HandleFinishType(Player, mission.SubMissionInfo, null);
try
{
FinishTypeHandlers.TryGetValue(mission.SubMissionInfo.FinishType, out var handler);
handler?.Init(Player, mission.SubMissionInfo, null);
if (doFinishTypeAction)
handler?.HandleFinishType(Player, mission.SubMissionInfo, null);
} catch
{
}
}
if (SkipSubMissionList.Contains(missionId))
@@ -234,7 +264,11 @@ namespace EggLink.DanhengServer.Game.Mission
if (missionId == 1021301)
{
Player.LineupManager!.SetExtraLineup(Proto.ExtraLineupType.LineupHeliobus, [1021213]);
Player.SendPacket(new PacketSyncLineupNotify(Player.LineupManager!.GetCurLineup()!));
Player.SceneInstance!.SyncLineup();
}
PluginEvent.InvokeOnPlayerFinishMainMission(Player, missionId);
}
public void FinishSubMission(int missionId)
@@ -337,10 +371,7 @@ namespace EggLink.DanhengServer.Game.Mission
FinishSubMission(100040119);
}
if (missionId == 102130113)
{
Player.LineupManager!.SetExtraLineup(Proto.ExtraLineupType.LineupHeliobus, [1021213, 1021205]);
}
PluginEvent.InvokeOnPlayerFinishSubMission(Player, missionId);
}
public void HandleFinishAction(Data.Config.MissionInfo info, int subMissionId)

View File

@@ -32,6 +32,8 @@ using EggLink.DanhengServer.Server.Packet.Send.Avatar;
using System.Numerics;
using EggLink.DanhengServer.Game.Challenge;
using EggLink.DanhengServer.Game.Drop;
using static EggLink.DanhengServer.Plugin.Event.PluginEvent;
using EggLink.DanhengServer.Plugin.Event;
namespace EggLink.DanhengServer.Game.Player
{
@@ -189,6 +191,7 @@ namespace EggLink.DanhengServer.Game.Player
SendPacket(new PacketStaminaInfoScNotify(this));
InvokeOnPlayerLogin(this);
}
public void OnLogoutAsync()
@@ -198,6 +201,8 @@ namespace EggLink.DanhengServer.Game.Player
EnterScene(OldEntryId, 0, false);
MoveTo(LastPos!, LastRot!);
}
InvokeOnPlayerLogout(this);
}
public void SendPacket(BasePacket packet)
@@ -303,6 +308,8 @@ namespace EggLink.DanhengServer.Game.Player
{
OnStaminaRecover();
InvokeOnPlayerHeartBeat(this);
DatabaseHelper.ToSaveUidList.SafeAdd(Uid);
}
@@ -404,6 +411,9 @@ namespace EggLink.DanhengServer.Game.Player
// plane event
InventoryManager!.HandlePlaneEvent(prop.PropInfo.EventID);
// handle plugin event
InvokeOnPlayerInteract(this, prop);
return prop;
}
}

View File

@@ -253,17 +253,13 @@ namespace EggLink.DanhengServer.Game.Scene
// load from database
var propData = Scene.Player.GetScenePropData(Scene.FloorId, group.Id, info.ID);
if (propData != null)
if (propData != null && Scene.Excel.PlaneType != PlaneTypeEnum.Raid) // raid is not saved
{
prop.State = propData.State;
}
else
{
prop.State = info.State;
//if (excel.PropStateList.Contains(PropStateEnum.Closed) && info.State == PropStateEnum.Locked)
//{
// prop.SetState(PropStateEnum.Closed);
//}
}
return prop;
}

View File

@@ -8,6 +8,7 @@
<RootNamespace>EggLink.DanhengServer</RootNamespace>
<StartupObject>EggLink.DanhengServer.Program.EntryPoint</StartupObject>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<AssemblyName>DanhengServer</AssemblyName>
</PropertyGroup>
<ItemGroup>

View File

@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace EggLink.DanhengServer.Plugin.Constructor
{
public interface IPlugin
{
public void OnLoad();
public void OnUnload();
}
}

View File

@@ -0,0 +1,70 @@
using EggLink.DanhengServer.Game.Player;
using EggLink.DanhengServer.Game.Scene.Entity;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace EggLink.DanhengServer.Plugin.Event
{
public static class PluginEvent
{
#region Player
public delegate void OnPlayerHeartBeatHandler(PlayerInstance player);
public delegate void OnPlayerLoginHandler(PlayerInstance player);
public delegate void OnPlayerLogoutHandler(PlayerInstance player);
public delegate void OnPlayerFinishSubMissionHandler(PlayerInstance player, int missionId);
public delegate void OnPlayerFinishMainMissionHandler(PlayerInstance player, int missionId);
public delegate void OnPlayerInteractHandler(PlayerInstance player, EntityProp prop);
#endregion
#region Common
#endregion
#region Event
public static event OnPlayerHeartBeatHandler? OnPlayerHeartBeat;
public static event OnPlayerLoginHandler? OnPlayerLogin;
public static event OnPlayerLogoutHandler? OnPlayerLogout;
public static event OnPlayerFinishSubMissionHandler? OnPlayerFinishSubMission;
public static event OnPlayerFinishMainMissionHandler? OnPlayerFinishMainMission;
public static event OnPlayerInteractHandler? OnPlayerInteract;
#endregion
public static void InvokeOnPlayerHeartBeat(PlayerInstance player)
{
OnPlayerHeartBeat?.Invoke(player);
}
public static void InvokeOnPlayerLogin(PlayerInstance player)
{
OnPlayerLogin?.Invoke(player);
}
public static void InvokeOnPlayerLogout(PlayerInstance player)
{
OnPlayerLogout?.Invoke(player);
}
public static void InvokeOnPlayerFinishSubMission(PlayerInstance player, int missionId)
{
OnPlayerFinishSubMission?.Invoke(player, missionId);
}
public static void InvokeOnPlayerFinishMainMission(PlayerInstance player, int missionId)
{
OnPlayerFinishMainMission?.Invoke(player, missionId);
}
public static void InvokeOnPlayerInteract(PlayerInstance player, EntityProp prop)
{
OnPlayerInteract?.Invoke(player, prop);
}
}
}

View File

@@ -0,0 +1,108 @@
using EggLink.DanhengServer.Plugin.Constructor;
using EggLink.DanhengServer.Util;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace EggLink.DanhengServer.Plugin
{
public class PluginManager
{
private readonly static Logger logger = new("PluginManager");
public readonly static List<IPlugin> Plugins = [];
public readonly static Dictionary<IPlugin, List<Type>> PluginAssemblies = [];
public static void LoadPlugins()
{
// get all the plugins in the plugin directory
if (!Directory.Exists(ConfigManager.Config.Path.PluginPath))
{
Directory.CreateDirectory(ConfigManager.Config.Path.PluginPath);
}
var plugins = Directory.GetFiles(ConfigManager.Config.Path.PluginPath, "*.dll");
foreach (var plugin in plugins)
{
var fileInfo = new FileInfo(plugin);
LoadPlugin(fileInfo.FullName);
}
logger.Info($"Loaded {Plugins.Count} plugins");
}
public static void LoadPlugin(string plugin)
{
try
{
var assembly = Assembly.LoadFile(plugin);
var types = assembly.GetTypes();
bool isPlugin = false;
foreach (var type in types)
{
if (type.GetInterface("IPlugin") != null)
{
if (Activator.CreateInstance(type) is IPlugin pluginInstance)
{
pluginInstance.OnLoad();
Plugins.Add(pluginInstance);
if (!PluginAssemblies.TryGetValue(pluginInstance, out List<Type>? value))
{
value = new List<Type>();
PluginAssemblies[pluginInstance] = value;
}
value.AddRange(types);
isPlugin = true;
break;
}
else
{
logger.Error($"Failed to load plugin {plugin}: Plugin instance is null");
}
}
}
if (!isPlugin)
{
logger.Error($"Failed to load plugin {plugin}: Plugin does not implement IPlugin");
}
}
catch (Exception e)
{
logger.Error($"Failed to load plugin {plugin}: {e.Message}");
}
}
public static void UnloadPlugins()
{
foreach (var plugin in Plugins)
{
plugin.OnUnload();
}
logger.Info("Unloaded all plugins");
Plugins.Clear();
}
public static List<Type> GetPluginAssemblies()
{
var assemblies = new List<Type>();
foreach (var plugin in Plugins)
{
if (PluginAssemblies.TryGetValue(plugin, out List<Type>? value))
{
assemblies.AddRange(value);
}
}
return assemblies;
}
}
}

View File

@@ -10,6 +10,7 @@ using Newtonsoft.Json;
using EggLink.DanhengServer.Command;
using EggLink.DanhengServer.Handbook;
using EggLink.DanhengServer.Internationalization;
using EggLink.DanhengServer.Plugin;
namespace EggLink.DanhengServer.Program
{
@@ -75,6 +76,18 @@ namespace EggLink.DanhengServer.Program
return;
}
// Load the plugins
logger.Info("Loading plugins...");
try
{
PluginManager.LoadPlugins();
} catch (Exception e)
{
logger.Error("Failed to load plugins", e);
Console.ReadLine();
return;
}
// Load the game data
logger.Info("Loading game data...");
try
@@ -147,6 +160,7 @@ namespace EggLink.DanhengServer.Program
private static void PerformCleanup()
{
PluginManager.UnloadPlugins();
Listener.Connections.Values.ToList().ForEach(x => x.Stop());
DatabaseHelper.SaveThread?.Interrupt();

View File

@@ -1,11 +1,12 @@
using EggLink.DanhengServer.Proto;
using EggLink.DanhengServer.Server.Packet.Send.Scene;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace EggLink.DanhengServer.Server.Packet.Send.Scene
namespace EggLink.DanhengServer.Server.Packet.Recv.Scene
{
[Opcode(CmdIds.DeactivateFarmElementCsReq)]
public class HandlerDeactivateFarmElementCsReq : Handler

View File

@@ -63,9 +63,11 @@ namespace EggLink.DanhengServer.Server.Packet.Recv.Scene
raidConfig.MainMissionIDList.ForEach(missionId =>
{
player.MissionManager!.ReAcceptMainMission(missionId);
player.MissionManager!.RemoveMainMission(missionId);
});
player.MissionManager!.AcceptMainMission(raidConfig.MainMissionIDList[0]);
connection.SendPacket(CmdIds.StartRaidScRsp);
}
}

View File

@@ -26,23 +26,23 @@ namespace EggLink.DanhengServer.Server.Http.Handler
B5 = true,
};
if (urlData.AssetBundleUrl != null)
if (urlData.AssetBundleUrl != null && urlData.AssetBundleUrl.Length > 0)
{
gateServer.AssetBundleUrl = urlData.AssetBundleUrl;
}
if (urlData.ExResourceUrl != null)
if (urlData.ExResourceUrl != null && urlData.ExResourceUrl.Length > 0)
{
gateServer.ExResourceUrl = urlData.ExResourceUrl;
}
if (urlData.LuaUrl != null)
if (urlData.LuaUrl != null && urlData.LuaUrl.Length > 0)
{
gateServer.LuaUrl = urlData.LuaUrl;
gateServer.MdkResVersion = urlData.LuaUrl.Split('/')[^1].Split('_')[1];
}
if (urlData.IfixUrl != null)
if (urlData.IfixUrl != null && urlData.IfixUrl.Length > 0)
{
gateServer.IfixUrl = urlData.IfixUrl;
gateServer.IfixVersion = urlData.IfixUrl.Split('/')[^1].Split('_')[1];