Merge branch 'master' into patch-1
This commit is contained in:
commit
e0cd311bfc
99 changed files with 1576671 additions and 357 deletions
12
Core/Config/Attributes/ConfigCollectionAttribute.cs
Normal file
12
Core/Config/Attributes/ConfigCollectionAttribute.cs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
namespace Core.Config.Attributes;
|
||||||
|
|
||||||
|
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
|
||||||
|
internal class ConfigCollectionAttribute : Attribute
|
||||||
|
{
|
||||||
|
public string Path { get; }
|
||||||
|
|
||||||
|
public ConfigCollectionAttribute(string path)
|
||||||
|
{
|
||||||
|
Path = path;
|
||||||
|
}
|
||||||
|
}
|
148
Core/Config/BasePropertyConfig.cs
Normal file
148
Core/Config/BasePropertyConfig.cs
Normal file
|
@ -0,0 +1,148 @@
|
||||||
|
using Core.Config.Attributes;
|
||||||
|
|
||||||
|
namespace Core.Config;
|
||||||
|
|
||||||
|
[ConfigCollection("property/baseproperty.json")]
|
||||||
|
public class BasePropertyConfig : IConfig
|
||||||
|
{
|
||||||
|
public ConfigType Type => ConfigType.BaseProperty;
|
||||||
|
public int Identifier => Id;
|
||||||
|
|
||||||
|
public int Id { get; set; }
|
||||||
|
public int Lv { get; set; }
|
||||||
|
public int LifeMax { get; set; }
|
||||||
|
public int Life { get; set; }
|
||||||
|
public int Sheild { get; set; }
|
||||||
|
public int SheildDamageChange { get; set; }
|
||||||
|
public int SheildDamageReduce { get; set; }
|
||||||
|
public int Atk { get; set; }
|
||||||
|
public int Crit { get; set; }
|
||||||
|
public int CritDamage { get; set; }
|
||||||
|
public int Def { get; set; }
|
||||||
|
public int EnergyEfficiency { get; set; }
|
||||||
|
public int CdReduse { get; set; }
|
||||||
|
public int ReactionEfficiency { get; set; }
|
||||||
|
public int DamageChangeNormalSkill { get; set; }
|
||||||
|
public int DamageChange { get; set; }
|
||||||
|
public int DamageReduce { get; set; }
|
||||||
|
public int DamageChangeAuto { get; set; }
|
||||||
|
public int DamageChangeCast { get; set; }
|
||||||
|
public int DamageChangeUltra { get; set; }
|
||||||
|
public int DamageChangeQte { get; set; }
|
||||||
|
public int DamageChangePhys { get; set; }
|
||||||
|
public int DamageChangeElement1 { get; set; }
|
||||||
|
public int DamageChangeElement2 { get; set; }
|
||||||
|
public int DamageChangeElement3 { get; set; }
|
||||||
|
public int DamageChangeElement4 { get; set; }
|
||||||
|
public int DamageChangeElement5 { get; set; }
|
||||||
|
public int DamageChangeElement6 { get; set; }
|
||||||
|
public int DamageResistancePhys { get; set; }
|
||||||
|
public int DamageResistanceElement1 { get; set; }
|
||||||
|
public int DamageResistanceElement2 { get; set; }
|
||||||
|
public int DamageResistanceElement3 { get; set; }
|
||||||
|
public int DamageResistanceElement4 { get; set; }
|
||||||
|
public int DamageResistanceElement5 { get; set; }
|
||||||
|
public int DamageResistanceElement6 { get; set; }
|
||||||
|
public int HealChange { get; set; }
|
||||||
|
public int HealedChange { get; set; }
|
||||||
|
public int DamageReducePhys { get; set; }
|
||||||
|
public int DamageReduceElement1 { get; set; }
|
||||||
|
public int DamageReduceElement2 { get; set; }
|
||||||
|
public int DamageReduceElement3 { get; set; }
|
||||||
|
public int DamageReduceElement4 { get; set; }
|
||||||
|
public int DamageReduceElement5 { get; set; }
|
||||||
|
public int DamageReduceElement6 { get; set; }
|
||||||
|
public int ReactionChange1 { get; set; }
|
||||||
|
public int ReactionChange2 { get; set; }
|
||||||
|
public int ReactionChange3 { get; set; }
|
||||||
|
public int ReactionChange4 { get; set; }
|
||||||
|
public int ReactionChange5 { get; set; }
|
||||||
|
public int ReactionChange6 { get; set; }
|
||||||
|
public int ReactionChange7 { get; set; }
|
||||||
|
public int ReactionChange8 { get; set; }
|
||||||
|
public int ReactionChange9 { get; set; }
|
||||||
|
public int ReactionChange10 { get; set; }
|
||||||
|
public int ReactionChange11 { get; set; }
|
||||||
|
public int ReactionChange12 { get; set; }
|
||||||
|
public int ReactionChange13 { get; set; }
|
||||||
|
public int ReactionChange14 { get; set; }
|
||||||
|
public int ReactionChange15 { get; set; }
|
||||||
|
public int EnergyMax { get; set; }
|
||||||
|
public int Energy { get; set; }
|
||||||
|
public int SpecialEnergy1Max { get; set; }
|
||||||
|
public int SpecialEnergy1 { get; set; }
|
||||||
|
public int SpecialEnergy2Max { get; set; }
|
||||||
|
public int SpecialEnergy2 { get; set; }
|
||||||
|
public int SpecialEnergy3Max { get; set; }
|
||||||
|
public int SpecialEnergy3 { get; set; }
|
||||||
|
public int SpecialEnergy4Max { get; set; }
|
||||||
|
public int SpecialEnergy4 { get; set; }
|
||||||
|
public int StrengthMax { get; set; }
|
||||||
|
public int Strength { get; set; }
|
||||||
|
public int StrengthRecover { get; set; }
|
||||||
|
public int StrengthPunishTime { get; set; }
|
||||||
|
public int StrengthRun { get; set; }
|
||||||
|
public int StrengthSwim { get; set; }
|
||||||
|
public int StrengthFastSwim { get; set; }
|
||||||
|
public int StrengthClimb { get; set; }
|
||||||
|
public int StrengthFastClimb { get; set; }
|
||||||
|
public int HardnessMax { get; set; }
|
||||||
|
public int Hardness { get; set; }
|
||||||
|
public int HardnessRecover { get; set; }
|
||||||
|
public int HardnessPunishTime { get; set; }
|
||||||
|
public int HardnessChange { get; set; }
|
||||||
|
public int HardnessReduce { get; set; }
|
||||||
|
public int RageMax { get; set; }
|
||||||
|
public int Rage { get; set; }
|
||||||
|
public int RageRecover { get; set; }
|
||||||
|
public int RagePunishTime { get; set; }
|
||||||
|
public int RageChange { get; set; }
|
||||||
|
public int RageReduce { get; set; }
|
||||||
|
public int ToughMax { get; set; }
|
||||||
|
public int Tough { get; set; }
|
||||||
|
public int ToughRecover { get; set; }
|
||||||
|
public int ToughChange { get; set; }
|
||||||
|
public int ToughReduce { get; set; }
|
||||||
|
public int ToughRecoverDelayTime { get; set; }
|
||||||
|
public int ElementPower1 { get; set; }
|
||||||
|
public int ElementPower2 { get; set; }
|
||||||
|
public int ElementPower3 { get; set; }
|
||||||
|
public int ElementPower4 { get; set; }
|
||||||
|
public int ElementPower5 { get; set; }
|
||||||
|
public int ElementPower6 { get; set; }
|
||||||
|
public int SpecialDamageChange { get; set; }
|
||||||
|
public int StrengthFastClimbCost { get; set; }
|
||||||
|
public int ElementPropertyType { get; set; }
|
||||||
|
public int WeakTime { get; set; }
|
||||||
|
public int IgnoreDefRate { get; set; }
|
||||||
|
public int IgnoreDamageResistancePhys { get; set; }
|
||||||
|
public int IgnoreDamageResistanceElement1 { get; set; }
|
||||||
|
public int IgnoreDamageResistanceElement2 { get; set; }
|
||||||
|
public int IgnoreDamageResistanceElement3 { get; set; }
|
||||||
|
public int IgnoreDamageResistanceElement4 { get; set; }
|
||||||
|
public int IgnoreDamageResistanceElement5 { get; set; }
|
||||||
|
public int IgnoreDamageResistanceElement6 { get; set; }
|
||||||
|
public int SkillToughRatio { get; set; }
|
||||||
|
public int StrengthClimbJump { get; set; }
|
||||||
|
public int StrengthGliding { get; set; }
|
||||||
|
public int Mass { get; set; }
|
||||||
|
public int BrakingFrictionFactor { get; set; }
|
||||||
|
public int GravityScale { get; set; }
|
||||||
|
public int SpeedRatio { get; set; }
|
||||||
|
public int DamageChangePhantom { get; set; }
|
||||||
|
public int AutoAttackSpeed { get; set; }
|
||||||
|
public int CastAttackSpeed { get; set; }
|
||||||
|
public int StatusBuildUp1Max { get; set; }
|
||||||
|
public int StatusBuildUp1 { get; set; }
|
||||||
|
public int StatusBuildUp2Max { get; set; }
|
||||||
|
public int StatusBuildUp2 { get; set; }
|
||||||
|
public int StatusBuildUp3Max { get; set; }
|
||||||
|
public int StatusBuildUp3 { get; set; }
|
||||||
|
public int StatusBuildUp4Max { get; set; }
|
||||||
|
public int StatusBuildUp4 { get; set; }
|
||||||
|
public int StatusBuildUp5Max { get; set; }
|
||||||
|
public int StatusBuildUp5 { get; set; }
|
||||||
|
public int ParalysisTimeMax { get; set; }
|
||||||
|
public int ParalysisTime { get; set; }
|
||||||
|
public int ParalysisTimeRecover { get; set; }
|
||||||
|
}
|
17
Core/Config/BlueprintConfig.cs
Normal file
17
Core/Config/BlueprintConfig.cs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
using Core.Config.Attributes;
|
||||||
|
|
||||||
|
namespace Core.Config;
|
||||||
|
|
||||||
|
[ConfigCollection("blueprint/blueprintconfig.json")]
|
||||||
|
public class BlueprintConfig : IConfig
|
||||||
|
{
|
||||||
|
public ConfigType Type => ConfigType.Blueprint;
|
||||||
|
public int Identifier => Id;
|
||||||
|
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string BlueprintType { get; set; } = string.Empty;
|
||||||
|
public string EntityType { get; set; } = string.Empty;
|
||||||
|
public string EntityLogic { get; set; } = string.Empty;
|
||||||
|
public int ModelId { get; set; }
|
||||||
|
public int HalfHeight { get; set; }
|
||||||
|
}
|
49
Core/Config/ConfigCollection.cs
Normal file
49
Core/Config/ConfigCollection.cs
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
using System.Collections.Immutable;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using System.Text.Json;
|
||||||
|
|
||||||
|
namespace Core.Config;
|
||||||
|
public class ConfigCollection
|
||||||
|
{
|
||||||
|
private readonly ImmutableDictionary<int, IConfig> _configs;
|
||||||
|
|
||||||
|
public ConfigCollection(JsonDocument json, Type type)
|
||||||
|
{
|
||||||
|
_configs = LoadConfigs(json, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Count => _configs.Count;
|
||||||
|
|
||||||
|
public TConfig At<TConfig>(int index) where TConfig : IConfig
|
||||||
|
{
|
||||||
|
return (TConfig)_configs.Values.ElementAt(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<TConfig> Enumerate<TConfig>() where TConfig : IConfig
|
||||||
|
{
|
||||||
|
return _configs.Values.Cast<TConfig>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryGet<TConfig>(int identifier, [NotNullWhen(true)] out TConfig? config) where TConfig : IConfig
|
||||||
|
{
|
||||||
|
bool result = _configs.TryGetValue(identifier, out IConfig? cfg);
|
||||||
|
|
||||||
|
config = (TConfig?)cfg;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ImmutableDictionary<int, IConfig> LoadConfigs(JsonDocument json, Type type)
|
||||||
|
{
|
||||||
|
var builder = ImmutableDictionary.CreateBuilder<int, IConfig>();
|
||||||
|
|
||||||
|
foreach (JsonElement element in json.RootElement.EnumerateArray())
|
||||||
|
{
|
||||||
|
if (element.ValueKind != JsonValueKind.Object) throw new InvalidDataException($"LoadConfigs: expected array of {JsonValueKind.Object}, got array of {element.ValueKind}");
|
||||||
|
|
||||||
|
IConfig configItem = (element.Deserialize(type) as IConfig)!;
|
||||||
|
builder.Add(configItem.Identifier, configItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.ToImmutable();
|
||||||
|
}
|
||||||
|
}
|
62
Core/Config/ConfigManager.cs
Normal file
62
Core/Config/ConfigManager.cs
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
using System.Collections.Immutable;
|
||||||
|
using System.Reflection;
|
||||||
|
using Core.Config.Attributes;
|
||||||
|
using Core.Resources;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace Core.Config;
|
||||||
|
public class ConfigManager
|
||||||
|
{
|
||||||
|
private readonly ImmutableDictionary<ConfigType, ConfigCollection> _collectionsByEnum;
|
||||||
|
private readonly ImmutableDictionary<Type, ConfigCollection> _collectionsByType;
|
||||||
|
|
||||||
|
public ConfigManager(ILogger<ConfigManager> logger, IResourceProvider resourceProvider)
|
||||||
|
{
|
||||||
|
(_collectionsByEnum, _collectionsByType) = LoadConfigCollections(resourceProvider);
|
||||||
|
logger.LogInformation("Loaded {count} config collections", _collectionsByEnum.Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<TConfig> Enumerate<TConfig>() where TConfig : IConfig
|
||||||
|
{
|
||||||
|
return GetCollection<TConfig>().Enumerate<TConfig>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConfigCollection GetCollection<TConfigType>() where TConfigType : IConfig
|
||||||
|
{
|
||||||
|
return _collectionsByType[typeof(TConfigType)];
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConfigCollection GetCollection(ConfigType type)
|
||||||
|
{
|
||||||
|
return _collectionsByEnum[type];
|
||||||
|
}
|
||||||
|
|
||||||
|
public TConfig? GetConfig<TConfig>(int id) where TConfig : IConfig
|
||||||
|
{
|
||||||
|
if (_collectionsByType[typeof(TConfig)].TryGet(id, out TConfig? config))
|
||||||
|
return config;
|
||||||
|
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static (ImmutableDictionary<ConfigType, ConfigCollection>, ImmutableDictionary<Type, ConfigCollection>) LoadConfigCollections(IResourceProvider resourceProvider)
|
||||||
|
{
|
||||||
|
var builderByEnum = ImmutableDictionary.CreateBuilder<ConfigType, ConfigCollection>();
|
||||||
|
var builderByType = ImmutableDictionary.CreateBuilder<Type, ConfigCollection>();
|
||||||
|
|
||||||
|
IEnumerable<Type> types = Assembly.GetExecutingAssembly().GetTypes()
|
||||||
|
.Where(type => type.IsAssignableTo(typeof(IConfig)) && !type.IsAbstract);
|
||||||
|
|
||||||
|
foreach (Type type in types)
|
||||||
|
{
|
||||||
|
ConfigCollectionAttribute? attribute = type.GetCustomAttribute<ConfigCollectionAttribute>();
|
||||||
|
if (attribute == null) continue;
|
||||||
|
|
||||||
|
ConfigCollection collection = new(resourceProvider.GetJsonResource("data/config/" + attribute.Path), type);
|
||||||
|
builderByEnum.Add(collection.At<IConfig>(0).Type, collection);
|
||||||
|
builderByType.Add(collection.At<IConfig>(0).GetType(), collection);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (builderByEnum.ToImmutable(), builderByType.ToImmutable());
|
||||||
|
}
|
||||||
|
}
|
9
Core/Config/ConfigType.cs
Normal file
9
Core/Config/ConfigType.cs
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
namespace Core.Config;
|
||||||
|
public enum ConfigType
|
||||||
|
{
|
||||||
|
RoleInfo,
|
||||||
|
Weapon,
|
||||||
|
BaseProperty,
|
||||||
|
LevelEntity,
|
||||||
|
Blueprint
|
||||||
|
}
|
6
Core/Config/IConfig.cs
Normal file
6
Core/Config/IConfig.cs
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
namespace Core.Config;
|
||||||
|
public interface IConfig
|
||||||
|
{
|
||||||
|
ConfigType Type { get; }
|
||||||
|
int Identifier { get; }
|
||||||
|
}
|
27
Core/Config/LevelEntityConfig.cs
Normal file
27
Core/Config/LevelEntityConfig.cs
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
using Core.Config.Attributes;
|
||||||
|
|
||||||
|
namespace Core.Config;
|
||||||
|
|
||||||
|
[ConfigCollection("level_entity/levelentityconfig.json")]
|
||||||
|
public class LevelEntityConfig : IConfig
|
||||||
|
{
|
||||||
|
public ConfigType Type => ConfigType.LevelEntity;
|
||||||
|
public int Identifier => Id;
|
||||||
|
|
||||||
|
public int Id { get; set; }
|
||||||
|
public int MapId { get; set; }
|
||||||
|
public int EntityId { get; set; }
|
||||||
|
public string BlueprintType { get; set; } = string.Empty;
|
||||||
|
public string Name { get; set; } = string.Empty;
|
||||||
|
public bool InSleep { get; set; }
|
||||||
|
public bool IsHidden { get; set; }
|
||||||
|
public int AreaId { get; set; }
|
||||||
|
public Transform[] Transform { get; set; } = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Transform
|
||||||
|
{
|
||||||
|
public int X { get; set; }
|
||||||
|
public int Y { get; set; }
|
||||||
|
public int Z { get; set; }
|
||||||
|
}
|
69
Core/Config/RoleInfoConfig.cs
Normal file
69
Core/Config/RoleInfoConfig.cs
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
using Core.Config.Attributes;
|
||||||
|
|
||||||
|
namespace Core.Config;
|
||||||
|
|
||||||
|
[ConfigCollection("role/roleinfo.json")]
|
||||||
|
public class RoleInfoConfig : IConfig
|
||||||
|
{
|
||||||
|
public ConfigType Type => ConfigType.RoleInfo;
|
||||||
|
|
||||||
|
public int Identifier => Id;
|
||||||
|
|
||||||
|
public int Id { get; set; }
|
||||||
|
public int QualityId { get; set; }
|
||||||
|
public int RoleType { get; set; }
|
||||||
|
public bool IsTrial { get; set; }
|
||||||
|
public string Name { get; set; } = string.Empty;
|
||||||
|
public string NickName { get; set; } = string.Empty;
|
||||||
|
public string Introduction { get; set; } = string.Empty;
|
||||||
|
public int ParentId { get; set; }
|
||||||
|
public int Priority { get; set; }
|
||||||
|
public int PropertyId { get; set; }
|
||||||
|
public List<int> ShowProperty { get; set; } = [];
|
||||||
|
public int ElementId { get; set; }
|
||||||
|
public string RoleHeadIconLarge { get; set; } = string.Empty;
|
||||||
|
public string RoleHeadIconBig { get; set; } = string.Empty;
|
||||||
|
public string Card { get; set; } = string.Empty;
|
||||||
|
public string RoleHeadIcon { get; set; } = string.Empty;
|
||||||
|
public string FormationRoleCard { get; set; } = string.Empty;
|
||||||
|
public string RoleStand { get; set; } = string.Empty;
|
||||||
|
public int MeshId { get; set; }
|
||||||
|
public int UiMeshId { get; set; }
|
||||||
|
public string RoleBody { get; set; } = string.Empty;
|
||||||
|
public int BreachModel { get; set; }
|
||||||
|
public int SpecialEnergyBarId { get; set; }
|
||||||
|
public string CameraConfig { get; set; } = string.Empty;
|
||||||
|
public int CameraFloatHeight { get; set; }
|
||||||
|
public int EntityProperty { get; set; }
|
||||||
|
public int MaxLevel { get; set; }
|
||||||
|
public int LevelConsumeId { get; set; }
|
||||||
|
public int BreachId { get; set; }
|
||||||
|
public int SkillId { get; set; }
|
||||||
|
public int SkillTreeGroupId { get; set; }
|
||||||
|
public int ResonanceId { get; set; }
|
||||||
|
public int ResonantChainGroupId { get; set; }
|
||||||
|
public bool IsShow { get; set; }
|
||||||
|
public int InitWeaponItemId { get; set; }
|
||||||
|
public int WeaponType { get; set; }
|
||||||
|
public string SkillDAPath { get; set; } = string.Empty;
|
||||||
|
public string SkillLockDAPath { get; set; } = string.Empty;
|
||||||
|
public string UiScenePerformanceABP { get; set; } = string.Empty;
|
||||||
|
public int LockOnDefaultId { get; set; }
|
||||||
|
public int LockOnLookOnId { get; set; }
|
||||||
|
public string SkillEffectDA { get; set; } = string.Empty;
|
||||||
|
public string FootStepState { get; set; } = string.Empty;
|
||||||
|
public int PartyId { get; set; }
|
||||||
|
public string AttributesDescription { get; set; } = string.Empty;
|
||||||
|
public string Icon { get; set; } = string.Empty;
|
||||||
|
public int ItemQualityId { get; set; }
|
||||||
|
public string ObtainedShowDescription { get; set; } = string.Empty;
|
||||||
|
public int NumLimit { get; set; }
|
||||||
|
public bool ShowInBag { get; set; }
|
||||||
|
public List<float> WeaponScale { get; set; } = [];
|
||||||
|
public bool Intervene { get; set; }
|
||||||
|
public string CharacterVoice { get; set; } = string.Empty;
|
||||||
|
public int TrialRole { get; set; }
|
||||||
|
public bool IsAim { get; set; }
|
||||||
|
public int RoleGuide { get; set; }
|
||||||
|
public int RedDotDisableRule { get; set; }
|
||||||
|
}
|
7
Core/Config/Types/PropConfig.cs
Normal file
7
Core/Config/Types/PropConfig.cs
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
namespace Core.Config.Types;
|
||||||
|
public class PropConfig
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public float Value { get; set; }
|
||||||
|
public bool IsRatio { get; set; }
|
||||||
|
}
|
47
Core/Config/WeaponConfig.cs
Normal file
47
Core/Config/WeaponConfig.cs
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
using Core.Config.Attributes;
|
||||||
|
using Core.Config.Types;
|
||||||
|
|
||||||
|
namespace Core.Config;
|
||||||
|
|
||||||
|
[ConfigCollection("weapon/weaponconf.json")]
|
||||||
|
public class WeaponConfig : IConfig
|
||||||
|
{
|
||||||
|
public ConfigType Type => ConfigType.Weapon;
|
||||||
|
|
||||||
|
public int Identifier => ItemId;
|
||||||
|
|
||||||
|
public int ItemId { get; set; }
|
||||||
|
public string WeaponName { get; set; } = string.Empty;
|
||||||
|
public int QualityId { get; set; }
|
||||||
|
public int WeaponType { get; set; }
|
||||||
|
public int ModelId { get; set; }
|
||||||
|
public int TransformId { get; set; }
|
||||||
|
public List<int> Models { get; set; } = [];
|
||||||
|
public int ResonLevelLimit { get; set; }
|
||||||
|
public PropConfig? FirstPropId { get; set; }
|
||||||
|
public int FirstCurve { get; set; }
|
||||||
|
public PropConfig? SecondPropId { get; set; }
|
||||||
|
public int SecondCurve { get; set; }
|
||||||
|
public int ResonId { get; set; }
|
||||||
|
public int LevelId { get; set; }
|
||||||
|
public int BreachId { get; set; }
|
||||||
|
public string Desc { get; set; } = string.Empty;
|
||||||
|
public string TypeDescription { get; set; } = string.Empty;
|
||||||
|
public string AttributesDescription { get; set; } = string.Empty;
|
||||||
|
public string BgDescription { get; set; } = string.Empty;
|
||||||
|
public string Icon { get; set; } = string.Empty;
|
||||||
|
public string IconMiddle { get; set; } = string.Empty;
|
||||||
|
public string IconSmall { get; set; } = string.Empty;
|
||||||
|
public string Mesh { get; set; } = string.Empty;
|
||||||
|
public int MaxCapcity { get; set; }
|
||||||
|
public List<object> ItemAccess { get; set; } = [];
|
||||||
|
public int ObtainedShow { get; set; }
|
||||||
|
public string ObtainedShowDescription { get; set; } = string.Empty;
|
||||||
|
public int NumLimit { get; set; }
|
||||||
|
public bool ShowInBag { get; set; }
|
||||||
|
public int SortIndex { get; set; }
|
||||||
|
public string ResonanceIcon { get; set; } = string.Empty;
|
||||||
|
public int HiddenTime { get; set; }
|
||||||
|
public bool Destructible { get; set; }
|
||||||
|
public int RedDotDisableRule { get; set; }
|
||||||
|
}
|
29
Core/Core.csproj
Normal file
29
Core/Core.csproj
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Include="data\config\*\*.json">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Remove="data\config\blueprint\blueprintconfig.json" />
|
||||||
|
<None Remove="data\config\property\baseproperty.json" />
|
||||||
|
<None Remove="data\config\weapon\weaponconf.json" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="8.0.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="data\config\level_entity\" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
11
Core/Extensions/ServiceCollectionExtensions.cs
Normal file
11
Core/Extensions/ServiceCollectionExtensions.cs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
using Core.Resources;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
|
namespace Core.Extensions;
|
||||||
|
public static class ServiceCollectionExtensions
|
||||||
|
{
|
||||||
|
public static IServiceCollection UseLocalResources(this IServiceCollection services)
|
||||||
|
{
|
||||||
|
return services.AddSingleton<IResourceProvider, LocalResourceProvider>();
|
||||||
|
}
|
||||||
|
}
|
7
Core/Resources/IResourceProvider.cs
Normal file
7
Core/Resources/IResourceProvider.cs
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
using System.Text.Json;
|
||||||
|
|
||||||
|
namespace Core.Resources;
|
||||||
|
public interface IResourceProvider
|
||||||
|
{
|
||||||
|
JsonDocument GetJsonResource(string path);
|
||||||
|
}
|
11
Core/Resources/LocalResourceProvider.cs
Normal file
11
Core/Resources/LocalResourceProvider.cs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
using System.Text.Json;
|
||||||
|
|
||||||
|
namespace Core.Resources;
|
||||||
|
internal class LocalResourceProvider : IResourceProvider
|
||||||
|
{
|
||||||
|
public JsonDocument GetJsonResource(string path)
|
||||||
|
{
|
||||||
|
using FileStream fileStream = File.Open(path, FileMode.Open, FileAccess.Read);
|
||||||
|
return JsonDocument.Parse(fileStream);
|
||||||
|
}
|
||||||
|
}
|
12986
Core/data/config/blueprint/blueprintconfig.json
Normal file
12986
Core/data/config/blueprint/blueprintconfig.json
Normal file
File diff suppressed because it is too large
Load diff
1488979
Core/data/config/level_entity/levelentityconfig.json
Normal file
1488979
Core/data/config/level_entity/levelentityconfig.json
Normal file
File diff suppressed because it is too large
Load diff
65749
Core/data/config/property/baseproperty.json
Normal file
65749
Core/data/config/property/baseproperty.json
Normal file
File diff suppressed because it is too large
Load diff
2537
Core/data/config/role/roleinfo.json
Normal file
2537
Core/data/config/role/roleinfo.json
Normal file
File diff suppressed because it is too large
Load diff
3382
Core/data/config/weapon/weaponconf.json
Normal file
3382
Core/data/config/weapon/weaponconf.json
Normal file
File diff suppressed because it is too large
Load diff
|
@ -12,5 +12,5 @@ internal class AchievementController : Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
[NetEvent(MessageId.AchievementInfoRequest)]
|
[NetEvent(MessageId.AchievementInfoRequest)]
|
||||||
public ResponseMessage OnAchievementInfoRequest() => Response(MessageId.AchievementInfoResponse, new AchievementInfoResponse());
|
public RpcResult OnAchievementInfoRequest() => Response(MessageId.AchievementInfoResponse, new AchievementInfoResponse());
|
||||||
}
|
}
|
||||||
|
|
12
GameServer/Controllers/Attributes/ChatCommandAttribute.cs
Normal file
12
GameServer/Controllers/Attributes/ChatCommandAttribute.cs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
namespace GameServer.Controllers.Attributes;
|
||||||
|
|
||||||
|
[AttributeUsage(AttributeTargets.Method)]
|
||||||
|
internal class ChatCommandAttribute : Attribute
|
||||||
|
{
|
||||||
|
public string Command { get; }
|
||||||
|
|
||||||
|
public ChatCommandAttribute(string command)
|
||||||
|
{
|
||||||
|
Command = command;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
namespace GameServer.Controllers.Attributes;
|
||||||
|
|
||||||
|
[AttributeUsage(AttributeTargets.Class)]
|
||||||
|
internal class ChatCommandCategoryAttribute : Attribute
|
||||||
|
{
|
||||||
|
public string Category { get; }
|
||||||
|
|
||||||
|
public ChatCommandCategoryAttribute(string category)
|
||||||
|
{
|
||||||
|
Category = category;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
namespace GameServer.Controllers.Attributes;
|
||||||
|
|
||||||
|
[AttributeUsage(AttributeTargets.Method)]
|
||||||
|
internal class ChatCommandDescAttribute : Attribute
|
||||||
|
{
|
||||||
|
public string Description { get; }
|
||||||
|
|
||||||
|
public ChatCommandDescAttribute(string description)
|
||||||
|
{
|
||||||
|
Description = description;
|
||||||
|
}
|
||||||
|
}
|
14
GameServer/Controllers/Attributes/CombatRequestAttribute.cs
Normal file
14
GameServer/Controllers/Attributes/CombatRequestAttribute.cs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
using Protocol;
|
||||||
|
|
||||||
|
namespace GameServer.Controllers.Attributes;
|
||||||
|
|
||||||
|
[AttributeUsage(AttributeTargets.Method)]
|
||||||
|
internal class CombatRequestAttribute : Attribute
|
||||||
|
{
|
||||||
|
public CombatRequestData.MessageOneofCase MessageCase { get; }
|
||||||
|
|
||||||
|
public CombatRequestAttribute(CombatRequestData.MessageOneofCase messageCase)
|
||||||
|
{
|
||||||
|
MessageCase = messageCase;
|
||||||
|
}
|
||||||
|
}
|
77
GameServer/Controllers/ChatCommands/ChatCommandManager.cs
Normal file
77
GameServer/Controllers/ChatCommands/ChatCommandManager.cs
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
using System.Collections.Immutable;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
using System.Reflection;
|
||||||
|
using GameServer.Controllers.Attributes;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
|
namespace GameServer.Controllers.ChatCommands;
|
||||||
|
internal class ChatCommandManager
|
||||||
|
{
|
||||||
|
private delegate Task ChatCommandDelegate(IServiceProvider serviceProvider, string[] args);
|
||||||
|
private static readonly ImmutableDictionary<string, ImmutableDictionary<string, ChatCommandDelegate>> s_commandCategories;
|
||||||
|
private static readonly ImmutableArray<string> s_commandDescriptions;
|
||||||
|
|
||||||
|
private readonly IServiceProvider _serviceProvider;
|
||||||
|
|
||||||
|
static ChatCommandManager()
|
||||||
|
{
|
||||||
|
(s_commandCategories, s_commandDescriptions) = RegisterCommands();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<string> CommandDescriptions => s_commandDescriptions;
|
||||||
|
|
||||||
|
public ChatCommandManager(IServiceProvider serviceProvider)
|
||||||
|
{
|
||||||
|
_serviceProvider = serviceProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task InvokeCommandAsync(string category, string command, string[] args)
|
||||||
|
{
|
||||||
|
if (s_commandCategories.TryGetValue(category, out var commands))
|
||||||
|
{
|
||||||
|
if (commands.TryGetValue(command, out ChatCommandDelegate? commandDelegate))
|
||||||
|
await commandDelegate(_serviceProvider, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static (ImmutableDictionary<string, ImmutableDictionary<string, ChatCommandDelegate>>, ImmutableArray<string>) RegisterCommands()
|
||||||
|
{
|
||||||
|
IEnumerable<Type> types = Assembly.GetExecutingAssembly().GetTypes()
|
||||||
|
.Where(type => type.GetCustomAttribute<ChatCommandCategoryAttribute>() != null);
|
||||||
|
|
||||||
|
MethodInfo getServiceMethod = typeof(ServiceProviderServiceExtensions).GetMethod(nameof(ServiceProviderServiceExtensions.GetRequiredService), [typeof(IServiceProvider)])!;
|
||||||
|
var categories = ImmutableDictionary.CreateBuilder<string, ImmutableDictionary<string, ChatCommandDelegate>>();
|
||||||
|
var descriptions = ImmutableArray.CreateBuilder<string>();
|
||||||
|
|
||||||
|
foreach (Type type in types)
|
||||||
|
{
|
||||||
|
var commands = ImmutableDictionary.CreateBuilder<string, ChatCommandDelegate>();
|
||||||
|
foreach (MethodInfo method in type.GetMethods())
|
||||||
|
{
|
||||||
|
ChatCommandAttribute? cmdAttribute = method.GetCustomAttribute<ChatCommandAttribute>();
|
||||||
|
if (cmdAttribute == null) continue;
|
||||||
|
|
||||||
|
ParameterExpression serviceProviderParam = Expression.Parameter(typeof(IServiceProvider));
|
||||||
|
ParameterExpression argsParam = Expression.Parameter(typeof(string[]));
|
||||||
|
|
||||||
|
MethodCallExpression getServiceCall = Expression.Call(getServiceMethod.MakeGenericMethod(type), serviceProviderParam);
|
||||||
|
Expression handlerCall = Expression.Call(getServiceCall, method, argsParam);
|
||||||
|
|
||||||
|
if (method.ReturnType == typeof(void)) // Allow non-async methods as well
|
||||||
|
handlerCall = Expression.Block(handlerCall, Expression.Constant(Task.CompletedTask));
|
||||||
|
|
||||||
|
Expression<ChatCommandDelegate> lambda = Expression.Lambda<ChatCommandDelegate>(handlerCall, serviceProviderParam, argsParam);
|
||||||
|
commands.Add(cmdAttribute.Command, lambda.Compile());
|
||||||
|
|
||||||
|
ChatCommandDescAttribute? desc = method.GetCustomAttribute<ChatCommandDescAttribute>();
|
||||||
|
if (desc != null)
|
||||||
|
descriptions.Add(desc.Description);
|
||||||
|
}
|
||||||
|
|
||||||
|
ChatCommandCategoryAttribute categoryAttribute = type.GetCustomAttribute<ChatCommandCategoryAttribute>()!;
|
||||||
|
categories.Add(categoryAttribute.Category, commands.ToImmutable());
|
||||||
|
}
|
||||||
|
|
||||||
|
return (categories.ToImmutable(), descriptions.ToImmutable());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
using Core.Config;
|
||||||
|
using GameServer.Controllers.Attributes;
|
||||||
|
using GameServer.Models;
|
||||||
|
using GameServer.Models.Chat;
|
||||||
|
using GameServer.Network;
|
||||||
|
using GameServer.Systems.Entity;
|
||||||
|
using Protocol;
|
||||||
|
|
||||||
|
namespace GameServer.Controllers.ChatCommands;
|
||||||
|
|
||||||
|
[ChatCommandCategory("spawn")]
|
||||||
|
internal class ChatSpawnCommandHandler
|
||||||
|
{
|
||||||
|
private readonly ChatRoom _helperRoom;
|
||||||
|
private readonly EntitySystem _entitySystem;
|
||||||
|
private readonly EntityFactory _entityFactory;
|
||||||
|
private readonly PlayerSession _session;
|
||||||
|
private readonly ConfigManager _configManager;
|
||||||
|
private readonly CreatureController _creatureController;
|
||||||
|
|
||||||
|
public ChatSpawnCommandHandler(ModelManager modelManager, EntitySystem entitySystem, EntityFactory entityFactory, PlayerSession session, ConfigManager configManager, CreatureController creatureController)
|
||||||
|
{
|
||||||
|
_helperRoom = modelManager.Chat.GetChatRoom(1338);
|
||||||
|
_entitySystem = entitySystem;
|
||||||
|
_entityFactory = entityFactory;
|
||||||
|
_session = session;
|
||||||
|
_configManager = configManager;
|
||||||
|
_creatureController = creatureController;
|
||||||
|
}
|
||||||
|
|
||||||
|
[ChatCommand("monster")]
|
||||||
|
[ChatCommandDesc("/spawn monster [id] [x] [y] [z] - spawns monster with specified id and coordinates")]
|
||||||
|
public async Task OnSpawnMonsterCommand(string[] args)
|
||||||
|
{
|
||||||
|
if (args.Length != 4 ||
|
||||||
|
!(int.TryParse(args[0], out int levelEntityId) &&
|
||||||
|
int.TryParse(args[1], out int x) &&
|
||||||
|
int.TryParse(args[2], out int y) &&
|
||||||
|
int.TryParse(args[3], out int z)))
|
||||||
|
{
|
||||||
|
_helperRoom.AddMessage(1338, 0, "Usage: /spawn monster [id] [x] [y] [z]");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MonsterEntity monster = _entityFactory.CreateMonster(levelEntityId);
|
||||||
|
monster.Pos = new()
|
||||||
|
{
|
||||||
|
X = x,
|
||||||
|
Y = y,
|
||||||
|
Z = z
|
||||||
|
};
|
||||||
|
|
||||||
|
_entitySystem.Create(monster);
|
||||||
|
monster.InitProps(_configManager.GetConfig<BasePropertyConfig>(600000100)!); // TODO: monster property config
|
||||||
|
|
||||||
|
await _session.Push(MessageId.EntityAddNotify, new EntityAddNotify
|
||||||
|
{
|
||||||
|
IsAdd = true,
|
||||||
|
EntityPbs = { monster.Pb }
|
||||||
|
});
|
||||||
|
|
||||||
|
await _creatureController.UpdateAiHate();
|
||||||
|
|
||||||
|
_helperRoom.AddMessage(1338, 0, $"Successfully spawned monster with id {levelEntityId} at ({x}, {y}, {z})");
|
||||||
|
}
|
||||||
|
}
|
93
GameServer/Controllers/ChatController.cs
Normal file
93
GameServer/Controllers/ChatController.cs
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using GameServer.Controllers.Attributes;
|
||||||
|
using GameServer.Controllers.ChatCommands;
|
||||||
|
using GameServer.Models;
|
||||||
|
using GameServer.Models.Chat;
|
||||||
|
using GameServer.Network;
|
||||||
|
using GameServer.Network.Messages;
|
||||||
|
using Protocol;
|
||||||
|
|
||||||
|
namespace GameServer.Controllers;
|
||||||
|
internal partial class ChatController : Controller
|
||||||
|
{
|
||||||
|
private readonly ModelManager _modelManager;
|
||||||
|
|
||||||
|
public ChatController(PlayerSession session, ModelManager modelManager) : base(session)
|
||||||
|
{
|
||||||
|
_modelManager = modelManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
[NetEvent(MessageId.PrivateChatDataRequest)]
|
||||||
|
public async Task<RpcResult> OnPrivateChatDataRequest()
|
||||||
|
{
|
||||||
|
if (!_modelManager.Chat.AllChatRooms.Any())
|
||||||
|
{
|
||||||
|
ChatRoom chatRoom = _modelManager.Chat.GetChatRoom(1338); // Reversed Helper
|
||||||
|
chatRoom.AddMessage(1338, (int)ChatContentType.Text, BuildWelcomeMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
await PushPrivateChatHistory();
|
||||||
|
return Response(MessageId.PrivateChatDataResponse, new PrivateChatDataResponse()); // Response doesn't contain any useful info, everything is in notifies.
|
||||||
|
}
|
||||||
|
|
||||||
|
[NetEvent(MessageId.PrivateChatRequest)]
|
||||||
|
public async Task<RpcResult> OnPrivateChatRequest(PrivateChatRequest request, ChatCommandManager chatCommandManager)
|
||||||
|
{
|
||||||
|
ChatRoom chatRoom = _modelManager.Chat.GetChatRoom(1338);
|
||||||
|
|
||||||
|
chatRoom.AddMessage(_modelManager.Player.Id, request.ChatContentType, request.Content);
|
||||||
|
if (!request.Content.StartsWith('/'))
|
||||||
|
{
|
||||||
|
chatRoom.AddMessage(1338, 0, "huh?");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string content = MultipleSpacesRegex().Replace(request.Content, " ");
|
||||||
|
string[] split = content[1..].Split(' ');
|
||||||
|
if (split.Length >= 2)
|
||||||
|
{
|
||||||
|
await chatCommandManager.InvokeCommandAsync(split[0], split[1], split[2..]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await PushPrivateChatHistory();
|
||||||
|
return Response(MessageId.PrivateChatResponse, new PrivateChatResponse());
|
||||||
|
}
|
||||||
|
|
||||||
|
[NetEvent(MessageId.PrivateChatOperateRequest)]
|
||||||
|
public RpcResult OnPrivateChatOperateRequest() => Response(MessageId.PrivateChatOperateResponse, new PrivateChatOperateResponse());
|
||||||
|
|
||||||
|
private async Task PushPrivateChatHistory()
|
||||||
|
{
|
||||||
|
await Session.Push(MessageId.PrivateChatHistoryNotify, new PrivateChatHistoryNotify
|
||||||
|
{
|
||||||
|
AllChats =
|
||||||
|
{
|
||||||
|
_modelManager.Chat.AllChatRooms
|
||||||
|
.Select(chatRoom => new PrivateChatHistoryContentProto
|
||||||
|
{
|
||||||
|
TargetUid = chatRoom.TargetUid,
|
||||||
|
Chats = { chatRoom.ChatHistory }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string BuildWelcomeMessage()
|
||||||
|
{
|
||||||
|
StringBuilder builder = new();
|
||||||
|
builder.AppendLine("Welcome to ReversedRooms WutheringWaves private server!\nTo get support, join:\ndiscord.gg/reversedrooms");
|
||||||
|
builder.AppendLine("List of all commands:");
|
||||||
|
|
||||||
|
foreach (string description in ChatCommandManager.CommandDescriptions)
|
||||||
|
{
|
||||||
|
builder.AppendLine(description);
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
[GeneratedRegex(@"\s+")]
|
||||||
|
private static partial Regex MultipleSpacesRegex();
|
||||||
|
}
|
306
GameServer/Controllers/Combat/CombatManager.cs
Normal file
306
GameServer/Controllers/Combat/CombatManager.cs
Normal file
|
@ -0,0 +1,306 @@
|
||||||
|
using System.Collections.Immutable;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using GameServer.Controllers.Attributes;
|
||||||
|
using GameServer.Network;
|
||||||
|
using GameServer.Systems.Entity;
|
||||||
|
using GameServer.Systems.Entity.Component;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Protocol;
|
||||||
|
|
||||||
|
namespace GameServer.Controllers.Combat;
|
||||||
|
internal class CombatManager
|
||||||
|
{
|
||||||
|
private delegate Task<CombatResponseData> CombatRequestHandler(CombatManager combatManager, CombatRequestContext context);
|
||||||
|
private static readonly ImmutableDictionary<CombatRequestData.MessageOneofCase, CombatRequestHandler> s_requestHandlers;
|
||||||
|
|
||||||
|
private readonly ILogger _logger;
|
||||||
|
private readonly EntitySystem _entitySystem;
|
||||||
|
private readonly PlayerSession _session;
|
||||||
|
private readonly CreatureController _creatureController;
|
||||||
|
|
||||||
|
static CombatManager()
|
||||||
|
{
|
||||||
|
s_requestHandlers = MapRequestHandlers();
|
||||||
|
}
|
||||||
|
|
||||||
|
public CombatManager(ILogger<CombatManager> logger, EntitySystem entitySystem, PlayerSession session, CreatureController creatureController)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_entitySystem = entitySystem;
|
||||||
|
_session = session;
|
||||||
|
_creatureController = creatureController;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CombatRequest(CombatRequestData.MessageOneofCase.DamageExecuteRequest)]
|
||||||
|
public async Task<CombatResponseData> OnDamageExecuteRequest(CombatRequestContext context)
|
||||||
|
{
|
||||||
|
DamageExecuteRequest request = context.Request.DamageExecuteRequest;
|
||||||
|
|
||||||
|
EntityBase? entity = _entitySystem.Get<EntityBase>(request.TargetEntityId);
|
||||||
|
if (entity == null)
|
||||||
|
{
|
||||||
|
return new CombatResponseData
|
||||||
|
{
|
||||||
|
RequestId = context.Request.RequestId,
|
||||||
|
CombatCommon = context.Request.CombatCommon,
|
||||||
|
DamageExecuteResponse = new()
|
||||||
|
{
|
||||||
|
ErrorCode = (int)ErrorCode.ErrThrowDamageReqEntityIsAlreadyDead
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
EntityAttributeComponent attr = entity.ComponentSystem.Get<EntityAttributeComponent>();
|
||||||
|
attr.SetAttribute(EAttributeType.Life, (int)request.DamageId); // Pakchunk patch! (cur hp instead of damageid)
|
||||||
|
|
||||||
|
if (request.DamageId <= 0 && entity.Type != EEntityType.Player) // Player death not implemented
|
||||||
|
{
|
||||||
|
_entitySystem.Destroy(entity);
|
||||||
|
await _session.Push(MessageId.EntityRemoveNotify, new EntityRemoveNotify
|
||||||
|
{
|
||||||
|
IsRemove = true,
|
||||||
|
RemoveInfos =
|
||||||
|
{
|
||||||
|
new EntityRemoveInfo
|
||||||
|
{
|
||||||
|
EntityId = entity.Id,
|
||||||
|
Type = (int)ERemoveEntityType.RemoveTypeNormal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return new CombatResponseData
|
||||||
|
{
|
||||||
|
RequestId = context.Request.RequestId,
|
||||||
|
CombatCommon = context.Request.CombatCommon,
|
||||||
|
DamageExecuteResponse = new()
|
||||||
|
{
|
||||||
|
AttackerEntityId = request.AttackerEntityId,
|
||||||
|
TargetEntityId = request.TargetEntityId,
|
||||||
|
ShieldCoverDamage = 0,
|
||||||
|
Damage = (int)request.DamageId,
|
||||||
|
PartId = request.PartId
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[CombatRequest(CombatRequestData.MessageOneofCase.HitRequest)]
|
||||||
|
public CombatResponseData OnHitRequest(CombatRequestContext context)
|
||||||
|
{
|
||||||
|
return new CombatResponseData
|
||||||
|
{
|
||||||
|
RequestId = context.Request.RequestId,
|
||||||
|
CombatCommon = context.Request.CombatCommon,
|
||||||
|
HitResponse = new()
|
||||||
|
{
|
||||||
|
HitInfo = context.Request.HitRequest.HitInfo
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[CombatRequest(CombatRequestData.MessageOneofCase.LogicStateInitRequest)]
|
||||||
|
public CombatResponseData OnLogicStateInitRequest(CombatRequestContext context)
|
||||||
|
{
|
||||||
|
CombatResponseData rsp = new()
|
||||||
|
{
|
||||||
|
CombatCommon = context.Request.CombatCommon,
|
||||||
|
RequestId = context.Request.RequestId,
|
||||||
|
LogicStateInitResponse = new()
|
||||||
|
};
|
||||||
|
|
||||||
|
EntityBase? entity = _entitySystem.Get<EntityBase>(context.Request.CombatCommon.EntityId);
|
||||||
|
if (entity == null) return rsp;
|
||||||
|
|
||||||
|
EntityLogicStateComponent logicStateComponent = entity.ComponentSystem.Get<EntityLogicStateComponent>();
|
||||||
|
logicStateComponent.States = [.. context.Request.LogicStateInitRequest.InitData.States];
|
||||||
|
|
||||||
|
context.Notifies.Add(new CombatNotifyData
|
||||||
|
{
|
||||||
|
CombatCommon = context.Request.CombatCommon,
|
||||||
|
LogicStateInitNotify = new()
|
||||||
|
{
|
||||||
|
CombatCommon = context.Request.CombatCommon,
|
||||||
|
EntityId = entity.Id,
|
||||||
|
InitData = logicStateComponent.Pb.LogicStateComponentPb
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return rsp;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CombatRequest(CombatRequestData.MessageOneofCase.SwitchLogicStateRequest)]
|
||||||
|
public CombatResponseData OnSwitchLogicStateRequest(CombatRequestContext context)
|
||||||
|
{
|
||||||
|
CombatResponseData rsp = new()
|
||||||
|
{
|
||||||
|
CombatCommon = context.Request.CombatCommon,
|
||||||
|
RequestId = context.Request.RequestId,
|
||||||
|
SwitchLogicStateResponse = new()
|
||||||
|
};
|
||||||
|
|
||||||
|
EntityBase? entity = _entitySystem.Get<EntityBase>(context.Request.CombatCommon.EntityId);
|
||||||
|
if (entity == null)
|
||||||
|
{
|
||||||
|
rsp.SwitchLogicStateResponse.ErrorCode = (int)ErrorCode.ErrActionEntityNoExist;
|
||||||
|
return rsp;
|
||||||
|
}
|
||||||
|
|
||||||
|
EntityLogicStateComponent logicStateComponent = entity.ComponentSystem.Get<EntityLogicStateComponent>();
|
||||||
|
logicStateComponent.States = [.. context.Request.SwitchLogicStateRequest.States];
|
||||||
|
|
||||||
|
context.Notifies.Add(new CombatNotifyData
|
||||||
|
{
|
||||||
|
CombatCommon = context.Request.CombatCommon,
|
||||||
|
SwitchLogicStateNotify = new()
|
||||||
|
{
|
||||||
|
States = { logicStateComponent.States }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return rsp;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CombatRequest(CombatRequestData.MessageOneofCase.BattleStateChangeRequest)]
|
||||||
|
public CombatResponseData OnBattleStateChangeRequest(CombatRequestContext context)
|
||||||
|
{
|
||||||
|
return new CombatResponseData
|
||||||
|
{
|
||||||
|
CombatCommon = context.Request.CombatCommon,
|
||||||
|
RequestId = context.Request.RequestId,
|
||||||
|
BattleStateChangeResponse = new()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[CombatRequest(CombatRequestData.MessageOneofCase.ChangeStateConfirmRequest)]
|
||||||
|
public CombatResponseData OnChangeStateConfirmRequest(CombatRequestContext context)
|
||||||
|
{
|
||||||
|
CombatResponseData rsp = new()
|
||||||
|
{
|
||||||
|
CombatCommon = context.Request.CombatCommon,
|
||||||
|
RequestId = context.Request.RequestId,
|
||||||
|
ChangeStateConfirmResponse = new()
|
||||||
|
{
|
||||||
|
Error = new()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
EntityBase? entity = _entitySystem.Get<EntityBase>(context.Request.CombatCommon.EntityId);
|
||||||
|
if (entity == null)
|
||||||
|
{
|
||||||
|
rsp.ChangeStateConfirmResponse.Error.ErrorCode = (int)ErrorCode.ErrEntityIsNotAlive;
|
||||||
|
return rsp;
|
||||||
|
}
|
||||||
|
|
||||||
|
ChangeStateConfirmRequest request = context.Request.ChangeStateConfirmRequest;
|
||||||
|
if (entity.ComponentSystem.TryGet(out EntityFsmComponent? fsmComponent))
|
||||||
|
{
|
||||||
|
DFsm? dfsm = fsmComponent.Fsms.FirstOrDefault(fsm => fsm.FsmId == request.FsmId);
|
||||||
|
dfsm ??= new()
|
||||||
|
{
|
||||||
|
FsmId = request.FsmId,
|
||||||
|
Status = 1,
|
||||||
|
Flag = (int)EFsmStateFlag.Confirmed
|
||||||
|
};
|
||||||
|
|
||||||
|
dfsm.CurrentState = request.State;
|
||||||
|
context.Notifies.Add(new CombatNotifyData
|
||||||
|
{
|
||||||
|
CombatCommon = context.Request.CombatCommon,
|
||||||
|
ChangeStateConfirmNotify = new ChangeStateConfirmNotify
|
||||||
|
{
|
||||||
|
State = request.State,
|
||||||
|
FsmId = request.FsmId
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
rsp.ChangeStateConfirmResponse.State = context.Request.ChangeStateConfirmRequest.State;
|
||||||
|
rsp.ChangeStateConfirmResponse.FsmId = context.Request.ChangeStateConfirmRequest.FsmId;
|
||||||
|
|
||||||
|
return rsp;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CombatRequest(CombatRequestData.MessageOneofCase.FsmConditionPassRequest)]
|
||||||
|
public CombatResponseData OnFsmConditionPassRequest(CombatRequestContext context)
|
||||||
|
{
|
||||||
|
return new CombatResponseData
|
||||||
|
{
|
||||||
|
CombatCommon = context.Request.CombatCommon,
|
||||||
|
RequestId = context.Request.RequestId,
|
||||||
|
FsmConditionPassResponse = new()
|
||||||
|
{
|
||||||
|
FsmId = context.Request.FsmConditionPassRequest.FsmId,
|
||||||
|
Error = new()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[CombatRequest(CombatRequestData.MessageOneofCase.AiInformationRequest)]
|
||||||
|
public CombatResponseData OnAiInformationRequest(CombatRequestContext context)
|
||||||
|
{
|
||||||
|
// Currently like this, TODO!
|
||||||
|
context.Notifies.Add(new CombatNotifyData
|
||||||
|
{
|
||||||
|
CombatCommon = new CombatCommon
|
||||||
|
{
|
||||||
|
EntityId = context.Request.CombatCommon.EntityId, // id of monster
|
||||||
|
},
|
||||||
|
AiHateNotify = new AiHateNotify
|
||||||
|
{
|
||||||
|
HateList =
|
||||||
|
{
|
||||||
|
new AiHateEntity
|
||||||
|
{
|
||||||
|
EntityId = _creatureController.GetPlayerEntity()!.Id, // id of hated entity (the player)
|
||||||
|
HatredValue = 99999
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return new CombatResponseData
|
||||||
|
{
|
||||||
|
CombatCommon = context.Request.CombatCommon,
|
||||||
|
RequestId = context.Request.RequestId,
|
||||||
|
AiInformationResponse = new() // ?? contains nothing
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<CombatResponseData?> HandleRequest(CombatRequestContext context)
|
||||||
|
{
|
||||||
|
if (s_requestHandlers.TryGetValue(context.Request.MessageCase, out CombatRequestHandler? handler))
|
||||||
|
return handler(this, context)!;
|
||||||
|
|
||||||
|
_logger.LogWarning("Combat request not handled: {type}", context.Request.MessageCase);
|
||||||
|
return Task.FromResult<CombatResponseData?>(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ImmutableDictionary<CombatRequestData.MessageOneofCase, CombatRequestHandler> MapRequestHandlers()
|
||||||
|
{
|
||||||
|
var builder = ImmutableDictionary.CreateBuilder<CombatRequestData.MessageOneofCase, CombatRequestHandler>();
|
||||||
|
|
||||||
|
MethodInfo taskFromResultMethod = typeof(Task).GetMethod(nameof(Task.FromResult))!.MakeGenericMethod(typeof(CombatResponseData));
|
||||||
|
|
||||||
|
foreach (MethodInfo method in typeof(CombatManager).GetMethods())
|
||||||
|
{
|
||||||
|
CombatRequestAttribute? attribute = method.GetCustomAttribute<CombatRequestAttribute>();
|
||||||
|
if (attribute == null) continue;
|
||||||
|
|
||||||
|
ParameterExpression combatManagerParam = Expression.Parameter(typeof(CombatManager));
|
||||||
|
ParameterExpression contextParam = Expression.Parameter(typeof(CombatRequestContext));
|
||||||
|
|
||||||
|
Expression call = Expression.Call(combatManagerParam, method, contextParam);
|
||||||
|
if (method.ReturnType == typeof(CombatResponseData))
|
||||||
|
call = Expression.Call(taskFromResultMethod, call);
|
||||||
|
|
||||||
|
Expression<CombatRequestHandler> lambda = Expression.Lambda<CombatRequestHandler>(call, combatManagerParam, contextParam);
|
||||||
|
builder.Add(attribute.MessageCase, lambda.Compile());
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.ToImmutable();
|
||||||
|
}
|
||||||
|
}
|
14
GameServer/Controllers/Combat/CombatRequestContext.cs
Normal file
14
GameServer/Controllers/Combat/CombatRequestContext.cs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
using Protocol;
|
||||||
|
|
||||||
|
namespace GameServer.Controllers.Combat;
|
||||||
|
internal class CombatRequestContext
|
||||||
|
{
|
||||||
|
public CombatRequestData Request { get; }
|
||||||
|
public List<CombatNotifyData> Notifies { get; }
|
||||||
|
|
||||||
|
public CombatRequestContext(CombatRequestData request)
|
||||||
|
{
|
||||||
|
Request = request;
|
||||||
|
Notifies = [];
|
||||||
|
}
|
||||||
|
}
|
45
GameServer/Controllers/CombatMessageController.cs
Normal file
45
GameServer/Controllers/CombatMessageController.cs
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
using GameServer.Controllers.Attributes;
|
||||||
|
using GameServer.Controllers.Combat;
|
||||||
|
using GameServer.Network;
|
||||||
|
using GameServer.Network.Messages;
|
||||||
|
using Protocol;
|
||||||
|
|
||||||
|
namespace GameServer.Controllers;
|
||||||
|
internal class CombatMessageController : Controller
|
||||||
|
{
|
||||||
|
public CombatMessageController(PlayerSession session) : base(session)
|
||||||
|
{
|
||||||
|
// CombatMessageController.
|
||||||
|
}
|
||||||
|
|
||||||
|
[NetEvent(MessageId.CombatSendPackRequest)] // TODO: CombatSendPackRequest is important
|
||||||
|
public async Task<RpcResult> OnCombatSendPackRequest(CombatSendPackRequest request, CombatManager combatManager)
|
||||||
|
{
|
||||||
|
CombatReceivePackNotify combatPackNotify = new();
|
||||||
|
|
||||||
|
foreach (CombatSendData sendData in request.Data)
|
||||||
|
{
|
||||||
|
if (sendData.Request != null)
|
||||||
|
{
|
||||||
|
CombatRequestContext context = new(sendData.Request);
|
||||||
|
CombatResponseData? responseData = await combatManager.HandleRequest(context);
|
||||||
|
|
||||||
|
combatPackNotify.Data.AddRange(context.Notifies.Select(notify => new CombatReceiveData
|
||||||
|
{
|
||||||
|
CombatNotifyData = notify
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (responseData != null)
|
||||||
|
{
|
||||||
|
combatPackNotify.Data.Add(new CombatReceiveData
|
||||||
|
{
|
||||||
|
CombatResponseData = responseData
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await Session.Push(MessageId.CombatReceivePackNotify, combatPackNotify);
|
||||||
|
return Response(MessageId.CombatSendPackResponse, new CombatSendPackResponse());
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
using GameServer.Network;
|
global using GameServer.Controllers.Result;
|
||||||
|
using GameServer.Network;
|
||||||
using GameServer.Network.Messages;
|
using GameServer.Network.Messages;
|
||||||
using Google.Protobuf;
|
using Google.Protobuf;
|
||||||
using Protocol;
|
using Protocol;
|
||||||
|
@ -13,9 +14,9 @@ internal abstract class Controller
|
||||||
Session = session;
|
Session = session;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static ResponseMessage Response<TProtoBuf>(MessageId messageId, TProtoBuf protoBuf) where TProtoBuf : IMessage<TProtoBuf> => new()
|
protected static RpcResult Response<TProtoBuf>(MessageId messageId, TProtoBuf protoBuf) where TProtoBuf : IMessage<TProtoBuf> => new(new ResponseMessage
|
||||||
{
|
{
|
||||||
MessageId = messageId,
|
MessageId = messageId,
|
||||||
Payload = protoBuf.ToByteArray()
|
Payload = protoBuf.ToByteArray()
|
||||||
};
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
using GameServer.Controllers.Attributes;
|
using Core.Config;
|
||||||
|
using GameServer.Controllers.Attributes;
|
||||||
|
using GameServer.Extensions.Logic;
|
||||||
using GameServer.Models;
|
using GameServer.Models;
|
||||||
using GameServer.Network;
|
using GameServer.Network;
|
||||||
using GameServer.Network.Messages;
|
using GameServer.Network.Messages;
|
||||||
|
@ -13,22 +15,25 @@ internal class CreatureController : Controller
|
||||||
private readonly EntitySystem _entitySystem;
|
private readonly EntitySystem _entitySystem;
|
||||||
private readonly EntityFactory _entityFactory;
|
private readonly EntityFactory _entityFactory;
|
||||||
private readonly ModelManager _modelManager;
|
private readonly ModelManager _modelManager;
|
||||||
|
private readonly ConfigManager _configManager;
|
||||||
|
|
||||||
public CreatureController(PlayerSession session, EntitySystem entitySystem, EntityFactory entityFactory, ModelManager modelManager) : base(session)
|
public CreatureController(PlayerSession session, EntitySystem entitySystem, EntityFactory entityFactory, ModelManager modelManager, ConfigManager configManager) : base(session)
|
||||||
{
|
{
|
||||||
_entitySystem = entitySystem;
|
_entitySystem = entitySystem;
|
||||||
_entityFactory = entityFactory;
|
_entityFactory = entityFactory;
|
||||||
_modelManager = modelManager;
|
_modelManager = modelManager;
|
||||||
|
_configManager = configManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task JoinScene(int instanceId)
|
public async Task JoinScene(int instanceId)
|
||||||
{
|
{
|
||||||
_modelManager.Creature.SetSceneLoadingData(instanceId);
|
_modelManager.Creature.SetSceneLoadingData(instanceId);
|
||||||
CreateTeamPlayerEntities();
|
CreateTeamPlayerEntities();
|
||||||
|
CreateWorldEntities();
|
||||||
|
|
||||||
await Session.Push(MessageId.JoinSceneNotify, new JoinSceneNotify
|
await Session.Push(MessageId.JoinSceneNotify, new JoinSceneNotify
|
||||||
{
|
{
|
||||||
MaxEntityId = 10000,
|
MaxEntityId = 10000000,
|
||||||
TransitionOption = new TransitionOptionPb
|
TransitionOption = new TransitionOptionPb
|
||||||
{
|
{
|
||||||
TransitionType = (int)TransitionType.Empty
|
TransitionType = (int)TransitionType.Empty
|
||||||
|
@ -38,7 +43,7 @@ internal class CreatureController : Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
[NetEvent(MessageId.EntityActiveRequest)]
|
[NetEvent(MessageId.EntityActiveRequest)]
|
||||||
public async Task<ResponseMessage> OnEntityActiveRequest(EntityActiveRequest request)
|
public async Task<RpcResult> OnEntityActiveRequest(EntityActiveRequest request)
|
||||||
{
|
{
|
||||||
EntityActiveResponse response;
|
EntityActiveResponse response;
|
||||||
|
|
||||||
|
@ -48,7 +53,8 @@ internal class CreatureController : Controller
|
||||||
_entitySystem.Activate(entity);
|
_entitySystem.Activate(entity);
|
||||||
response = new EntityActiveResponse
|
response = new EntityActiveResponse
|
||||||
{
|
{
|
||||||
ErrorCode = (int)ErrorCode.Success
|
ErrorCode = (int)ErrorCode.Success,
|
||||||
|
IsVisible = entity.IsVisible
|
||||||
};
|
};
|
||||||
|
|
||||||
response.ComponentPbs.AddRange(entity.ComponentSystem.Pb);
|
response.ComponentPbs.AddRange(entity.ComponentSystem.Pb);
|
||||||
|
@ -63,13 +69,62 @@ internal class CreatureController : Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
[NetEvent(MessageId.SceneLoadingFinishRequest)]
|
[NetEvent(MessageId.SceneLoadingFinishRequest)]
|
||||||
public ResponseMessage OnSceneLoadingFinishRequest()
|
public async Task<RpcResult> OnSceneLoadingFinishRequest()
|
||||||
{
|
{
|
||||||
_modelManager.Creature.OnWorldDone();
|
_modelManager.Creature.OnWorldDone();
|
||||||
|
await UpdateAiHate();
|
||||||
|
|
||||||
return Response(MessageId.SceneLoadingFinishResponse, new SceneLoadingFinishResponse());
|
return Response(MessageId.SceneLoadingFinishResponse, new SceneLoadingFinishResponse());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[GameEvent(GameEventType.FormationUpdated)]
|
||||||
|
public async Task OnFormationUpdated()
|
||||||
|
{
|
||||||
|
// Remove old entities
|
||||||
|
|
||||||
|
IEnumerable<PlayerEntity> oldEntities = GetPlayerEntities().ToArray();
|
||||||
|
foreach (PlayerEntity oldEntity in oldEntities)
|
||||||
|
{
|
||||||
|
_entitySystem.Destroy(oldEntity);
|
||||||
|
}
|
||||||
|
|
||||||
|
await Session.Push(MessageId.EntityRemoveNotify, new EntityRemoveNotify
|
||||||
|
{
|
||||||
|
IsRemove = true,
|
||||||
|
RemoveInfos =
|
||||||
|
{
|
||||||
|
oldEntities.Select(entity => new EntityRemoveInfo
|
||||||
|
{
|
||||||
|
EntityId = entity.Id,
|
||||||
|
Type = (int)entity.Type
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Spawn new entities
|
||||||
|
|
||||||
|
CreateTeamPlayerEntities();
|
||||||
|
|
||||||
|
IEnumerable<PlayerEntity> newEntities = GetPlayerEntities();
|
||||||
|
await Session.Push(MessageId.EntityAddNotify, new EntityAddNotify
|
||||||
|
{
|
||||||
|
IsAdd = true,
|
||||||
|
EntityPbs =
|
||||||
|
{
|
||||||
|
newEntities.Select(entity => entity.Pb)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
_modelManager.Creature.PlayerEntityId = newEntities.First().Id;
|
||||||
|
await Session.Push(MessageId.UpdatePlayerAllFightRoleNotify, new UpdatePlayerAllFightRoleNotify
|
||||||
|
{
|
||||||
|
PlayerId = _modelManager.Player.Id,
|
||||||
|
FightRoleInfos = { GetFightRoleInfos() }
|
||||||
|
});
|
||||||
|
|
||||||
|
await UpdateAiHate();
|
||||||
|
}
|
||||||
|
|
||||||
[GameEvent(GameEventType.VisionSkillChanged)]
|
[GameEvent(GameEventType.VisionSkillChanged)]
|
||||||
public async Task OnVisionSkillChanged()
|
public async Task OnVisionSkillChanged()
|
||||||
{
|
{
|
||||||
|
@ -86,7 +141,20 @@ internal class CreatureController : Controller
|
||||||
|
|
||||||
public PlayerEntity? GetPlayerEntity()
|
public PlayerEntity? GetPlayerEntity()
|
||||||
{
|
{
|
||||||
return _entitySystem.EnumerateEntities().FirstOrDefault(entity => entity.Id == _modelManager.Creature.PlayerEntityId) as PlayerEntity;
|
return _entitySystem.Get<PlayerEntity>(_modelManager.Creature.PlayerEntityId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PlayerEntity? GetPlayerEntityByRoleId(int roleId)
|
||||||
|
{
|
||||||
|
return _entitySystem.EnumerateEntities()
|
||||||
|
.FirstOrDefault(e => e is PlayerEntity playerEntity && playerEntity.ConfigId == roleId && playerEntity.PlayerId == _modelManager.Player.Id) as PlayerEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<PlayerEntity> GetPlayerEntities()
|
||||||
|
{
|
||||||
|
return _entitySystem.EnumerateEntities()
|
||||||
|
.Where(e => e is PlayerEntity entity && entity.PlayerId == _modelManager.Player.Id)
|
||||||
|
.Cast<PlayerEntity>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task SwitchPlayerEntity(int roleId)
|
public async Task SwitchPlayerEntity(int roleId)
|
||||||
|
@ -96,24 +164,55 @@ internal class CreatureController : Controller
|
||||||
|
|
||||||
prevEntity.IsCurrentRole = false;
|
prevEntity.IsCurrentRole = false;
|
||||||
|
|
||||||
PlayerEntity? newEntity = _entitySystem.EnumerateEntities().FirstOrDefault(e => e is PlayerEntity playerEntity && playerEntity.ConfigId == roleId) as PlayerEntity;
|
if (_entitySystem.EnumerateEntities().FirstOrDefault(e => e is PlayerEntity playerEntity && playerEntity.ConfigId == roleId) is not PlayerEntity newEntity) return;
|
||||||
if (newEntity == null) return;
|
|
||||||
|
|
||||||
_modelManager.Creature.PlayerEntityId = newEntity.Id;
|
_modelManager.Creature.PlayerEntityId = newEntity.Id;
|
||||||
newEntity.IsCurrentRole = true;
|
newEntity.IsCurrentRole = true;
|
||||||
|
|
||||||
await OnVisionSkillChanged();
|
await UpdateAiHate();
|
||||||
}
|
}
|
||||||
|
|
||||||
private SceneInformation CreateSceneInfo()
|
public async Task UpdateAiHate()
|
||||||
{
|
{
|
||||||
SceneInformation scene = new()
|
IEnumerable<EntityBase> monsters = _entitySystem.EnumerateEntities().Where(e => e is MonsterEntity);
|
||||||
|
if (!monsters.Any()) return;
|
||||||
|
|
||||||
|
await Session.Push(MessageId.CombatReceivePackNotify, new CombatReceivePackNotify
|
||||||
|
{
|
||||||
|
Data =
|
||||||
|
{
|
||||||
|
monsters.Select(monster => new CombatReceiveData
|
||||||
|
{
|
||||||
|
CombatNotifyData = new()
|
||||||
|
{
|
||||||
|
CombatCommon = new() { EntityId = monster.Id },
|
||||||
|
AiHateNotify = new()
|
||||||
|
{
|
||||||
|
HateList =
|
||||||
|
{
|
||||||
|
GetPlayerEntities().Select(player => new AiHateEntity
|
||||||
|
{
|
||||||
|
EntityId = player.Id,
|
||||||
|
HatredValue = 99999 // currently this, TODO!
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private SceneInformation CreateSceneInfo() => new()
|
||||||
{
|
{
|
||||||
InstanceId = _modelManager.Creature.InstanceId,
|
InstanceId = _modelManager.Creature.InstanceId,
|
||||||
OwnerId = _modelManager.Creature.OwnerId,
|
OwnerId = _modelManager.Creature.OwnerId,
|
||||||
CurContextId = _modelManager.Player.Id,
|
CurContextId = _modelManager.Player.Id,
|
||||||
TimeInfo = new(),
|
TimeInfo = new(),
|
||||||
AoiData = new(),
|
AoiData = new PlayerSceneAoiData
|
||||||
|
{
|
||||||
|
Entities = { _entitySystem.Pb }
|
||||||
|
},
|
||||||
PlayerInfos =
|
PlayerInfos =
|
||||||
{
|
{
|
||||||
new ScenePlayerInformation
|
new ScenePlayerInformation
|
||||||
|
@ -121,50 +220,86 @@ internal class CreatureController : Controller
|
||||||
PlayerId = _modelManager.Player.Id,
|
PlayerId = _modelManager.Player.Id,
|
||||||
Level = 1,
|
Level = 1,
|
||||||
IsOffline = false,
|
IsOffline = false,
|
||||||
Location = new()
|
Location = _modelManager.Player.Position,
|
||||||
{
|
PlayerName = _modelManager.Player.Name,
|
||||||
X = 4000,
|
FightRoleInfos = { GetFightRoleInfos() }
|
||||||
Y = -2000,
|
|
||||||
Z = 260
|
|
||||||
},
|
|
||||||
PlayerName = _modelManager.Player.Name
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
for (int i = 0; i < _modelManager.Player.Characters.Length; i++)
|
private IEnumerable<FightRoleInformation> GetFightRoleInfos()
|
||||||
{
|
{
|
||||||
scene.PlayerInfos[0].FightRoleInfos.Add(new FightRoleInformation
|
return GetPlayerEntities().Select(playerEntity => new FightRoleInformation
|
||||||
{
|
{
|
||||||
EntityId = i + 1,
|
EntityId = playerEntity.Id,
|
||||||
CurHp = 1000,
|
CurHp = playerEntity.Health,
|
||||||
MaxHp = 1000,
|
MaxHp = playerEntity.HealthMax,
|
||||||
IsControl = i == 0,
|
IsControl = playerEntity.Id == _modelManager.Creature.PlayerEntityId,
|
||||||
RoleId = _modelManager.Player.Characters[i],
|
RoleId = playerEntity.ConfigId,
|
||||||
RoleLevel = 1,
|
RoleLevel = 1,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
scene.AoiData.Entities.AddRange(_entitySystem.Pb);
|
|
||||||
return scene;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CreateTeamPlayerEntities()
|
private void CreateTeamPlayerEntities()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < _modelManager.Player.Characters.Length; i++)
|
for (int i = 0; i < _modelManager.Formation.RoleIds.Length; i++)
|
||||||
{
|
{
|
||||||
PlayerEntity entity = _entityFactory.CreatePlayer(_modelManager.Player.Characters[i], _modelManager.Player.Id);
|
int roleId = _modelManager.Formation.RoleIds[i];
|
||||||
entity.Pos = new()
|
|
||||||
{
|
PlayerEntity entity = _entityFactory.CreatePlayer(roleId, _modelManager.Player.Id);
|
||||||
X = 4000,
|
entity.Pos = _modelManager.Player.Position.Clone();
|
||||||
Y = -2000,
|
|
||||||
Z = 260
|
|
||||||
};
|
|
||||||
entity.IsCurrentRole = i == 0;
|
entity.IsCurrentRole = i == 0;
|
||||||
|
|
||||||
_entitySystem.Create(entity);
|
_entitySystem.Create(entity);
|
||||||
|
entity.ComponentSystem.Get<EntityAttributeComponent>().SetAll(_modelManager.Roles.GetRoleById(roleId)!.GetAttributeList());
|
||||||
|
|
||||||
|
CreateConcomitants(entity);
|
||||||
|
entity.WeaponId = _modelManager.Inventory.GetEquippedWeapon(roleId)?.Id ?? 0;
|
||||||
|
|
||||||
if (i == 0) _modelManager.Creature.PlayerEntityId = entity.Id;
|
if (i == 0) _modelManager.Creature.PlayerEntityId = entity.Id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void CreateConcomitants(PlayerEntity entity)
|
||||||
|
{
|
||||||
|
(int roleId, int summonConfigId) = entity.ConfigId switch
|
||||||
|
{
|
||||||
|
1302 => (5002, 10070301),
|
||||||
|
_ => (-1, -1)
|
||||||
|
};
|
||||||
|
|
||||||
|
if (roleId != -1)
|
||||||
|
{
|
||||||
|
PlayerEntity concomitant = _entityFactory.CreatePlayer(roleId, 0);
|
||||||
|
_entitySystem.Create(concomitant);
|
||||||
|
|
||||||
|
EntityConcomitantsComponent concomitants = entity.ComponentSystem.Get<EntityConcomitantsComponent>();
|
||||||
|
concomitants.CustomEntityIds.Clear();
|
||||||
|
concomitants.CustomEntityIds.Add(concomitant.Id);
|
||||||
|
|
||||||
|
EntitySummonerComponent summoner = concomitant.ComponentSystem.Create<EntitySummonerComponent>();
|
||||||
|
summoner.SummonerId = entity.Id;
|
||||||
|
summoner.SummonConfigId = summonConfigId;
|
||||||
|
summoner.SummonType = ESummonType.ConcomitantCustom;
|
||||||
|
summoner.PlayerId = _modelManager.Player.Id;
|
||||||
|
concomitant.InitProps(_configManager.GetConfig<BasePropertyConfig>(roleId)!);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateWorldEntities()
|
||||||
|
{
|
||||||
|
Vector playerPos = _modelManager.Player.Position;
|
||||||
|
|
||||||
|
// Test monster
|
||||||
|
MonsterEntity monster = _entityFactory.CreateMonster(106003002); // Turtle.
|
||||||
|
monster.Pos = new()
|
||||||
|
{
|
||||||
|
X = playerPos.X + 250,
|
||||||
|
Y = playerPos.Y + 250,
|
||||||
|
Z = playerPos.Z
|
||||||
|
};
|
||||||
|
|
||||||
|
_entitySystem.Create(monster);
|
||||||
|
monster.InitProps(_configManager.GetConfig<BasePropertyConfig>(600000100)!);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,8 +12,8 @@ internal class DailyActivityController : Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
[NetEvent(MessageId.ActivityRequest)]
|
[NetEvent(MessageId.ActivityRequest)]
|
||||||
public ResponseMessage OnActivityRequest() => Response(MessageId.ActivityResponse, new ActivityResponse());
|
public RpcResult OnActivityRequest() => Response(MessageId.ActivityResponse, new ActivityResponse());
|
||||||
|
|
||||||
[NetEvent(MessageId.LivenessRequest)]
|
[NetEvent(MessageId.LivenessRequest)]
|
||||||
public ResponseMessage OnLivenessRequest() => Response(MessageId.LivenessResponse, new LivenessResponse());
|
public RpcResult OnLivenessRequest() => Response(MessageId.LivenessResponse, new LivenessResponse());
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,5 +12,5 @@ internal class ExchangeRewardController : Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
[NetEvent(MessageId.ExchangeRewardInfoRequest)]
|
[NetEvent(MessageId.ExchangeRewardInfoRequest)]
|
||||||
public ResponseMessage OnExchangeRewardInfoRequest() => Response(MessageId.ExchangeRewardInfoResponse, new ExchangeRewardInfoResponse());
|
public RpcResult OnExchangeRewardInfoRequest() => Response(MessageId.ExchangeRewardInfoResponse, new ExchangeRewardInfoResponse());
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ namespace GameServer.Controllers;
|
||||||
internal class ExploreProgressController : Controller
|
internal class ExploreProgressController : Controller
|
||||||
{
|
{
|
||||||
private static readonly int[] s_areaIds = [1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 100, 101, 102, 103, 107, 110, 113, 124, 122, 199, 301, 302, 303, 401, 402, 403, 404, 405, 406, 407, 408, 708, 601, 602, 603, 606, 607, 608, 609, 202, 203, 204, 501, 502, 503, 504, 508, 802, 803, 805, 807, 702, 703, 704, 705, 706, 709, 1201, 1202, 1203, 1204, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1301, 119, 120, 10001, 10002, 10003, 10004, 10005, 11001, 12001, 12002, 12003, 1500001, 1500002, 14001, 14002, 14003, 14004, 14005, 14006, 14007, 14008, 14011, 14012, 14013, 14021, 14022, 123, 125, 51, 804];
|
private static readonly int[] s_areaIds = [1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 100, 101, 102, 103, 107, 110, 113, 124, 122, 199, 301, 302, 303, 401, 402, 403, 404, 405, 406, 407, 408, 708, 601, 602, 603, 606, 607, 608, 609, 202, 203, 204, 501, 502, 503, 504, 508, 802, 803, 805, 807, 702, 703, 704, 705, 706, 709, 1201, 1202, 1203, 1204, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1301, 119, 120, 10001, 10002, 10003, 10004, 10005, 11001, 12001, 12002, 12003, 1500001, 1500002, 14001, 14002, 14003, 14004, 14005, 14006, 14007, 14008, 14011, 14012, 14013, 14021, 14022, 123, 125, 51, 804];
|
||||||
private static readonly (int, int)[] s_exploreIds = [(1, 2), (2, 2), (3, 2), (10, 3), (11, 4), (12, 4), (13, 4), (21, 6), (22, 6), (23, 6), (24, 6), (31, 8), (32, 8), (33, 8), (34, 8), (41, 10), (42, 10), (43, 10), (44, 10), (51, 12), (52, 12), (53, 12), (54, 12), (6, 3), (7, 3), (8, 3), (9, 3), (14, 4), (15, 4), (16, 5), (17, 5), (18, 5), (19, 5), (25, 6), (26, 7), (27, 7), (28, 7), (29, 7), (45, 10), (55, 12), (4, 2), (5, 2), (20, 5), (30, 7), (35, 8)];
|
private static readonly (int, int)[] s_exploreIds = [(1, 2), (2, 2), (3, 2), (11, 4), (12, 4), (13, 4), (21, 6), (22, 6), (23, 6), (24, 6), (31, 8), (32, 8), (33, 8), (34, 8), (41, 10), (42, 10), (43, 10), (44, 10), (51, 12), (52, 12), (53, 12), (54, 12), (6, 3), (7, 3), (8, 3), (9, 3), (14, 4), (15, 4), (16, 5), (17, 5), (18, 5), (19, 5), (25, 6), (26, 7), (27, 7), (28, 7), (29, 7), (45, 10), (55, 12), (4, 2), (5, 2), (20, 5), (30, 7), (35, 8)];
|
||||||
|
|
||||||
public ExploreProgressController(PlayerSession session) : base(session)
|
public ExploreProgressController(PlayerSession session) : base(session)
|
||||||
{
|
{
|
||||||
|
@ -15,7 +15,7 @@ internal class ExploreProgressController : Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
[NetEvent(MessageId.ExploreProgressRequest)]
|
[NetEvent(MessageId.ExploreProgressRequest)]
|
||||||
public ResponseMessage OnExploreProgressRequest()
|
public RpcResult OnExploreProgressRequest()
|
||||||
{
|
{
|
||||||
return Response(MessageId.ExploreProgressResponse, new ExploreProgressResponse
|
return Response(MessageId.ExploreProgressResponse, new ExploreProgressResponse
|
||||||
{
|
{
|
||||||
|
|
|
@ -90,13 +90,13 @@ internal class EventHandlerFactory
|
||||||
var builder = ImmutableDictionary.CreateBuilder<MessageId, RpcHandler>();
|
var builder = ImmutableDictionary.CreateBuilder<MessageId, RpcHandler>();
|
||||||
|
|
||||||
MethodInfo getServiceMethod = typeof(ServiceProviderServiceExtensions).GetMethod(nameof(ServiceProviderServiceExtensions.GetRequiredService), [typeof(IServiceProvider)])!;
|
MethodInfo getServiceMethod = typeof(ServiceProviderServiceExtensions).GetMethod(nameof(ServiceProviderServiceExtensions.GetRequiredService), [typeof(IServiceProvider)])!;
|
||||||
MethodInfo taskFromResultMethod = typeof(Task).GetMethod(nameof(Task.FromResult))!.MakeGenericMethod(typeof(ResponseMessage));
|
MethodInfo taskFromResultMethod = typeof(Task).GetMethod(nameof(Task.FromResult))!.MakeGenericMethod(typeof(RpcResult));
|
||||||
|
|
||||||
foreach (Type type in controllerTypes)
|
foreach (Type type in controllerTypes)
|
||||||
{
|
{
|
||||||
IEnumerable<MethodInfo> methods = type.GetMethods()
|
IEnumerable<MethodInfo> methods = type.GetMethods()
|
||||||
.Where(method => method.GetCustomAttribute<NetEventAttribute>() != null
|
.Where(method => method.GetCustomAttribute<NetEventAttribute>() != null
|
||||||
&& (method.ReturnType == typeof(Task<ResponseMessage>) || method.ReturnType == typeof(ResponseMessage)));
|
&& (method.ReturnType == typeof(Task<RpcResult>) || method.ReturnType == typeof(RpcResult)));
|
||||||
|
|
||||||
foreach (MethodInfo method in methods)
|
foreach (MethodInfo method in methods)
|
||||||
{
|
{
|
||||||
|
@ -108,7 +108,7 @@ internal class EventHandlerFactory
|
||||||
MethodCallExpression getServiceCall = Expression.Call(getServiceMethod.MakeGenericMethod(type), serviceProviderParam);
|
MethodCallExpression getServiceCall = Expression.Call(getServiceMethod.MakeGenericMethod(type), serviceProviderParam);
|
||||||
Expression handlerCall = Expression.Call(getServiceCall, method, FetchArgumentsForMethod(method, serviceProviderParam, getServiceMethod, dataParam));
|
Expression handlerCall = Expression.Call(getServiceCall, method, FetchArgumentsForMethod(method, serviceProviderParam, getServiceMethod, dataParam));
|
||||||
|
|
||||||
if (method.ReturnType == typeof(ResponseMessage)) // Allow non-async methods as well
|
if (method.ReturnType == typeof(RpcResult)) // Allow non-async methods as well
|
||||||
handlerCall = Expression.Call(taskFromResultMethod, handlerCall);
|
handlerCall = Expression.Call(taskFromResultMethod, handlerCall);
|
||||||
|
|
||||||
Expression<RpcHandler> lambda = Expression.Lambda<RpcHandler>(handlerCall, serviceProviderParam, dataParam);
|
Expression<RpcHandler> lambda = Expression.Lambda<RpcHandler>(handlerCall, serviceProviderParam, dataParam);
|
||||||
|
|
19
GameServer/Controllers/FormationAttributeController.cs
Normal file
19
GameServer/Controllers/FormationAttributeController.cs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
using GameServer.Controllers.Attributes;
|
||||||
|
using GameServer.Network;
|
||||||
|
using GameServer.Network.Messages;
|
||||||
|
using Protocol;
|
||||||
|
|
||||||
|
namespace GameServer.Controllers;
|
||||||
|
internal class FormationAttributeController : Controller
|
||||||
|
{
|
||||||
|
public FormationAttributeController(PlayerSession session) : base(session)
|
||||||
|
{
|
||||||
|
// FormationAttributeController.
|
||||||
|
}
|
||||||
|
|
||||||
|
[NetEvent(MessageId.TimeCheckRequest)]
|
||||||
|
public RpcResult OnTimeCheckRequest() => Response(MessageId.TimeCheckResponse, new TimeCheckResponse());
|
||||||
|
|
||||||
|
[NetEvent(MessageId.FormationAttrRequest)]
|
||||||
|
public RpcResult OnFormationAttrRequest() => Response(MessageId.FormationAttrResponse, new FormationAttrResponse());
|
||||||
|
}
|
|
@ -2,6 +2,8 @@
|
||||||
using GameServer.Models;
|
using GameServer.Models;
|
||||||
using GameServer.Network;
|
using GameServer.Network;
|
||||||
using GameServer.Network.Messages;
|
using GameServer.Network.Messages;
|
||||||
|
using GameServer.Systems.Entity;
|
||||||
|
using GameServer.Systems.Event;
|
||||||
using Protocol;
|
using Protocol;
|
||||||
|
|
||||||
namespace GameServer.Controllers;
|
namespace GameServer.Controllers;
|
||||||
|
@ -15,20 +17,29 @@ internal class FormationController : Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
[NetEvent(MessageId.GetFormationDataRequest)]
|
[NetEvent(MessageId.GetFormationDataRequest)]
|
||||||
public ResponseMessage OnGetFormationDataRequest() => Response(MessageId.GetFormationDataResponse, new GetFormationDataResponse
|
public RpcResult OnGetFormationDataRequest() => Response(MessageId.GetFormationDataResponse, new GetFormationDataResponse
|
||||||
{
|
{
|
||||||
Formations =
|
Formations =
|
||||||
{
|
{
|
||||||
new FightFormation
|
new FightFormation
|
||||||
{
|
{
|
||||||
CurRole = _modelManager.Player.Characters[0],
|
CurRole = _modelManager.Formation.RoleIds[0],
|
||||||
FormationId = 1,
|
FormationId = 1,
|
||||||
IsCurrent = true,
|
IsCurrent = true,
|
||||||
RoleIds = { _modelManager.Player.Characters },
|
RoleIds = { _modelManager.Formation.RoleIds },
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
[NetEvent(MessageId.FormationAttrRequest)]
|
[NetEvent(MessageId.UpdateFormationRequest)]
|
||||||
public ResponseMessage OnFormationAttrRequest() => Response(MessageId.FormationAttrResponse, new FormationAttrResponse());
|
public async Task<RpcResult> OnUpdateFormationRequest(UpdateFormationRequest request, EventSystem eventSystem)
|
||||||
|
{
|
||||||
|
_modelManager.Formation.Set([.. request.Formation.RoleIds]);
|
||||||
|
await eventSystem.Emit(GameEventType.FormationUpdated);
|
||||||
|
|
||||||
|
return Response(MessageId.UpdateFormationResponse, new UpdateFormationResponse
|
||||||
|
{
|
||||||
|
Formation = request.Formation
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,5 +12,25 @@ internal class FriendSystemController : Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
[NetEvent(MessageId.FriendAllRequest)]
|
[NetEvent(MessageId.FriendAllRequest)]
|
||||||
public ResponseMessage OnFriendAllRequest() => Response(MessageId.FriendAllResponse, new FriendAllResponse());
|
public RpcResult OnFriendAllRequest() => Response(MessageId.FriendAllResponse, new FriendAllResponse
|
||||||
|
{
|
||||||
|
FriendInfoList =
|
||||||
|
{
|
||||||
|
CreateDummyFriendInfo(1338, "Yangyang", "discord.gg/reversedrooms", 1402)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
private static FriendInfo CreateDummyFriendInfo(int id, string name, string signature, int headIconId) => new()
|
||||||
|
{
|
||||||
|
Info = new()
|
||||||
|
{
|
||||||
|
PlayerId = id,
|
||||||
|
Name = name,
|
||||||
|
Signature = signature,
|
||||||
|
Level = 5,
|
||||||
|
HeadId = headIconId,
|
||||||
|
IsOnline = true,
|
||||||
|
LastOfflineTime = -1
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,5 +12,5 @@ internal class GachaController : Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
[NetEvent(MessageId.GachaInfoRequest)]
|
[NetEvent(MessageId.GachaInfoRequest)]
|
||||||
public ResponseMessage OnGachaInfoRequest() => Response(MessageId.GachaInfoResponse, new GachaInfoResponse());
|
public RpcResult OnGachaInfoRequest() => Response(MessageId.GachaInfoResponse, new GachaInfoResponse());
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,5 +12,5 @@ internal class InfluenceReputationController : Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
[NetEvent(MessageId.InfluenceInfoRequest)]
|
[NetEvent(MessageId.InfluenceInfoRequest)]
|
||||||
public ResponseMessage OnInfluenceInfoRequest() => Response(MessageId.InfluenceInfoResponse, new InfluenceInfoResponse());
|
public RpcResult OnInfluenceInfoRequest() => Response(MessageId.InfluenceInfoResponse, new InfluenceInfoResponse());
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
using GameServer.Controllers.Attributes;
|
using Core.Config;
|
||||||
|
using GameServer.Controllers.Attributes;
|
||||||
|
using GameServer.Extensions.Logic;
|
||||||
|
using GameServer.Models;
|
||||||
using GameServer.Network;
|
using GameServer.Network;
|
||||||
using GameServer.Network.Messages;
|
using GameServer.Systems.Entity;
|
||||||
|
using GameServer.Systems.Entity.Component;
|
||||||
|
using GameServer.Systems.Event;
|
||||||
using Protocol;
|
using Protocol;
|
||||||
|
|
||||||
namespace GameServer.Controllers;
|
namespace GameServer.Controllers;
|
||||||
|
@ -12,14 +17,120 @@ internal class InventoryController : Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
[NetEvent(MessageId.NormalItemRequest)]
|
[NetEvent(MessageId.NormalItemRequest)]
|
||||||
public ResponseMessage OnNormalItemRequest() => Response(MessageId.NormalItemResponse, new NormalItemResponse());
|
public RpcResult OnNormalItemRequest() => Response(MessageId.NormalItemResponse, new NormalItemResponse());
|
||||||
|
|
||||||
[NetEvent(MessageId.WeaponItemRequest)]
|
[NetEvent(MessageId.WeaponItemRequest)]
|
||||||
public ResponseMessage OnWeaponItemRequest() => Response(MessageId.WeaponItemResponse, new WeaponItemResponse());
|
public RpcResult OnWeaponItemRequest(ModelManager modelManager) => Response(MessageId.WeaponItemResponse, new WeaponItemResponse
|
||||||
|
{
|
||||||
|
WeaponItemList =
|
||||||
|
{
|
||||||
|
modelManager.Inventory.WeaponList
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
[NetEvent(MessageId.PhantomItemRequest)]
|
[NetEvent(MessageId.PhantomItemRequest)]
|
||||||
public ResponseMessage OnPhantomItemRequest() => Response(MessageId.PhantomItemResponse, new PhantomItemResponse());
|
public RpcResult OnPhantomItemRequest() => Response(MessageId.PhantomItemResponse, new PhantomItemResponse());
|
||||||
|
|
||||||
[NetEvent(MessageId.ItemExchangeInfoRequest)]
|
[NetEvent(MessageId.ItemExchangeInfoRequest)]
|
||||||
public ResponseMessage OnItemExchangeInfoRequest() => Response(MessageId.ItemExchangeInfoResponse, new ItemExchangeInfoResponse());
|
public RpcResult OnItemExchangeInfoRequest() => Response(MessageId.ItemExchangeInfoResponse, new ItemExchangeInfoResponse());
|
||||||
|
|
||||||
|
[NetEvent(MessageId.EquipTakeOnRequest)]
|
||||||
|
public async Task<RpcResult> OnEquipTakeOnRequest(EquipTakeOnRequest request, ModelManager modelManager, CreatureController creatureController, ConfigManager configManager)
|
||||||
|
{
|
||||||
|
WeaponItem? weapon = modelManager.Inventory.GetWeaponById(request.Data.EquipIncId);
|
||||||
|
if (weapon == null) return Response(MessageId.EquipTakeOnResponse, new EquipTakeOnResponse
|
||||||
|
{
|
||||||
|
ErrorCode = (int)ErrorCode.ErrItemIdInvaild
|
||||||
|
});
|
||||||
|
|
||||||
|
WeaponConfig weaponConf = configManager.GetConfig<WeaponConfig>(weapon.Id)!;
|
||||||
|
|
||||||
|
roleInfo? role = modelManager.Roles.GetRoleById(request.Data.RoleId);
|
||||||
|
if (role == null) return Response(MessageId.EquipTakeOnResponse, new EquipTakeOnResponse
|
||||||
|
{
|
||||||
|
ErrorCode = (int)ErrorCode.NotValidRole
|
||||||
|
});
|
||||||
|
|
||||||
|
// Take off previous weapon
|
||||||
|
WeaponItem? prevWeapon = modelManager.Inventory.WeaponList.SingleOrDefault(weapon => weapon.RoleId == role.RoleId);
|
||||||
|
if (prevWeapon != null) prevWeapon.RoleId = 0;
|
||||||
|
|
||||||
|
// Set new weapon
|
||||||
|
weapon.RoleId = role.RoleId;
|
||||||
|
role.ApplyWeaponProperties(weaponConf);
|
||||||
|
|
||||||
|
// Update role prop data on client
|
||||||
|
await Session.Push(MessageId.PbRolePropsNotify, new PbRolePropsNotify
|
||||||
|
{
|
||||||
|
RoleId = role.RoleId,
|
||||||
|
BaseProp = { role.BaseProp },
|
||||||
|
AddProp = { role.AddProp }
|
||||||
|
});
|
||||||
|
|
||||||
|
PlayerEntity? entity = creatureController.GetPlayerEntityByRoleId(request.Data.RoleId);
|
||||||
|
if (entity != null)
|
||||||
|
{
|
||||||
|
// Update entity equipment
|
||||||
|
EntityEquipComponent equipComponent = entity.ComponentSystem.Get<EntityEquipComponent>();
|
||||||
|
equipComponent.WeaponId = weapon.Id;
|
||||||
|
|
||||||
|
await Session.Push(MessageId.EntityEquipChangeNotify, new EntityEquipChangeNotify
|
||||||
|
{
|
||||||
|
EntityId = entity.Id,
|
||||||
|
EquipComponent = equipComponent.Pb.EquipComponent
|
||||||
|
});
|
||||||
|
|
||||||
|
// Update entity gameplay attributes
|
||||||
|
EntityAttributeComponent attrComponent = entity.ComponentSystem.Get<EntityAttributeComponent>();
|
||||||
|
attrComponent.SetAll(role.GetAttributeList());
|
||||||
|
|
||||||
|
await Session.Push(MessageId.AttributeChangedNotify, new AttributeChangedNotify
|
||||||
|
{
|
||||||
|
Id = entity.Id,
|
||||||
|
Attributes = { attrComponent.Pb.AttributeComponent.GameAttributes }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Response
|
||||||
|
EquipTakeOnResponse response = new()
|
||||||
|
{
|
||||||
|
DataList =
|
||||||
|
{
|
||||||
|
new RoleLoadEquipData
|
||||||
|
{
|
||||||
|
RoleId = request.Data.RoleId,
|
||||||
|
Pos = request.Data.Pos,
|
||||||
|
EquipIncId = request.Data.EquipIncId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (prevWeapon != null)
|
||||||
|
{
|
||||||
|
response.DataList.Add(new RoleLoadEquipData
|
||||||
|
{
|
||||||
|
EquipIncId = prevWeapon.IncrId
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return Response(MessageId.EquipTakeOnResponse, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
[GameEvent(GameEventType.EnterGame)]
|
||||||
|
public async Task OnEnterGame()
|
||||||
|
{
|
||||||
|
await Session.Push(MessageId.ItemPkgOpenNotify, new ItemPkgOpenNotify
|
||||||
|
{
|
||||||
|
OpenPkg = { 0, 2, 1, 3, 4, 5, 6, 7 }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[GameEvent(GameEventType.DebugUnlockAllWeapons)]
|
||||||
|
public void DebugUnlockAllWeapons(ConfigManager configManager, ModelManager modelManager)
|
||||||
|
{
|
||||||
|
foreach (WeaponConfig weaponConf in configManager.Enumerate<WeaponConfig>())
|
||||||
|
{
|
||||||
|
modelManager.Inventory.AddNewWeapon(weaponConf.ItemId);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
using GameServer.Controllers.Attributes;
|
using GameServer.Controllers.Attributes;
|
||||||
using GameServer.Network;
|
using GameServer.Network;
|
||||||
using GameServer.Network.Messages;
|
|
||||||
using GameServer.Systems.Event;
|
using GameServer.Systems.Event;
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using Protocol;
|
using Protocol;
|
||||||
|
|
||||||
namespace GameServer.Controllers;
|
namespace GameServer.Controllers;
|
||||||
|
@ -14,29 +12,36 @@ internal class LoginController : Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
[NetEvent(MessageId.LoginRequest)]
|
[NetEvent(MessageId.LoginRequest)]
|
||||||
public async Task<ResponseMessage> OnLoginRequest(EventSystem eventSystem)
|
public async Task<RpcResult> OnLoginRequest(EventSystem eventSystem)
|
||||||
{
|
{
|
||||||
await eventSystem.Emit(GameEventType.Login);
|
await eventSystem.Emit(GameEventType.Login);
|
||||||
|
|
||||||
|
// Debug
|
||||||
|
await eventSystem.Emit(GameEventType.DebugUnlockAllRoles);
|
||||||
|
await eventSystem.Emit(GameEventType.DebugUnlockAllWeapons);
|
||||||
|
|
||||||
return Response(MessageId.LoginResponse, new LoginResponse
|
return Response(MessageId.LoginResponse, new LoginResponse
|
||||||
{
|
{
|
||||||
Code = 0,
|
Code = 0,
|
||||||
Platform = "PC",
|
Platform = "CBT3_EU",
|
||||||
Timestamp = DateTimeOffset.Now.ToUnixTimeSeconds()
|
Timestamp = DateTimeOffset.Now.ToUnixTimeSeconds()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
[NetEvent(MessageId.EnterGameRequest)]
|
[NetEvent(MessageId.EnterGameRequest)]
|
||||||
public async Task<ResponseMessage> OnEnterGameRequest(EnterGameRequest request, ILogger<LoginController> logger, EventSystem eventSystem)
|
public RpcResult OnEnterGameRequest()
|
||||||
{
|
{
|
||||||
logger.LogInformation("Enter Game Request:\n{req}", request);
|
return Response(MessageId.EnterGameResponse, new EnterGameResponse())
|
||||||
|
.AddPostEvent(GameEventType.EnterGame)
|
||||||
|
.AddPostEvent(GameEventType.PushDataDone);
|
||||||
|
}
|
||||||
|
|
||||||
await eventSystem.Emit(GameEventType.EnterGame);
|
[GameEvent(GameEventType.PushDataDone)]
|
||||||
|
public async Task OnPushDataDone()
|
||||||
|
{
|
||||||
await Session.Push(MessageId.PushDataCompleteNotify, new PushDataCompleteNotify());
|
await Session.Push(MessageId.PushDataCompleteNotify, new PushDataCompleteNotify());
|
||||||
|
|
||||||
return Response(MessageId.EnterGameResponse, new EnterGameResponse());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[NetEvent(MessageId.HeartbeatRequest)]
|
[NetEvent(MessageId.HeartbeatRequest)]
|
||||||
public ResponseMessage OnHeartbeatRequest() => Response(MessageId.HeartbeatResponse, new HeartbeatResponse());
|
public RpcResult OnHeartbeatRequest() => Response(MessageId.HeartbeatResponse, new HeartbeatResponse());
|
||||||
}
|
}
|
|
@ -12,5 +12,5 @@ internal class LordGymController : Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
[NetEvent(MessageId.LordGymInfoRequest)]
|
[NetEvent(MessageId.LordGymInfoRequest)]
|
||||||
public ResponseMessage OnLordGymInfoRequest() => Response(MessageId.LordGymInfoResponse, new LordGymInfoResponse());
|
public RpcResult OnLordGymInfoRequest() => Response(MessageId.LordGymInfoResponse, new LordGymInfoResponse());
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using GameServer.Controllers.Attributes;
|
using GameServer.Controllers.Attributes;
|
||||||
using GameServer.Models;
|
using GameServer.Models;
|
||||||
using GameServer.Network;
|
using GameServer.Network;
|
||||||
|
using GameServer.Network.Messages;
|
||||||
using GameServer.Systems.Event;
|
using GameServer.Systems.Event;
|
||||||
using Protocol;
|
using Protocol;
|
||||||
|
|
||||||
|
@ -40,26 +41,58 @@ internal class PlayerInfoController : Controller
|
||||||
{
|
{
|
||||||
Key = (int)PlayerAttrKey.HeadPhoto,
|
Key = (int)PlayerAttrKey.HeadPhoto,
|
||||||
ValueType = (int)PlayerAttrType.Int32,
|
ValueType = (int)PlayerAttrType.Int32,
|
||||||
Int32Value = 1601
|
Int32Value = 1402
|
||||||
},
|
},
|
||||||
new PlayerAttr
|
new PlayerAttr
|
||||||
{
|
{
|
||||||
Key = (int)PlayerAttrKey.HeadFrame,
|
Key = (int)PlayerAttrKey.HeadFrame,
|
||||||
ValueType = (int)PlayerAttrType.Int32,
|
ValueType = (int)PlayerAttrType.Int32,
|
||||||
Int32Value = 80060009
|
Int32Value = 80060009
|
||||||
|
},
|
||||||
|
new PlayerAttr
|
||||||
|
{
|
||||||
|
Key = (int)PlayerAttrKey.Sex,
|
||||||
|
ValueType = (int)PlayerAttrType.Int32,
|
||||||
|
Int32Value = 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
RoleShowList =
|
||||||
|
{
|
||||||
|
new RoleShowEntry
|
||||||
|
{
|
||||||
|
Level = 1,
|
||||||
|
RoleId = 1501 // Rover
|
||||||
|
}
|
||||||
|
},
|
||||||
|
CurCardId = 80060000,
|
||||||
|
CardUnlockList =
|
||||||
|
{
|
||||||
|
new CardShowEntry
|
||||||
|
{
|
||||||
|
CardId = 80060000,
|
||||||
|
IsRead = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
for (int i = 0; i < player.Characters.Length; i++)
|
|
||||||
{
|
|
||||||
basicInfo.RoleShowList.Add(new RoleShowEntry
|
|
||||||
{
|
|
||||||
Level = 1,
|
|
||||||
RoleId = player.Characters[i]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
await Session.Push(MessageId.BasicInfoNotify, basicInfo);
|
await Session.Push(MessageId.BasicInfoNotify, basicInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[NetEvent(MessageId.PlayerBasicInfoGetRequest)]
|
||||||
|
public RpcResult OnPlayerBasicInfoGetRequest()
|
||||||
|
{
|
||||||
|
return Response(MessageId.PlayerBasicInfoGetResponse, new PlayerBasicInfoGetResponse
|
||||||
|
{
|
||||||
|
Info = new PlayerDetails
|
||||||
|
{
|
||||||
|
Name = "Yangyang",
|
||||||
|
Signature = "discord.gg/reversedrooms",
|
||||||
|
HeadId = 1402,
|
||||||
|
PlayerId = 1338,
|
||||||
|
IsOnline = true,
|
||||||
|
LastOfflineTime = -1,
|
||||||
|
Level = 5
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
21
GameServer/Controllers/Result/RpcResult.cs
Normal file
21
GameServer/Controllers/Result/RpcResult.cs
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
using GameServer.Network.Messages;
|
||||||
|
using GameServer.Systems.Event;
|
||||||
|
|
||||||
|
namespace GameServer.Controllers.Result;
|
||||||
|
internal class RpcResult
|
||||||
|
{
|
||||||
|
public ResponseMessage Response { get; }
|
||||||
|
public List<GameEventType> PostEvents { get; }
|
||||||
|
|
||||||
|
public RpcResult(ResponseMessage response)
|
||||||
|
{
|
||||||
|
Response = response;
|
||||||
|
PostEvents = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public RpcResult AddPostEvent(GameEventType type)
|
||||||
|
{
|
||||||
|
PostEvents.Add(type);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,5 +12,5 @@ internal class RoguelikeController : Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
[NetEvent(MessageId.RoguelikeSeasonDataRequest)]
|
[NetEvent(MessageId.RoguelikeSeasonDataRequest)]
|
||||||
public ResponseMessage OnRoguelikeSeasonDataRequest() => Response(MessageId.RoguelikeSeasonDataResponse, new RoguelikeSeasonDataResponse());
|
public RpcResult OnRoguelikeSeasonDataRequest() => Response(MessageId.RoguelikeSeasonDataResponse, new RoguelikeSeasonDataResponse());
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
using GameServer.Controllers.Attributes;
|
using Core.Config;
|
||||||
|
using GameServer.Controllers.Attributes;
|
||||||
|
using GameServer.Extensions.Logic;
|
||||||
using GameServer.Models;
|
using GameServer.Models;
|
||||||
using GameServer.Network;
|
using GameServer.Network;
|
||||||
using GameServer.Network.Messages;
|
|
||||||
using GameServer.Systems.Event;
|
using GameServer.Systems.Event;
|
||||||
using Protocol;
|
using Protocol;
|
||||||
|
|
||||||
|
@ -13,27 +14,37 @@ internal class RoleController : Controller
|
||||||
// RoleController.
|
// RoleController.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[GameEvent(GameEventType.DebugUnlockAllRoles)]
|
||||||
|
public void UnlockAllRoles(ConfigManager configManager, ModelManager modelManager)
|
||||||
|
{
|
||||||
|
foreach (RoleInfoConfig roleConfig in configManager.Enumerate<RoleInfoConfig>())
|
||||||
|
{
|
||||||
|
roleInfo role = modelManager.Roles.Create(roleConfig.Id);
|
||||||
|
role.BaseProp.AddRange(CreateBasePropList(configManager.GetConfig<BasePropertyConfig>(roleConfig.Id)));
|
||||||
|
|
||||||
|
WeaponItem weapon = modelManager.Inventory.AddNewWeapon(roleConfig.InitWeaponItemId);
|
||||||
|
weapon.RoleId = role.RoleId;
|
||||||
|
|
||||||
|
role.ApplyWeaponProperties(configManager.GetConfig<WeaponConfig>(weapon.Id)!);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[GameEvent(GameEventType.EnterGame)]
|
[GameEvent(GameEventType.EnterGame)]
|
||||||
public async Task OnEnterGame(ModelManager modelManager)
|
public async Task OnEnterGame(ModelManager modelManager)
|
||||||
{
|
{
|
||||||
PlayerModel player = modelManager.Player;
|
|
||||||
|
|
||||||
await Session.Push(MessageId.PbGetRoleListNotify, new PbGetRoleListNotify
|
await Session.Push(MessageId.PbGetRoleListNotify, new PbGetRoleListNotify
|
||||||
{
|
{
|
||||||
RoleList =
|
RoleList =
|
||||||
{
|
{
|
||||||
player.Characters.Select(i => new roleInfo
|
modelManager.Roles.Roles
|
||||||
{
|
|
||||||
RoleId = i,
|
|
||||||
Level = 1
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
[NetEvent(MessageId.SwitchRoleRequest)]
|
[NetEvent(MessageId.SwitchRoleRequest)]
|
||||||
public ResponseMessage OnSwitchRoleRequest(SwitchRoleRequest request)
|
public async Task<RpcResult> OnSwitchRoleRequest(SwitchRoleRequest request, CreatureController creatureController)
|
||||||
{
|
{
|
||||||
|
await creatureController.SwitchPlayerEntity(request.RoleId);
|
||||||
return Response(MessageId.SwitchRoleResponse, new SwitchRoleResponse
|
return Response(MessageId.SwitchRoleResponse, new SwitchRoleResponse
|
||||||
{
|
{
|
||||||
RoleId = request.RoleId
|
RoleId = request.RoleId
|
||||||
|
@ -41,5 +52,150 @@ internal class RoleController : Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
[NetEvent(MessageId.RoleFavorListRequest)]
|
[NetEvent(MessageId.RoleFavorListRequest)]
|
||||||
public ResponseMessage OnRoleFavorListRequest() => Response(MessageId.RoleFavorListResponse, new RoleFavorListResponse());
|
public RpcResult OnRoleFavorListRequest() => Response(MessageId.RoleFavorListResponse, new RoleFavorListResponse());
|
||||||
|
|
||||||
|
private static List<ArrayIntInt> CreateBasePropList(BasePropertyConfig? config)
|
||||||
|
{
|
||||||
|
List<ArrayIntInt> baseProp = [];
|
||||||
|
if (config == null) return baseProp;
|
||||||
|
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.Lv, Value = config.Lv });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.LifeMax, Value = config.LifeMax });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.Life, Value = config.Life });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.Sheild, Value = config.Sheild });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.SheildDamageChange, Value = config.SheildDamageChange });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.SheildDamageReduce, Value = config.SheildDamageReduce });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.Atk, Value = config.Atk });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.Crit, Value = config.Crit });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.CritDamage, Value = config.CritDamage });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.Def, Value = config.Def });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.EnergyEfficiency, Value = config.EnergyEfficiency });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.CdReduse, Value = config.CdReduse });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ReactionEfficiency, Value = config.ReactionEfficiency });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageChangeNormalSkill, Value = config.DamageChangeNormalSkill });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageChange, Value = config.DamageChange });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageReduce, Value = config.DamageReduce });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageChangeAuto, Value = config.DamageChangeAuto });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageChangeCast, Value = config.DamageChangeCast });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageChangeUltra, Value = config.DamageChangeUltra });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageChangeQte, Value = config.DamageChangeQte });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageChangePhys, Value = config.DamageChangePhys });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageChangeElement1, Value = config.DamageChangeElement1 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageChangeElement2, Value = config.DamageChangeElement2 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageChangeElement3, Value = config.DamageChangeElement3 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageChangeElement4, Value = config.DamageChangeElement4 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageChangeElement5, Value = config.DamageChangeElement5 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageChangeElement6, Value = config.DamageChangeElement6 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageResistancePhys, Value = config.DamageResistancePhys });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageResistanceElement1, Value = config.DamageResistanceElement1 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageResistanceElement2, Value = config.DamageResistanceElement2 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageResistanceElement3, Value = config.DamageResistanceElement3 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageResistanceElement4, Value = config.DamageResistanceElement4 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageResistanceElement5, Value = config.DamageResistanceElement5 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageResistanceElement6, Value = config.DamageResistanceElement6 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.HealChange, Value = config.HealChange });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.HealedChange, Value = config.HealedChange });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageReducePhys, Value = config.DamageReducePhys });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageReduceElement1, Value = config.DamageReduceElement1 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageReduceElement2, Value = config.DamageReduceElement2 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageReduceElement3, Value = config.DamageReduceElement3 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageReduceElement4, Value = config.DamageReduceElement4 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageReduceElement5, Value = config.DamageReduceElement5 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageReduceElement6, Value = config.DamageReduceElement6 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ReactionChange1, Value = config.ReactionChange1 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ReactionChange2, Value = config.ReactionChange2 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ReactionChange3, Value = config.ReactionChange3 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ReactionChange4, Value = config.ReactionChange4 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ReactionChange5, Value = config.ReactionChange5 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ReactionChange6, Value = config.ReactionChange6 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ReactionChange7, Value = config.ReactionChange7 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ReactionChange8, Value = config.ReactionChange8 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ReactionChange9, Value = config.ReactionChange9 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ReactionChange10, Value = config.ReactionChange10 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ReactionChange11, Value = config.ReactionChange11 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ReactionChange12, Value = config.ReactionChange12 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ReactionChange13, Value = config.ReactionChange13 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ReactionChange14, Value = config.ReactionChange14 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ReactionChange15, Value = config.ReactionChange15 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.EnergyMax, Value = config.EnergyMax });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.Energy, Value = config.Energy });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.SpecialEnergy1Max, Value = config.SpecialEnergy1Max });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.SpecialEnergy1, Value = config.SpecialEnergy1 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.SpecialEnergy2Max, Value = config.SpecialEnergy2Max });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.SpecialEnergy2, Value = config.SpecialEnergy2 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.SpecialEnergy3Max, Value = config.SpecialEnergy3Max });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.SpecialEnergy3, Value = config.SpecialEnergy3 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.SpecialEnergy4Max, Value = config.SpecialEnergy4Max });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.SpecialEnergy4, Value = config.SpecialEnergy4 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.StrengthMax, Value = config.StrengthMax });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.Strength, Value = config.Strength });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.StrengthRecover, Value = config.StrengthRecover });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.StrengthPunishTime, Value = config.StrengthPunishTime });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.StrengthRun, Value = config.StrengthRun });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.StrengthSwim, Value = config.StrengthSwim });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.StrengthFastSwim, Value = config.StrengthFastSwim });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.StrengthClimb, Value = config.StrengthClimb });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.StrengthFastClimb, Value = config.StrengthFastClimb });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.HardnessMax, Value = config.HardnessMax });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.Hardness, Value = config.Hardness });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.HardnessRecover, Value = config.HardnessRecover });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.HardnessPunishTime, Value = config.HardnessPunishTime });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.HardnessChange, Value = config.HardnessChange });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.HardnessReduce, Value = config.HardnessReduce });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.RageMax, Value = config.RageMax });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.Rage, Value = config.Rage });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.RageRecover, Value = config.RageRecover });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.RagePunishTime, Value = config.RagePunishTime });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.RageChange, Value = config.RageChange });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.RageReduce, Value = config.RageReduce });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ToughMax, Value = config.ToughMax });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.Tough, Value = config.Tough });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ToughRecover, Value = config.ToughRecover });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ToughChange, Value = config.ToughChange });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ToughReduce, Value = config.ToughReduce });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ToughRecoverDelayTime, Value = config.ToughRecoverDelayTime });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ElementPower1, Value = config.ElementPower1 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ElementPower2, Value = config.ElementPower2 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ElementPower3, Value = config.ElementPower3 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ElementPower4, Value = config.ElementPower4 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ElementPower5, Value = config.ElementPower5 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ElementPower6, Value = config.ElementPower6 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.SpecialDamageChange, Value = config.SpecialDamageChange });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.StrengthFastClimbCost, Value = config.StrengthFastClimbCost });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ElementPropertyType, Value = config.ElementPropertyType });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.WeakTime, Value = config.WeakTime });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.IgnoreDefRate, Value = config.IgnoreDefRate });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.IgnoreDamageResistancePhys, Value = config.IgnoreDamageResistancePhys });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.IgnoreDamageResistanceElement1, Value = config.IgnoreDamageResistanceElement1 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.IgnoreDamageResistanceElement2, Value = config.IgnoreDamageResistanceElement2 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.IgnoreDamageResistanceElement3, Value = config.IgnoreDamageResistanceElement3 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.IgnoreDamageResistanceElement4, Value = config.IgnoreDamageResistanceElement4 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.IgnoreDamageResistanceElement5, Value = config.IgnoreDamageResistanceElement5 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.IgnoreDamageResistanceElement6, Value = config.IgnoreDamageResistanceElement6 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.SkillToughRatio, Value = config.SkillToughRatio });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.StrengthClimbJump, Value = config.StrengthClimbJump });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.StrengthGliding, Value = config.StrengthGliding });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.Mass, Value = config.Mass });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.BrakingFrictionFactor, Value = config.BrakingFrictionFactor });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.GravityScale, Value = config.GravityScale });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.SpeedRatio, Value = config.SpeedRatio });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageChangePhantom, Value = config.DamageChangePhantom });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.AutoAttackSpeed, Value = config.AutoAttackSpeed });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.CastAttackSpeed, Value = config.CastAttackSpeed });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.StatusBuildUp1Max, Value = config.StatusBuildUp1Max });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.StatusBuildUp1, Value = config.StatusBuildUp1 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.StatusBuildUp2Max, Value = config.StatusBuildUp2Max });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.StatusBuildUp2, Value = config.StatusBuildUp2 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.StatusBuildUp3Max, Value = config.StatusBuildUp3Max });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.StatusBuildUp3, Value = config.StatusBuildUp3 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.StatusBuildUp4Max, Value = config.StatusBuildUp4Max });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.StatusBuildUp4, Value = config.StatusBuildUp4 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.StatusBuildUp5Max, Value = config.StatusBuildUp5Max });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.StatusBuildUp5, Value = config.StatusBuildUp5 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ParalysisTimeMax, Value = config.ParalysisTimeMax });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ParalysisTime, Value = config.ParalysisTime });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ParalysisTimeRecover, Value = config.ParalysisTimeRecover });
|
||||||
|
|
||||||
|
return baseProp;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ internal class RouletteController : Controller
|
||||||
{
|
{
|
||||||
await Session.Push(MessageId.ExploreToolAllNotify, new ExploreToolAllNotify
|
await Session.Push(MessageId.ExploreToolAllNotify, new ExploreToolAllNotify
|
||||||
{
|
{
|
||||||
SkillList = { 1001, 1004, 1003 },
|
SkillList = { 3001, 3002, 1005, 1006, 1001, 1004, 1003, 1007, 1009 },
|
||||||
ExploreSkill = 1001
|
ExploreSkill = 1001
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -34,14 +34,14 @@ internal class RouletteController : Controller
|
||||||
},
|
},
|
||||||
new ExploreSkillRoulette
|
new ExploreSkillRoulette
|
||||||
{
|
{
|
||||||
SkillIds = {1001, 1004, 1003, 0, 0, 0, 0, 0},
|
SkillIds = {10002, 10004, 0, 0, 0, 0, 0, 0},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
[NetEvent(MessageId.VisionExploreSkillSetRequest)]
|
[NetEvent(MessageId.VisionExploreSkillSetRequest)]
|
||||||
public async Task<ResponseMessage> OnVisionExploreSkillSetRequest(VisionExploreSkillSetRequest request, CreatureController creatureController, EventSystem eventSystem)
|
public async Task<RpcResult> OnVisionExploreSkillSetRequest(VisionExploreSkillSetRequest request, CreatureController creatureController, EventSystem eventSystem)
|
||||||
{
|
{
|
||||||
PlayerEntity? playerEntity = creatureController.GetPlayerEntity();
|
PlayerEntity? playerEntity = creatureController.GetPlayerEntity();
|
||||||
if (playerEntity == null) return Response(MessageId.VisionExploreSkillSetResponse, new VisionExploreSkillSetResponse { ErrCode = (int)ErrorCode.PlayerNotInAnyScene });
|
if (playerEntity == null) return Response(MessageId.VisionExploreSkillSetResponse, new VisionExploreSkillSetResponse { ErrCode = (int)ErrorCode.PlayerNotInAnyScene });
|
||||||
|
|
|
@ -12,5 +12,5 @@ internal class ShopController : Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
[NetEvent(MessageId.PayShopInfoRequest)]
|
[NetEvent(MessageId.PayShopInfoRequest)]
|
||||||
public ResponseMessage OnPayShopInfoRequest() => Response(MessageId.PayShopInfoResponse, new PayShopInfoResponse());
|
public RpcResult OnPayShopInfoRequest() => Response(MessageId.PayShopInfoResponse, new PayShopInfoResponse());
|
||||||
}
|
}
|
||||||
|
|
19
GameServer/Controllers/TeleportController.cs
Normal file
19
GameServer/Controllers/TeleportController.cs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
using GameServer.Controllers.Attributes;
|
||||||
|
using GameServer.Network;
|
||||||
|
using GameServer.Network.Messages;
|
||||||
|
using Protocol;
|
||||||
|
|
||||||
|
namespace GameServer.Controllers;
|
||||||
|
internal class TeleportController : Controller
|
||||||
|
{
|
||||||
|
public TeleportController(PlayerSession session) : base(session)
|
||||||
|
{
|
||||||
|
// TeleportController.
|
||||||
|
}
|
||||||
|
|
||||||
|
[NetEvent(MessageId.TeleportFinishRequest)]
|
||||||
|
public RpcResult OnTeleportFinishRequest() => Response(MessageId.TeleportFinishResponse, new TeleportFinishResponse());
|
||||||
|
|
||||||
|
[NetEvent(MessageId.TeleportDataRequest)]
|
||||||
|
public RpcResult OnTeleportDataRequest() => Response(MessageId.TeleportDataResponse, new TeleportDataResponse());
|
||||||
|
}
|
|
@ -12,8 +12,8 @@ internal class TowerController : Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
[NetEvent(MessageId.TowerChallengeRequest)]
|
[NetEvent(MessageId.TowerChallengeRequest)]
|
||||||
public ResponseMessage OnTowerChallengeRequest() => Response(MessageId.TowerChallengeResponse, new TowerChallengeResponse());
|
public RpcResult OnTowerChallengeRequest() => Response(MessageId.TowerChallengeResponse, new TowerChallengeResponse());
|
||||||
|
|
||||||
[NetEvent(MessageId.CycleTowerChallengeRequest)]
|
[NetEvent(MessageId.CycleTowerChallengeRequest)]
|
||||||
public ResponseMessage OnCycleTowerChallengeRequest() => Response(MessageId.CycleTowerChallengeResponse, new CycleTowerChallengeResponse());
|
public RpcResult OnCycleTowerChallengeRequest() => Response(MessageId.CycleTowerChallengeResponse, new CycleTowerChallengeResponse());
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ internal class TutorialController : Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
[NetEvent(MessageId.TutorialInfoRequest)]
|
[NetEvent(MessageId.TutorialInfoRequest)]
|
||||||
public ResponseMessage OnTutorialInfoRequest()
|
public RpcResult OnTutorialInfoRequest()
|
||||||
{
|
{
|
||||||
int[] tutorials = [30001, 30002, 30003, 30004, 30005, 30006, 30007, 30011, 30012, 30008, 30009, 30010, 30013, 30014, 30015, 30016, 30017, 30018, 30019, 30020, 30021, 30022, 30023, 30024, 40001, 30025, 30026, 30027, 30028, 30029, 30030, 30031, 30032, 30033, 30034, 30035, 30036, 50001, 50002, 50003, 50004, 50005, 50006, 50007, 50008, 50009, 50010, 50011, 33001, 34017, 34018, 32001, 32002, 32003, 32004, 32005, 32006, 32007, 32008, 32009, 32010, 32011, 32012, 32013, 32014, 32015, 32016, 32017, 32018, 32019, 32020, 32021, 33002, 33003, 33004, 33005, 34001, 34002, 34003, 34004, 34005, 34006, 34007, 34008, 34009, 34010, 34011, 34012, 34013, 34014, 34015, 34016, 34019, 34020, 34021, 34022, 34023, 34024, 34025, 34027, 34028, 34029, 34030, 34031, 34032, 34033];
|
int[] tutorials = [30001, 30002, 30003, 30004, 30005, 30006, 30007, 30011, 30012, 30008, 30009, 30010, 30013, 30014, 30015, 30016, 30017, 30018, 30019, 30020, 30021, 30022, 30023, 30024, 40001, 30025, 30026, 30027, 30028, 30029, 30030, 30031, 30032, 30033, 30034, 30035, 30036, 50001, 50002, 50003, 50004, 50005, 50006, 50007, 50008, 50009, 50010, 50011, 33001, 34017, 34018, 32001, 32002, 32003, 32004, 32005, 32006, 32007, 32008, 32009, 32010, 32011, 32012, 32013, 32014, 32015, 32016, 32017, 32018, 32019, 32020, 32021, 33002, 33003, 33004, 33005, 34001, 34002, 34003, 34004, 34005, 34006, 34007, 34008, 34009, 34010, 34011, 34012, 34013, 34014, 34015, 34016, 34019, 34020, 34021, 34022, 34023, 34024, 34025, 34027, 34028, 34029, 34030, 34031, 34032, 34033];
|
||||||
TutorialInfoResponse rsp = new();
|
TutorialInfoResponse rsp = new();
|
||||||
|
@ -30,7 +30,7 @@ internal class TutorialController : Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
[NetEvent(MessageId.GetDetectionLabelInfoRequest)]
|
[NetEvent(MessageId.GetDetectionLabelInfoRequest)]
|
||||||
public ResponseMessage OnGetDetectionLabelInfoRequest()
|
public RpcResult OnGetDetectionLabelInfoRequest()
|
||||||
{
|
{
|
||||||
int[] guides = [0, 1, 2, 3, 14, 15, 16, 4, 21, 22, 7, 5, 18, 6, 61, 8, 9, 10, 11, 12, 13, 17, 19];
|
int[] guides = [0, 1, 2, 3, 14, 15, 16, 4, 21, 22, 7, 5, 18, 6, 61, 8, 9, 10, 11, 12, 13, 17, 19];
|
||||||
int[] detectionTexts = [1, 2, 3, 4, 5, 6, 7, 0, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 21, 22, 61];
|
int[] detectionTexts = [1, 2, 3, 4, 5, 6, 7, 0, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 21, 22, 61];
|
||||||
|
@ -43,7 +43,7 @@ internal class TutorialController : Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
[NetEvent(MessageId.GuideInfoRequest)]
|
[NetEvent(MessageId.GuideInfoRequest)]
|
||||||
public ResponseMessage OnGuideInfoRequest() => Response(MessageId.GuideInfoResponse, new GuideInfoResponse()
|
public RpcResult OnGuideInfoRequest() => Response(MessageId.GuideInfoResponse, new GuideInfoResponse()
|
||||||
{
|
{
|
||||||
GuideGroupFinishList = { 60001, 60002, 60003, 60004, 60005, 60006, 60007, 60008, 60009, 60010, 60011, 60012, 60013, 60014, 60015, 60016, 60017, 60018, 60019, 60020, 60021, 60101, 60102, 60103, 62002, 62004, 62005, 62006, 62007, 62009, 62010, 62011, 62012, 62013, 62014, 62015, 62016, 62017, 62022, 62027, 62028, 62029, 62030, 62031, 62032, 62033, 62034, 62036, 65001, 67001, 67002, 67003, 67004, 67005, 67006, 67007, 67008, 67009, 67010, 67011, 67012, 67013, 67014, 67015, 67016, 67017, 67018, 67019, 67022, 62001, 62008, 62018, 62019, 62020, 62021, 62023, 62024, 62025, 62026, 62035, 65002, 65003, 65004, 65005 }
|
GuideGroupFinishList = { 60001, 60002, 60003, 60004, 60005, 60006, 60007, 60008, 60009, 60010, 60011, 60012, 60013, 60014, 60015, 60016, 60017, 60018, 60019, 60020, 60021, 60101, 60102, 60103, 62002, 62004, 62005, 62006, 62007, 62009, 62010, 62011, 62012, 62013, 62014, 62015, 62016, 62017, 62022, 62027, 62028, 62029, 62030, 62031, 62032, 62033, 62034, 62036, 65001, 67001, 67002, 67003, 67004, 67005, 67006, 67007, 67008, 67009, 67010, 67011, 67012, 67013, 67014, 67015, 67016, 67017, 67018, 67019, 67022, 62001, 62008, 62018, 62019, 62020, 62021, 62023, 62024, 62025, 62026, 62035, 65002, 65003, 65004, 65005 }
|
||||||
});
|
});
|
||||||
|
|
|
@ -19,14 +19,14 @@ internal class WorldController : Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
[NetEvent(MessageId.EntityOnLandedRequest)]
|
[NetEvent(MessageId.EntityOnLandedRequest)]
|
||||||
public ResponseMessage OnEntityOnLandedRequest() => Response(MessageId.EntityOnLandedResponse, new EntityOnLandedResponse());
|
public RpcResult OnEntityOnLandedRequest() => Response(MessageId.EntityOnLandedResponse, new EntityOnLandedResponse());
|
||||||
|
|
||||||
[NetEvent(MessageId.PlayerMotionRequest)]
|
[NetEvent(MessageId.PlayerMotionRequest)]
|
||||||
public ResponseMessage OnPlayerMotionRequest() => Response(MessageId.PlayerMotionResponse, new PlayerMotionResponse());
|
public RpcResult OnPlayerMotionRequest() => Response(MessageId.PlayerMotionResponse, new PlayerMotionResponse());
|
||||||
|
|
||||||
[NetEvent(MessageId.EntityLoadCompleteRequest)]
|
[NetEvent(MessageId.EntityLoadCompleteRequest)]
|
||||||
public ResponseMessage OnEntityLoadCompleteRequest() => Response(MessageId.EntityLoadCompleteResponse, new EntityLoadCompleteResponse());
|
public RpcResult OnEntityLoadCompleteRequest() => Response(MessageId.EntityLoadCompleteResponse, new EntityLoadCompleteResponse());
|
||||||
|
|
||||||
[NetEvent(MessageId.UpdateSceneDateRequest)]
|
[NetEvent(MessageId.UpdateSceneDateRequest)]
|
||||||
public ResponseMessage OnUpdateSceneDateRequest() => Response(MessageId.UpdateSceneDateResponse, new UpdateSceneDateResponse());
|
public RpcResult OnUpdateSceneDateRequest() => Response(MessageId.UpdateSceneDateResponse, new UpdateSceneDateResponse());
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
using GameServer.Controllers.Attributes;
|
using GameServer.Controllers.Attributes;
|
||||||
using GameServer.Network;
|
using GameServer.Network;
|
||||||
using GameServer.Network.Messages;
|
using GameServer.Network.Messages;
|
||||||
|
using GameServer.Settings;
|
||||||
|
using GameServer.Systems.Entity;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
using Protocol;
|
using Protocol;
|
||||||
|
|
||||||
namespace GameServer.Controllers;
|
namespace GameServer.Controllers;
|
||||||
|
@ -12,9 +15,56 @@ internal class WorldMapController : Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
[NetEvent(MessageId.MapTraceInfoRequest)]
|
[NetEvent(MessageId.MapTraceInfoRequest)]
|
||||||
public ResponseMessage OnMapTraceInfoRequest() => Response(MessageId.MapTraceInfoResponse, new MapTraceInfoResponse()
|
public RpcResult OnMapTraceInfoRequest() => Response(MessageId.MapTraceInfoResponse, new MapTraceInfoResponse()
|
||||||
{
|
{
|
||||||
// Don't.
|
// Don't.
|
||||||
//MarkIdList = { 1, 2, 3, 1000, 1001, 1002, 1003, 1004, 1005, 1007, 1008, 1009, 3000, 3002, 3003, 3005, 3010, 3011, 3012, 4020, 4021, 4022, 4023, 5001, 5002, 5003, 5004, 5005, 5006, 5007, 5021, 5022, 5023, 5025, 5026, 5027, 5028, 5029, 5030, 5031, 380000, 380002, 380003, 380004, 380006, 380007, 380015, 301203, 380013, 380014, 301204, 300201, 300202, 300203, 300301, 300302, 300303, 300304, 300306, 300309, 300310, 300311, 300312, 300313, 300401, 300402, 300403, 300404, 300405, 300406, 300407, 300408, 300410, 300413, 300501, 300502, 300506, 300507, 300508, 300509, 300510, 300511, 300601, 300603, 300604, 300605, 300606, 300607, 300608, 300701, 300703, 300704, 300707, 300708, 300711, 300712, 300713, 300901, 300902, 300911, 300912, 300914, 300915, 300918, 301001, 301003, 301004, 301005, 301006, 301007, 301008, 301009, 301010, 301012, 301013, 301014, 301015, 10000, 10001, 10002, 10003, 10005, 10006, 300801, 301201, 300412, 3015, 3016, 3017, 300411 }
|
//MarkIdList = { 1, 2, 3, 1000, 1001, 1002, 1003, 1004, 1005, 1007, 1008, 1009, 3000, 3002, 3003, 3005, 3010, 3011, 3012, 4020, 4021, 4022, 4023, 5001, 5002, 5003, 5004, 5005, 5006, 5007, 5021, 5022, 5023, 5025, 5026, 5027, 5028, 5029, 5030, 5031, 380000, 380002, 380003, 380004, 380006, 380007, 380015, 301203, 380013, 380014, 301204, 300201, 300202, 300203, 300301, 300302, 300303, 300304, 300306, 300309, 300310, 300311, 300312, 300313, 300401, 300402, 300403, 300404, 300405, 300406, 300407, 300408, 300410, 300413, 300501, 300502, 300506, 300507, 300508, 300509, 300510, 300511, 300601, 300603, 300604, 300605, 300606, 300607, 300608, 300701, 300703, 300704, 300707, 300708, 300711, 300712, 300713, 300901, 300902, 300911, 300912, 300914, 300915, 300918, 301001, 301003, 301004, 301005, 301006, 301007, 301008, 301009, 301010, 301012, 301013, 301014, 301015, 10000, 10001, 10002, 10003, 10005, 10006, 300801, 301201, 300412, 3015, 3016, 3017, 300411 }
|
||||||
});
|
});
|
||||||
|
|
||||||
|
[NetEvent(MessageId.MapUnlockFieldInfoRequest)]
|
||||||
|
public RpcResult OnMapUnlockFieldInfoRequest() => Response(MessageId.MapUnlockFieldInfoResponse, new MapUnlockFieldInfoResponse
|
||||||
|
{
|
||||||
|
FieldId = { Enumerable.Range(1, 12) }
|
||||||
|
});
|
||||||
|
|
||||||
|
[NetEvent(MessageId.MapMarkRequest)]
|
||||||
|
public async Task<RpcResult> OnMapMarkRequest(MapMarkRequest request, IOptions<GameplayFeatureSettings> gameplayFeatures, CreatureController creatureController)
|
||||||
|
{
|
||||||
|
if (gameplayFeatures.Value.TeleportByMapMark)
|
||||||
|
{
|
||||||
|
PlayerEntity? entity = creatureController.GetPlayerEntity();
|
||||||
|
|
||||||
|
if (entity != null)
|
||||||
|
{
|
||||||
|
await Session.Push(MessageId.TeleportNotify, new TeleportNotify
|
||||||
|
{
|
||||||
|
PosX = request.MarkPointRequestInfo.PosX * 100,
|
||||||
|
PosY = request.MarkPointRequestInfo.PosY * 100,
|
||||||
|
PosZ = request.MarkPointRequestInfo.PosZ * 100,
|
||||||
|
PosA = 0,
|
||||||
|
MapId = 8,
|
||||||
|
Reason = (int)TeleportReason.Gm,
|
||||||
|
TransitionOption = new TransitionOptionPb
|
||||||
|
{
|
||||||
|
TransitionType = (int)TransitionType.Empty
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Response(MessageId.MapMarkResponse, new MapMarkResponse
|
||||||
|
{
|
||||||
|
Info = new MarkPointInfo
|
||||||
|
{
|
||||||
|
PosX = request.MarkPointRequestInfo.PosX,
|
||||||
|
PosY = request.MarkPointRequestInfo.PosY,
|
||||||
|
PosZ = request.MarkPointRequestInfo.PosZ,
|
||||||
|
ConfigId = request.MarkPointRequestInfo.ConfigId,
|
||||||
|
MapId = request.MarkPointRequestInfo.MapId,
|
||||||
|
MarkId = 1,
|
||||||
|
MarkInfo = request.MarkPointRequestInfo.MarkInfo,
|
||||||
|
MarkType = request.MarkPointRequestInfo.MarkType
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
39
GameServer/Extensions/Logic/RoleInfoExtensions.cs
Normal file
39
GameServer/Extensions/Logic/RoleInfoExtensions.cs
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
using Core.Config;
|
||||||
|
using Protocol;
|
||||||
|
|
||||||
|
namespace GameServer.Extensions.Logic;
|
||||||
|
internal static class RoleInfoExtensions
|
||||||
|
{
|
||||||
|
public static IEnumerable<GameplayAttributeData> GetAttributeList(this roleInfo role)
|
||||||
|
{
|
||||||
|
return role.BaseProp.Select(prop => new GameplayAttributeData
|
||||||
|
{
|
||||||
|
AttributeType = prop.Key,
|
||||||
|
BaseValue = prop.Value,
|
||||||
|
CurrentValue = prop.Value + ((role.AddProp.SingleOrDefault(p => p.Key == prop.Key)?.Value) ?? 0),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ApplyWeaponProperties(this roleInfo role, WeaponConfig weaponConf)
|
||||||
|
{
|
||||||
|
role.AddProp.Clear();
|
||||||
|
|
||||||
|
if (weaponConf.FirstPropId != null)
|
||||||
|
{
|
||||||
|
role.AddProp.Add(new ArrayIntInt
|
||||||
|
{
|
||||||
|
Key = weaponConf.FirstPropId.Id,
|
||||||
|
Value = (int)weaponConf.FirstPropId.Value
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (weaponConf.SecondPropId != null)
|
||||||
|
{
|
||||||
|
role.AddProp.Add(new ArrayIntInt
|
||||||
|
{
|
||||||
|
Key = weaponConf.SecondPropId.Id,
|
||||||
|
Value = (int)weaponConf.SecondPropId.Value
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using GameServer.Controllers;
|
using GameServer.Controllers;
|
||||||
|
using GameServer.Controllers.Attributes;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
namespace GameServer.Extensions;
|
namespace GameServer.Extensions;
|
||||||
|
@ -17,4 +18,17 @@ internal static class ServiceCollectionExtensions
|
||||||
|
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static IServiceCollection AddCommands(this IServiceCollection services)
|
||||||
|
{
|
||||||
|
IEnumerable<Type> handlerTypes = Assembly.GetExecutingAssembly().GetTypes()
|
||||||
|
.Where(t => t.GetCustomAttribute<ChatCommandCategoryAttribute>() != null);
|
||||||
|
|
||||||
|
foreach (Type type in handlerTypes)
|
||||||
|
{
|
||||||
|
services.AddScoped(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
return services;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,13 +5,19 @@
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
<ApplicationIcon>icon.ico</ApplicationIcon>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Include="icon.ico" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Core\Core.csproj" />
|
||||||
<ProjectReference Include="..\KcpSharp\KcpSharp.csproj" />
|
<ProjectReference Include="..\KcpSharp\KcpSharp.csproj" />
|
||||||
<ProjectReference Include="..\Protocol\Protocol.csproj" />
|
<ProjectReference Include="..\Protocol\Protocol.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
32
GameServer/Models/Chat/ChatRoom.cs
Normal file
32
GameServer/Models/Chat/ChatRoom.cs
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
using Google.Protobuf;
|
||||||
|
using Protocol;
|
||||||
|
|
||||||
|
namespace GameServer.Models.Chat;
|
||||||
|
internal class ChatRoom
|
||||||
|
{
|
||||||
|
private readonly List<ChatContentProto> _messages;
|
||||||
|
private int _msgIdCounter;
|
||||||
|
|
||||||
|
public int TargetUid { get; }
|
||||||
|
|
||||||
|
public ChatRoom(int targetUid)
|
||||||
|
{
|
||||||
|
TargetUid = targetUid;
|
||||||
|
_messages = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<ChatContentProto> ChatHistory => _messages;
|
||||||
|
|
||||||
|
public void AddMessage(int senderId, int contentType, string content)
|
||||||
|
{
|
||||||
|
_messages.Add(new ChatContentProto
|
||||||
|
{
|
||||||
|
SenderUid = senderId,
|
||||||
|
ChatContentType = contentType,
|
||||||
|
Content = content,
|
||||||
|
MsgId = NextMessageId().ToString()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private int NextMessageId() => Interlocked.Increment(ref _msgIdCounter);
|
||||||
|
}
|
29
GameServer/Models/ChatModel.cs
Normal file
29
GameServer/Models/ChatModel.cs
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
using GameServer.Models.Chat;
|
||||||
|
|
||||||
|
namespace GameServer.Models;
|
||||||
|
internal class ChatModel
|
||||||
|
{
|
||||||
|
private readonly Dictionary<int, ChatRoom> _rooms;
|
||||||
|
|
||||||
|
public ChatModel()
|
||||||
|
{
|
||||||
|
_rooms = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets chat room for specified player id.
|
||||||
|
/// Creates new one if it doesn't exist.
|
||||||
|
/// </summary>
|
||||||
|
public ChatRoom GetChatRoom(int id)
|
||||||
|
{
|
||||||
|
if (!_rooms.TryGetValue(id, out ChatRoom? chatRoom))
|
||||||
|
{
|
||||||
|
chatRoom = new ChatRoom(id);
|
||||||
|
_rooms[id] = chatRoom;
|
||||||
|
}
|
||||||
|
|
||||||
|
return chatRoom;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<ChatRoom> AllChatRooms => _rooms.Values;
|
||||||
|
}
|
18
GameServer/Models/FormationModel.cs
Normal file
18
GameServer/Models/FormationModel.cs
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
namespace GameServer.Models;
|
||||||
|
internal class FormationModel
|
||||||
|
{
|
||||||
|
public int[] RoleIds { get; }
|
||||||
|
|
||||||
|
public FormationModel()
|
||||||
|
{
|
||||||
|
RoleIds = new int[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Set(int[] roleIds)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < RoleIds.Length; i++)
|
||||||
|
{
|
||||||
|
RoleIds[i] = roleIds[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
34
GameServer/Models/InventoryModel.cs
Normal file
34
GameServer/Models/InventoryModel.cs
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
using Core.Config;
|
||||||
|
using Protocol;
|
||||||
|
|
||||||
|
namespace GameServer.Models;
|
||||||
|
internal class InventoryModel
|
||||||
|
{
|
||||||
|
private int _itemIncrId;
|
||||||
|
|
||||||
|
public List<WeaponItem> WeaponList { get; } = [];
|
||||||
|
|
||||||
|
public WeaponItem? GetEquippedWeapon(int roleId)
|
||||||
|
{
|
||||||
|
return WeaponList.SingleOrDefault(weapon => weapon.RoleId == roleId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WeaponItem? GetWeaponById(int incrId)
|
||||||
|
{
|
||||||
|
return WeaponList.SingleOrDefault(weapon => weapon.IncrId == incrId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WeaponItem AddNewWeapon(int weaponId)
|
||||||
|
{
|
||||||
|
WeaponItem weapon = new()
|
||||||
|
{
|
||||||
|
Id = weaponId,
|
||||||
|
IncrId = ++_itemIncrId,
|
||||||
|
WeaponLevel = 1,
|
||||||
|
WeaponResonLevel = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
WeaponList.Add(weapon);
|
||||||
|
return weapon;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
using GameServer.Controllers.Attributes;
|
using Core.Config;
|
||||||
|
using GameServer.Controllers.Attributes;
|
||||||
using GameServer.Settings;
|
using GameServer.Settings;
|
||||||
using GameServer.Systems.Event;
|
using GameServer.Systems.Event;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
|
@ -7,13 +8,15 @@ namespace GameServer.Models;
|
||||||
internal class ModelManager
|
internal class ModelManager
|
||||||
{
|
{
|
||||||
private readonly IOptions<PlayerStartingValues> _playerStartingValues;
|
private readonly IOptions<PlayerStartingValues> _playerStartingValues;
|
||||||
|
private readonly ConfigManager _configManager;
|
||||||
|
|
||||||
private PlayerModel? _playerModel;
|
private PlayerModel? _playerModel;
|
||||||
private CreatureModel? _creatureModel;
|
private CreatureModel? _creatureModel;
|
||||||
|
|
||||||
public ModelManager(IOptions<PlayerStartingValues> playerStartingValues)
|
public ModelManager(IOptions<PlayerStartingValues> playerStartingValues, ConfigManager configManager)
|
||||||
{
|
{
|
||||||
_playerStartingValues = playerStartingValues;
|
_playerStartingValues = playerStartingValues;
|
||||||
|
_configManager = configManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
[GameEvent(GameEventType.Login)]
|
[GameEvent(GameEventType.Login)]
|
||||||
|
@ -21,9 +24,16 @@ internal class ModelManager
|
||||||
{
|
{
|
||||||
_playerModel = PlayerModel.CreateDefaultPlayer(_playerStartingValues.Value);
|
_playerModel = PlayerModel.CreateDefaultPlayer(_playerStartingValues.Value);
|
||||||
_creatureModel = new CreatureModel(_playerModel.Id);
|
_creatureModel = new CreatureModel(_playerModel.Id);
|
||||||
|
|
||||||
|
Formation.Set(_playerStartingValues.Value.Characters);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PlayerModel Player => _playerModel ?? throw new InvalidOperationException($"Trying to access {nameof(PlayerModel)} instance before initialization!");
|
public PlayerModel Player => _playerModel ?? throw new InvalidOperationException($"Trying to access {nameof(PlayerModel)} instance before initialization!");
|
||||||
|
|
||||||
public CreatureModel Creature => _creatureModel ?? throw new InvalidOperationException($"Trying to access {nameof(CreatureModel)} instance before initialization!");
|
public CreatureModel Creature => _creatureModel ?? throw new InvalidOperationException($"Trying to access {nameof(CreatureModel)} instance before initialization!");
|
||||||
|
|
||||||
|
public RoleModel Roles { get; } = new();
|
||||||
|
public FormationModel Formation { get; } = new();
|
||||||
|
public InventoryModel Inventory { get; } = new();
|
||||||
|
public ChatModel Chat { get; } = new();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using GameServer.Settings;
|
using Protocol;
|
||||||
|
using GameServer.Settings;
|
||||||
|
|
||||||
namespace GameServer.Models;
|
namespace GameServer.Models;
|
||||||
internal class PlayerModel
|
internal class PlayerModel
|
||||||
|
@ -6,11 +7,13 @@ internal class PlayerModel
|
||||||
public int Id { get; private set; }
|
public int Id { get; private set; }
|
||||||
public string Name { get; private set; }
|
public string Name { get; private set; }
|
||||||
public int[] Characters { get; private set; }
|
public int[] Characters { get; private set; }
|
||||||
|
public Vector Position { get; private set; }
|
||||||
|
|
||||||
public PlayerModel()
|
public PlayerModel()
|
||||||
{
|
{
|
||||||
Name = string.Empty;
|
Name = string.Empty;
|
||||||
Characters = [];
|
Characters = [];
|
||||||
|
Position = new Vector();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PlayerModel CreateDefaultPlayer(PlayerStartingValues startingValues)
|
public static PlayerModel CreateDefaultPlayer(PlayerStartingValues startingValues)
|
||||||
|
@ -19,7 +22,8 @@ internal class PlayerModel
|
||||||
{
|
{
|
||||||
Id = 1337,
|
Id = 1337,
|
||||||
Name = startingValues.Name,
|
Name = startingValues.Name,
|
||||||
Characters = startingValues.Characters
|
Characters = startingValues.Characters,
|
||||||
|
Position = startingValues.Position.Clone()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
170
GameServer/Models/RoleModel.cs
Normal file
170
GameServer/Models/RoleModel.cs
Normal file
|
@ -0,0 +1,170 @@
|
||||||
|
using Core.Config;
|
||||||
|
using Protocol;
|
||||||
|
|
||||||
|
namespace GameServer.Models;
|
||||||
|
internal class RoleModel
|
||||||
|
{
|
||||||
|
public List<roleInfo> Roles { get; } = [];
|
||||||
|
|
||||||
|
public roleInfo Create(int id)
|
||||||
|
{
|
||||||
|
roleInfo info = new()
|
||||||
|
{
|
||||||
|
RoleId = id,
|
||||||
|
Level = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
Roles.Add(info);
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
public roleInfo? GetRoleById(int roleId)
|
||||||
|
{
|
||||||
|
return Roles.SingleOrDefault(role => role.RoleId == roleId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<ArrayIntInt> CreateBasePropList(BasePropertyConfig? config)
|
||||||
|
{
|
||||||
|
List<ArrayIntInt> baseProp = [];
|
||||||
|
if (config == null) return baseProp;
|
||||||
|
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.Lv, Value = config.Lv });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.LifeMax, Value = config.LifeMax });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.Life, Value = config.Life });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.Sheild, Value = config.Sheild });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.SheildDamageChange, Value = config.SheildDamageChange });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.SheildDamageReduce, Value = config.SheildDamageReduce });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.Atk, Value = config.Atk });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.Crit, Value = config.Crit });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.CritDamage, Value = config.CritDamage });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.Def, Value = config.Def });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.EnergyEfficiency, Value = config.EnergyEfficiency });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.CdReduse, Value = config.CdReduse });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ReactionEfficiency, Value = config.ReactionEfficiency });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageChangeNormalSkill, Value = config.DamageChangeNormalSkill });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageChange, Value = config.DamageChange });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageReduce, Value = config.DamageReduce });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageChangeAuto, Value = config.DamageChangeAuto });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageChangeCast, Value = config.DamageChangeCast });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageChangeUltra, Value = config.DamageChangeUltra });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageChangeQte, Value = config.DamageChangeQte });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageChangePhys, Value = config.DamageChangePhys });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageChangeElement1, Value = config.DamageChangeElement1 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageChangeElement2, Value = config.DamageChangeElement2 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageChangeElement3, Value = config.DamageChangeElement3 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageChangeElement4, Value = config.DamageChangeElement4 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageChangeElement5, Value = config.DamageChangeElement5 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageChangeElement6, Value = config.DamageChangeElement6 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageResistancePhys, Value = config.DamageResistancePhys });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageResistanceElement1, Value = config.DamageResistanceElement1 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageResistanceElement2, Value = config.DamageResistanceElement2 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageResistanceElement3, Value = config.DamageResistanceElement3 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageResistanceElement4, Value = config.DamageResistanceElement4 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageResistanceElement5, Value = config.DamageResistanceElement5 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageResistanceElement6, Value = config.DamageResistanceElement6 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.HealChange, Value = config.HealChange });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.HealedChange, Value = config.HealedChange });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageReducePhys, Value = config.DamageReducePhys });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageReduceElement1, Value = config.DamageReduceElement1 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageReduceElement2, Value = config.DamageReduceElement2 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageReduceElement3, Value = config.DamageReduceElement3 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageReduceElement4, Value = config.DamageReduceElement4 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageReduceElement5, Value = config.DamageReduceElement5 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageReduceElement6, Value = config.DamageReduceElement6 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ReactionChange1, Value = config.ReactionChange1 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ReactionChange2, Value = config.ReactionChange2 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ReactionChange3, Value = config.ReactionChange3 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ReactionChange4, Value = config.ReactionChange4 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ReactionChange5, Value = config.ReactionChange5 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ReactionChange6, Value = config.ReactionChange6 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ReactionChange7, Value = config.ReactionChange7 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ReactionChange8, Value = config.ReactionChange8 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ReactionChange9, Value = config.ReactionChange9 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ReactionChange10, Value = config.ReactionChange10 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ReactionChange11, Value = config.ReactionChange11 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ReactionChange12, Value = config.ReactionChange12 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ReactionChange13, Value = config.ReactionChange13 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ReactionChange14, Value = config.ReactionChange14 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ReactionChange15, Value = config.ReactionChange15 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.EnergyMax, Value = config.EnergyMax });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.Energy, Value = config.Energy });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.SpecialEnergy1Max, Value = config.SpecialEnergy1Max });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.SpecialEnergy1, Value = config.SpecialEnergy1 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.SpecialEnergy2Max, Value = config.SpecialEnergy2Max });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.SpecialEnergy2, Value = config.SpecialEnergy2 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.SpecialEnergy3Max, Value = config.SpecialEnergy3Max });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.SpecialEnergy3, Value = config.SpecialEnergy3 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.SpecialEnergy4Max, Value = config.SpecialEnergy4Max });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.SpecialEnergy4, Value = config.SpecialEnergy4 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.StrengthMax, Value = config.StrengthMax });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.Strength, Value = config.Strength });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.StrengthRecover, Value = config.StrengthRecover });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.StrengthPunishTime, Value = config.StrengthPunishTime });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.StrengthRun, Value = config.StrengthRun });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.StrengthSwim, Value = config.StrengthSwim });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.StrengthFastSwim, Value = config.StrengthFastSwim });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.StrengthClimb, Value = config.StrengthClimb });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.StrengthFastClimb, Value = config.StrengthFastClimb });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.HardnessMax, Value = config.HardnessMax });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.Hardness, Value = config.Hardness });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.HardnessRecover, Value = config.HardnessRecover });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.HardnessPunishTime, Value = config.HardnessPunishTime });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.HardnessChange, Value = config.HardnessChange });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.HardnessReduce, Value = config.HardnessReduce });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.RageMax, Value = config.RageMax });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.Rage, Value = config.Rage });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.RageRecover, Value = config.RageRecover });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.RagePunishTime, Value = config.RagePunishTime });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.RageChange, Value = config.RageChange });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.RageReduce, Value = config.RageReduce });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ToughMax, Value = config.ToughMax });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.Tough, Value = config.Tough });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ToughRecover, Value = config.ToughRecover });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ToughChange, Value = config.ToughChange });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ToughReduce, Value = config.ToughReduce });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ToughRecoverDelayTime, Value = config.ToughRecoverDelayTime });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ElementPower1, Value = config.ElementPower1 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ElementPower2, Value = config.ElementPower2 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ElementPower3, Value = config.ElementPower3 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ElementPower4, Value = config.ElementPower4 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ElementPower5, Value = config.ElementPower5 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ElementPower6, Value = config.ElementPower6 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.SpecialDamageChange, Value = config.SpecialDamageChange });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.StrengthFastClimbCost, Value = config.StrengthFastClimbCost });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ElementPropertyType, Value = config.ElementPropertyType });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.WeakTime, Value = config.WeakTime });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.IgnoreDefRate, Value = config.IgnoreDefRate });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.IgnoreDamageResistancePhys, Value = config.IgnoreDamageResistancePhys });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.IgnoreDamageResistanceElement1, Value = config.IgnoreDamageResistanceElement1 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.IgnoreDamageResistanceElement2, Value = config.IgnoreDamageResistanceElement2 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.IgnoreDamageResistanceElement3, Value = config.IgnoreDamageResistanceElement3 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.IgnoreDamageResistanceElement4, Value = config.IgnoreDamageResistanceElement4 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.IgnoreDamageResistanceElement5, Value = config.IgnoreDamageResistanceElement5 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.IgnoreDamageResistanceElement6, Value = config.IgnoreDamageResistanceElement6 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.SkillToughRatio, Value = config.SkillToughRatio });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.StrengthClimbJump, Value = config.StrengthClimbJump });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.StrengthGliding, Value = config.StrengthGliding });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.Mass, Value = config.Mass });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.BrakingFrictionFactor, Value = config.BrakingFrictionFactor });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.GravityScale, Value = config.GravityScale });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.SpeedRatio, Value = config.SpeedRatio });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.DamageChangePhantom, Value = config.DamageChangePhantom });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.AutoAttackSpeed, Value = config.AutoAttackSpeed });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.CastAttackSpeed, Value = config.CastAttackSpeed });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.StatusBuildUp1Max, Value = config.StatusBuildUp1Max });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.StatusBuildUp1, Value = config.StatusBuildUp1 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.StatusBuildUp2Max, Value = config.StatusBuildUp2Max });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.StatusBuildUp2, Value = config.StatusBuildUp2 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.StatusBuildUp3Max, Value = config.StatusBuildUp3Max });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.StatusBuildUp3, Value = config.StatusBuildUp3 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.StatusBuildUp4Max, Value = config.StatusBuildUp4Max });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.StatusBuildUp4, Value = config.StatusBuildUp4 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.StatusBuildUp5Max, Value = config.StatusBuildUp5Max });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.StatusBuildUp5, Value = config.StatusBuildUp5 });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ParalysisTimeMax, Value = config.ParalysisTimeMax });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ParalysisTime, Value = config.ParalysisTime });
|
||||||
|
baseProp.Add(new() { Key = (int)EAttributeType.ParalysisTimeRecover, Value = config.ParalysisTimeRecover });
|
||||||
|
|
||||||
|
return baseProp;
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,7 +4,7 @@ using Protocol;
|
||||||
namespace GameServer.Network.Messages;
|
namespace GameServer.Network.Messages;
|
||||||
|
|
||||||
internal delegate Task PushHandler(IServiceProvider serviceProvider, ReadOnlySpan<byte> data);
|
internal delegate Task PushHandler(IServiceProvider serviceProvider, ReadOnlySpan<byte> data);
|
||||||
internal delegate Task<ResponseMessage> RpcHandler(IServiceProvider serviceProvider, ReadOnlySpan<byte> data);
|
internal delegate Task<RpcResult> RpcHandler(IServiceProvider serviceProvider, ReadOnlySpan<byte> data);
|
||||||
internal class MessageManager
|
internal class MessageManager
|
||||||
{
|
{
|
||||||
private readonly EventHandlerFactory _handlerFactory;
|
private readonly EventHandlerFactory _handlerFactory;
|
||||||
|
@ -16,7 +16,7 @@ internal class MessageManager
|
||||||
_serviceProvider = serviceProvider;
|
_serviceProvider = serviceProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<ResponseMessage?> ExecuteRpc(MessageId messageId, ReadOnlyMemory<byte> data)
|
public async Task<RpcResult?> ExecuteRpc(MessageId messageId, ReadOnlyMemory<byte> data)
|
||||||
{
|
{
|
||||||
RpcHandler? handler = _handlerFactory.GetRpcHandler(messageId);
|
RpcHandler? handler = _handlerFactory.GetRpcHandler(messageId);
|
||||||
if (handler != null)
|
if (handler != null)
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using GameServer.Network.Messages;
|
using GameServer.Network.Messages;
|
||||||
|
using GameServer.Systems.Event;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace GameServer.Network.Rpc;
|
namespace GameServer.Network.Rpc;
|
||||||
|
@ -7,26 +8,33 @@ internal class RpcManager
|
||||||
private readonly IRpcEndPoint _endPoint;
|
private readonly IRpcEndPoint _endPoint;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
private readonly MessageManager _messageManager;
|
private readonly MessageManager _messageManager;
|
||||||
|
private readonly EventSystem _eventSystem;
|
||||||
|
|
||||||
public RpcManager(MessageManager messageManager, IRpcEndPoint endPoint, ILogger<RpcManager> logger)
|
public RpcManager(MessageManager messageManager, IRpcEndPoint endPoint, ILogger<RpcManager> logger, EventSystem eventSystem)
|
||||||
{
|
{
|
||||||
_endPoint = endPoint;
|
_endPoint = endPoint;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_messageManager = messageManager;
|
_messageManager = messageManager;
|
||||||
|
_eventSystem = eventSystem;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Execute(RequestMessage request)
|
public async Task Execute(RequestMessage request)
|
||||||
{
|
{
|
||||||
ResponseMessage? response = await _messageManager.ExecuteRpc(request.MessageId, request.Payload);
|
RpcResult? result = await _messageManager.ExecuteRpc(request.MessageId, request.Payload);
|
||||||
if (response == null)
|
if (result == null)
|
||||||
{
|
{
|
||||||
_logger.LogWarning("Rpc was not handled properly (message: {msg_id}, id: {rpc_id})", request.MessageId, request.RpcID);
|
_logger.LogWarning("Rpc was not handled properly (message: {msg_id}, id: {rpc_id})", request.MessageId, request.RpcID);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
response.RpcID = request.RpcID;
|
result.Response.RpcID = request.RpcID;
|
||||||
await _endPoint.SendRpcResult(response);
|
await _endPoint.SendRpcResult(result.Response);
|
||||||
|
|
||||||
_logger.LogInformation("Rpc with id {rpc_id} was handled, return message: {msg_id}", request.RpcID, response.MessageId);
|
foreach (GameEventType postEvent in result.PostEvents)
|
||||||
|
{
|
||||||
|
await _eventSystem.Emit(postEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger.LogInformation("Rpc with id {rpc_id} was handled, return message: {msg_id}", request.RpcID, result.Response.MessageId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
using GameServer.Controllers.Factory;
|
using Core.Config;
|
||||||
|
using Core.Extensions;
|
||||||
|
using GameServer.Controllers.ChatCommands;
|
||||||
|
using GameServer.Controllers.Combat;
|
||||||
|
using GameServer.Controllers.Factory;
|
||||||
using GameServer.Controllers.Manager;
|
using GameServer.Controllers.Manager;
|
||||||
using GameServer.Extensions;
|
using GameServer.Extensions;
|
||||||
using GameServer.Models;
|
using GameServer.Models;
|
||||||
|
@ -20,20 +24,38 @@ internal static class Program
|
||||||
{
|
{
|
||||||
private static async Task Main(string[] args)
|
private static async Task Main(string[] args)
|
||||||
{
|
{
|
||||||
|
Console.Title = "Wuthering Waves | Game Server";
|
||||||
|
Console.WriteLine(" __ __ __ .__ .__ __ __ \r\n/ \\ / \\__ ___/ |_| |__ ___________|__| ____ ____ / \\ / \\_____ ___ __ ____ ______\r\n\\ \\/\\/ / | \\ __\\ | \\_/ __ \\_ __ \\ |/ \\ / ___\\ \\ \\/\\/ /\\__ \\\\ \\/ // __ \\ / ___/\r\n \\ /| | /| | | Y \\ ___/| | \\/ | | \\/ /_/ > \\ / / __ \\\\ /\\ ___/ \\___ \\ \r\n \\__/\\ / |____/ |__| |___| /\\___ >__| |__|___| /\\___ / \\__/\\ / (____ /\\_/ \\___ >____ >\r\n \\/ \\/ \\/ \\//_____/ \\/ \\/ \\/ \\/ \r\n\r\n\t\t\t\t\t\t\t\t\t\t\t\tGame Server\n");
|
||||||
|
|
||||||
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
|
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
|
||||||
builder.Logging.AddConsole();
|
builder.Logging.AddConsole();
|
||||||
|
|
||||||
builder.SetupConfiguration();
|
builder.SetupConfiguration();
|
||||||
builder.Services.AddControllers()
|
builder.Services.UseLocalResources()
|
||||||
|
.AddControllers()
|
||||||
|
.AddCommands()
|
||||||
|
.AddSingleton<ConfigManager>()
|
||||||
.AddSingleton<KcpGateway>().AddScoped<PlayerSession>()
|
.AddSingleton<KcpGateway>().AddScoped<PlayerSession>()
|
||||||
.AddScoped<MessageManager>().AddSingleton<EventHandlerFactory>()
|
.AddScoped<MessageManager>().AddSingleton<EventHandlerFactory>()
|
||||||
.AddScoped<RpcManager>().AddScoped<IRpcEndPoint, RpcSessionEndPoint>()
|
.AddScoped<RpcManager>().AddScoped<IRpcEndPoint, RpcSessionEndPoint>()
|
||||||
.AddSingleton<SessionManager>()
|
.AddSingleton<SessionManager>()
|
||||||
.AddScoped<EventSystem>().AddScoped<EntitySystem>().AddScoped<EntityFactory>()
|
.AddScoped<EventSystem>().AddScoped<EntitySystem>().AddScoped<EntityFactory>()
|
||||||
.AddScoped<ModelManager>().AddScoped<ControllerManager>()
|
.AddScoped<ModelManager>().AddScoped<ControllerManager>()
|
||||||
|
.AddScoped<CombatManager>().AddScoped<ChatCommandManager>()
|
||||||
.AddHostedService<WWGameServer>();
|
.AddHostedService<WWGameServer>();
|
||||||
|
|
||||||
await builder.Build().RunAsync();
|
IHost host = builder.Build();
|
||||||
|
|
||||||
|
ILogger logger = host.Services.GetRequiredService<ILoggerFactory>().CreateLogger("WutheringWaves");
|
||||||
|
logger.LogInformation("Support: discord.gg/reversedrooms or discord.xeondev.com");
|
||||||
|
logger.LogInformation("Preparing server...");
|
||||||
|
|
||||||
|
host.Services.GetRequiredService<IHostApplicationLifetime>().ApplicationStarted.Register(() =>
|
||||||
|
{
|
||||||
|
logger.LogInformation("Server started! Let's play Wuthering Waves!");
|
||||||
|
});
|
||||||
|
|
||||||
|
await host.RunAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void SetupConfiguration(this HostApplicationBuilder builder)
|
private static void SetupConfiguration(this HostApplicationBuilder builder)
|
||||||
|
@ -41,5 +63,6 @@ internal static class Program
|
||||||
builder.Configuration.AddJsonFile("gameplay.json");
|
builder.Configuration.AddJsonFile("gameplay.json");
|
||||||
builder.Services.Configure<GatewaySettings>(builder.Configuration.GetRequiredSection("Gateway"));
|
builder.Services.Configure<GatewaySettings>(builder.Configuration.GetRequiredSection("Gateway"));
|
||||||
builder.Services.Configure<PlayerStartingValues>(builder.Configuration.GetRequiredSection("StartingValues"));
|
builder.Services.Configure<PlayerStartingValues>(builder.Configuration.GetRequiredSection("StartingValues"));
|
||||||
|
builder.Services.Configure<GameplayFeatureSettings>(builder.Configuration.GetRequiredSection("Features"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
5
GameServer/Settings/GameplayFeatureSettings.cs
Normal file
5
GameServer/Settings/GameplayFeatureSettings.cs
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
namespace GameServer.Settings;
|
||||||
|
internal class GameplayFeatureSettings
|
||||||
|
{
|
||||||
|
public bool TeleportByMapMark { get; set; }
|
||||||
|
}
|
|
@ -1,6 +1,9 @@
|
||||||
namespace GameServer.Settings;
|
using Protocol;
|
||||||
|
|
||||||
|
namespace GameServer.Settings;
|
||||||
internal class PlayerStartingValues
|
internal class PlayerStartingValues
|
||||||
{
|
{
|
||||||
public required string Name { get; set; }
|
public required string Name { get; set; }
|
||||||
public required int[] Characters { get; set; }
|
public required int[] Characters { get; set; }
|
||||||
|
public required Vector Position { get; set; }
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,14 @@ internal class EntityAttributeComponent : EntityComponentBase
|
||||||
_gameplayAttributes = [];
|
_gameplayAttributes = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetAll(IEnumerable<GameplayAttributeData> attributes)
|
||||||
|
{
|
||||||
|
foreach (GameplayAttributeData attr in attributes)
|
||||||
|
{
|
||||||
|
SetAttribute((EAttributeType)attr.AttributeType, attr.CurrentValue, attr.BaseValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void SetAttribute(EAttributeType type, int currentValue, int baseValue)
|
public void SetAttribute(EAttributeType type, int currentValue, int baseValue)
|
||||||
{
|
{
|
||||||
if (!_gameplayAttributes.TryGetValue(type, out GameplayAttributeData? attribute))
|
if (!_gameplayAttributes.TryGetValue(type, out GameplayAttributeData? attribute))
|
||||||
|
@ -37,6 +45,7 @@ internal class EntityAttributeComponent : EntityComponentBase
|
||||||
}
|
}
|
||||||
|
|
||||||
attribute.CurrentValue = currentValue;
|
attribute.CurrentValue = currentValue;
|
||||||
|
attribute.BaseValue = currentValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetAttribute(EAttributeType type)
|
public int GetAttribute(EAttributeType type)
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using Protocol;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using Protocol;
|
||||||
|
|
||||||
namespace GameServer.Systems.Entity.Component;
|
namespace GameServer.Systems.Entity.Component;
|
||||||
internal class EntityComponentSystem
|
internal class EntityComponentSystem
|
||||||
|
@ -25,7 +26,7 @@ internal class EntityComponentSystem
|
||||||
return (_components.Single(component => component is TEntityComponent) as TEntityComponent)!;
|
return (_components.Single(component => component is TEntityComponent) as TEntityComponent)!;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryGet<TEntityComponent>(out TEntityComponent? component) where TEntityComponent : EntityComponentBase
|
public bool TryGet<TEntityComponent>([NotNullWhen(true)] out TEntityComponent? component) where TEntityComponent : EntityComponentBase
|
||||||
{
|
{
|
||||||
return (component = _components.SingleOrDefault(component => component is TEntityComponent) as TEntityComponent) != null;
|
return (component = _components.SingleOrDefault(component => component is TEntityComponent) as TEntityComponent) != null;
|
||||||
}
|
}
|
||||||
|
|
22
GameServer/Systems/Entity/Component/EntityEquipComponent.cs
Normal file
22
GameServer/Systems/Entity/Component/EntityEquipComponent.cs
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
using Protocol;
|
||||||
|
|
||||||
|
namespace GameServer.Systems.Entity.Component;
|
||||||
|
internal class EntityEquipComponent : EntityComponentBase
|
||||||
|
{
|
||||||
|
public int WeaponId { get; set; }
|
||||||
|
|
||||||
|
public EntityEquipComponent()
|
||||||
|
{
|
||||||
|
// EntityEquipComponent.
|
||||||
|
}
|
||||||
|
|
||||||
|
public override EntityComponentType Type => EntityComponentType.Equip;
|
||||||
|
|
||||||
|
public override EntityComponentPb Pb => new()
|
||||||
|
{
|
||||||
|
EquipComponent = new EquipComponentPb
|
||||||
|
{
|
||||||
|
WeaponId = WeaponId
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
using Protocol;
|
||||||
|
|
||||||
|
namespace GameServer.Systems.Entity.Component;
|
||||||
|
internal class EntityFightBuffComponent : EntityComponentBase
|
||||||
|
{
|
||||||
|
public List<FightBuffInformation> BuffInfoList { get; } = [];
|
||||||
|
|
||||||
|
public override EntityComponentType Type => EntityComponentType.FightBuff;
|
||||||
|
|
||||||
|
public override EntityComponentPb Pb => new()
|
||||||
|
{
|
||||||
|
FightBuffComponent = new()
|
||||||
|
{
|
||||||
|
FightBuffInfos =
|
||||||
|
{
|
||||||
|
BuffInfoList
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
22
GameServer/Systems/Entity/Component/EntityFsmComponent.cs
Normal file
22
GameServer/Systems/Entity/Component/EntityFsmComponent.cs
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
using Protocol;
|
||||||
|
|
||||||
|
namespace GameServer.Systems.Entity.Component;
|
||||||
|
internal class EntityFsmComponent : EntityComponentBase
|
||||||
|
{
|
||||||
|
public List<DFsm> Fsms { get; } = [];
|
||||||
|
public int CommonHashCode { get; set; }
|
||||||
|
|
||||||
|
public override EntityComponentType Type => EntityComponentType.EntityFsm;
|
||||||
|
|
||||||
|
public override EntityComponentPb Pb => new()
|
||||||
|
{
|
||||||
|
EntityFsmComponentPb = new()
|
||||||
|
{
|
||||||
|
Fsms =
|
||||||
|
{
|
||||||
|
Fsms
|
||||||
|
},
|
||||||
|
CommonHashCode = CommonHashCode
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
using Protocol;
|
||||||
|
|
||||||
|
namespace GameServer.Systems.Entity.Component;
|
||||||
|
internal class EntityLogicStateComponent : EntityComponentBase
|
||||||
|
{
|
||||||
|
public List<int> States { get; set; }
|
||||||
|
|
||||||
|
public EntityLogicStateComponent()
|
||||||
|
{
|
||||||
|
States = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public override EntityComponentType Type => EntityComponentType.LogicState;
|
||||||
|
|
||||||
|
public override EntityComponentPb Pb => new()
|
||||||
|
{
|
||||||
|
LogicStateComponentPb = new()
|
||||||
|
{
|
||||||
|
States = { States }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
using Protocol;
|
||||||
|
|
||||||
|
namespace GameServer.Systems.Entity.Component;
|
||||||
|
internal class EntityMonsterAiComponent : EntityComponentBase
|
||||||
|
{
|
||||||
|
public override EntityComponentType Type => EntityComponentType.MonsterAi;
|
||||||
|
|
||||||
|
public int AiTeamInitId { get; set; }
|
||||||
|
|
||||||
|
public override EntityComponentPb Pb => new()
|
||||||
|
{
|
||||||
|
MonsterAiComponentPb = new MonsterAiComponentPb
|
||||||
|
{
|
||||||
|
AiTeamInitId = AiTeamInitId,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
using Protocol;
|
||||||
|
|
||||||
|
namespace GameServer.Systems.Entity.Component;
|
||||||
|
internal class EntitySummonerComponent : EntityComponentBase
|
||||||
|
{
|
||||||
|
public int SummonConfigId { get; set; }
|
||||||
|
public ESummonType SummonType { get; set; }
|
||||||
|
public long SummonerId { get; set; }
|
||||||
|
public int PlayerId { get; set; }
|
||||||
|
public int SummonSkillId { get; set; }
|
||||||
|
|
||||||
|
public override EntityComponentType Type => EntityComponentType.Summoner;
|
||||||
|
|
||||||
|
public override EntityComponentPb Pb => new()
|
||||||
|
{
|
||||||
|
SummonerComponent = new()
|
||||||
|
{
|
||||||
|
SummonCfgId = SummonConfigId,
|
||||||
|
Type = (int)SummonType,
|
||||||
|
SummonerId = SummonerId,
|
||||||
|
PlayerId = PlayerId,
|
||||||
|
SummonSkillId = SummonSkillId
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
using GameServer.Systems.Entity.Component;
|
using Core.Config;
|
||||||
|
using GameServer.Systems.Entity.Component;
|
||||||
using Protocol;
|
using Protocol;
|
||||||
|
|
||||||
namespace GameServer.Systems.Entity;
|
namespace GameServer.Systems.Entity;
|
||||||
|
@ -27,6 +28,9 @@ internal abstract class EntityBase
|
||||||
public virtual void OnCreate()
|
public virtual void OnCreate()
|
||||||
{
|
{
|
||||||
State = EntityState.Born;
|
State = EntityState.Born;
|
||||||
|
|
||||||
|
_ = ComponentSystem.Create<EntityLogicStateComponent>();
|
||||||
|
_ = ComponentSystem.Create<EntityFightBuffComponent>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void Activate()
|
public virtual void Activate()
|
||||||
|
@ -41,4 +45,146 @@ internal abstract class EntityBase
|
||||||
public abstract EntityConfigType ConfigType { get; }
|
public abstract EntityConfigType ConfigType { get; }
|
||||||
|
|
||||||
public abstract EntityPb Pb { get; }
|
public abstract EntityPb Pb { get; }
|
||||||
|
|
||||||
|
public void InitProps(BasePropertyConfig config)
|
||||||
|
{
|
||||||
|
EntityAttributeComponent attributeComponent = ComponentSystem.Get<EntityAttributeComponent>();
|
||||||
|
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.Lv, config.Lv);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.LifeMax, config.LifeMax);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.Life, config.Life);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.Sheild, config.Sheild);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.SheildDamageChange, config.SheildDamageChange);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.SheildDamageReduce, config.SheildDamageReduce);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.Atk, config.Atk);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.Crit, config.Crit);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.CritDamage, config.CritDamage);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.Def, config.Def);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.EnergyEfficiency, config.EnergyEfficiency);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.CdReduse, config.CdReduse);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.ReactionEfficiency, config.ReactionEfficiency);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.DamageChangeNormalSkill, config.DamageChangeNormalSkill);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.DamageChange, config.DamageChange);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.DamageReduce, config.DamageReduce);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.DamageChangeAuto, config.DamageChangeAuto);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.DamageChangeCast, config.DamageChangeCast);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.DamageChangeUltra, config.DamageChangeUltra);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.DamageChangeQte, config.DamageChangeQte);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.DamageChangePhys, config.DamageChangePhys);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.DamageChangeElement1, config.DamageChangeElement1);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.DamageChangeElement2, config.DamageChangeElement2);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.DamageChangeElement3, config.DamageChangeElement3);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.DamageChangeElement4, config.DamageChangeElement4);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.DamageChangeElement5, config.DamageChangeElement5);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.DamageChangeElement6, config.DamageChangeElement6);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.DamageResistancePhys, config.DamageResistancePhys);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.DamageResistanceElement1, config.DamageResistanceElement1);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.DamageResistanceElement2, config.DamageResistanceElement2);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.DamageResistanceElement3, config.DamageResistanceElement3);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.DamageResistanceElement4, config.DamageResistanceElement4);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.DamageResistanceElement5, config.DamageResistanceElement5);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.DamageResistanceElement6, config.DamageResistanceElement6);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.HealChange, config.HealChange);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.HealedChange, config.HealedChange);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.DamageReducePhys, config.DamageReducePhys);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.DamageReduceElement1, config.DamageReduceElement1);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.DamageReduceElement2, config.DamageReduceElement2);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.DamageReduceElement3, config.DamageReduceElement3);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.DamageReduceElement4, config.DamageReduceElement4);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.DamageReduceElement5, config.DamageReduceElement5);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.DamageReduceElement6, config.DamageReduceElement6);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.ReactionChange1, config.ReactionChange1);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.ReactionChange2, config.ReactionChange2);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.ReactionChange3, config.ReactionChange3);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.ReactionChange4, config.ReactionChange4);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.ReactionChange5, config.ReactionChange5);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.ReactionChange6, config.ReactionChange6);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.ReactionChange7, config.ReactionChange7);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.ReactionChange8, config.ReactionChange8);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.ReactionChange9, config.ReactionChange9);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.ReactionChange10, config.ReactionChange10);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.ReactionChange11, config.ReactionChange11);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.ReactionChange12, config.ReactionChange12);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.ReactionChange13, config.ReactionChange13);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.ReactionChange14, config.ReactionChange14);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.ReactionChange15, config.ReactionChange15);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.EnergyMax, config.EnergyMax);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.Energy, config.Energy);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.SpecialEnergy1Max, config.SpecialEnergy1Max);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.SpecialEnergy1, config.SpecialEnergy1);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.SpecialEnergy2Max, config.SpecialEnergy2Max);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.SpecialEnergy2, config.SpecialEnergy2);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.SpecialEnergy3Max, config.SpecialEnergy3Max);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.SpecialEnergy3, config.SpecialEnergy3);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.SpecialEnergy4Max, config.SpecialEnergy4Max);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.SpecialEnergy4, config.SpecialEnergy4);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.StrengthMax, config.StrengthMax);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.Strength, config.Strength);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.StrengthRecover, config.StrengthRecover);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.StrengthPunishTime, config.StrengthPunishTime);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.StrengthRun, config.StrengthRun);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.StrengthSwim, config.StrengthSwim);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.StrengthFastSwim, config.StrengthFastSwim);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.StrengthClimb, config.StrengthClimb);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.StrengthFastClimb, config.StrengthFastClimb);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.HardnessMax, config.HardnessMax);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.Hardness, config.Hardness);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.HardnessRecover, config.HardnessRecover);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.HardnessPunishTime, config.HardnessPunishTime);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.HardnessChange, config.HardnessChange);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.HardnessReduce, config.HardnessReduce);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.RageMax, config.RageMax);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.Rage, config.Rage);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.RageRecover, config.RageRecover);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.RagePunishTime, config.RagePunishTime);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.RageChange, config.RageChange);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.RageReduce, config.RageReduce);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.ToughMax, config.ToughMax);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.Tough, config.Tough);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.ToughRecover, config.ToughRecover);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.ToughChange, config.ToughChange);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.ToughReduce, config.ToughReduce);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.ToughRecoverDelayTime, config.ToughRecoverDelayTime);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.ElementPower1, config.ElementPower1);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.ElementPower2, config.ElementPower2);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.ElementPower3, config.ElementPower3);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.ElementPower4, config.ElementPower4);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.ElementPower5, config.ElementPower5);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.ElementPower6, config.ElementPower6);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.SpecialDamageChange, config.SpecialDamageChange);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.StrengthFastClimbCost, config.StrengthFastClimbCost);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.ElementPropertyType, config.ElementPropertyType);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.WeakTime, config.WeakTime);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.IgnoreDefRate, config.IgnoreDefRate);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.IgnoreDamageResistancePhys, config.IgnoreDamageResistancePhys);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.IgnoreDamageResistanceElement1, config.IgnoreDamageResistanceElement1);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.IgnoreDamageResistanceElement2, config.IgnoreDamageResistanceElement2);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.IgnoreDamageResistanceElement3, config.IgnoreDamageResistanceElement3);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.IgnoreDamageResistanceElement4, config.IgnoreDamageResistanceElement4);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.IgnoreDamageResistanceElement5, config.IgnoreDamageResistanceElement5);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.IgnoreDamageResistanceElement6, config.IgnoreDamageResistanceElement6);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.SkillToughRatio, config.SkillToughRatio);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.StrengthClimbJump, config.StrengthClimbJump);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.StrengthGliding, config.StrengthGliding);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.Mass, config.Mass);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.BrakingFrictionFactor, config.BrakingFrictionFactor);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.GravityScale, config.GravityScale);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.SpeedRatio, config.SpeedRatio);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.DamageChangePhantom, config.DamageChangePhantom);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.AutoAttackSpeed, config.AutoAttackSpeed);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.CastAttackSpeed, config.CastAttackSpeed);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.StatusBuildUp1Max, config.StatusBuildUp1Max);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.StatusBuildUp1, config.StatusBuildUp1);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.StatusBuildUp2Max, config.StatusBuildUp2Max);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.StatusBuildUp2, config.StatusBuildUp2);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.StatusBuildUp3Max, config.StatusBuildUp3Max);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.StatusBuildUp3, config.StatusBuildUp3);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.StatusBuildUp4Max, config.StatusBuildUp4Max);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.StatusBuildUp4, config.StatusBuildUp4);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.StatusBuildUp5Max, config.StatusBuildUp5Max);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.StatusBuildUp5, config.StatusBuildUp5);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.ParalysisTimeMax, config.ParalysisTimeMax);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.ParalysisTime, config.ParalysisTime);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.ParalysisTimeRecover, config.ParalysisTimeRecover);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,5 +6,7 @@ internal class EntityFactory
|
||||||
public PlayerEntity CreatePlayer(int characterConfigId, int playerId)
|
public PlayerEntity CreatePlayer(int characterConfigId, int playerId)
|
||||||
=> new(NextId(), characterConfigId, playerId);
|
=> new(NextId(), characterConfigId, playerId);
|
||||||
|
|
||||||
|
public MonsterEntity CreateMonster(int levelEntityId) => new(NextId(), levelEntityId);
|
||||||
|
|
||||||
private long NextId() => Interlocked.Increment(ref _entityIdCounter);
|
private long NextId() => Interlocked.Increment(ref _entityIdCounter);
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,11 @@ internal class EntitySystem
|
||||||
_entities.Add(entity);
|
_entities.Add(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Destroy(EntityBase entity)
|
||||||
|
{
|
||||||
|
_ = _entities.Remove(entity);
|
||||||
|
}
|
||||||
|
|
||||||
public void Activate(EntityBase entity)
|
public void Activate(EntityBase entity)
|
||||||
{
|
{
|
||||||
entity.Activate();
|
entity.Activate();
|
||||||
|
|
73
GameServer/Systems/Entity/MonsterEntity.cs
Normal file
73
GameServer/Systems/Entity/MonsterEntity.cs
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
using GameServer.Systems.Entity.Component;
|
||||||
|
using Protocol;
|
||||||
|
|
||||||
|
namespace GameServer.Systems.Entity;
|
||||||
|
internal class MonsterEntity : EntityBase
|
||||||
|
{
|
||||||
|
public MonsterEntity(long id, int configId) : base(id)
|
||||||
|
{
|
||||||
|
ConfigId = configId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int ConfigId { get; }
|
||||||
|
|
||||||
|
public override EEntityType Type => EEntityType.Monster;
|
||||||
|
public override EntityConfigType ConfigType => EntityConfigType.Level;
|
||||||
|
|
||||||
|
public override void OnCreate()
|
||||||
|
{
|
||||||
|
base.OnCreate();
|
||||||
|
|
||||||
|
EntityAttributeComponent attributeComponent = ComponentSystem.Create<EntityAttributeComponent>();
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.LifeMax, 100);
|
||||||
|
attributeComponent.SetAttribute(EAttributeType.Life, 100);
|
||||||
|
|
||||||
|
State = EntityState.Born;
|
||||||
|
|
||||||
|
EntityMonsterAiComponent aiComponent = ComponentSystem.Create<EntityMonsterAiComponent>();
|
||||||
|
aiComponent.AiTeamInitId = 100;
|
||||||
|
|
||||||
|
EntityFsmComponent fsm = ComponentSystem.Create<EntityFsmComponent>();
|
||||||
|
|
||||||
|
fsm.Fsms.Add(new DFsm
|
||||||
|
{
|
||||||
|
FsmId = 10007, // Main State Machine
|
||||||
|
CurrentState = 10013, // Battle Branching
|
||||||
|
Status = 1, // ??
|
||||||
|
Flag = (int)EFsmStateFlag.Confirmed
|
||||||
|
});
|
||||||
|
|
||||||
|
fsm.Fsms.Add(new DFsm
|
||||||
|
{
|
||||||
|
FsmId = 10007, // Main State Machine
|
||||||
|
CurrentState = 10015, // Moving Combat
|
||||||
|
Status = 1, // ??
|
||||||
|
Flag = (int)EFsmStateFlag.Confirmed
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public override EntityPb Pb
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
EntityPb pb = new()
|
||||||
|
{
|
||||||
|
Id = Id,
|
||||||
|
EntityType = (int)Type,
|
||||||
|
ConfigType = (int)ConfigType,
|
||||||
|
EntityState = (int)State,
|
||||||
|
ConfigId = ConfigId,
|
||||||
|
Pos = Pos,
|
||||||
|
Rot = Rot,
|
||||||
|
LivingStatus = (int)LivingStatus,
|
||||||
|
IsVisible = IsVisible,
|
||||||
|
InitLinearVelocity = new(),
|
||||||
|
InitPos = new()
|
||||||
|
};
|
||||||
|
|
||||||
|
pb.ComponentPbs.AddRange(ComponentSystem.Pb);
|
||||||
|
|
||||||
|
return pb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,6 +15,24 @@ internal class PlayerEntity : EntityBase
|
||||||
|
|
||||||
public bool IsCurrentRole { get; set; }
|
public bool IsCurrentRole { get; set; }
|
||||||
|
|
||||||
|
public int WeaponId
|
||||||
|
{
|
||||||
|
get => ComponentSystem.Get<EntityEquipComponent>().WeaponId;
|
||||||
|
set => ComponentSystem.Get<EntityEquipComponent>().WeaponId = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Health
|
||||||
|
{
|
||||||
|
get => ComponentSystem.Get<EntityAttributeComponent>().GetAttribute(EAttributeType.Life);
|
||||||
|
set => ComponentSystem.Get<EntityAttributeComponent>().SetAttribute(EAttributeType.Life, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int HealthMax
|
||||||
|
{
|
||||||
|
get => ComponentSystem.Get<EntityAttributeComponent>().GetAttribute(EAttributeType.LifeMax);
|
||||||
|
set => ComponentSystem.Get<EntityAttributeComponent>().SetAttribute(EAttributeType.LifeMax, value);
|
||||||
|
}
|
||||||
|
|
||||||
public override void OnCreate()
|
public override void OnCreate()
|
||||||
{
|
{
|
||||||
base.OnCreate();
|
base.OnCreate();
|
||||||
|
@ -25,24 +43,40 @@ internal class PlayerEntity : EntityBase
|
||||||
|
|
||||||
EntityVisionSkillComponent visionSkillComponent = ComponentSystem.Create<EntityVisionSkillComponent>();
|
EntityVisionSkillComponent visionSkillComponent = ComponentSystem.Create<EntityVisionSkillComponent>();
|
||||||
visionSkillComponent.SetExploreTool(1001);
|
visionSkillComponent.SetExploreTool(1001);
|
||||||
|
|
||||||
|
_ = ComponentSystem.Create<EntityEquipComponent>();
|
||||||
|
_ = ComponentSystem.Create<EntityAttributeComponent>();
|
||||||
|
|
||||||
|
// TODO: temporary solution to enable glider and wall run, should implement proper buff management.
|
||||||
|
EntityFightBuffComponent fightBuffComponent = ComponentSystem.Get<EntityFightBuffComponent>();
|
||||||
|
fightBuffComponent.BuffInfoList.Add(new FightBuffInformation
|
||||||
|
{
|
||||||
|
BuffId = 3004,
|
||||||
|
EntityId = Id,
|
||||||
|
InstigatorId = Id,
|
||||||
|
IsActive = true,
|
||||||
|
Duration = -1,
|
||||||
|
LeftDuration = -1,
|
||||||
|
Level = 1,
|
||||||
|
StackCount = 1
|
||||||
|
});
|
||||||
|
|
||||||
|
fightBuffComponent.BuffInfoList.Add(new FightBuffInformation
|
||||||
|
{
|
||||||
|
BuffId = 3003,
|
||||||
|
EntityId = Id,
|
||||||
|
InstigatorId = Id,
|
||||||
|
IsActive = true,
|
||||||
|
Duration = -1,
|
||||||
|
LeftDuration = -1,
|
||||||
|
Level = 1,
|
||||||
|
StackCount = 1
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Activate()
|
public override void Activate()
|
||||||
{
|
{
|
||||||
base.Activate();
|
base.Activate();
|
||||||
|
|
||||||
_ = ComponentSystem.Create<EntityAttributeComponent>();
|
|
||||||
InitAttributes();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void InitAttributes()
|
|
||||||
{
|
|
||||||
EntityAttributeComponent attributeComponent = ComponentSystem.Get<EntityAttributeComponent>();
|
|
||||||
attributeComponent.SetAttribute(EAttributeType.Life, 1000);
|
|
||||||
attributeComponent.SetAttribute(EAttributeType.LifeMax, 1000);
|
|
||||||
attributeComponent.SetAttribute(EAttributeType.Lv, 1);
|
|
||||||
attributeComponent.SetAttribute(EAttributeType.AutoAttackSpeed, 10000);
|
|
||||||
attributeComponent.SetAttribute(EAttributeType.CastAttackSpeed, 10000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override EEntityType Type => EEntityType.Player;
|
public override EEntityType Type => EEntityType.Player;
|
||||||
|
|
|
@ -3,7 +3,13 @@ internal enum GameEventType
|
||||||
{
|
{
|
||||||
Login = 1,
|
Login = 1,
|
||||||
EnterGame,
|
EnterGame,
|
||||||
|
PushDataDone,
|
||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
VisionSkillChanged
|
FormationUpdated,
|
||||||
|
VisionSkillChanged,
|
||||||
|
|
||||||
|
// Debug
|
||||||
|
DebugUnlockAllRoles,
|
||||||
|
DebugUnlockAllWeapons
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using GameServer.Controllers.Factory;
|
using Core.Config;
|
||||||
|
using GameServer.Controllers.Factory;
|
||||||
using GameServer.Network.Kcp;
|
using GameServer.Network.Kcp;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
|
|
||||||
|
@ -7,8 +8,9 @@ internal class WWGameServer : IHostedService
|
||||||
{
|
{
|
||||||
private readonly KcpGateway _gateway;
|
private readonly KcpGateway _gateway;
|
||||||
|
|
||||||
public WWGameServer(KcpGateway gateway, EventHandlerFactory messageHandlerFactory)
|
public WWGameServer(KcpGateway gateway, ConfigManager manager, EventHandlerFactory messageHandlerFactory)
|
||||||
{
|
{
|
||||||
|
_ = manager;
|
||||||
_ = messageHandlerFactory;
|
_ = messageHandlerFactory;
|
||||||
_gateway = gateway;
|
_gateway = gateway;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,14 @@
|
||||||
{
|
{
|
||||||
"StartingValues": {
|
"StartingValues": {
|
||||||
"Name": "ReversedRooms",
|
"Name": "ReversedRooms",
|
||||||
"Characters": [ 1601, 1302, 1203 ]
|
"Characters": [ 1402, 1302, 1203 ],
|
||||||
|
"Position": {
|
||||||
|
"X": -35823,
|
||||||
|
"Y": 67132,
|
||||||
|
"Z": 4067
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Features": {
|
||||||
|
"TeleportByMapMark": true
|
||||||
}
|
}
|
||||||
}
|
}
|
BIN
GameServer/icon.ico
Normal file
BIN
GameServer/icon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 199 KiB |
|
@ -795,6 +795,8 @@ public enum MessageId
|
||||||
NewBieCourseRewardResponse = 12153,
|
NewBieCourseRewardResponse = 12153,
|
||||||
NewJourneyRequest = 12214,
|
NewJourneyRequest = 12214,
|
||||||
NewJourneyResponse = 12215,
|
NewJourneyResponse = 12215,
|
||||||
|
ClientCurrentRoleReportRequest = 12217,
|
||||||
|
ClientCurrentRoleReportResponse = 12218,
|
||||||
NormalItemAddNotify = 5268,
|
NormalItemAddNotify = 5268,
|
||||||
NormalItemRemoveNotify = 5269,
|
NormalItemRemoveNotify = 5269,
|
||||||
NormalItemRequest = 5265,
|
NormalItemRequest = 5265,
|
||||||
|
|
|
@ -1573,6 +1573,17 @@ message ClientBasicInfoRequest { // MessageId: 5165
|
||||||
message ClientBasicInfoResponse { // MessageId: 3017
|
message ClientBasicInfoResponse { // MessageId: 3017
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message ClientCurrentRoleReportRequest { // MessageId: 12217
|
||||||
|
int32 player_id = 1;
|
||||||
|
int32 current_role_id = 2;
|
||||||
|
int64 current_entity_id = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ClientCurrentRoleReportResponse { // MessageId: 12218
|
||||||
|
int32 player_id = 1;
|
||||||
|
int64 current_entity_id = 2;
|
||||||
|
}
|
||||||
|
|
||||||
message ClientDataComponentPb {
|
message ClientDataComponentPb {
|
||||||
bool is_static_init = 1;
|
bool is_static_init = 1;
|
||||||
int64 owner_id = 2;
|
int64 owner_id = 2;
|
||||||
|
@ -1604,6 +1615,7 @@ message CombatMaxCaseMessageResponse { // MessageId: 11987
|
||||||
|
|
||||||
message CombatNotifyData {
|
message CombatNotifyData {
|
||||||
CombatCommon combat_common = 1;
|
CombatCommon combat_common = 1;
|
||||||
|
oneof message {
|
||||||
CreateBulletNotify create_bullet_notify = 2;
|
CreateBulletNotify create_bullet_notify = 2;
|
||||||
DestroyBulletNotify destroy_bullet_notify = 3;
|
DestroyBulletNotify destroy_bullet_notify = 3;
|
||||||
DamageExecuteNotify damage_execute_notify = 4;
|
DamageExecuteNotify damage_execute_notify = 4;
|
||||||
|
@ -1661,21 +1673,26 @@ message CombatNotifyData {
|
||||||
RecoverPropChangedNotify recover_prop_changed_notify = 58;
|
RecoverPropChangedNotify recover_prop_changed_notify = 58;
|
||||||
RemoveBuffByIdS2cRequestNotify remove_buff_by_id_s2c_request_notify = 59;
|
RemoveBuffByIdS2cRequestNotify remove_buff_by_id_s2c_request_notify = 59;
|
||||||
FormationBuffRemoveByIdS2cRequestNotify formation_buff_remove_by_id_s2c_request_notify = 60;
|
FormationBuffRemoveByIdS2cRequestNotify formation_buff_remove_by_id_s2c_request_notify = 60;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
message CombatPushData {
|
message CombatPushData {
|
||||||
CombatCommon combat_common = 1;
|
CombatCommon combat_common = 1;
|
||||||
|
oneof message {
|
||||||
FormationBuffApplyS2cResponsePush formation_buff_apply_s2c_response_push = 2;
|
FormationBuffApplyS2cResponsePush formation_buff_apply_s2c_response_push = 2;
|
||||||
FormationBuffRemoveS2cResponsePush formation_buff_remove_s2c_response_push = 3;
|
FormationBuffRemoveS2cResponsePush formation_buff_remove_s2c_response_push = 3;
|
||||||
ApplyBuffS2cResponsePush apply_buff_s2c_response_push = 4;
|
ApplyBuffS2cResponsePush apply_buff_s2c_response_push = 4;
|
||||||
RemoveBuffS2cResponsePush remove_buff_s2c_response_push = 5;
|
RemoveBuffS2cResponsePush remove_buff_s2c_response_push = 5;
|
||||||
RemoveBuffByIdS2cResponsePush remove_buff_by_id_s2c_response_push = 6;
|
RemoveBuffByIdS2cResponsePush remove_buff_by_id_s2c_response_push = 6;
|
||||||
FormationBuffRemoveByIdS2cResponsePush formation_buff_remove_by_id_s2c_response_push = 7;
|
FormationBuffRemoveByIdS2cResponsePush formation_buff_remove_by_id_s2c_response_push = 7;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
message CombatReceiveData {
|
message CombatReceiveData {
|
||||||
|
oneof message {
|
||||||
CombatNotifyData combat_notify_data = 2;
|
CombatNotifyData combat_notify_data = 2;
|
||||||
CombatResponseData combat_response_data = 3;
|
CombatResponseData combat_response_data = 3;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
message CombatReceivePackNotify { // MessageId: 1332
|
message CombatReceivePackNotify { // MessageId: 1332
|
||||||
|
@ -1685,6 +1702,7 @@ message CombatReceivePackNotify { // MessageId: 1332
|
||||||
message CombatRequestData {
|
message CombatRequestData {
|
||||||
CombatCommon combat_common = 1;
|
CombatCommon combat_common = 1;
|
||||||
int32 request_id = 2;
|
int32 request_id = 2;
|
||||||
|
oneof message {
|
||||||
CreateBulletRequest create_bullet_request = 3;
|
CreateBulletRequest create_bullet_request = 3;
|
||||||
DestroyBulletRequest destroy_bullet_request = 4;
|
DestroyBulletRequest destroy_bullet_request = 4;
|
||||||
DamageExecuteRequest damage_execute_request = 5;
|
DamageExecuteRequest damage_execute_request = 5;
|
||||||
|
@ -1745,12 +1763,14 @@ message CombatRequestData {
|
||||||
DrownEndTeleportRequest drown_end_teleport_request = 60;
|
DrownEndTeleportRequest drown_end_teleport_request = 60;
|
||||||
MonsterDrownRequest monster_drown_request = 61;
|
MonsterDrownRequest monster_drown_request = 61;
|
||||||
CombatMaxCaseMessageRequest combat_max_case_message_request = 62;
|
CombatMaxCaseMessageRequest combat_max_case_message_request = 62;
|
||||||
|
}
|
||||||
CombatContext context = 100;
|
CombatContext context = 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
message CombatResponseData {
|
message CombatResponseData {
|
||||||
CombatCommon combat_common = 1;
|
CombatCommon combat_common = 1;
|
||||||
int32 request_id = 2;
|
int32 request_id = 2;
|
||||||
|
oneof message {
|
||||||
CreateBulletResponse create_bullet_response = 3;
|
CreateBulletResponse create_bullet_response = 3;
|
||||||
DestroyBulletResponse destroy_bullet_response = 4;
|
DestroyBulletResponse destroy_bullet_response = 4;
|
||||||
DamageExecuteResponse damage_execute_response = 5;
|
DamageExecuteResponse damage_execute_response = 5;
|
||||||
|
@ -1810,6 +1830,7 @@ message CombatResponseData {
|
||||||
RTimeStopResponse r_time_stop_response = 59;
|
RTimeStopResponse r_time_stop_response = 59;
|
||||||
DrownEndTeleportResponse drown_end_teleport_response = 60;
|
DrownEndTeleportResponse drown_end_teleport_response = 60;
|
||||||
MonsterDrownResponse monster_drown_response = 61;
|
MonsterDrownResponse monster_drown_response = 61;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
message CombatSendData {
|
message CombatSendData {
|
||||||
|
@ -2623,6 +2644,7 @@ message EntityActiveRequest { // MessageId: 1541
|
||||||
message EntityActiveResponse { // MessageId: 1542
|
message EntityActiveResponse { // MessageId: 1542
|
||||||
int32 error_code = 1;
|
int32 error_code = 1;
|
||||||
repeated EntityComponentPb component_pbs = 2;
|
repeated EntityComponentPb component_pbs = 2;
|
||||||
|
bool is_visible = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
message EntityAddBubbleNotify { // MessageId: 12203
|
message EntityAddBubbleNotify { // MessageId: 12203
|
||||||
|
@ -7890,6 +7912,7 @@ message SeasonData {
|
||||||
int64 end_time = 3;
|
int64 end_time = 3;
|
||||||
repeated RoguelikeToken roguelike_token_list = 4;
|
repeated RoguelikeToken roguelike_token_list = 4;
|
||||||
repeated SeasonReward season_reward_list = 5;
|
repeated SeasonReward season_reward_list = 5;
|
||||||
|
int32 token_item_count = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
message SeasonReward {
|
message SeasonReward {
|
||||||
|
@ -10921,6 +10944,7 @@ enum ErrorCode {
|
||||||
ERROR_CODE_ERR_ENTITY_PATROL_COMPONENT_NOT_EXIST = 600088;
|
ERROR_CODE_ERR_ENTITY_PATROL_COMPONENT_NOT_EXIST = 600088;
|
||||||
ERROR_CODE_ERR_INTERACT_IS_NOT_PARTICIPANT = 600089;
|
ERROR_CODE_ERR_INTERACT_IS_NOT_PARTICIPANT = 600089;
|
||||||
ERROR_CODE_ERR_VISION_ENTITY_INTERACT_FAIL = 600090;
|
ERROR_CODE_ERR_VISION_ENTITY_INTERACT_FAIL = 600090;
|
||||||
|
ERROR_CODE_ERR_MAX_DROP_TIMES = 600091;
|
||||||
ERROR_CODE_ERR_SCENE_WORLD_NOT_EXIST = 700000;
|
ERROR_CODE_ERR_SCENE_WORLD_NOT_EXIST = 700000;
|
||||||
ERROR_CODE_ERR_PLAYER_NOT_IN_SCENE = 700001;
|
ERROR_CODE_ERR_PLAYER_NOT_IN_SCENE = 700001;
|
||||||
ERROR_CODE_ERR_DROP_ENTITY_NOT_EXIST = 700002;
|
ERROR_CODE_ERR_DROP_ENTITY_NOT_EXIST = 700002;
|
||||||
|
@ -11287,6 +11311,7 @@ enum ErrorCode {
|
||||||
ERROR_CODE_ERR_ITEM_POS_INVAILD = 900058;
|
ERROR_CODE_ERR_ITEM_POS_INVAILD = 900058;
|
||||||
ERROR_CODE_ERR_ITEM_ID_INVAILD = 900059;
|
ERROR_CODE_ERR_ITEM_ID_INVAILD = 900059;
|
||||||
ERROR_CODE_ERR_ROULETTE_FUNC_ID_INVAILD = 900060;
|
ERROR_CODE_ERR_ROULETTE_FUNC_ID_INVAILD = 900060;
|
||||||
|
ERROR_CODE_ERR_STATE_IS_RUNNING = 900061;
|
||||||
ERROR_CODE_ERR_BUFF_ITEM_CONFIG = 1000000;
|
ERROR_CODE_ERR_BUFF_ITEM_CONFIG = 1000000;
|
||||||
ERROR_CODE_ERR_BUFF_ITEM_NOT_SHARE = 1000001;
|
ERROR_CODE_ERR_BUFF_ITEM_NOT_SHARE = 1000001;
|
||||||
ERROR_CODE_ERR_BUFF_ITEM_SHARE_ROLE_ID = 1000002;
|
ERROR_CODE_ERR_BUFF_ITEM_SHARE_ROLE_ID = 1000002;
|
||||||
|
@ -11745,6 +11770,9 @@ enum ErrorCode {
|
||||||
ERROR_CODE_ERR_EXPLORE_SKILL_PULL_GIANT_NOT_EXIST = 1800027;
|
ERROR_CODE_ERR_EXPLORE_SKILL_PULL_GIANT_NOT_EXIST = 1800027;
|
||||||
ERROR_CODE_ERR_HTTP_RPC_PARAM = 1800028;
|
ERROR_CODE_ERR_HTTP_RPC_PARAM = 1800028;
|
||||||
ERROR_CODE_ERR_PLAYER_NOT_IN_GAME_NODE = 1800029;
|
ERROR_CODE_ERR_PLAYER_NOT_IN_GAME_NODE = 1800029;
|
||||||
|
ERROR_CODE_ERR_APPLY_JOIN_PLAYER_CUR_ROLE_IS_DEAD = 1800030;
|
||||||
|
ERROR_CODE_ERR_PLAYER_CUR_ROLE_IS_DEAD_NO_JOIN = 1800031;
|
||||||
|
ERROR_CODE_ERR_PLAYER_CUR_ROLE_IS_DEAD = 1800032;
|
||||||
ERROR_CODE_ERR_CALABASH_LEVEL_REQUEST = 1900000;
|
ERROR_CODE_ERR_CALABASH_LEVEL_REQUEST = 1900000;
|
||||||
ERROR_CODE_ERR_CALABASH_LEVEL_REWARD_DONE = 1900001;
|
ERROR_CODE_ERR_CALABASH_LEVEL_REWARD_DONE = 1900001;
|
||||||
ERROR_CODE_ERR_CALABASH_LEVEL_CONFIG = 1900002;
|
ERROR_CODE_ERR_CALABASH_LEVEL_CONFIG = 1900002;
|
||||||
|
@ -11783,6 +11811,7 @@ enum ErrorCode {
|
||||||
ERROR_CODE_ERR_NEW_BIE_COURSE_CONFIG = 1900035;
|
ERROR_CODE_ERR_NEW_BIE_COURSE_CONFIG = 1900035;
|
||||||
ERROR_CODE_ERR_NEW_BIE_COURSE_REWARD_HAD = 1900036;
|
ERROR_CODE_ERR_NEW_BIE_COURSE_REWARD_HAD = 1900036;
|
||||||
ERROR_CODE_ERR_NEW_BIE_COURSE_LEVEL = 1900037;
|
ERROR_CODE_ERR_NEW_BIE_COURSE_LEVEL = 1900037;
|
||||||
|
ERROR_CODE_ERR_DETECTION_TARGET_SILENCE = 1900038;
|
||||||
ERROR_CODE_ERR_DO_COMMON_REWARD_CONFIG_ERROR = 2000000;
|
ERROR_CODE_ERR_DO_COMMON_REWARD_CONFIG_ERROR = 2000000;
|
||||||
ERROR_CODE_INST_PLAY_NOT_SETTLE = 2000001;
|
ERROR_CODE_INST_PLAY_NOT_SETTLE = 2000001;
|
||||||
ERROR_CODE_INST_PLAY_NOT_FINISH_EXECUTE = 2000002;
|
ERROR_CODE_INST_PLAY_NOT_FINISH_EXECUTE = 2000002;
|
||||||
|
@ -12280,6 +12309,7 @@ enum WorldTeamLeaveReason {
|
||||||
WORLD_TEAM_LEAVE_REASON_BE_KICK = 1;
|
WORLD_TEAM_LEAVE_REASON_BE_KICK = 1;
|
||||||
WORLD_TEAM_LEAVE_REASON_DISSOLVE = 2;
|
WORLD_TEAM_LEAVE_REASON_DISSOLVE = 2;
|
||||||
WORLD_TEAM_LEAVE_REASON_LOGOUT = 3;
|
WORLD_TEAM_LEAVE_REASON_LOGOUT = 3;
|
||||||
|
WORLD_TEAM_LEAVE_REASON_TO_OWN_BIG_WORLD = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum WorldTeamPlayerChangeType {
|
enum WorldTeamPlayerChangeType {
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
# WutheringWaves
|
# WutheringWaves
|
||||||
|
|
||||||
Wuthering Waves server emulator (0.8.2)
|
Wuthering Waves server emulator (0.9.0)
|
||||||
|
|
||||||
## How to run
|
## How to run
|
||||||
- Compile and run SDKServer and GameServer using dotnet8 (Visual Studio 2022 recommended)
|
- Compile and run SDKServer and GameServer using dotnet8 (Visual Studio 2022 recommended)
|
||||||
|
|
||||||
## Connecting
|
## Connecting
|
||||||
- Download [Game Client](https://nogatekeep.ing/assets/ww/0.8.2/ww.7z), it's **pre-patched** and redirects http requests to `127.0.0.1:5500`
|
- Get game client from somewhere. For example using official launcher (you can find it in our discord)
|
||||||
|
- [Download and extract patch](https://nogatekeep.ing/assets/ww/0.9.0/WuWa-0.9-patch.zip) to the game folder, it will redirect all http requests to `127.0.0.1:5500`
|
||||||
- Run game and connect to the server
|
- Run game and connect to the server
|
||||||
|
|
||||||
## Need help?
|
## Need help?
|
||||||
|
|
|
@ -4,10 +4,10 @@ namespace SDKServer.Handlers;
|
||||||
|
|
||||||
internal static class HotPatchHandler
|
internal static class HotPatchHandler
|
||||||
{
|
{
|
||||||
public static string OnConfigRequest() => "N2wiD0yJQntN+Kv98DJOLWvjpgvdTa3/KRA9Rf288hPWxbPgAOzkf/mSfCXKMOFldB3zoIftzB7NIGkF+slYu1MoBcFyxkhx+lRW9oDsuqKVS32cgEyuopKuN71QdjPII82UGXGd4M5mBilVEkTaRKBZVypka5CB79x5Rs2iiPTxOk1zdOUi5F6uUD0cjQod/KM+7TtaiUsSNS+FVBldLPWJOdcQWomUw+q5cCLBJqhxYUJg/hQAt8rRRHyDj2H+0RAdMt1WS5qbYb+QkVCvZlT4UWUyaes3p3xsyyr0HpiqzHXf5iLjaxSv5iKNrLUpLMexn2c3bf+TG7Kca/QYwbJYz4TeYk8zuV7A1ccC4fgSSxwC50xChiOuPwyi7NWkP7Z2FEyqtBWpgoWo6+uFn+f1PaalaZt9e2JZXvmZjcY5pQwGfbXSHAGu3yopAScBvsX1nQzrRgi8LFN/2XTMaoYjfZp+FiNiVMFCK7IlcfjeL1Shd5FrwcKnEGPeu6dVBvrZnKWaK81lzZnZc0Yce95rZMa7o8ccQBTWXE/S/ZXV10ctCO6KYa1/+l+zhvAfPt3WcU7OvcOh24kg/WSYOZFg9nFaLpMzSCTqZPhi7OE1LU5o0uLfk8kFJtJFj7CVG0YiD/dZhWhA0HW6WZmbE/DESkUMagfVPanZCZpweBBnmmRnJZr+LMm5btmgmZZ8/pwGk/JbvpwRaSvP1Cw/hIVq6m/EJ+j+oHr/EscxoVa2f9pGB20TOS7ggTPiwkvfWxX04CXCQ6VgQ8dFNZB4tO6LiNsCfSARDz0VNjqdpdRpON0W2KjfhKlX4IlhsQj9Cnet4Dk/knWe/vO2e2/JGw4JGXzJmguhT9EQE81IaGoKkcOBjED5odgONH37TyNK86piMBHYHRy/ZhpKOHbMhNh5Vv2mv94kzLMD6elXnRiL888tcc3hgi2fmZR6DVKvbiN2SIXRABQy6YNtKQVjMBzJEGART29AyD4r89L85T4jbheTiyXiDIX4H0eGGfqLsCJnSocV7GLm2ZJrKY/ebsg50fadj3AlxnU2Hqkxyn3Xdmf5ilM9lQ8xurrtsbGSSn6cQ/56X8Vm5gJa/4bFyMvuSl4ygKuAq6Ae8S7faeRUPkmObPOBdU841OmMWrjf8IeXzt+jkK00VglUC8y+ZhvX33ZYNXGjAACwZF11GCS3plkhI7zwtOlLNavtO94INQQGulQ/fG+mu4BAh19xtMiZpUXIumleO0ehq5LHiE/UYMZizvONyvPbCnqmkvEI8f9kgkODPkPBfQjqQ7qeGpU7BdbKEv83BTr5SyG6m80Fq0BDVdX5BwkGdk28YeJdbjUhUH0/fmSr7ODw6YYpE3x8TaDpOq+taNZu40KZ6USeNqEofSZPHC4e1+SwSpjldOoQTdH7BBaQ6hN0plJkm+4HL7KbWAQOX82W7H3Ks/GoMeHmokTo9T2JUTi+dzNpuaOjxlxyiuoDkiZ+0cOcLIbKk5Df0cphrkq2GrvCJ5g4FGvLvcPrs8tdA15D89i8Ygrh6ERy6beiwTCEtK5sqWM11URUrCCTRi3JRprzq+R+ghOPVGK1svfpUbzAyWZK6ugt3OYdg0Ze3WKFnvLqRAhWu6ouy+iHrT8D1qVna+6IZ3OCZbDpTlszQTA+5YNY9iO2O9seOJvbUOep5T04RETWFEr0vunp3M0FAH9OtaUN9ePmshqk3h1wC0oftx+8d5QvyJ/EkrXi4LA1huKDGtbf2P8RK2oH7wXKZaMZKYl2IGtc1lzIebtzkkqY/6ygl4K8mhFUf1g4vXSvA17mjdcemrptVCxB5EAnjiyBbjhVtoSE4RAmN7ysA95MeF104cf4AFUS2V3c4h7RTRb0HRIOfWhPc/UP6UZnXYx+ALCKyfSDXZ7v9Ctxfqnd/WwxKg233tcPBOgOVP72wSYiXt3HtHve5/NqBrz3PW7KJLoA5wTG43iURlkhvgIXJV6PK6BbCXgusT0ZHOtKUYIbhomZ1Wa+2VmCcljQdfN/qH7C1nS6Icr+OGHqoA4XBoj3OMZ1wQrP+9BwWhp9dxsLlT8lNQny8f9IIzvxZNyDNK7WOfRAHuO1x0Wf8aqA11SM8BL99m90PuLzMXK7zZgqKxJVF1Ry640/JMr8vaK01aKGwMEQXaUt/so94Z/FXm8uwZJ9Rw7ZIviyzdPmq7JXNa8W2kkeEEdekBKdCOD+Q63F0pzFoqvkrqram17GJHbGN/0DXoYrQGkJjuo7ZiwdJGagtuFah7Fut+bWvfmy5CnK6/6VKmLaWxPqjXZrCPru05KoKaMEPtJNElGIGkYmohX4fbwwwe0LvwZBrST+45+KzcApMOIqj2iSo+m5iwEMwpMIdJoor6Tsx7gdhS3ekeK9Ad7hZBFLNSYxL+sirfBfMHVYIDCLRrDwkssT0Qzd8wUTZG88TkyKxLWKMNAqwkab5lvEc5Vk3gjFLyQXbxKk8zhx9pBa9fWIcVJeQpVhJXayqWYBTsLCXZ42aWRehX9M6tuR9j8cyXHNQI6NXDB5WA05P5qKV8VauoVoLIWZlmVoH/bfiiPxTHTFdj08jpwPWtDKPYG6XRt3/DgF+e9TcIxsDT/Tci885fA6SP4e46yML5F4e4bUMusTkjBkMBuqrSzAZyIuj1Xady3xFW35EanmzAH0jOoz2Qycgv5BpFmjmHytw1nOxAC/gOja8UwzIxgFmB55QGQKikI8u9hNCAJEMkz1yozOucWR7rUbtj9YvXXTAfn/p3Ea517/FnxjVMvpUwJssldhApzEdN+eyNbs806+ucaJvevmM5IP7/xDFgAf/wx1zorLQHT6N5rDqqvRnDr7inwcLyQSjcS+DU47UEnyvTzoZ6jBwrJWJ22a8O4jwnVmqMqmsfjrcprJ/HjTwIbnKzN1fIIIZQuC0V2E5IyxcPdYMJPBBGQM6jd583pYU5Zg6bjdNy5K7w==";
|
public static string OnConfigRequest() => "{\r\n \"PackageVersion\": \"0.9.0\",\r\n \"LauncherVersion\": \"0.9.0\",\r\n \"ResourceVersion\": \"0.9.3\",\r\n \"LauncherIndexSha1\": {},\r\n \"ResourceIndexSha1\": {\r\n \"0.9.1\": \"F9E8CE07677A58BE26B8D1A193712167A5AD7D6E\",\r\n \"0.9.2\": \"2ACEAED17AC801D6860C61E4AFB4F9E8FB07EC71\",\r\n \"0.9.3\": \"6627F17FAA25267DFFB6875F845DF4CFA2DE67EA\"\r\n },\r\n \"ChangeList\": \"1162610\",\r\n \"CompatibleChangeLists\": [],\r\n \"Versions\": [\r\n {\r\n \"Name\": \"en\",\r\n \"Version\": \"0.9.3\",\r\n \"IndexSha1\": {\r\n \"0.9.1\": \"80083122F01DEFAE73F24F41F1B9D4F87B72B1BF\",\r\n \"0.9.2\": \"1C41F2D5DF38027153F16C777B9FAD3F27578E17\",\r\n \"0.9.3\": \"7A611990E039B3D7AD1EA505E1E9F544D310E9B8\"\r\n }\r\n },\r\n {\r\n \"Name\": \"ja\",\r\n \"Version\": \"0.9.3\",\r\n \"IndexSha1\": {\r\n \"0.9.1\": \"DBA7744B8994E20BB85D993DF9D2A214A3C09460\",\r\n \"0.9.2\": \"C22680FDAAEB25787B83800DDD1CB6C5AC66D285\",\r\n \"0.9.3\": \"8CACF6381D82BA3B577DF804DA2599ADDD8A5AE8\"\r\n }\r\n },\r\n {\r\n \"Name\": \"ko\",\r\n \"Version\": \"0.9.3\",\r\n \"IndexSha1\": {\r\n \"0.9.1\": \"DCA10D3FA125185A7F5F919FDD580474497912C6\",\r\n \"0.9.2\": \"1FEF3B7B05A1D5C8A346E03868976217B4C49E59\",\r\n \"0.9.3\": \"89631EAA41697A4ABFE785A53273FB50745114C9\"\r\n }\r\n },\r\n {\r\n \"Name\": \"zh\",\r\n \"Version\": \"0.9.3\",\r\n \"IndexSha1\": {\r\n \"0.9.1\": \"20CCECCEBBB910C14BE3CF111037F15287CB46E7\",\r\n \"0.9.2\": \"A176E35CFB6DB0C1CDE8B1B1EC141BD9479CFE59\",\r\n \"0.9.3\": \"66E3A0365D324E303A56F85E347F05EBBEA56645\"\r\n }\r\n }\r\n ]\r\n}";
|
||||||
|
|
||||||
public static string OnKeyListRequest() => "dJf580+dhY42au4yMyAS8bT83C9lOj2Igaw6GHLdgMgu45ugRZGzR2HUowgKaW/qQMY2v1+DubYu4hOeINFYWRbKpZUoKO+FHvPeeBAt00gqLBeHEnChvUSOPpAeJJp8ryfahbqy+LQ5d+2W/UOP83XZEVUIYPWleXbWUVMXLCCznOg76nWywXdHe9/Yukff8Di99tDt3NiSTdQPEtmk/c4vgXay+QTcFW8mwHgEhVh6vb9jQOMwvG4cmmjnigedTqW7Q4jm6GbgSWdb/tesmg70Jrjj4aHn6PI9jMSBSwk3tClBx8/Qwz1Ji+gyt/7XwvFmf+MZ8MyAH1DuIKrsomr7IfsMboKlr3T0EEIwVsb6idrbYaphGhefSemA/v2D";
|
public static string OnKeyListRequest() => "{\r\n \"Hash\": \"da39a3ee5e6b4b0d3255bfef95601890afd80709\",\r\n \"Random\": \"CtBIsHPiwhwOqqBYxj\",\r\n \"Key\": \"EYA/aRYz0h2W77M07J2AHTftgGQiIcFQFpgGsdsm65Ee8YqP6uI86fIG4EWftUr7B2vLbh/U62yi21e4CeGIpr+HppDDmpprS/QTmZYQ0OX9q/KB06+4ihmwzSim1iTedixejDPQ8BP90iH7CI6Se/+BhfslZh3MxDmzzl8W9bw=\"\r\n}";
|
||||||
|
|
||||||
public static FileContentHttpResult OnPakDataRequest()
|
public static FileContentHttpResult OnPakDataRequest()
|
||||||
=> TypedResults.File(Convert.FromHexString("446144334C5075782F544D35586C5A623669315A6A66774A32536265514843762B43567567764F41596B737A596874397164455861454B51626376474F664E544B536335754135444867385A674263356C4245654D6C374C43392F64326565473755796E754E59655753446C48624F544430785338514D39577165306F45706D5541353879377856304B38445970706D47683338386F51744C7A307472314C7743667A416D2F69536D70633D0A"));
|
=> TypedResults.File([]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,12 @@ public record BaseConfigModel
|
||||||
[JsonPropertyName("SecondaryUrl")]
|
[JsonPropertyName("SecondaryUrl")]
|
||||||
public required CdnUrlEntry[] SecondaryUrl { get; set; }
|
public required CdnUrlEntry[] SecondaryUrl { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("SpeedRatio")]
|
||||||
|
public int SpeedRatio { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("PriceRatio")]
|
||||||
|
public int PriceRatio { get; set; }
|
||||||
|
|
||||||
[JsonPropertyName("GmOpen")]
|
[JsonPropertyName("GmOpen")]
|
||||||
public bool GmOpen { get; set; }
|
public bool GmOpen { get; set; }
|
||||||
|
|
||||||
|
|
|
@ -7,19 +7,22 @@ internal static class Program
|
||||||
{
|
{
|
||||||
private static async Task Main(string[] args)
|
private static async Task Main(string[] args)
|
||||||
{
|
{
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
Console.Title = "Wuthering Waves | SDK Server";
|
||||||
|
Console.WriteLine(" __ __ __ .__ .__ __ __ \r\n/ \\ / \\__ ___/ |_| |__ ___________|__| ____ ____ / \\ / \\_____ ___ __ ____ ______\r\n\\ \\/\\/ / | \\ __\\ | \\_/ __ \\_ __ \\ |/ \\ / ___\\ \\ \\/\\/ /\\__ \\\\ \\/ // __ \\ / ___/\r\n \\ /| | /| | | Y \\ ___/| | \\/ | | \\/ /_/ > \\ / / __ \\\\ /\\ ___/ \\___ \\ \r\n \\__/\\ / |____/ |__| |___| /\\___ >__| |__|___| /\\___ / \\__/\\ / (____ /\\_/ \\___ >____ >\r\n \\/ \\/ \\/ \\//_____/ \\/ \\/ \\/ \\/ \r\n\r\n\t\t\t\t\t\t\t\t\t\t\t\tSDK Server\n");
|
||||||
|
|
||||||
|
WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
|
||||||
builder.WebHost.UseUrls("http://*:5500");
|
builder.WebHost.UseUrls("http://*:5500");
|
||||||
builder.Logging.AddSimpleConsole();
|
builder.Logging.AddSimpleConsole();
|
||||||
|
|
||||||
var app = builder.Build();
|
WebApplication app = builder.Build();
|
||||||
app.UseMiddleware<NotFoundMiddleware>();
|
app.UseMiddleware<NotFoundMiddleware>();
|
||||||
|
|
||||||
app.MapGet("/api/login", LoginHandler.Login);
|
app.MapGet("/api/login", LoginHandler.Login);
|
||||||
app.MapGet("/config/index.json", ConfigHandler.GetBaseConfig);
|
app.MapGet("/index.json", ConfigHandler.GetBaseConfig);
|
||||||
|
|
||||||
app.MapGet("/dev/client/7cyFLmtLJlUauZ1hM8DsL5Sj7cXxSNQD/Windows/KeyList_0.8.0.json", HotPatchHandler.OnKeyListRequest);
|
app.MapGet("/dev/client/mtZyW6ZYIu1pE0TCHUbXcM1oU8vx4hnb/Windows/KeyList_0.9.0.json", HotPatchHandler.OnKeyListRequest);
|
||||||
app.MapGet("/dev/client/7cyFLmtLJlUauZ1hM8DsL5Sj7cXxSNQD/Windows/config.json", HotPatchHandler.OnConfigRequest);
|
app.MapGet("/dev/client/mtZyW6ZYIu1pE0TCHUbXcM1oU8vx4hnb/Windows/config.json", HotPatchHandler.OnConfigRequest);
|
||||||
app.MapGet("/dev/client/7cyFLmtLJlUauZ1hM8DsL5Sj7cXxSNQD/Windows/client_key/0.8.0/xFrH845q3t8Pgy5eB2/PakData", HotPatchHandler.OnPakDataRequest);
|
app.MapGet("/dev/client/mtZyW6ZYIu1pE0TCHUbXcM1oU8vx4hnb/Windows/client_key/0.9.0/CtBIsHPiwhwOqqBYxj/PakData", HotPatchHandler.OnPakDataRequest);
|
||||||
|
|
||||||
await app.RunAsync();
|
await app.RunAsync();
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,13 @@
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<ApplicationIcon>icon.ico</ApplicationIcon>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Include="icon.ico" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="..\.editorconfig" Link=".editorconfig" />
|
<None Include="..\.editorconfig" Link=".editorconfig" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
BIN
SDKServer/icon.ico
Normal file
BIN
SDKServer/icon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 199 KiB |
52
TrafficAnalyzer/Program.cs
Normal file
52
TrafficAnalyzer/Program.cs
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
using Google.Protobuf;
|
||||||
|
using Protocol;
|
||||||
|
|
||||||
|
namespace TrafficAnalyzer;
|
||||||
|
|
||||||
|
internal static class Program
|
||||||
|
{
|
||||||
|
private const int StdInSize = 65535;
|
||||||
|
private const string ProtoAssembly = "Protocol";
|
||||||
|
private const string ProtoNamespace = "Protocol";
|
||||||
|
private const string MessageParserProperty = "Parser";
|
||||||
|
|
||||||
|
private static readonly DumpOptions s_objectDumperOpts = new() { DumpStyle = DumpStyle.CSharp, IndentSize = 4, IndentChar = ' ', IgnoreDefaultValues = true };
|
||||||
|
|
||||||
|
private static void Main(string[] args)
|
||||||
|
{
|
||||||
|
Console.SetIn(new StreamReader(Console.OpenStandardInput(StdInSize), Console.InputEncoding, false, StdInSize));
|
||||||
|
|
||||||
|
List<Tuple<int, byte[]>> inList = [];
|
||||||
|
|
||||||
|
string? idInput;
|
||||||
|
string? payloadInput;
|
||||||
|
|
||||||
|
while (!string.IsNullOrEmpty(idInput = Console.ReadLine()) && (payloadInput = Console.ReadLine()) != null)
|
||||||
|
{
|
||||||
|
int messageId = int.Parse(idInput);
|
||||||
|
byte[] payload = Convert.FromHexString(payloadInput);
|
||||||
|
|
||||||
|
inList.Add(Tuple.Create(messageId, payload));
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ((int messageId, byte[] payload) in inList)
|
||||||
|
{
|
||||||
|
string messageName = ((MessageId)messageId).ToString();
|
||||||
|
|
||||||
|
Type? type = Type.GetType($"{ProtoNamespace}.{messageName},{ProtoAssembly}");
|
||||||
|
if (type is null)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Message with id {messageName} wasn't found in proto definition.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageParser parser = (MessageParser)type.GetProperty(MessageParserProperty)!.GetValue(null)!;
|
||||||
|
IMessage message = parser.ParseFrom(payload);
|
||||||
|
|
||||||
|
string outputInitializer = ObjectDumper.Dump(message, s_objectDumperOpts);
|
||||||
|
|
||||||
|
Console.WriteLine($"Message: {messageName}");
|
||||||
|
Console.WriteLine(outputInitializer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
18
TrafficAnalyzer/TrafficAnalyzer.csproj
Normal file
18
TrafficAnalyzer/TrafficAnalyzer.csproj
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="ObjectDumper.NET" Version="4.1.15" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Protocol\Protocol.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
|
@ -12,9 +12,13 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GameServer", "GameServer\GameServer.csproj", "{78D639E8-D607-41F1-B0B8-AB1611ADE08F}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GameServer", "GameServer\GameServer.csproj", "{78D639E8-D607-41F1-B0B8-AB1611ADE08F}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KcpSharp", "KcpSharp\KcpSharp.csproj", "{C2BDCF0A-C256-4E97-9D9A-45FF5C8614CD}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KcpSharp", "KcpSharp\KcpSharp.csproj", "{C2BDCF0A-C256-4E97-9D9A-45FF5C8614CD}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Protocol", "Protocol\Protocol.csproj", "{9900A88C-7818-4335-84F7-1538ECC8B338}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Protocol", "Protocol\Protocol.csproj", "{9900A88C-7818-4335-84F7-1538ECC8B338}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Core", "Core\Core.csproj", "{C025BDED-6DC7-493D-8D10-05DCCB3072F3}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TrafficAnalyzer", "TrafficAnalyzer\TrafficAnalyzer.csproj", "{7DA57BA1-215F-4DD8-86A9-CAC62908A6F3}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
@ -38,6 +42,14 @@ Global
|
||||||
{9900A88C-7818-4335-84F7-1538ECC8B338}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{9900A88C-7818-4335-84F7-1538ECC8B338}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{9900A88C-7818-4335-84F7-1538ECC8B338}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{9900A88C-7818-4335-84F7-1538ECC8B338}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{9900A88C-7818-4335-84F7-1538ECC8B338}.Release|Any CPU.Build.0 = Release|Any CPU
|
{9900A88C-7818-4335-84F7-1538ECC8B338}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{C025BDED-6DC7-493D-8D10-05DCCB3072F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{C025BDED-6DC7-493D-8D10-05DCCB3072F3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{C025BDED-6DC7-493D-8D10-05DCCB3072F3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{C025BDED-6DC7-493D-8D10-05DCCB3072F3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{7DA57BA1-215F-4DD8-86A9-CAC62908A6F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{7DA57BA1-215F-4DD8-86A9-CAC62908A6F3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{7DA57BA1-215F-4DD8-86A9-CAC62908A6F3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{7DA57BA1-215F-4DD8-86A9-CAC62908A6F3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
Loading…
Reference in a new issue