mirror of
https://github.com/Anime-Game-Servers/Weedwacker.git
synced 2024-10-07 09:54:46 +00:00
OpenStates, fix some null pointers, many Login Packets, basic script engine
This commit is contained in:
parent
35236e9b40
commit
823ccee8fc
22
src/GameServer/Data/Excel/OpenStateData.cs
Normal file
22
src/GameServer/Data/Excel/OpenStateData.cs
Normal file
@ -0,0 +1,22 @@
|
||||
using Newtonsoft.Json;
|
||||
using Weedwacker.GameServer.Enums;
|
||||
|
||||
namespace Weedwacker.GameServer.Data.Excel
|
||||
{
|
||||
[Resource("OpenStateConfigData.json")]
|
||||
internal class OpenStateData
|
||||
{
|
||||
[JsonProperty] public readonly int id; // maps to OpenStateType enum
|
||||
[JsonProperty] public readonly bool defaultState;
|
||||
[JsonProperty] public readonly bool allowClientOpen;
|
||||
[JsonProperty] public readonly int systemOpenUiId;
|
||||
[JsonProperty] public readonly OpenStateCond[] cond;
|
||||
|
||||
public class OpenStateCond
|
||||
{
|
||||
[JsonProperty] public readonly OpenStateCondType condType;
|
||||
[JsonProperty] public readonly int param;
|
||||
[JsonProperty] public readonly int param2;
|
||||
}
|
||||
}
|
||||
}
|
23
src/GameServer/Data/Excel/SceneTagData.cs
Normal file
23
src/GameServer/Data/Excel/SceneTagData.cs
Normal file
@ -0,0 +1,23 @@
|
||||
using Newtonsoft.Json;
|
||||
using Weedwacker.GameServer.Enums;
|
||||
|
||||
namespace Weedwacker.GameServer.Data.Excel
|
||||
{
|
||||
[Resource("SceneTagConfigData.json")]
|
||||
internal class SceneTagData
|
||||
{
|
||||
[JsonProperty] public readonly int id;
|
||||
[JsonProperty] public readonly string sceneTagName;
|
||||
[JsonProperty] public readonly int sceneId;
|
||||
[JsonProperty] public readonly bool isDefaultValid;
|
||||
//TODO Missing one field
|
||||
[JsonProperty] public readonly TagCond[] cond;
|
||||
|
||||
public class TagCond
|
||||
{
|
||||
[JsonProperty] public readonly SceneTagCondType condType;
|
||||
[JsonProperty] public readonly int param1;
|
||||
[JsonProperty] public readonly int? param2;
|
||||
}
|
||||
}
|
||||
}
|
20
src/GameServer/Data/Excel/WeatherData.cs
Normal file
20
src/GameServer/Data/Excel/WeatherData.cs
Normal file
@ -0,0 +1,20 @@
|
||||
using Newtonsoft.Json;
|
||||
using Weedwacker.GameServer.Enums;
|
||||
|
||||
namespace Weedwacker.GameServer.Data.Excel
|
||||
{
|
||||
[Resource("WeatherExcelConfigData.json")]
|
||||
internal class WeatherData
|
||||
{
|
||||
[JsonProperty] public readonly int areaId;
|
||||
[JsonProperty] public readonly int weatherAreaId;
|
||||
[JsonProperty] public readonly string maxHeightStr;
|
||||
[JsonProperty] public readonly int gadgetId;
|
||||
[JsonProperty] public readonly bool isDefaultValid;
|
||||
[JsonProperty] public readonly int priority;
|
||||
[JsonProperty] public readonly string profileName;
|
||||
[JsonProperty] public readonly ClimateType defaultClimate;
|
||||
[JsonProperty] public readonly bool isUseDefault;
|
||||
[JsonProperty] public readonly int sceneId;
|
||||
}
|
||||
}
|
@ -1,11 +1,13 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Text.RegularExpressions;
|
||||
using Newtonsoft.Json;
|
||||
using NLua;
|
||||
using Weedwacker.GameServer.Data.BinOut.AbilityGroup;
|
||||
using Weedwacker.GameServer.Data.BinOut.Scene.Point;
|
||||
using Weedwacker.GameServer.Data.BinOut.Scene.SceneNpcBorn;
|
||||
using Weedwacker.GameServer.Data.BinOut.Talent;
|
||||
using Weedwacker.GameServer.Data.Excel;
|
||||
using Weedwacker.GameServer.Systems.Script.Scene;
|
||||
using Weedwacker.Shared.Utils;
|
||||
using static Weedwacker.GameServer.Data.SerializationSettings;
|
||||
|
||||
@ -47,24 +49,27 @@ namespace Weedwacker.GameServer.Data
|
||||
public readonly static SortedList<int, MonsterCurveData> MonsterCurveDataMap = new(); // level
|
||||
public readonly static SortedList<int, MonsterData> MonsterDataMap = new(); // id
|
||||
public readonly static SortedList<int, MonsterDescribeData> MonsterDescribeDataMap = new(); // id
|
||||
public readonly static SortedList<int, OpenStateData> OpenStateDataMap = new(); // id
|
||||
public readonly static SortedList<string, BaseConfigTalent[]> RelicAffixConfigDataMap = new(); // openConfig
|
||||
public readonly static SortedList<int, ShopData> ShopDataMap = new(); // shopId
|
||||
public readonly static SortedList<int, RewardData> RewardDataMap = new(); // RewardId
|
||||
public readonly static SortedList<int, ShopGoodsData> ShopGoodsDataMap = new(); // goodsId
|
||||
public readonly static ConcurrentDictionary<string, BaseConfigTalent[]> TeamResonanceConfigDataMap = new(); // openConfig
|
||||
public readonly static ConcurrentDictionary<string, BaseConfigTalent[]> WeaponAffixConfigDataMap = new(); // openConfig
|
||||
public readonly static SortedList<int, WeaponCurveData> WeaponCurveDataMap = new(); // level
|
||||
public readonly static SortedList<Tuple<int, int>, WeaponPromoteData> WeaponPromoteDataMap = new(); // <weaponPromoteId, promoteLevel>
|
||||
public readonly static SortedList<int, ReliquaryAffixData> ReliquaryAffixDataMap = new(); // id
|
||||
public readonly static SortedList<int, ReliquaryMainPropData> ReliquaryMainPropDataMap = new(); // id
|
||||
public readonly static SortedList<Tuple<int, int>, ReliquaryLevelData> ReliquaryLevelDataMap = new(); // <rank, level>
|
||||
public readonly static SortedList<int, ReliquarySetData> ReliquarySetDataMap = new(); // setid
|
||||
public readonly static SortedList<int, SceneData> SceneDataMap = new(); //id
|
||||
public readonly static SortedList<int, SceneData> SceneDataMap = new(); // id
|
||||
public readonly static ConcurrentDictionary<string, ScenePointData> ScenePointDataMap = new(); // filename
|
||||
public readonly static ConcurrentDictionary<int, SceneNpcBornData> SceneNpcBornDataMap = new(); // sceneId
|
||||
public readonly static SortedList<int, SceneTagData> SceneTagDataMap = new(); // id
|
||||
public readonly static SortedList<int, TeamResonanceData> TeamResonanceDataMap = new(); // teamResonanceId
|
||||
public readonly static ConcurrentDictionary<string, BaseConfigTalent[]> WeaponAffixConfigDataMap = new(); // openConfig
|
||||
public readonly static SortedList<int, WeaponCurveData> WeaponCurveDataMap = new(); // level
|
||||
public readonly static SortedList<Tuple<int, int>, WeaponPromoteData> WeaponPromoteDataMap = new(); // <weaponPromoteId, promoteLevel>
|
||||
public readonly static SortedList<int, WeatherData> WeatherDataMap = new(); // areaId
|
||||
|
||||
|
||||
public readonly static SortedList<int, SceneInfo> SceneScripts = new();
|
||||
|
||||
static readonly JsonSerializer Serializer = new()
|
||||
{
|
||||
@ -83,7 +88,23 @@ namespace Weedwacker.GameServer.Data
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static async Task LoadScripts(string path)
|
||||
{
|
||||
var dirs = Directory.GetDirectories(Path.Combine(path, "Scene"));
|
||||
foreach(var fileAndPath in dirs)
|
||||
{
|
||||
string fullPath = Path.GetFullPath(fileAndPath);
|
||||
int sceneId = int.Parse(fullPath.Split("\\").Last());
|
||||
await LoadSceneScripts(sceneId, path);
|
||||
}
|
||||
}
|
||||
|
||||
static async Task LoadSceneScripts(int sceneId, string scriptPath)
|
||||
{
|
||||
Lua lua = new();
|
||||
var SceneX = await SceneInfo.CreateAsync(lua, sceneId, scriptPath);
|
||||
SceneScripts.Add(sceneId, SceneX);
|
||||
}
|
||||
|
||||
|
||||
static async Task LoadBinOutFolder<Obj, Key>(string path, Func<Obj, Key> keySelector, IDictionary<Key, Obj> map) where Key : notnull
|
||||
@ -166,6 +187,7 @@ namespace Weedwacker.GameServer.Data
|
||||
{
|
||||
string excelPath = Path.Combine(resourcesPath, "ExcelBinOutput/");
|
||||
string binPath = Path.Combine(resourcesPath, "BinOutput/");
|
||||
string scriptPath = Path.Combine(resourcesPath, "Scripts/");
|
||||
await Task.WhenAll(new Task[]
|
||||
{
|
||||
LoadExcel(excelPath, o => o.sortId, AvatarCodexDataMap),
|
||||
@ -194,6 +216,7 @@ namespace Weedwacker.GameServer.Data
|
||||
LoadExcel(excelPath, o => o.level, MonsterCurveDataMap),
|
||||
LoadExcel(excelPath, o => o.id, MonsterDataMap),
|
||||
LoadExcel(excelPath, o => o.id, MonsterDescribeDataMap),
|
||||
LoadExcel(excelPath, o => o.id, OpenStateDataMap),
|
||||
LoadExcel(excelPath, o => o.fetterId, PhotographExpressionDataMap),
|
||||
LoadExcel(excelPath, o => o.fetterId, PhotographPosenameDataMap),
|
||||
LoadExcel(excelPath, o => o.proudSkillId, ProudSkillDataMap),
|
||||
@ -204,12 +227,14 @@ namespace Weedwacker.GameServer.Data
|
||||
LoadExcel(excelPath, o => o.setId, ReliquarySetDataMap),
|
||||
LoadExcel(excelPath, o => o.rewardId, RewardDataMap),
|
||||
LoadExcel(excelPath, o => o.id, SceneDataMap),
|
||||
LoadExcel(excelPath, o => o.id, SceneTagDataMap),
|
||||
LoadExcel(excelPath, o => o.shopId, ShopDataMap),
|
||||
LoadExcel(excelPath, o=> o.goodsId, ShopGoodsDataMap),
|
||||
LoadExcel(excelPath, o => o.teamResonanceId, TeamResonanceDataMap),
|
||||
LoadExcel<ItemData, int, WeaponData>(excelPath, o => o.id, ItemDataMap),
|
||||
LoadExcel(excelPath, o => o.level, WeaponCurveDataMap),
|
||||
LoadExcel(excelPath, o => Tuple.Create(o.weaponPromoteId, o.promoteLevel), WeaponPromoteDataMap),
|
||||
LoadExcel(excelPath, o => o.areaId, WeatherDataMap),
|
||||
|
||||
LoadBinOutFolder(Path.Combine(binPath, "Scene/SceneNpcBorn"), o => o.sceneId, SceneNpcBornDataMap),
|
||||
LoadBinOutFolder(Path.Combine(binPath, "AbilityGroup"), AbilityGroupDataMap),
|
||||
@ -220,6 +245,8 @@ namespace Weedwacker.GameServer.Data
|
||||
LoadBinOutFolder(Path.Combine(binPath, "Scene/Point"), ScenePointDataMap, false)
|
||||
});
|
||||
|
||||
await LoadScripts(scriptPath);
|
||||
|
||||
Logger.DebugWriteLine("Loaded Resources");
|
||||
}
|
||||
}
|
||||
|
@ -156,6 +156,23 @@ namespace Weedwacker.GameServer.Database
|
||||
return player;
|
||||
}
|
||||
|
||||
// Don't create a player when requested by gameUid
|
||||
public static async Task<Player?> GetPlayerByGameUidAsync(int gameUid)
|
||||
{
|
||||
var player = await Players.Find(w => w.GameUid == gameUid).FirstOrDefaultAsync();
|
||||
if (player == null) return null;
|
||||
|
||||
//Attach player systems to the player
|
||||
player.Avatars = await GetAvatarsByPlayerAsync(player) ?? await SaveAvatarsAsync(new AvatarManager(player)); // Load avatars before inventory, so that we can attach weapons while loading them
|
||||
player.Inventory = await GetInventoryByPlayerAsync(player) ?? await SaveInventoryAsync(new InventoryManager(player));
|
||||
player.Inventory.ShopManager = await GetShopsByPlayerAsync(player) ?? await SaveShopsAsync(new ShopManager(player));
|
||||
player.SocialManager = await GetSocialByPlayerAsync(player) ?? await SaveSocialAsync(new SocialManager(player));
|
||||
player.TeamManager = await GetTeamsByPlayerAsync(player) ?? await SaveTeamsAsync(new TeamManager(player));
|
||||
await player.OnLoadAsync();
|
||||
|
||||
return player;
|
||||
}
|
||||
|
||||
public static async Task<AvatarManager> SaveAvatarsAsync(AvatarManager avatars)
|
||||
{
|
||||
await Avatars.ReplaceOneAsync<AvatarManager>(w => w.OwnerId == avatars.OwnerId, avatars, Replace);
|
||||
|
16
src/GameServer/Enums/ClimateType.cs
Normal file
16
src/GameServer/Enums/ClimateType.cs
Normal file
@ -0,0 +1,16 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
|
||||
namespace Weedwacker.GameServer.Enums
|
||||
{
|
||||
[JsonConverter(typeof(StringEnumConverter))]
|
||||
public enum ClimateType
|
||||
{
|
||||
CLIMATE_DESERT,
|
||||
CLIMATE_SUNNY,
|
||||
CLIMATE_CLOUDY,
|
||||
CLIMATE_MIST,
|
||||
CLIMATE_RAIN,
|
||||
CLIMATE_THUNDERSTORM
|
||||
}
|
||||
}
|
15
src/GameServer/Enums/OpenStateCondType.cs
Normal file
15
src/GameServer/Enums/OpenStateCondType.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
|
||||
namespace Weedwacker.GameServer.Enums
|
||||
{
|
||||
[JsonConverter(typeof(StringEnumConverter))]
|
||||
public enum OpenStateCondType
|
||||
{
|
||||
OPEN_STATE_COND_PARENT_QUEST,
|
||||
OPEN_STATE_COND_QUEST,
|
||||
OPEN_STATE_COND_PLAYER_LEVEL,
|
||||
OPEN_STATE_OFFERING_LEVEL,
|
||||
OPEN_STATE_CITY_REPUTATION_LEVEL
|
||||
}
|
||||
}
|
15
src/GameServer/Enums/SceneTagCondType.cs
Normal file
15
src/GameServer/Enums/SceneTagCondType.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
|
||||
namespace Weedwacker.GameServer.Enums
|
||||
{
|
||||
[JsonConverter(typeof(StringEnumConverter))]
|
||||
public enum SceneTagCondType
|
||||
{
|
||||
NONE, // Don't use
|
||||
SCENE_TAG_COND_TYPE_SPECIFIC_ACTIVITY_OPEN,
|
||||
SCENE_TAG_COND_TYPE_ACTIVITY_CONTENT_OPEN,
|
||||
SCENE_TAG_COND_TYPE_QUEST_GLOBAL_VAR_EQUAL,
|
||||
SCENE_TAG_COND_TYPE_QUEST_FINISH,
|
||||
}
|
||||
}
|
@ -9,6 +9,7 @@ using Weedwacker.GameServer.Data;
|
||||
using Weedwacker.GameServer.Systems.Avatar;
|
||||
using Weedwacker.GameServer.Systems.World;
|
||||
using Weedwacker.Shared.Authentication;
|
||||
using Weedwacker.Shared.Network.Proto;
|
||||
using Weedwacker.Shared.Utils.Configuration;
|
||||
|
||||
namespace Weedwacker.GameServer
|
||||
@ -16,6 +17,7 @@ namespace Weedwacker.GameServer
|
||||
internal static class GameServer
|
||||
{
|
||||
private static readonly HttpClient client = new HttpClient();
|
||||
|
||||
public static GameConfig Configuration;
|
||||
public static SortedList<int,Connection> OnlinePlayers = new(); // <gameUid,connection>
|
||||
private static HashSet<World> Worlds = new();
|
||||
@ -68,5 +70,23 @@ namespace Weedwacker.GameServer
|
||||
//TODO
|
||||
return int.MaxValue;
|
||||
}
|
||||
|
||||
internal static async Task<SocialDetail?> GetSocialDetailByUid(int askerUid, uint reqUid)
|
||||
{
|
||||
SocialDetail socialDetail;
|
||||
if (OnlinePlayers.TryGetValue((int)reqUid, out Connection session))
|
||||
{
|
||||
return session.Player.SocialManager.GetSocialDetail(askerUid);
|
||||
}
|
||||
else
|
||||
{
|
||||
var player = await Database.DatabaseManager.GetPlayerByGameUidAsync((int)reqUid);
|
||||
if (player != null)
|
||||
return player.SocialManager.GetSocialDetail(askerUid);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,8 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MongoDB.Driver" Version="2.17.1" />
|
||||
<PackageReference Include="MongoDB.Driver" Version="2.18.0" />
|
||||
<PackageReference Include="NLua" Version="1.4.32" />
|
||||
<PackageReference Include="Vim.Math3D" Version="1.6.0" />
|
||||
<ProjectReference Include="..\Shared\Shared.csproj" />
|
||||
</ItemGroup>
|
||||
|
34
src/GameServer/Packet/Recv/HandleEnterSceneDoneReq.cs
Normal file
34
src/GameServer/Packet/Recv/HandleEnterSceneDoneReq.cs
Normal file
@ -0,0 +1,34 @@
|
||||
using Weedwacker.GameServer.Enums;
|
||||
using Weedwacker.GameServer.Packet.Send;
|
||||
|
||||
namespace Weedwacker.GameServer.Packet.Recv
|
||||
{
|
||||
[OpCode((ushort)OpCode.EnterSceneDoneReq)]
|
||||
internal class HandleEnterSceneDoneReq : BaseHandler
|
||||
{
|
||||
public override async Task HandleAsync(Connection session, byte[] header, byte[] payload)
|
||||
{
|
||||
// Finished loading
|
||||
session.Player.SceneLoadState = SceneLoadState.LOADED;
|
||||
|
||||
// Done
|
||||
|
||||
// Spawn player in world
|
||||
await session.Player.Scene.SpawnPlayerAsync(session.Player);
|
||||
|
||||
// Spawn other entites already in world
|
||||
await session.Player.Scene.ShowOtherEntitiesAsync(session.Player);
|
||||
|
||||
// Locations
|
||||
await session.SendPacketAsync(new PacketWorldPlayerLocationNotify(session.Player.World));
|
||||
await session.SendPacketAsync(new PacketScenePlayerLocationNotify(session.Player.Scene));
|
||||
await session.SendPacketAsync(new PacketWorldPlayerRTTNotify(session.Player.World));
|
||||
|
||||
|
||||
// Reset timer for sending player locations
|
||||
session.Player.ResetSendPlayerLocTime();
|
||||
//Rsp
|
||||
await session.SendPacketAsync(new PacketEnterSceneDoneRsp(session.Player));
|
||||
}
|
||||
}
|
||||
}
|
22
src/GameServer/Packet/Recv/HandleEnterSceneReadyReq.cs
Normal file
22
src/GameServer/Packet/Recv/HandleEnterSceneReadyReq.cs
Normal file
@ -0,0 +1,22 @@
|
||||
using Weedwacker.GameServer.Enums;
|
||||
using Weedwacker.GameServer.Packet.Send;
|
||||
using Weedwacker.Shared.Network.Proto;
|
||||
|
||||
namespace Weedwacker.GameServer.Packet.Recv
|
||||
{
|
||||
[OpCode((ushort)OpCode.EnterSceneReadyReq)]
|
||||
internal class HandleEnterSceneReadyReq : BaseHandler
|
||||
{
|
||||
public override async Task HandleAsync(Connection session, byte[] header, byte[] payload)
|
||||
{
|
||||
EnterSceneReadyReq proto = EnterSceneReadyReq.Parser.ParseFrom(payload);
|
||||
// Reject player if invalid token
|
||||
if (session.Player.EnterSceneToken == proto.EnterSceneToken)
|
||||
{
|
||||
await session.Player.World.BroadcastPacketAsync(new PacketEnterScenePeerNotify(session.Player));
|
||||
|
||||
}
|
||||
await session.SendPacketAsync(new PacketEnterSceneReadyRsp(session.Player, proto.EnterSceneToken));
|
||||
}
|
||||
}
|
||||
}
|
27
src/GameServer/Packet/Recv/HandleEnterWorldAreaReq.cs
Normal file
27
src/GameServer/Packet/Recv/HandleEnterWorldAreaReq.cs
Normal file
@ -0,0 +1,27 @@
|
||||
using Weedwacker.GameServer.Enums;
|
||||
using Weedwacker.GameServer.Packet.Send;
|
||||
using Weedwacker.Shared.Network.Proto;
|
||||
|
||||
namespace Weedwacker.GameServer.Packet.Recv
|
||||
{
|
||||
[OpCode((ushort)OpCode.EnterWorldAreaReq)]
|
||||
internal class HandleEnterWorldAreaReq : BaseHandler
|
||||
{
|
||||
public override async Task HandleAsync(Connection session, byte[] header, byte[] payload)
|
||||
{
|
||||
/*
|
||||
* The client determines the AreaID from its position relative to
|
||||
* the polygonData's min and max Area in sceneX_worldArea.json
|
||||
* AreaType == 1 => looks in level1Area, use id2
|
||||
* AreaType == 2 => looks in level2Areas, use id1
|
||||
*/
|
||||
EnterWorldAreaReq req = EnterWorldAreaReq.Parser.ParseFrom(payload);
|
||||
uint areaId = req.AreaId;
|
||||
uint areaType = req.AreaType;
|
||||
|
||||
await session.Player.EnterWorldAreaAsync(areaType, areaId);
|
||||
|
||||
await session.SendPacketAsync(new PacketEnterWorldAreaRsp(session.Player, areaId, areaType));
|
||||
}
|
||||
}
|
||||
}
|
19
src/GameServer/Packet/Recv/HandleGetPlayerSocialDetailReq.cs
Normal file
19
src/GameServer/Packet/Recv/HandleGetPlayerSocialDetailReq.cs
Normal file
@ -0,0 +1,19 @@
|
||||
using Weedwacker.GameServer.Enums;
|
||||
using Weedwacker.GameServer.Packet.Send;
|
||||
using Weedwacker.Shared.Network.Proto;
|
||||
|
||||
namespace Weedwacker.GameServer.Packet.Recv
|
||||
{
|
||||
[OpCode((ushort)OpCode.GetPlayerSocialDetailReq)]
|
||||
internal class HandleGetPlayerSocialDetailReq : BaseHandler
|
||||
{
|
||||
public override async Task HandleAsync(Connection session, byte[] header, byte[] payload)
|
||||
{
|
||||
GetPlayerSocialDetailReq req = GetPlayerSocialDetailReq.Parser.ParseFrom(payload);
|
||||
|
||||
SocialDetail? detail = await GameServer.GetSocialDetailByUid(session.Player.GameUid, req.Uid);
|
||||
|
||||
await session.SendPacketAsync(new PacketGetPlayerSocialDetailRsp(detail));
|
||||
}
|
||||
}
|
||||
}
|
@ -12,7 +12,7 @@ using Weedwacker.Shared.Utils;
|
||||
|
||||
namespace Weedwacker.GameServer.Packet.Recv
|
||||
{
|
||||
[OpCode("GetPlayerTokenReq")]
|
||||
[OpCode((ushort)OpCode.GetPlayerTokenReq)]
|
||||
internal class HandleGetPlayerTokenReq : BaseHandler
|
||||
{
|
||||
public override async Task HandleAsync(Connection session, byte[] header, byte[] payload)
|
||||
@ -39,6 +39,8 @@ namespace Weedwacker.GameServer.Packet.Recv
|
||||
session.Stop();
|
||||
return;
|
||||
}
|
||||
else
|
||||
GameServer.OnlinePlayers.Add(session.Player.GameUid, session);
|
||||
|
||||
// Update the player's session pointer
|
||||
session.Player.Session = session;
|
||||
|
17
src/GameServer/Packet/Recv/HandlePathfindingEnterSceneReq.cs
Normal file
17
src/GameServer/Packet/Recv/HandlePathfindingEnterSceneReq.cs
Normal file
@ -0,0 +1,17 @@
|
||||
using Weedwacker.GameServer.Enums;
|
||||
using Weedwacker.GameServer.Packet.Send;
|
||||
using Weedwacker.Shared.Network.Proto;
|
||||
|
||||
namespace Weedwacker.GameServer.Packet.Recv
|
||||
{
|
||||
[OpCode((ushort)OpCode.PathfindingEnterSceneReq)]
|
||||
internal class HandlePathfindingEnterSceneReq : BaseHandler
|
||||
{
|
||||
public override async Task HandleAsync(Connection session, byte[] header, byte[] payload)
|
||||
{
|
||||
PacketHead head = PacketHead.Parser.ParseFrom(header);
|
||||
PathfindingEnterSceneReq req = PathfindingEnterSceneReq.Parser.ParseFrom(payload);
|
||||
await session.SendPacketAsync(new PacketPathfindingEnterSceneRsp(head.ClientSequenceId));
|
||||
}
|
||||
}
|
||||
}
|
@ -4,7 +4,7 @@ using Weedwacker.Shared.Network.Proto;
|
||||
|
||||
namespace Weedwacker.GameServer.Packet.Recv
|
||||
{
|
||||
[OpCode("PingReq")]
|
||||
[OpCode((ushort)OpCode.PingReq)]
|
||||
internal class HandlePingReq : BaseHandler
|
||||
{
|
||||
public override async Task HandleAsync(Connection session, byte[] header, byte[] payload)
|
||||
|
@ -4,7 +4,7 @@ using Weedwacker.Shared.Network.Proto;
|
||||
|
||||
namespace Weedwacker.GameServer.Packet.Recv
|
||||
{
|
||||
[OpCode("PlayerLoginReq")]
|
||||
[OpCode((ushort)OpCode.PlayerLoginReq)]
|
||||
internal class HandlePlayerLoginReq : BaseHandler
|
||||
{
|
||||
public override async Task HandleAsync(Connection session, byte[] header, byte[] payload)
|
||||
|
@ -4,7 +4,7 @@ using Weedwacker.Shared.Network.Proto;
|
||||
|
||||
namespace Weedwacker.GameServer.Packet.Recv
|
||||
{
|
||||
[OpCode("PlayerSetPauseReq")]
|
||||
[OpCode((ushort)OpCode.PlayerSetPauseReq)]
|
||||
internal class HandlePlayerSetPauseReq : BaseHandler
|
||||
{
|
||||
public override async Task HandleAsync(Connection session, byte[] header, byte[] payload)
|
||||
|
19
src/GameServer/Packet/Recv/HandlePostEnterSceneReq.cs
Normal file
19
src/GameServer/Packet/Recv/HandlePostEnterSceneReq.cs
Normal file
@ -0,0 +1,19 @@
|
||||
using Weedwacker.GameServer.Enums;
|
||||
using Weedwacker.GameServer.Packet.Send;
|
||||
|
||||
namespace Weedwacker.GameServer.Packet.Recv
|
||||
{
|
||||
[OpCode((ushort)OpCode.PostEnterSceneReq)]
|
||||
internal class HandlePostEnterSceneReq : BaseHandler
|
||||
{
|
||||
public override async Task HandleAsync(Connection session, byte[] header, byte[] payload)
|
||||
{
|
||||
if (session.Player.Scene.SceneData.type == SceneType.SCENE_ROOM)
|
||||
{
|
||||
//await session.Player.QuestManager.TriggerEventAsync(QuestTrigger.QUEST_CONTENT_ENTER_ROOM, session.Player.SceneId, 0);
|
||||
}
|
||||
|
||||
await session.SendPacketAsync(new PacketPostEnterSceneRsp(session.Player));
|
||||
}
|
||||
}
|
||||
}
|
40
src/GameServer/Packet/Recv/HandleSceneInitFinishReq.cs
Normal file
40
src/GameServer/Packet/Recv/HandleSceneInitFinishReq.cs
Normal file
@ -0,0 +1,40 @@
|
||||
using Weedwacker.GameServer.Enums;
|
||||
using Weedwacker.GameServer.Packet.Send;
|
||||
|
||||
namespace Weedwacker.GameServer.Packet.Recv
|
||||
{
|
||||
[OpCode((ushort)OpCode.SceneInitFinishReq)]
|
||||
internal class HandleSceneInitFinishReq : BaseHandler
|
||||
{
|
||||
public override async Task HandleAsync(Connection session, byte[] header, byte[] payload)
|
||||
{
|
||||
// Info packets
|
||||
await Task.WhenAll(new Task[]
|
||||
{
|
||||
session.SendPacketAsync(new PacketServerTimeNotify()),
|
||||
session.Player.World.BroadcastPacketAsync(new PacketWorldPlayerInfoNotify(session.Player.World)),
|
||||
session.SendPacketAsync(new PacketWorldDataNotify(session.Player.World)),
|
||||
session.SendPacketAsync(new PacketPlayerWorldSceneInfoListNotify(session.Player.Scene)),
|
||||
session.SendPacketAsync(new PacketSceneForceUnlockNotify()),
|
||||
session.SendPacketAsync(new BasePacket(OpCode.SceneDataNotify)),
|
||||
session.SendPacketAsync(new PacketHostPlayerNotify(session.Player.World)),
|
||||
session.SendPacketAsync(new PacketSceneTimeNotify(session.Player)),
|
||||
session.SendPacketAsync(new PacketPlayerGameTimeNotify(session.Player)),
|
||||
session.Player.Scene.BroadcastPacketAsync(new PacketPlayerEnterSceneInfoNotify(session.Player)),
|
||||
session.Player.Scene.UpdateActiveAreaWeathersAsync(session.Player.WorldAreaIds),
|
||||
|
||||
session.SendPacketAsync(new PacketScenePlayerInfoNotify(session.Player.World)),
|
||||
session.Player.Scene.BroadcastPacketAsync(new PacketSceneTeamUpdateNotify(session.Player)),
|
||||
session.Player.Scene.BroadcastPacketAsync(new PacketSyncTeamEntityNotify(session.Player)),
|
||||
session.Player.Scene.BroadcastPacketAsync(new PacketSyncScenePlayTeamEntityNotify(session.Player)),
|
||||
|
||||
}); ;
|
||||
|
||||
// Done Packet
|
||||
await session.SendPacketAsync(new PacketSceneInitFinishRsp(session.Player));
|
||||
|
||||
// Set state
|
||||
session.Player.SceneLoadState = SceneLoadState.INIT;
|
||||
}
|
||||
}
|
||||
}
|
22
src/GameServer/Packet/Recv/HandleSetOpenStateReq.cs
Normal file
22
src/GameServer/Packet/Recv/HandleSetOpenStateReq.cs
Normal file
@ -0,0 +1,22 @@
|
||||
using Weedwacker.GameServer.Enums;
|
||||
using Weedwacker.GameServer.Packet.Send;
|
||||
using Weedwacker.Shared.Network.Proto;
|
||||
|
||||
namespace Weedwacker.GameServer.Packet.Recv
|
||||
{
|
||||
[OpCode((ushort)OpCode.SetOpenStateReq)]
|
||||
internal class HandleSetOpenStateReq : BaseHandler
|
||||
{
|
||||
public override async Task HandleAsync(Connection session, byte[] header, byte[] payload)
|
||||
{
|
||||
var req = SetOpenStateReq.Parser.ParseFrom(payload);
|
||||
uint openState = req.Key;
|
||||
uint value = req.Value;
|
||||
|
||||
if (await session.Player.OpenStateManager.SetOpenStateFromClientAsync(openState, value))
|
||||
await session.SendPacketAsync(new PacketSetOpenStateRsp(openState, value));
|
||||
else
|
||||
await session.SendPacketAsync(new PacketSetOpenStateRsp(Retcode.RetFail));
|
||||
}
|
||||
}
|
||||
}
|
19
src/GameServer/Packet/Send/PacketEnterSceneDoneRsp.cs
Normal file
19
src/GameServer/Packet/Send/PacketEnterSceneDoneRsp.cs
Normal file
@ -0,0 +1,19 @@
|
||||
using Google.Protobuf;
|
||||
using Weedwacker.GameServer.Systems.Player;
|
||||
using Weedwacker.Shared.Network.Proto;
|
||||
|
||||
namespace Weedwacker.GameServer.Packet.Send
|
||||
{
|
||||
internal class PacketEnterSceneDoneRsp : BasePacket
|
||||
{
|
||||
public PacketEnterSceneDoneRsp(Player player) : base(Enums.OpCode.EnterSceneDoneRsp)
|
||||
{
|
||||
EnterSceneDoneRsp p = new EnterSceneDoneRsp()
|
||||
{
|
||||
EnterSceneToken = player.EnterSceneToken
|
||||
};
|
||||
|
||||
Data = p.ToByteArray();
|
||||
}
|
||||
}
|
||||
}
|
22
src/GameServer/Packet/Send/PacketEnterScenePeerNotify.cs
Normal file
22
src/GameServer/Packet/Send/PacketEnterScenePeerNotify.cs
Normal file
@ -0,0 +1,22 @@
|
||||
using Google.Protobuf;
|
||||
using Weedwacker.GameServer.Systems.Player;
|
||||
using Weedwacker.Shared.Network.Proto;
|
||||
|
||||
namespace Weedwacker.GameServer.Packet.Send
|
||||
{
|
||||
internal class PacketEnterScenePeerNotify : BasePacket
|
||||
{
|
||||
public PacketEnterScenePeerNotify(Player player) : base(Enums.OpCode.EnterScenePeerNotify)
|
||||
{
|
||||
EnterScenePeerNotify proto = new EnterScenePeerNotify()
|
||||
{
|
||||
DestSceneId = (uint)player.SceneId,
|
||||
PeerId = player.PeerId,
|
||||
HostPeerId = player.World.GetHostPeerId(),
|
||||
EnterSceneToken = player.EnterSceneToken
|
||||
};
|
||||
|
||||
Data = proto.ToByteArray();
|
||||
}
|
||||
}
|
||||
}
|
20
src/GameServer/Packet/Send/PacketEnterSceneReadyRsp.cs
Normal file
20
src/GameServer/Packet/Send/PacketEnterSceneReadyRsp.cs
Normal file
@ -0,0 +1,20 @@
|
||||
using Google.Protobuf;
|
||||
using Weedwacker.GameServer.Systems.Player;
|
||||
using Weedwacker.Shared.Network.Proto;
|
||||
|
||||
namespace Weedwacker.GameServer.Packet.Send
|
||||
{
|
||||
internal class PacketEnterSceneReadyRsp : BasePacket
|
||||
{
|
||||
public PacketEnterSceneReadyRsp(Player player, uint token) : base(Enums.OpCode.EnterSceneReadyRsp, 11)
|
||||
{
|
||||
EnterSceneReadyRsp p = new EnterSceneReadyRsp();
|
||||
if (token == player.EnterSceneToken)
|
||||
p.EnterSceneToken = token;
|
||||
else
|
||||
p.Retcode = (int)Retcode.RetEnterSceneTokenInvalid;
|
||||
|
||||
Data = p.ToByteArray();
|
||||
}
|
||||
}
|
||||
}
|
20
src/GameServer/Packet/Send/PacketEnterWorldAreaRsp.cs
Normal file
20
src/GameServer/Packet/Send/PacketEnterWorldAreaRsp.cs
Normal file
@ -0,0 +1,20 @@
|
||||
using Google.Protobuf;
|
||||
using Weedwacker.GameServer.Systems.Player;
|
||||
using Weedwacker.Shared.Network.Proto;
|
||||
|
||||
namespace Weedwacker.GameServer.Packet.Send
|
||||
{
|
||||
internal class PacketEnterWorldAreaRsp : BasePacket
|
||||
{
|
||||
public PacketEnterWorldAreaRsp(Player player, uint areaId, uint areaType) : base(Enums.OpCode.EnterWorldAreaRsp)
|
||||
{
|
||||
EnterWorldAreaRsp p = new()
|
||||
{
|
||||
AreaId = areaId,
|
||||
AreaType = areaType
|
||||
};
|
||||
|
||||
Data = p.ToByteArray();
|
||||
}
|
||||
}
|
||||
}
|
24
src/GameServer/Packet/Send/PacketGetPlayerSocialDetailRsp.cs
Normal file
24
src/GameServer/Packet/Send/PacketGetPlayerSocialDetailRsp.cs
Normal file
@ -0,0 +1,24 @@
|
||||
using Google.Protobuf;
|
||||
using Weedwacker.Shared.Network.Proto;
|
||||
|
||||
namespace Weedwacker.GameServer.Packet.Send
|
||||
{
|
||||
internal class PacketGetPlayerSocialDetailRsp : BasePacket
|
||||
{
|
||||
public PacketGetPlayerSocialDetailRsp(SocialDetail? detail) : base(Enums.OpCode.GetPlayerSocialDetailRsp)
|
||||
{
|
||||
GetPlayerSocialDetailRsp proto = new GetPlayerSocialDetailRsp();
|
||||
|
||||
if (detail != null)
|
||||
{
|
||||
proto.DetailData = detail;
|
||||
}
|
||||
else
|
||||
{
|
||||
proto.Retcode = (int)Retcode.RetSvrError;
|
||||
}
|
||||
|
||||
Data = proto.ToByteArray();
|
||||
}
|
||||
}
|
||||
}
|
20
src/GameServer/Packet/Send/PacketHostPlayerNotify.cs
Normal file
20
src/GameServer/Packet/Send/PacketHostPlayerNotify.cs
Normal file
@ -0,0 +1,20 @@
|
||||
using Google.Protobuf;
|
||||
using Weedwacker.GameServer.Systems.World;
|
||||
using Weedwacker.Shared.Network.Proto;
|
||||
|
||||
namespace Weedwacker.GameServer.Packet.Send
|
||||
{
|
||||
internal class PacketHostPlayerNotify : BasePacket
|
||||
{
|
||||
public PacketHostPlayerNotify(World world) : base(Enums.OpCode.HostPlayerNotify)
|
||||
{
|
||||
HostPlayerNotify p = new()
|
||||
{
|
||||
HostUid = (uint)world.Host.GameUid,
|
||||
HostPeerId = world.GetHostPeerId()
|
||||
};
|
||||
|
||||
Data = p.ToByteArray();
|
||||
}
|
||||
}
|
||||
}
|
28
src/GameServer/Packet/Send/PacketOpenStateChangeNotify.cs
Normal file
28
src/GameServer/Packet/Send/PacketOpenStateChangeNotify.cs
Normal file
@ -0,0 +1,28 @@
|
||||
using Google.Protobuf;
|
||||
using Weedwacker.Shared.Network.Proto;
|
||||
|
||||
namespace Weedwacker.GameServer.Packet.Send
|
||||
{
|
||||
internal class PacketOpenStateChangeNotify : BasePacket
|
||||
{
|
||||
public PacketOpenStateChangeNotify(int openState, int value) : base(Enums.OpCode.OpenStateChangeNotify)
|
||||
{
|
||||
OpenStateChangeNotify proto = new OpenStateChangeNotify();
|
||||
proto.OpenStateMap.Add((uint)openState, (uint)value);
|
||||
|
||||
Data = proto.ToByteArray();
|
||||
}
|
||||
|
||||
public PacketOpenStateChangeNotify(IEnumerable<Tuple<int, int>> openStates) : base(Enums.OpCode.OpenStateChangeNotify)
|
||||
{
|
||||
|
||||
OpenStateChangeNotify proto = new OpenStateChangeNotify();
|
||||
foreach (var openState in openStates)
|
||||
{
|
||||
proto.OpenStateMap.Add((uint)openState.Item1, (uint)openState.Item2);
|
||||
}
|
||||
|
||||
Data = proto.ToByteArray();
|
||||
}
|
||||
}
|
||||
}
|
22
src/GameServer/Packet/Send/PacketOpenStateUpdateNotify.cs
Normal file
22
src/GameServer/Packet/Send/PacketOpenStateUpdateNotify.cs
Normal file
@ -0,0 +1,22 @@
|
||||
using Google.Protobuf;
|
||||
using Weedwacker.GameServer.Data;
|
||||
using Weedwacker.GameServer.Systems.Player;
|
||||
using Weedwacker.Shared.Network.Proto;
|
||||
|
||||
namespace Weedwacker.GameServer.Packet.Send
|
||||
{
|
||||
internal class PacketOpenStateUpdateNotify : BasePacket
|
||||
{
|
||||
public PacketOpenStateUpdateNotify(Player player) : base(Enums.OpCode.OpenStateUpdateNotify)
|
||||
{
|
||||
OpenStateUpdateNotify proto = new OpenStateUpdateNotify();
|
||||
|
||||
foreach ( var openState in player.OpenStates)
|
||||
{
|
||||
proto.OpenStateMap.Add((uint)openState.Key, (uint)openState.Value);
|
||||
}
|
||||
|
||||
Data = proto.ToByteArray();
|
||||
}
|
||||
}
|
||||
}
|
11
src/GameServer/Packet/Send/PacketPathfindingEnterSceneRsp.cs
Normal file
11
src/GameServer/Packet/Send/PacketPathfindingEnterSceneRsp.cs
Normal file
@ -0,0 +1,11 @@
|
||||
using Weedwacker.GameServer.Enums;
|
||||
|
||||
namespace Weedwacker.GameServer.Packet.Send
|
||||
{
|
||||
internal class PacketPathfindingEnterSceneRsp : BasePacket
|
||||
{
|
||||
public PacketPathfindingEnterSceneRsp(uint clientSequence) : base(OpCode.PathfindingEnterSceneRsp, clientSequence)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
using Google.Protobuf;
|
||||
using Weedwacker.GameServer.Systems.Inventory;
|
||||
using Weedwacker.GameServer.Systems.Player;
|
||||
using Weedwacker.GameServer.Systems.World;
|
||||
using Weedwacker.Shared.Network.Proto;
|
||||
|
||||
namespace Weedwacker.GameServer.Packet.Send
|
||||
{
|
||||
internal class PacketPlayerEnterSceneInfoNotify : BasePacket
|
||||
{
|
||||
public PacketPlayerEnterSceneInfoNotify(Player player) : base(Enums.OpCode.PlayerEnterSceneInfoNotify)
|
||||
{
|
||||
PlayerEnterSceneInfoNotify proto = new PlayerEnterSceneInfoNotify()
|
||||
{
|
||||
CurAvatarEntityId = player.TeamManager.GetCurrentAvatarEntity().Id,
|
||||
EnterSceneToken = player.EnterSceneToken
|
||||
};
|
||||
|
||||
proto.TeamEnterInfo = new TeamEnterSceneInfo()
|
||||
{
|
||||
TeamEntityId = player.TeamManager.EntityId,
|
||||
TeamAbilityInfo = new(), //player.TeamManager.AbilitySyncState,
|
||||
AbilityControlBlock = new() //TODO
|
||||
};
|
||||
|
||||
proto.MpLevelEntityInfo = new MPLevelEntityInfo()
|
||||
{
|
||||
AuthorityPeerId = player.World.GetHostPeerId(),
|
||||
AbilityInfo = new(), //TODO
|
||||
EntityId = player.World.LevelEntityId
|
||||
};
|
||||
|
||||
foreach (AvatarEntity avatar in player.TeamManager.ActiveTeam.Values)
|
||||
{
|
||||
WeaponItem weapon = avatar.Avatar.GetWeapon();
|
||||
|
||||
AvatarEnterSceneInfo avatarInfo = new AvatarEnterSceneInfo()
|
||||
{
|
||||
AvatarGuid = avatar.Avatar.Guid,
|
||||
AvatarEntityId = avatar.Id,
|
||||
WeaponGuid = weapon.Guid,
|
||||
WeaponEntityId = weapon.WeaponEntityId,
|
||||
AvatarAbilityInfo = new(), //TODO
|
||||
WeaponAbilityInfo = new() //TODO
|
||||
};
|
||||
|
||||
proto.AvatarEnterInfo.Add(avatarInfo);
|
||||
}
|
||||
|
||||
Data = proto.ToByteArray();
|
||||
}
|
||||
}
|
||||
}
|
21
src/GameServer/Packet/Send/PacketPlayerGameTimeNotify.cs
Normal file
21
src/GameServer/Packet/Send/PacketPlayerGameTimeNotify.cs
Normal file
@ -0,0 +1,21 @@
|
||||
using Google.Protobuf;
|
||||
using Weedwacker.GameServer.Systems.Player;
|
||||
using Weedwacker.Shared.Network.Proto;
|
||||
|
||||
namespace Weedwacker.GameServer.Packet.Send
|
||||
{
|
||||
internal class PacketPlayerGameTimeNotify : BasePacket
|
||||
{
|
||||
public PacketPlayerGameTimeNotify(Player player) : base(Enums.OpCode.PlayerGameTimeNotify)
|
||||
{
|
||||
PlayerGameTimeNotify proto = new PlayerGameTimeNotify()
|
||||
{
|
||||
GameTime = player.Scene.Time,
|
||||
Uid = (uint)player.GameUid,
|
||||
//IsHome = TODO
|
||||
};
|
||||
|
||||
Data = proto.ToByteArray();
|
||||
}
|
||||
}
|
||||
}
|
28
src/GameServer/Packet/Send/PacketPlayerStoreNotify.cs
Normal file
28
src/GameServer/Packet/Send/PacketPlayerStoreNotify.cs
Normal file
@ -0,0 +1,28 @@
|
||||
using Google.Protobuf;
|
||||
using Weedwacker.GameServer.Systems.Player;
|
||||
using Weedwacker.Shared.Network.Proto;
|
||||
|
||||
namespace Weedwacker.GameServer.Packet.Send
|
||||
{
|
||||
internal class PacketPlayerStoreNotify : BasePacket
|
||||
{
|
||||
public PacketPlayerStoreNotify(Player player) : base(Enums.OpCode.PlayerStoreNotify)
|
||||
{
|
||||
BuildHeader(2);
|
||||
|
||||
PlayerStoreNotify p = new PlayerStoreNotify()
|
||||
{
|
||||
StoreType = StoreType.Pack,
|
||||
WeightLimit = 30000
|
||||
};
|
||||
|
||||
foreach (var item in player.Inventory.GuidMap.Values)
|
||||
{
|
||||
Item itemProto = item.ToProto();
|
||||
p.ItemList.Add(itemProto);
|
||||
}
|
||||
|
||||
Data = p.ToByteArray();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
using Google.Protobuf;
|
||||
using Weedwacker.GameServer.Systems.World;
|
||||
using Weedwacker.Shared.Network.Proto;
|
||||
|
||||
namespace Weedwacker.GameServer.Packet.Send
|
||||
{
|
||||
internal class PacketPlayerWorldSceneInfoListNotify : BasePacket
|
||||
{
|
||||
public PacketPlayerWorldSceneInfoListNotify(Scene scene) : base(Enums.OpCode.PlayerWorldSceneInfoListNotify)
|
||||
{
|
||||
PlayerWorldSceneInfoListNotify p = new();
|
||||
|
||||
PlayerWorldSceneInfo sceneInfo = new()
|
||||
{
|
||||
SceneId = (uint)scene.GetId(),
|
||||
IsLocked = false, //TODO
|
||||
};
|
||||
sceneInfo.SceneTagIdList.AddRange(scene.SceneTags);
|
||||
|
||||
p.InfoList.Add(sceneInfo);
|
||||
|
||||
Data = p.ToByteArray();
|
||||
}
|
||||
}
|
||||
}
|
19
src/GameServer/Packet/Send/PacketPostEnterSceneRsp.cs
Normal file
19
src/GameServer/Packet/Send/PacketPostEnterSceneRsp.cs
Normal file
@ -0,0 +1,19 @@
|
||||
using Google.Protobuf;
|
||||
using Weedwacker.GameServer.Systems.Player;
|
||||
using Weedwacker.Shared.Network.Proto;
|
||||
|
||||
namespace Weedwacker.GameServer.Packet.Send
|
||||
{
|
||||
internal class PacketPostEnterSceneRsp : BasePacket
|
||||
{
|
||||
public PacketPostEnterSceneRsp(Player player) : base(Enums.OpCode.PostEnterSceneRsp)
|
||||
{
|
||||
PostEnterSceneRsp p = new PostEnterSceneRsp()
|
||||
{
|
||||
EnterSceneToken = player.EnterSceneToken
|
||||
};
|
||||
|
||||
Data = p.ToByteArray();
|
||||
}
|
||||
}
|
||||
}
|
25
src/GameServer/Packet/Send/PacketSceneAreaWeatherNotify.cs
Normal file
25
src/GameServer/Packet/Send/PacketSceneAreaWeatherNotify.cs
Normal file
@ -0,0 +1,25 @@
|
||||
using Google.Protobuf;
|
||||
using Weedwacker.GameServer.Enums;
|
||||
using Weedwacker.Shared.Network.Proto;
|
||||
|
||||
namespace Weedwacker.GameServer.Packet.Send
|
||||
{
|
||||
internal class PacketSceneAreaWeatherNotify : BasePacket
|
||||
{
|
||||
public PacketSceneAreaWeatherNotify(ClimateType climateType, int weatherAreaId) : base(Enums.OpCode.SceneAreaWeatherNotify)
|
||||
{
|
||||
SceneAreaWeatherNotify p = new()
|
||||
{
|
||||
ClimateType = (uint)climateType,
|
||||
WeatherAreaId = (uint)weatherAreaId,
|
||||
/* TODO
|
||||
TransDuration = ,
|
||||
WeatherGadgetId = ,
|
||||
WeatherValueMap = ,
|
||||
*/
|
||||
};
|
||||
|
||||
Data = p.ToByteArray();
|
||||
}
|
||||
}
|
||||
}
|
27
src/GameServer/Packet/Send/PacketSceneForceUnlockNotify.cs
Normal file
27
src/GameServer/Packet/Send/PacketSceneForceUnlockNotify.cs
Normal file
@ -0,0 +1,27 @@
|
||||
using Google.Protobuf;
|
||||
using Weedwacker.Shared.Network.Proto;
|
||||
|
||||
namespace Weedwacker.GameServer.Packet.Send
|
||||
{
|
||||
internal class PacketSceneForceUnlockNotify : BasePacket
|
||||
{
|
||||
/*
|
||||
* 1,
|
||||
* 47,
|
||||
* 37,
|
||||
* What do the numbers mean???
|
||||
*/
|
||||
public PacketSceneForceUnlockNotify() : base(Enums.OpCode.SceneForceUnlockNotify)
|
||||
{
|
||||
SceneForceUnlockNotify p = new()
|
||||
{
|
||||
/* TODO
|
||||
IsAdd = ,
|
||||
ForceIdList =
|
||||
*/
|
||||
};
|
||||
|
||||
Data = p.ToByteArray();
|
||||
}
|
||||
}
|
||||
}
|
16
src/GameServer/Packet/Send/PacketSceneInitFinishRsp.cs
Normal file
16
src/GameServer/Packet/Send/PacketSceneInitFinishRsp.cs
Normal file
@ -0,0 +1,16 @@
|
||||
using Google.Protobuf;
|
||||
using Weedwacker.GameServer.Systems.Player;
|
||||
using Weedwacker.Shared.Network.Proto;
|
||||
|
||||
namespace Weedwacker.GameServer.Packet.Send
|
||||
{
|
||||
internal class PacketSceneInitFinishRsp : BasePacket
|
||||
{
|
||||
public PacketSceneInitFinishRsp(Player player) : base(Enums.OpCode.SceneInitFinishRsp, 11)
|
||||
{
|
||||
SceneInitFinishRsp p = new SceneInitFinishRsp() { EnterSceneToken = player.EnterSceneToken };
|
||||
|
||||
Data = p.ToByteArray();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
using Google.Protobuf;
|
||||
using Weedwacker.GameServer.Systems.Player;
|
||||
using Weedwacker.GameServer.Systems.World;
|
||||
using Weedwacker.Shared.Network.Proto;
|
||||
|
||||
namespace Weedwacker.GameServer.Packet.Send
|
||||
{
|
||||
internal class PacketScenePlayerLocationNotify : BasePacket
|
||||
{
|
||||
public PacketScenePlayerLocationNotify(Scene scene) : base(Enums.OpCode.ScenePlayerLocationNotify)
|
||||
{
|
||||
ScenePlayerLocationNotify proto = new ScenePlayerLocationNotify()
|
||||
{
|
||||
SceneId = (uint)scene.GetId(),
|
||||
//VehicleLocList = , //TODO
|
||||
};
|
||||
|
||||
foreach (Player p in scene.Players)
|
||||
{
|
||||
proto.PlayerLocList.Add(p.GetPlayerLocationInfo());
|
||||
}
|
||||
|
||||
Data = proto.ToByteArray();
|
||||
}
|
||||
}
|
||||
}
|
@ -14,9 +14,9 @@ namespace Weedwacker.GameServer.Packet.Send
|
||||
IsInMp = player.IsInMultiplayer()
|
||||
};
|
||||
|
||||
foreach (Player p in player.World.Players)
|
||||
foreach (Player p in player.Scene.Players)
|
||||
{
|
||||
foreach (AvatarEntity avatar in p.TeamManager.ActiveTeam)
|
||||
foreach (AvatarEntity avatar in p.TeamManager.ActiveTeam.Values)
|
||||
{
|
||||
//TODO
|
||||
AbilitySyncStateInfo avatarAbilityInfo = new();
|
||||
|
21
src/GameServer/Packet/Send/PacketSceneTimeNotify.cs
Normal file
21
src/GameServer/Packet/Send/PacketSceneTimeNotify.cs
Normal file
@ -0,0 +1,21 @@
|
||||
using Google.Protobuf;
|
||||
using Weedwacker.GameServer.Systems.Player;
|
||||
using Weedwacker.Shared.Network.Proto;
|
||||
|
||||
namespace Weedwacker.GameServer.Packet.Send
|
||||
{
|
||||
internal class PacketSceneTimeNotify : BasePacket
|
||||
{
|
||||
public PacketSceneTimeNotify(Player player) : base(Enums.OpCode.SceneTimeNotify)
|
||||
{
|
||||
SceneTimeNotify proto = new SceneTimeNotify()
|
||||
{
|
||||
SceneId = (uint)player.SceneId,
|
||||
SceneTime = player.Scene.Time,
|
||||
IsPaused = false //TODO
|
||||
};
|
||||
|
||||
Data = proto.ToByteArray();
|
||||
}
|
||||
}
|
||||
}
|
18
src/GameServer/Packet/Send/PacketServerTimeNotify.cs
Normal file
18
src/GameServer/Packet/Send/PacketServerTimeNotify.cs
Normal file
@ -0,0 +1,18 @@
|
||||
using Google.Protobuf;
|
||||
using Weedwacker.Shared.Network.Proto;
|
||||
|
||||
namespace Weedwacker.GameServer.Packet.Send
|
||||
{
|
||||
internal class PacketServerTimeNotify : BasePacket
|
||||
{
|
||||
public PacketServerTimeNotify() : base(Enums.OpCode.ServerTimeNotify)
|
||||
{
|
||||
ServerTimeNotify proto = new ServerTimeNotify()
|
||||
{
|
||||
ServerTime = (ulong)DateTimeOffset.Now.ToUnixTimeMilliseconds()
|
||||
};
|
||||
|
||||
Data = proto.ToByteArray();
|
||||
}
|
||||
}
|
||||
}
|
29
src/GameServer/Packet/Send/PacketSetOpenStateRsp.cs
Normal file
29
src/GameServer/Packet/Send/PacketSetOpenStateRsp.cs
Normal file
@ -0,0 +1,29 @@
|
||||
using Google.Protobuf;
|
||||
using Weedwacker.Shared.Network.Proto;
|
||||
|
||||
namespace Weedwacker.GameServer.Packet.Send
|
||||
{
|
||||
internal class PacketSetOpenStateRsp : BasePacket
|
||||
{
|
||||
public PacketSetOpenStateRsp(uint openState, uint value) : base(Enums.OpCode.SetOpenStateRsp)
|
||||
{
|
||||
SetOpenStateRsp proto = new SetOpenStateRsp()
|
||||
{
|
||||
Key = openState,
|
||||
Value = value
|
||||
};
|
||||
|
||||
Data = proto.ToByteArray();
|
||||
}
|
||||
|
||||
public PacketSetOpenStateRsp(Retcode retcode) : base(Enums.OpCode.SetOpenStateRsp)
|
||||
{
|
||||
SetOpenStateRsp proto = new SetOpenStateRsp()
|
||||
{
|
||||
Retcode = (int)retcode
|
||||
};
|
||||
|
||||
Data = proto.ToByteArray();
|
||||
}
|
||||
}
|
||||
}
|
25
src/GameServer/Packet/Send/PacketStoreWeightLimitNotify.cs
Normal file
25
src/GameServer/Packet/Send/PacketStoreWeightLimitNotify.cs
Normal file
@ -0,0 +1,25 @@
|
||||
using Google.Protobuf;
|
||||
using Weedwacker.GameServer.Systems.Inventory;
|
||||
using Weedwacker.Shared.Network.Proto;
|
||||
|
||||
namespace Weedwacker.GameServer.Packet.Send
|
||||
{
|
||||
internal class PacketStoreWeightLimitNotify : BasePacket
|
||||
{
|
||||
public PacketStoreWeightLimitNotify() : base(Enums.OpCode.StoreWeightLimitNotify)
|
||||
{
|
||||
StoreWeightLimitNotify p = new StoreWeightLimitNotify()
|
||||
{
|
||||
StoreType = StoreType.Pack,
|
||||
WeightLimit = 30000,
|
||||
WeaponCountLimit = WeaponTab.InventoryLimit,
|
||||
ReliquaryCountLimit = RelicTab.InventoryLimit,
|
||||
MaterialCountLimit = MaterialsTab.InventoryLimit,
|
||||
FurnitureCountLimit = FurnitureTab.InventoryLimit
|
||||
|
||||
};
|
||||
|
||||
Data = p.ToByteArray();
|
||||
}
|
||||
}
|
||||
}
|
21
src/GameServer/Packet/Send/PacketWorldDataNotify.cs
Normal file
21
src/GameServer/Packet/Send/PacketWorldDataNotify.cs
Normal file
@ -0,0 +1,21 @@
|
||||
using Google.Protobuf;
|
||||
using Weedwacker.GameServer.Systems.World;
|
||||
using Weedwacker.Shared.Network.Proto;
|
||||
|
||||
namespace Weedwacker.GameServer.Packet.Send
|
||||
{
|
||||
internal class PacketWorldDataNotify : BasePacket
|
||||
{
|
||||
public PacketWorldDataNotify(World world) : base(Enums.OpCode.WorldDataNotify)
|
||||
{
|
||||
int worldLevel = world.WorldLevel;
|
||||
int isMp = world.IsMultiplayer ? 1 : 0;
|
||||
|
||||
WorldDataNotify proto = new WorldDataNotify();
|
||||
proto.WorldPropMap.Add(1, new PropValue() { Type = 1, Ival = worldLevel, Val = worldLevel });
|
||||
proto.WorldPropMap.Add(2, new PropValue() { Type = 2, Ival = isMp, Val = isMp });
|
||||
|
||||
Data = proto.ToByteArray();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
using Google.Protobuf;
|
||||
using Weedwacker.GameServer.Systems.Player;
|
||||
using Weedwacker.GameServer.Systems.World;
|
||||
using Weedwacker.Shared.Network.Proto;
|
||||
|
||||
namespace Weedwacker.GameServer.Packet.Send
|
||||
{
|
||||
internal class PacketWorldPlayerLocationNotify : BasePacket
|
||||
{
|
||||
public PacketWorldPlayerLocationNotify(World world) : base(Enums.OpCode.WorldPlayerLocationNotify)
|
||||
{
|
||||
WorldPlayerLocationNotify proto = new WorldPlayerLocationNotify();
|
||||
|
||||
foreach (Player p in world.Players)
|
||||
{
|
||||
proto.PlayerWorldLocList.Add(new PlayerWorldLocationInfo() { SceneId = (uint)p.SceneId, PlayerLoc = p.GetPlayerLocationInfo()});
|
||||
}
|
||||
|
||||
Data = proto.ToByteArray();
|
||||
}
|
||||
}
|
||||
}
|
@ -77,7 +77,7 @@ namespace Weedwacker.GameServer.Systems.Avatar
|
||||
if(Owner.TeamManager.GetCurrentTeamInfo().AvatarInfo.Count < (Owner.IsInMultiplayer() ? GameServer.Configuration.Server.GameOptions.AvatarLimits.SinglePlayerTeam : GameServer.Configuration.Server.GameOptions.AvatarLimits.SinglePlayerTeam))
|
||||
{
|
||||
addToTeam = true;
|
||||
Owner.TeamManager.GetCurrentTeamInfo().AddAvatar(avatar);
|
||||
await Owner.TeamManager.AddToTeamAsync(avatar);
|
||||
}
|
||||
if (notify) await Owner.SendPacketAsync(new PacketAvatarAddNotify(avatar, addToTeam));
|
||||
|
||||
|
@ -1,12 +1,14 @@
|
||||
using MongoDB.Bson.Serialization.Attributes;
|
||||
using Weedwacker.GameServer.Data.Excel;
|
||||
using Weedwacker.GameServer.Database;
|
||||
using Weedwacker.GameServer.Systems.Player;
|
||||
using Weedwacker.Shared.Network.Proto;
|
||||
|
||||
namespace Weedwacker.GameServer.Systems.Avatar
|
||||
{
|
||||
internal class TeamInfo
|
||||
{
|
||||
private TeamManager Manager;
|
||||
public string TeamName;
|
||||
[BsonSerializer(typeof(IntSortedListSerializer<Avatar>))]
|
||||
[BsonElement] public SortedList<int, Avatar> AvatarInfo { get; private set; } = new(); // <index, avatar>> clone avatars for abyss teams
|
||||
@ -39,7 +41,10 @@ namespace Weedwacker.GameServer.Systems.Avatar
|
||||
return false;
|
||||
}
|
||||
|
||||
AvatarInfo.Add(index, IsTowerTeam ? avatar.Clone() : avatar);
|
||||
if (!AvatarInfo.ContainsKey(index))
|
||||
AvatarInfo.Add(index, IsTowerTeam ? avatar.Clone() : avatar);
|
||||
else
|
||||
AvatarInfo[index] = IsTowerTeam ? avatar.Clone() : avatar;
|
||||
|
||||
//TODO update team resonance and add team openConfigs
|
||||
|
||||
|
@ -17,14 +17,13 @@ namespace Weedwacker.GameServer.Systems.Inventory
|
||||
public int Count;
|
||||
[BsonIgnore] public ulong Guid; // Player unique id. Generated each session
|
||||
[BsonIgnore] public bool IsNew { get; protected set; } = false;
|
||||
[BsonIgnore] public ItemData ItemData { get; protected set; }
|
||||
|
||||
[BsonIgnore] public ItemData ItemData => GameData.ItemDataMap[ItemId];
|
||||
|
||||
|
||||
public GameItem(ulong guid, int itemId, int count)
|
||||
{
|
||||
Guid = guid;
|
||||
ItemId = itemId;
|
||||
ItemData = GameData.ItemDataMap[itemId];
|
||||
IsNew = true;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
using MongoDB.Bson.Serialization.Attributes;
|
||||
using Weedwacker.GameServer.Data;
|
||||
using Weedwacker.GameServer.Data.Excel;
|
||||
using Weedwacker.Shared.Network.Proto;
|
||||
|
||||
@ -6,7 +7,7 @@ namespace Weedwacker.GameServer.Systems.Inventory
|
||||
{
|
||||
internal class MaterialItem : GameItem
|
||||
{
|
||||
[BsonIgnore] public new MaterialData ItemData { get; private set; }
|
||||
[BsonIgnore] public new MaterialData ItemData => (MaterialData)GameData.ItemDataMap[ItemId];
|
||||
|
||||
public MaterialItem(ulong guid, int itemId, int count) : base(guid, itemId, count)
|
||||
{
|
||||
|
@ -10,8 +10,7 @@ namespace Weedwacker.GameServer.Systems.Inventory
|
||||
{
|
||||
[BsonElement] public int MainPropId { get; protected set; }
|
||||
[BsonElement] public HashSet<int>? AppendPropIdList { get; private set; } = new();
|
||||
[BsonIgnore] public new ReliquaryData ItemData { get; protected set; }
|
||||
|
||||
[BsonIgnore] public new ReliquaryData ItemData => (ReliquaryData)GameData.ItemDataMap[ItemId];
|
||||
public ReliquaryItem(ulong guid, int itemId, int uniqueId) : base(guid, itemId)
|
||||
{
|
||||
Id = uniqueId;
|
||||
@ -28,7 +27,6 @@ namespace Weedwacker.GameServer.Systems.Inventory
|
||||
|
||||
public async Task OnLoadAsync(ulong guid)
|
||||
{
|
||||
ItemData = (ReliquaryData)GameData.ItemDataMap[ItemId];
|
||||
Guid = guid;
|
||||
}
|
||||
public EquipType GetEquipSlot()
|
||||
|
@ -19,10 +19,11 @@ namespace Weedwacker.GameServer.Systems.Inventory
|
||||
foreach(MaterialItem item in Items.Values)
|
||||
{
|
||||
item.Guid = Owner.GetNextGameGuid();
|
||||
Inventory.GuidMap.Add(item.Guid, item);
|
||||
}
|
||||
}
|
||||
|
||||
internal override async Task<GameItem?> AddItemAsync(int itemId, int count = 1)
|
||||
public override async Task<GameItem?> AddItemAsync(int itemId, int count = 1)
|
||||
{
|
||||
if (Items.TryGetValue(itemId, out GameItem? material))
|
||||
{
|
||||
|
@ -13,7 +13,7 @@ namespace Weedwacker.GameServer.Systems.Inventory
|
||||
private static string mongoPathToItems = $"{nameof(InventoryManager.SubInventories)}.{ItemType.ITEM_MATERIAL}.{nameof(FoodTab)}.{nameof(Items)}";
|
||||
public FoodTab(Player.Player owner, InventoryManager inventory) : base(owner, inventory) { }
|
||||
|
||||
internal override async Task<GameItem?> AddItemAsync(int itemId, int count = 1)
|
||||
public override async Task<GameItem?> AddItemAsync(int itemId, int count = 1)
|
||||
{
|
||||
if (Items.TryGetValue(itemId, out GameItem? material))
|
||||
{
|
||||
|
@ -24,15 +24,17 @@ namespace Weedwacker.GameServer.Systems.Inventory
|
||||
foreach (FurnitureItem item in Items.Values)
|
||||
{
|
||||
item.Guid = Owner.GetNextGameGuid();
|
||||
Inventory.GuidMap.Add(item.Guid, item);
|
||||
}
|
||||
foreach (MaterialItem item in Materials.Values)
|
||||
{
|
||||
item.Guid = Owner.GetNextGameGuid();
|
||||
Inventory.GuidMap.Add(item.Guid, item);
|
||||
}
|
||||
}
|
||||
|
||||
//TODO FurnitureItem
|
||||
internal override async Task<GameItem?> AddItemAsync(int itemId, int count = 1)
|
||||
public override async Task<GameItem?> AddItemAsync(int itemId, int count = 1)
|
||||
{
|
||||
|
||||
if (GameData.ItemDataMap[itemId].itemType == ItemType.ITEM_MATERIAL)
|
||||
|
@ -12,7 +12,7 @@ namespace Weedwacker.GameServer.Systems.Inventory
|
||||
private static string mongoPathToItems = $"{nameof(InventoryManager.SubInventories)}.{ItemType.ITEM_MATERIAL}.{nameof(GadgetTab)}.{nameof(Items)}";
|
||||
public GadgetTab(Player.Player owner, InventoryManager inventory) : base(owner, inventory) { }
|
||||
|
||||
internal override async Task<GameItem?> AddItemAsync(int itemId, int count = 1)
|
||||
public override async Task<GameItem?> AddItemAsync(int itemId, int count = 1)
|
||||
{
|
||||
if (Items.TryGetValue(itemId, out GameItem? material))
|
||||
{
|
||||
|
@ -104,7 +104,7 @@ namespace Weedwacker.GameServer.Systems.Inventory
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
internal override async Task<GameItem?> AddItemAsync(int itemId, int count = 1)
|
||||
public override async Task<GameItem?> AddItemAsync(int itemId, int count = 1)
|
||||
{
|
||||
MaterialData data = (MaterialData)GameData.ItemDataMap[itemId];
|
||||
List<BaseItemUse> ops = new();
|
||||
|
@ -13,7 +13,7 @@ namespace Weedwacker.GameServer.Systems.Inventory
|
||||
internal class MaterialsTab : InventoryTab
|
||||
{
|
||||
private string mongoPathToItems = $"{nameof(InventoryManager.SubInventories)}.{ItemType.ITEM_MATERIAL}.{nameof(MaterialsTab)}.{nameof(Items)}";
|
||||
[BsonIgnore] public new const int InventoryLimit = 9999;
|
||||
[BsonIgnore] public new const int InventoryLimit = 2000;
|
||||
|
||||
public MaterialsTab(Player.Player owner, InventoryManager inventory) : base(owner, inventory) { }
|
||||
|
||||
@ -24,10 +24,11 @@ namespace Weedwacker.GameServer.Systems.Inventory
|
||||
foreach (MaterialItem item in Items.Values)
|
||||
{
|
||||
item.Guid = Owner.GetNextGameGuid();
|
||||
inventory.GuidMap.Add(item.Guid, item);
|
||||
}
|
||||
}
|
||||
|
||||
internal override async Task<GameItem?> AddItemAsync(int itemId, int count = 1)
|
||||
public override async Task<GameItem?> AddItemAsync(int itemId, int count = 1)
|
||||
{
|
||||
if (Items.TryGetValue(itemId, out GameItem? material))
|
||||
{
|
||||
|
@ -15,7 +15,7 @@ namespace Weedwacker.GameServer.Systems.Inventory
|
||||
private static string mongoPathToItems = $"{nameof(InventoryManager.SubInventories)}.{ItemType.ITEM_MATERIAL}.{nameof(PreciousTab)}.{nameof(Items)}";
|
||||
public PreciousTab(Player.Player owner, InventoryManager inventory) : base(owner, inventory) { }
|
||||
|
||||
internal override async Task<GameItem?> AddItemAsync(int itemId, int count = 1)
|
||||
public override async Task<GameItem?> AddItemAsync(int itemId, int count = 1)
|
||||
{
|
||||
if (Items.TryGetValue(itemId, out GameItem? material))
|
||||
{
|
||||
|
@ -14,7 +14,7 @@ namespace Weedwacker.GameServer.Systems.Inventory
|
||||
private static string mongoPathToItems = $"{nameof(InventoryManager.SubInventories)}.{ItemType.ITEM_MATERIAL}.{nameof(PromoteTab)}.{nameof(Items)}";
|
||||
public PromoteTab(Player.Player owner, InventoryManager inventory) : base(owner, inventory) { }
|
||||
|
||||
internal override async Task<GameItem?> AddItemAsync(int itemId, int count = 1)
|
||||
public override async Task<GameItem?> AddItemAsync(int itemId, int count = 1)
|
||||
{
|
||||
if (Items.TryGetValue(itemId, out GameItem? material))
|
||||
{
|
||||
|
@ -14,7 +14,7 @@ namespace Weedwacker.GameServer.Systems.Inventory
|
||||
private static string mongoPathToItems = $"{nameof(InventoryManager.SubInventories)}.{ItemType.ITEM_MATERIAL}.{nameof(QuestTab)}.{nameof(Items)}";
|
||||
public QuestTab(Player.Player owner, InventoryManager inventory) : base(owner, inventory) { }
|
||||
|
||||
internal override async Task<GameItem?> AddItemAsync(int itemId, int count = 1)
|
||||
public override async Task<GameItem?> AddItemAsync(int itemId, int count = 1)
|
||||
{
|
||||
if (Items.TryGetValue(itemId, out GameItem? material))
|
||||
{
|
||||
|
@ -34,7 +34,7 @@ namespace Weedwacker.GameServer.Systems.Inventory
|
||||
}
|
||||
}
|
||||
|
||||
internal override async Task<GameItem> AddItemAsync(int itemId, int count = 1)
|
||||
public override async Task<GameItem> AddItemAsync(int itemId, int count = 1)
|
||||
{
|
||||
if (GameData.ItemDataMap[itemId].itemType == ItemType.ITEM_MATERIAL)
|
||||
{
|
||||
|
@ -16,7 +16,7 @@ namespace Weedwacker.GameServer.Systems.Inventory
|
||||
}
|
||||
|
||||
// return null if no update item
|
||||
internal abstract Task<GameItem?> AddItemAsync(int itemId, int count = 1);
|
||||
public abstract Task<GameItem?> AddItemAsync(int itemId, int count = 1);
|
||||
|
||||
// Delete if count reaches 0
|
||||
internal abstract Task<bool> RemoveItemAsync(GameItem item, int count = 1);
|
||||
|
@ -27,15 +27,17 @@ namespace Weedwacker.GameServer.Systems.Inventory
|
||||
foreach (WeaponItem item in Items.Values)
|
||||
{
|
||||
item.Guid = Owner.GetNextGameGuid();
|
||||
Inventory.GuidMap.Add(item.Guid, item);
|
||||
if (item.EquippedAvatar != 0) await inventory.EquipWeapon(owner.Avatars.Avatars[item.EquippedAvatar].Guid, item.Guid);
|
||||
}
|
||||
foreach (MaterialItem item in UpgradeMaterials.Values)
|
||||
{
|
||||
item.Guid = Owner.GetNextGameGuid();
|
||||
Inventory.GuidMap.Add(item.Guid, item);
|
||||
}
|
||||
}
|
||||
|
||||
internal override async Task<GameItem> AddItemAsync(int itemId, int count = 1)
|
||||
public override async Task<GameItem> AddItemAsync(int itemId, int count = 1)
|
||||
{
|
||||
|
||||
if (GameData.ItemDataMap[itemId].itemType == ItemType.ITEM_MATERIAL)
|
||||
|
@ -10,13 +10,11 @@ namespace Weedwacker.GameServer.Systems.Inventory
|
||||
[BsonElement] public List<int>? Affixes { get; protected set; } = new();
|
||||
[BsonElement] public int Refinement { get; protected set; } = 0;
|
||||
[BsonIgnore] public uint WeaponEntityId;
|
||||
[BsonIgnore] public new WeaponData ItemData;
|
||||
[BsonIgnore] public new WeaponData ItemData => (WeaponData)GameData.ItemDataMap[ItemId];
|
||||
|
||||
public WeaponItem(ulong guid, int itemId, int uniqueId) : base(guid, itemId)
|
||||
{
|
||||
Id = uniqueId;
|
||||
|
||||
ItemData = (WeaponData)GameData.ItemDataMap[ItemId];
|
||||
Level = 1;
|
||||
|
||||
if (ItemData.skillAffix != null)
|
||||
@ -33,7 +31,6 @@ namespace Weedwacker.GameServer.Systems.Inventory
|
||||
|
||||
public async Task OnLoadAsync(ulong guid)
|
||||
{
|
||||
ItemData = (WeaponData)GameData.ItemDataMap[ItemId];
|
||||
Guid = guid;
|
||||
Count = 1;
|
||||
}
|
||||
|
150
src/GameServer/Systems/Player/OpenStateManager.cs
Normal file
150
src/GameServer/Systems/Player/OpenStateManager.cs
Normal file
@ -0,0 +1,150 @@
|
||||
using MongoDB.Driver;
|
||||
using Weedwacker.GameServer.Data;
|
||||
using Weedwacker.GameServer.Data.Excel;
|
||||
using Weedwacker.GameServer.Database;
|
||||
using Weedwacker.GameServer.Enums;
|
||||
using Weedwacker.GameServer.Packet.Send;
|
||||
|
||||
namespace Weedwacker.GameServer.Systems.Player
|
||||
{
|
||||
internal class OpenStateManager
|
||||
{
|
||||
private Player Owner;
|
||||
|
||||
public OpenStateManager(Player owner)
|
||||
{
|
||||
Owner = owner;
|
||||
}
|
||||
|
||||
public async Task OnPlayerCreate()
|
||||
{
|
||||
foreach(int openState in DEFAULT_OPEN_STATES)
|
||||
{
|
||||
await SetOpenStateAsync(openState, 1);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task OnLoginAsync()
|
||||
{
|
||||
// Try unlocking open states on player login. This handles accounts where unlock conditions were
|
||||
// already met before certain open state unlocks were implemented.
|
||||
await TryUnlockOpenStatesAsync(false);
|
||||
|
||||
// Send notify to the client.
|
||||
await Owner.SendPacketAsync(new PacketOpenStateUpdateNotify(Owner));
|
||||
|
||||
}
|
||||
|
||||
// Set of open states that are set per default for all accounts.
|
||||
public static HashSet<int> DEFAULT_OPEN_STATES = (HashSet<int>)GameData.OpenStateDataMap.Where(w => w.Value.defaultState == true).Select(s => s.Key);
|
||||
|
||||
private async Task SetOpenStateAsync(int openState, int value, bool sendNotify = true)
|
||||
{
|
||||
int previousValue = Owner.OpenStates.GetValueOrDefault((OpenStateType)openState, 0);
|
||||
|
||||
if (value != previousValue)
|
||||
{
|
||||
Owner.OpenStates.Add((OpenStateType)openState, value);
|
||||
|
||||
// Update Database
|
||||
var filter = Builders<Player>.Filter.Where(w => w.AccountUid == Owner.AccountUid);
|
||||
var update = Builders<Player>.Update.Set($"{nameof(Player.OpenStates)}.{(OpenStateType)openState}", value);
|
||||
await DatabaseManager.UpdatePlayerAsync(filter, update);
|
||||
|
||||
if (sendNotify)
|
||||
{
|
||||
await Owner.SendPacketAsync(new PacketOpenStateChangeNotify(openState, value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**********
|
||||
Condition checking for setting open states.
|
||||
**********/
|
||||
private bool AreConditionsMet(OpenStateData openState)
|
||||
{
|
||||
// Check all conditions and test if at least one of them is violated.
|
||||
foreach (var condition in openState.cond)
|
||||
{
|
||||
switch (condition.condType)
|
||||
{
|
||||
// For level conditions, check if the player has reached the necessary level.
|
||||
case OpenStateCondType.OPEN_STATE_COND_PLAYER_LEVEL:
|
||||
{
|
||||
if (Owner.PlayerProperties[PlayerProperty.PROP_PLAYER_LEVEL] < condition.param)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else continue;
|
||||
}
|
||||
case OpenStateCondType.OPEN_STATE_COND_QUEST:
|
||||
{
|
||||
// ToDo: Implement.
|
||||
return false;
|
||||
}
|
||||
case OpenStateCondType.OPEN_STATE_COND_PARENT_QUEST:
|
||||
{
|
||||
// ToDo: Implement.
|
||||
return false;
|
||||
}
|
||||
case OpenStateCondType.OPEN_STATE_OFFERING_LEVEL:
|
||||
{
|
||||
// ToDo: Implement.
|
||||
return false;
|
||||
}
|
||||
case OpenStateCondType.OPEN_STATE_CITY_REPUTATION_LEVEL:
|
||||
{
|
||||
// ToDo: Implement.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Done. If we didn't find any violations, all conditions are met.
|
||||
return true;
|
||||
}
|
||||
|
||||
/**********
|
||||
Setting open states from the client (via `SetOpenStateReq`).
|
||||
**********/
|
||||
public async Task<bool> SetOpenStateFromClientAsync(uint openState, uint value)
|
||||
{
|
||||
OpenStateData data = GameData.OpenStateDataMap[(int)openState];
|
||||
|
||||
// Make sure that this is an open state that the client is allowed to set,
|
||||
// and that it doesn't have any further conditions attached.
|
||||
if (data == null || !data.allowClientOpen || !AreConditionsMet(data))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set.
|
||||
await SetOpenStateAsync((int)openState, (int)value);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**********
|
||||
Triggered unlocking of open states (unlock states whose conditions have been met.)
|
||||
**********/
|
||||
public async Task TryUnlockOpenStatesAsync(bool sendNotify)
|
||||
{
|
||||
// Get list of open states that are not yet unlocked.
|
||||
var lockedStates = GameData.OpenStateDataMap.Where(s => Owner.OpenStates.GetValueOrDefault((OpenStateType)s.Key, 0) == 0);
|
||||
|
||||
// Try unlocking all of them.
|
||||
foreach (var state in lockedStates)
|
||||
{
|
||||
// To auto-unlock a state, it has to meet three conditions:
|
||||
// * it can not be a state that is unlocked by the client,
|
||||
// * it has to meet all its unlock conditions
|
||||
if (!state.Value.allowClientOpen && AreConditionsMet(state.Value))
|
||||
{
|
||||
await SetOpenStateAsync(state.Key, 1, sendNotify);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,8 @@ namespace Weedwacker.GameServer.Systems.Player
|
||||
[BsonIgnore] public World.World? World;
|
||||
[BsonIgnore] public Scene? Scene { get; private set; }
|
||||
[BsonElement] public int SceneId { get; private set; }
|
||||
[BsonElement] public int RegionId { get; private set; }
|
||||
[BsonElement] public Tuple<int, int> WorldAreaIds { get; private set; } // <areaID1, areaID2>
|
||||
[BsonElement] public int RegionId { get; private set; } = 1;
|
||||
[BsonIgnore] public uint PeerId;
|
||||
[BsonIgnore] public Vector3 Position;
|
||||
[BsonIgnore] public Vector3 Rotation;
|
||||
@ -35,11 +36,14 @@ namespace Weedwacker.GameServer.Systems.Player
|
||||
public int NextResinRefresh;
|
||||
public int LastDailyReset;
|
||||
public Dictionary<PlayerProperty, int> PlayerProperties { get; set; } = new(); // SET ONLY THROUGH THE PROPMANAGER
|
||||
public Dictionary<OpenStateType, int> OpenStates = new(); // SET ONLY THROUGH THE OPENSTATEMANAGER
|
||||
[BsonIgnore] public PlayerPropertyManager PropManager;
|
||||
[BsonIgnore] public OpenStateManager OpenStateManager;
|
||||
[BsonIgnore] public ResinManager ResinManager;
|
||||
[BsonIgnore] public Connection? Session; // Set by HandleGetPlayerTokenReq
|
||||
[BsonIgnore] public string Token { get; set; } // Obtained and used When Logging in
|
||||
[BsonIgnore] public uint EnterSceneToken;
|
||||
private long NextSendPlayerLocTime = 0;
|
||||
[BsonIgnore] private bool Paused;
|
||||
[BsonIgnore] public bool HasSentLoginPackets { get; private set; } = false;
|
||||
[BsonIgnore] private ulong NextGuid = 0;
|
||||
@ -54,6 +58,7 @@ namespace Weedwacker.GameServer.Systems.Player
|
||||
[BsonIgnore] public TeamManager TeamManager; // Loaded by DatabaseManager
|
||||
|
||||
|
||||
|
||||
public Player(string heroName, string accountUid, int gameUid)
|
||||
{
|
||||
Profile = new(heroName);
|
||||
@ -67,19 +72,19 @@ namespace Weedwacker.GameServer.Systems.Player
|
||||
PropManager = new(this);
|
||||
ResinManager = new(this);
|
||||
SocialManager = new(this);
|
||||
OpenStateManager = new(this);
|
||||
}
|
||||
|
||||
private async Task OnCreate()
|
||||
{
|
||||
await PropManager.SetPropertyAsync(PlayerProperty.PROP_PLAYER_LEVEL, 1, false);
|
||||
await PropManager.SetPropertyAsync(PlayerProperty.PROP_PLAYER_WORLD_LEVEL, 1, false);
|
||||
await PropManager.SetPropertyAsync(PlayerProperty.PROP_IS_SPRING_AUTO_USE, 1, false);
|
||||
await PropManager.SetPropertyAsync(PlayerProperty.PROP_SPRING_AUTO_USE_PERCENT, 50, false);
|
||||
await ResinManager.AddResinAsync(160);
|
||||
await PropManager.SetPropertyAsync(PlayerProperty.PROP_IS_FLYABLE, 0, false);
|
||||
await PropManager.SetPropertyAsync(PlayerProperty.PROP_MAX_STAMINA, 10000, false);
|
||||
await PropManager.SetPropertyAsync(PlayerProperty.PROP_CUR_PERSIST_STAMINA, 10000, false);
|
||||
SceneId = 3;
|
||||
RegionId = 1;
|
||||
|
||||
// Pick character
|
||||
Session.State = SessionState.PICKING_CHARACTER;
|
||||
@ -91,6 +96,11 @@ namespace Weedwacker.GameServer.Systems.Player
|
||||
return ((ulong)GameUid << 32) + nextId;
|
||||
}
|
||||
|
||||
public void ResetSendPlayerLocTime()
|
||||
{
|
||||
NextSendPlayerLocTime = DateTimeOffset.Now.ToUnixTimeMilliseconds() + 5000;
|
||||
}
|
||||
|
||||
public async Task<bool> SetMainCharacter(int avatarId, string heroName)
|
||||
{
|
||||
if (GameData.AvatarHeroEntityDataMap.ContainsKey(avatarId) && MainCharacterId == 0)
|
||||
@ -98,10 +108,11 @@ namespace Weedwacker.GameServer.Systems.Player
|
||||
MainCharacterId = avatarId;
|
||||
Profile.HeroName = heroName;
|
||||
Profile.Nickname = heroName;
|
||||
Profile.HeadImage = new() { AvatarId = (uint)avatarId, CostumeId = 0 };
|
||||
|
||||
// Update Database
|
||||
var filter = Builders<Player>.Filter.Where(w => w.AccountUid == AccountUid);
|
||||
var update = Builders<Player>.Update.Set(w => w.Profile.HeroName, heroName).Set(w => w.Profile.Nickname, heroName).Set(w => w.MainCharacterId, avatarId);
|
||||
var update = Builders<Player>.Update.Set(w => w.Profile, Profile).Set(w => w.MainCharacterId, avatarId);
|
||||
await DatabaseManager.UpdatePlayerAsync(filter, update);
|
||||
return true;
|
||||
}
|
||||
@ -119,14 +130,31 @@ namespace Weedwacker.GameServer.Systems.Player
|
||||
Scene = scene;
|
||||
if (scene == null) SceneId = 0;
|
||||
else SceneId = scene.SceneData.id;
|
||||
|
||||
// Update Database
|
||||
var filter = Builders<Player>.Filter.Where(w => w.AccountUid == AccountUid);
|
||||
var update = Builders<Player>.Update.Set(w => w.SceneId, SceneId);
|
||||
await DatabaseManager.UpdatePlayerAsync(filter, update);
|
||||
}
|
||||
|
||||
public async Task EnterWorldAreaAsync(uint areaType, uint areaID, bool isInit = false)
|
||||
{
|
||||
if (areaType == 2)
|
||||
{
|
||||
if (!isInit) await Scene.UpdateActiveAreaWeathersAsync(WorldAreaIds);
|
||||
WorldAreaIds = Tuple.Create(WorldAreaIds.Item1, (int)areaID);
|
||||
}
|
||||
else
|
||||
WorldAreaIds = Tuple.Create((int)areaID, WorldAreaIds.Item2);
|
||||
|
||||
// Update Database
|
||||
var filter = Builders<Player>.Filter.Where(w => w.AccountUid == AccountUid);
|
||||
var update = Builders<Player>.Update.Set(w => w.WorldAreaIds, WorldAreaIds);
|
||||
await DatabaseManager.UpdatePlayerAsync(filter, update);
|
||||
}
|
||||
|
||||
public async Task OnLoginAsync()
|
||||
{
|
||||
// Create world
|
||||
World.World world = new(this);
|
||||
|
||||
|
||||
// Show opening cutscene if player has no avatars
|
||||
if (Avatars.GetAvatarCount() == 0)
|
||||
{
|
||||
@ -134,17 +162,25 @@ namespace Weedwacker.GameServer.Systems.Player
|
||||
return;
|
||||
|
||||
}
|
||||
else if (SceneId == 0)
|
||||
|
||||
await SendPacketAsync(new PacketPlayerDataNotify(this));
|
||||
await OpenStateManager.OnLoginAsync();
|
||||
await SendPacketAsync(new PacketStoreWeightLimitNotify());
|
||||
await SendPacketAsync(new PacketPlayerStoreNotify(this));
|
||||
await SendPacketAsync(new PacketAvatarDataNotify(this));
|
||||
|
||||
// Create world
|
||||
World.World world = new(this);
|
||||
if (SceneId == 0 || Position == new Vector3(0,0,0)) // new player?
|
||||
{
|
||||
SceneId = 3;
|
||||
WorldAreaIds = Tuple.Create(1, 109); // beach
|
||||
await EnterWorldAreaAsync(1, 1, true);
|
||||
await world.AddPlayerAsync(this, EnterReason.Login, EnterType.Self, true);
|
||||
}
|
||||
else
|
||||
await world.AddPlayerAsync(this, EnterReason.Login);
|
||||
|
||||
await SendPacketAsync(new PacketPlayerDataNotify(this));
|
||||
await SendPacketAsync(new PacketAvatarDataNotify(this));
|
||||
|
||||
// Multiplayer setting
|
||||
await PropManager.SetPropertyAsync(PlayerProperty.PROP_PLAYER_MP_SETTING_TYPE, (int)MpSettingType.EnterAfterApply, false);
|
||||
await PropManager.SetPropertyAsync(PlayerProperty.PROP_IS_MP_MODE_AVAILABLE, 1, false);
|
||||
@ -161,6 +197,7 @@ namespace Weedwacker.GameServer.Systems.Player
|
||||
BattlePassManager = new(this);
|
||||
GadgetManager = new(this);
|
||||
EnergyManager = new(this);
|
||||
OpenStateManager = new(this);
|
||||
}
|
||||
public bool IsInMultiplayer() { return World != null && World.IsMultiplayer; }
|
||||
|
||||
@ -207,6 +244,16 @@ namespace Weedwacker.GameServer.Systems.Player
|
||||
return onlineInfo;
|
||||
}
|
||||
|
||||
public PlayerLocationInfo GetPlayerLocationInfo()
|
||||
{
|
||||
return new PlayerLocationInfo()
|
||||
{
|
||||
Uid = (uint)GameUid,
|
||||
Pos = new() { X = Position.X, Y = Position.Y, Z = Position.Z },
|
||||
Rot = new() { X = Rotation.X, Y = Rotation.Y, Z = Rotation.Z }
|
||||
};
|
||||
}
|
||||
|
||||
public async Task SendPacketAsync(BasePacket packet)
|
||||
{
|
||||
await Session.SendPacketAsync(packet);
|
||||
|
@ -9,10 +9,10 @@ namespace Weedwacker.GameServer.Systems.Player
|
||||
public string Nickname;
|
||||
public int Level = 1;
|
||||
public int WorldLevel = 1;
|
||||
public Tuple<int, int>? Birthday; // <Day,Month>
|
||||
public Birthday Birthday = new() { Day = 0, Month = 0 }; // <Day,Month>
|
||||
public ProfilePicture? HeadImage; // <avatarId, skinId>
|
||||
public string? HeroName;
|
||||
public string? Signature;
|
||||
public string? Signature = "";
|
||||
public int Achievements;
|
||||
public int DaysSinceLastLogin;
|
||||
public int LastActiveTime;
|
||||
|
@ -1,4 +1,5 @@
|
||||
using MongoDB.Bson.Serialization.Attributes;
|
||||
using MongoDB.Driver;
|
||||
using Vim.Math3d;
|
||||
using Weedwacker.GameServer.Database;
|
||||
using Weedwacker.GameServer.Enums;
|
||||
@ -18,17 +19,19 @@ namespace Weedwacker.GameServer.Systems.Player
|
||||
[BsonElement] public SortedList<int, TeamInfo> Teams { get; private set; } = new(); // <index, team>
|
||||
[BsonSerializer(typeof(IntSortedListSerializer<TeamInfo>))]
|
||||
[BsonElement] public SortedList<int, TeamInfo> TowerTeams { get; private set; } = new(); // Store Abyss teams separately
|
||||
[BsonElement] public int CurrentTeamIndex { get; private set; } = 1; // count from 0
|
||||
public int CurrentCharacterIndex = 0; // count from 0
|
||||
[BsonIgnore] public SortedSet<AvatarEntity> ActiveTeam { get; private set; } = new();
|
||||
[BsonIgnore] public TeamInfo MpTeam = new();
|
||||
[BsonElement] public int CurrentTeamIndex { get; private set; } = 1; // count from 1
|
||||
public int CurrentCharacterIndex = 0; // count from 0
|
||||
[BsonIgnore] public SortedList<int, AvatarEntity> ActiveTeam = new(); // index
|
||||
|
||||
[BsonIgnore] public uint EntityId;
|
||||
[BsonIgnore] public AbilitySyncStateInfo AbilitySyncState = new(); //TODO
|
||||
|
||||
public TeamManager(Player player)
|
||||
{
|
||||
Owner = player;
|
||||
OwnerId = player.GameUid;
|
||||
for (int i = 0; i < GameServer.Configuration.Server.GameOptions.Constants.DEFAULT_TEAMS; i++)
|
||||
for (int i = 1; i <= GameServer.Configuration.Server.GameOptions.Constants.DEFAULT_TEAMS; i++)
|
||||
{
|
||||
Teams.Add(i, new TeamInfo());
|
||||
}
|
||||
@ -37,16 +40,23 @@ namespace Weedwacker.GameServer.Systems.Player
|
||||
public async Task OnLoadAsync(Player owner)
|
||||
{
|
||||
Owner = owner;
|
||||
ActiveTeam = new();
|
||||
// Point to the "real" avatars
|
||||
Teams.Values.AsParallel().ForAll(async w => { foreach (var entry in w.AvatarInfo)
|
||||
var reloadedTeams = new SortedList<int, TeamInfo>();
|
||||
foreach (var team in Teams)
|
||||
{
|
||||
reloadedTeams.Add(team.Key, new(team.Value.TeamName));
|
||||
foreach(var entry in team.Value.AvatarInfo)
|
||||
{
|
||||
w.AvatarInfo.Add(entry.Key, owner.Avatars.GetAvatarById(entry.Value.AvatarId));
|
||||
reloadedTeams[team.Key].AvatarInfo.Add(entry.Key, owner.Avatars.GetAvatarById(entry.Value.AvatarId));
|
||||
}
|
||||
});
|
||||
}
|
||||
Teams = reloadedTeams;
|
||||
|
||||
// You stay simple clones >:)
|
||||
TowerTeams.Values.AsParallel().ForAll(async w => await w.OnLoadAsync(owner));
|
||||
foreach (ushort avatar in Teams[CurrentTeamIndex].AvatarInfo.Keys)
|
||||
ActiveTeam.Add(new AvatarEntity(Teams[CurrentTeamIndex], avatar));
|
||||
foreach (ushort characterIndex in Teams[CurrentTeamIndex].AvatarInfo.Keys)
|
||||
ActiveTeam.Add(characterIndex, new AvatarEntity(Teams[CurrentTeamIndex], characterIndex));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -66,6 +76,21 @@ namespace Weedwacker.GameServer.Systems.Player
|
||||
return -1;
|
||||
}
|
||||
|
||||
public async Task AddToTeamAsync(Avatar.Avatar avatar, int teamIndex = -1, int cIndex = -1)
|
||||
{
|
||||
if(teamIndex == -1)
|
||||
{
|
||||
Teams[CurrentTeamIndex].AddAvatar(avatar);
|
||||
}
|
||||
else
|
||||
{
|
||||
Teams[teamIndex].AddAvatar(avatar, cIndex == -1 ? CurrentCharacterIndex : cIndex);
|
||||
}
|
||||
|
||||
// Update Database
|
||||
await DatabaseManager.SaveTeamsAsync(this);
|
||||
}
|
||||
|
||||
private bool SetCurrentTeamId(int currentTeamIndex)
|
||||
{
|
||||
if (Teams.ContainsKey(currentTeamIndex))
|
||||
@ -94,7 +119,7 @@ namespace Weedwacker.GameServer.Systems.Player
|
||||
}
|
||||
|
||||
public TeamInfo GetCurrentSinglePlayerTeamInfo() { return Teams[CurrentTeamIndex]; }
|
||||
public AvatarEntity GetCurrentAvatarEntity() { return ActiveTeam.ElementAt(CurrentCharacterIndex); }
|
||||
public AvatarEntity GetCurrentAvatarEntity() { return ActiveTeam[CurrentCharacterIndex]; }
|
||||
|
||||
public bool IsSpawned()
|
||||
{
|
||||
@ -116,65 +141,17 @@ namespace Weedwacker.GameServer.Systems.Player
|
||||
return GameServer.Configuration.Server.GameOptions.AvatarLimits.SinglePlayerTeam;
|
||||
}
|
||||
|
||||
//TODO
|
||||
public async Task UpdateTeamEntities()
|
||||
{
|
||||
// If current team has changed
|
||||
AvatarEntity currentEntity = GetCurrentAvatarEntity();
|
||||
Dictionary<int, AvatarEntity> existingAvatars = new();
|
||||
int prevSelectedAvatarIndex = -1;
|
||||
|
||||
foreach (AvatarEntity entity in ActiveTeam)
|
||||
if (Owner.IsInMultiplayer())
|
||||
{
|
||||
existingAvatars.Add(entity.Avatar.AvatarId, entity);
|
||||
}
|
||||
|
||||
|
||||
// Add back entities into team
|
||||
for (int i = 0; i < GetCurrentTeamInfo().AvatarInfo.Count; i++)
|
||||
else
|
||||
{
|
||||
int avatarId = GetCurrentTeamInfo().AvatarInfo[i].AvatarId;
|
||||
AvatarEntity entity;
|
||||
|
||||
if (existingAvatars.ContainsKey(avatarId))
|
||||
{
|
||||
entity = existingAvatars[avatarId];
|
||||
existingAvatars.Remove(avatarId);
|
||||
if (entity == currentEntity)
|
||||
{
|
||||
prevSelectedAvatarIndex = i;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
entity = new AvatarEntity(Owner.Scene, Owner.Avatars.GetAvatarById(avatarId));
|
||||
}
|
||||
|
||||
ActiveTeam.Add(entity);
|
||||
}
|
||||
|
||||
// Unload removed entities
|
||||
foreach (AvatarEntity entity in existingAvatars.Values)
|
||||
{
|
||||
Owner.Scene.RemoveEntityAsync(entity);
|
||||
}
|
||||
|
||||
// Set new selected character index
|
||||
if (prevSelectedAvatarIndex == -1)
|
||||
{
|
||||
// Previous selected avatar is not in the same spot, we will select the current one in the prev slot
|
||||
prevSelectedAvatarIndex = Math.Min(CurrentCharacterIndex, ActiveTeam.Count - 1);
|
||||
}
|
||||
CurrentCharacterIndex = prevSelectedAvatarIndex;
|
||||
|
||||
// Packets
|
||||
await Owner.World.BroadcastPacketAsync(new PacketSceneTeamUpdateNotify(Owner));
|
||||
|
||||
// Check if character changed
|
||||
if (currentEntity != GetCurrentAvatarEntity())
|
||||
{
|
||||
// Remove and Add
|
||||
await Owner.Scene.ReplaceEntityAsync(currentEntity, GetCurrentAvatarEntity());
|
||||
}
|
||||
}
|
||||
|
||||
public async Task SetupAvatarTeamAsync(int teamId, List<long> list)
|
||||
@ -256,10 +233,10 @@ namespace Weedwacker.GameServer.Systems.Player
|
||||
int index = -1;
|
||||
for (int i = 0; i < ActiveTeam.Count; i++)
|
||||
{
|
||||
if (guid == ActiveTeam.ElementAt(i).Avatar.Guid)
|
||||
if (guid == ActiveTeam[i].Avatar.Guid)
|
||||
{
|
||||
index = i;
|
||||
newEntity = ActiveTeam.ElementAt(i);
|
||||
newEntity = ActiveTeam[i];
|
||||
}
|
||||
}
|
||||
|
||||
@ -301,7 +278,7 @@ namespace Weedwacker.GameServer.Systems.Player
|
||||
|
||||
for (int i = 0; i < ActiveTeam.Count; i++)
|
||||
{
|
||||
AvatarEntity entity = ActiveTeam.ElementAt(i);
|
||||
AvatarEntity entity = ActiveTeam[i];
|
||||
if (entity.LiveState == LifeState.LIFE_ALIVE)
|
||||
{
|
||||
replaceIndex = i;
|
||||
@ -326,7 +303,7 @@ namespace Weedwacker.GameServer.Systems.Player
|
||||
|
||||
public async Task<bool> ReviveAvatarAsync(Avatar.Avatar avatar)
|
||||
{
|
||||
foreach (AvatarEntity entity in ActiveTeam)
|
||||
foreach (AvatarEntity entity in ActiveTeam.Values)
|
||||
{
|
||||
if (entity.Avatar == avatar)
|
||||
{
|
||||
@ -349,7 +326,7 @@ namespace Weedwacker.GameServer.Systems.Player
|
||||
|
||||
public async Task<bool> HealAvatar(Avatar.Avatar avatar, int healRate, int healAmount)
|
||||
{
|
||||
foreach (AvatarEntity entity in ActiveTeam)
|
||||
foreach (AvatarEntity entity in ActiveTeam.Values)
|
||||
{
|
||||
if (entity.Avatar == avatar)
|
||||
{
|
||||
|
@ -1,37 +1,100 @@
|
||||
using Vim.Math3d;
|
||||
using System.Text.RegularExpressions;
|
||||
using NLua;
|
||||
using Vim.Math3d;
|
||||
|
||||
namespace Weedwacker.GameServer.Systems.Script.Scene
|
||||
{
|
||||
internal class SceneInfo
|
||||
{
|
||||
public SceneConfig scene_config;
|
||||
public SortedList<int, int> blocks; // <index, blockId>
|
||||
public SortedList<int, Rectangle> block_rects; // <index, Rectangle>
|
||||
public HashSet<string>? dummy_points; // load dummy points from Scene<sceneId>_<string>.lua
|
||||
public HashSet<string>? routes_config; // load routes from ???
|
||||
Lua LuaState;
|
||||
public SceneConfig? scene_config;
|
||||
|
||||
public SortedList<int, int>? blocks; // <index ,blockIds>
|
||||
public SortedList<int, Rectangle>? block_rects = new(); // <index, rectangle>
|
||||
public LuaTable dummy_points;// => LuaState.GetTable("dummy_points"); // load dummy points from Scene<sceneId>_<string>.lua
|
||||
public LuaTable routes_config;// => LuaState.GetTable("routes_config"); // load routes from ???
|
||||
|
||||
public static Task<SceneInfo> CreateAsync(Lua lua, int sceneId, string scriptPath)
|
||||
{
|
||||
var scene = new SceneInfo();
|
||||
return scene.InitializeAsync(lua, sceneId, scriptPath);
|
||||
}
|
||||
|
||||
private async Task<SceneInfo> InitializeAsync(Lua lua, int sceneId, string scriptPath)
|
||||
{
|
||||
LuaState = lua;
|
||||
|
||||
FileInfo sceneInfo = new(Path.Combine(scriptPath, "Scene", $"{sceneId}", $"scene{sceneId}.lua"));
|
||||
string script = await File.ReadAllTextAsync(sceneInfo.FullName);
|
||||
//script = Regex.Unescape(script);
|
||||
script = Regex.Replace(script, @"\r\n", "; "); // replace new lines with ';'
|
||||
script = Regex.Replace(script, "\"", "'"); // replace " with '
|
||||
lua.DoString($"_SCENE{sceneId} = {{}}");
|
||||
lua.DoString("loadScene = load (\"" + @script +"\""+ $", \";_;\", \"bt\" , _SCENE{sceneId})");
|
||||
lua.DoString("loadScene()");
|
||||
if(lua[$"_SCENE{sceneId}.{nameof(scene_config)}"] != null)
|
||||
scene_config = new(lua.GetTable($"_SCENE{sceneId}.{nameof(scene_config)}"));
|
||||
if (lua[$"_SCENE{sceneId}.{nameof(blocks)}"] != null)
|
||||
{
|
||||
var bloks = lua.GetTable($"_SCENE{sceneId}.{nameof(blocks)}");
|
||||
blocks = new SortedList<int, int>(lua.GetTableDict(bloks).ToDictionary(w => (int)(long)w.Key, w => (int)(long)w.Value));
|
||||
}
|
||||
if (lua[$"_SCENE{sceneId}.{nameof(block_rects)}"] != null)
|
||||
{
|
||||
var rects = lua.GetTable($"_SCENE{sceneId}.{nameof(block_rects)}");
|
||||
var rectDict = lua.GetTableDict(rects);
|
||||
block_rects = new SortedList<int, Rectangle>(rectDict.ToDictionary(w => (int)(long)w.Key, w => new Rectangle(w.Value as LuaTable)));
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public class SceneConfig
|
||||
{
|
||||
public Vector2 begin_pos; // x,z
|
||||
public Vector2 size; // x,z
|
||||
public Vector3 born_pos;
|
||||
public Vector3 born_rot;
|
||||
public int die_y;
|
||||
private LuaTable Table;
|
||||
// ONLY X,Z
|
||||
public Vector3 begin_pos => new Vector3((float?)(double?)Table[$"{nameof(begin_pos)}.x"] ?? 0, default, (float?)(double?)Table[$"{nameof(begin_pos)}.z"] ?? 0);
|
||||
// ONLY X,Z
|
||||
public Vector3 size => new Vector3((float?)(double?)Table[$"{nameof(size)}.x"] ?? 0, default, (float?)(double?)Table[$"{nameof(begin_pos)}.z"] ?? 0);
|
||||
public Vector3 born_pos => new Vector3((float?)(double?)Table[$"{nameof(born_pos)}.x"] ?? 0, (float?)(double?)Table[$"{nameof(born_pos)}.y"] ?? 0, (float?)(double?)Table[$"{nameof(born_pos)}.z"] ?? 0);
|
||||
public Vector3 born_rot => new Vector3((float?)(double?)Table[$"{nameof(born_rot)}.x"] ?? 0, (float?)(double?)Table[$"{nameof(born_rot)}.y"] ?? 0, (float?)(double?)Table[$"{nameof(born_rot)}.z"] ?? 0);
|
||||
public float? die_y => (int?)(long?)Table[$"die_y"];
|
||||
public RoomInfo room_safe_pos;
|
||||
public Vector2 vision_anchor; // x,z
|
||||
// ONLY X,Z
|
||||
public Vector3 vision_anchor => new Vector3((float?)(double?)Table[$"{nameof(vision_anchor)}.x"] ?? 0, default, (float?)(double?)Table[$"{nameof(vision_anchor)}.z"] ?? 0);
|
||||
|
||||
public SceneConfig(LuaTable table)
|
||||
{
|
||||
Table = table;
|
||||
room_safe_pos = new(Table);
|
||||
}
|
||||
}
|
||||
|
||||
public class Rectangle
|
||||
{
|
||||
public Vector2 min; // x,z
|
||||
public Vector2 max; // x,z
|
||||
private LuaTable Table;
|
||||
// ONLY X,Z
|
||||
public Vector3 min => new Vector3((float?)(double?)Table[$"{nameof(min)}.x"] ?? 0, default, (float?)(double?)Table[$"{nameof(min)}.z"] ?? 0);
|
||||
// ONLY X,Z
|
||||
public Vector3 max => new Vector3((float?)(double?)Table[$"{nameof(max)}.x"] ?? 0, default, (float?)(double?)Table[$"{nameof(max)}.z"] ?? 0);
|
||||
|
||||
public Rectangle(LuaTable table)
|
||||
{
|
||||
Table = table;
|
||||
}
|
||||
}
|
||||
|
||||
public class RoomInfo
|
||||
{
|
||||
public int scene_id;
|
||||
public Vector3 safe_pos;
|
||||
public Vector3 safe_rot;
|
||||
private LuaTable Table;
|
||||
public int? scene_id => (int?)(long?)Table[$"{nameof(scene_id)}"] ?? 0;
|
||||
public Vector3 safe_pos => new Vector3((float?)(double?)Table[$"{nameof(safe_pos)}.x"] ?? 0, (float?)(double?)Table[$"{nameof(safe_pos)}.y"] ?? 0, (float?)(double?)Table[$"{nameof(safe_pos)}.z"] ?? 0);
|
||||
public Vector3 safe_rot => new Vector3((float?)(double?)Table[$"{nameof(safe_rot)}.x"] ?? 0, (float?)(double?)Table[$"{nameof(safe_rot)}.y"] ?? 0, (float?)(double?)Table[$"{nameof(safe_rot)}.z"] ?? 0);
|
||||
|
||||
public RoomInfo(LuaTable table)
|
||||
{
|
||||
Table = table[$"{nameof(SceneConfig.room_safe_pos)}"] as LuaTable;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
32
src/GameServer/Systems/Script/Scene/SceneScriptManager.cs
Normal file
32
src/GameServer/Systems/Script/Scene/SceneScriptManager.cs
Normal file
@ -0,0 +1,32 @@
|
||||
using NLua;
|
||||
using Weedwacker.GameServer.Enums;
|
||||
using Weedwacker.GameServer.Systems.Script;
|
||||
using Weedwacker.GameServer.Systems.Script.Scene;
|
||||
|
||||
namespace Weedwacker.GameServer.Systems.World
|
||||
{
|
||||
internal class SceneScriptManager
|
||||
{
|
||||
private Lua LuaState;
|
||||
public SceneInfo Info;
|
||||
public Dictionary<int, SceneBlock> Blocks;
|
||||
public Dictionary<int, SceneGroup> Groups;
|
||||
public ScriptMonsterSpawnService ScriptMonsterSpawnService;
|
||||
|
||||
public static Task<SceneScriptManager> CreateAsync(int sceneId, string scriptPath)
|
||||
{
|
||||
var scene = new SceneScriptManager();
|
||||
scene.LuaState = new();
|
||||
return scene.InitializeAsync(sceneId, scriptPath);
|
||||
}
|
||||
|
||||
private async Task<SceneScriptManager> InitializeAsync(int sceneId, string scriptPath)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
internal Task CallEvent(EventType eventType, ScriptArgs scriptArgs)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
using MongoDB.Bson.Serialization.Attributes;
|
||||
using Weedwacker.GameServer.Database;
|
||||
using Weedwacker.GameServer.Systems.Avatar;
|
||||
using Weedwacker.Shared.Network.Proto;
|
||||
|
||||
namespace Weedwacker.GameServer.Systems.Social
|
||||
{
|
||||
@ -7,12 +9,14 @@ namespace Weedwacker.GameServer.Systems.Social
|
||||
{
|
||||
[BsonId][BsonElement("_id")] public int OwnerId { get; private set; }
|
||||
[BsonIgnore] private Player.Player Owner;
|
||||
[BsonElement] public HashSet<int> ShowAvatarList = new(); // avatarId
|
||||
[BsonElement] public bool IsShowAvatar = false;
|
||||
[BsonSerializer(typeof(IntDictionarySerializer<Friendship>))]
|
||||
[BsonElement] public Dictionary<int, Friendship> Friends { get; private set; } = new(); // GameUid
|
||||
[BsonSerializer(typeof(IntDictionarySerializer<Friendship>))]
|
||||
[BsonElement] public Dictionary<int, Friendship> PendingRequests { get; private set; } = new(); // GameUid
|
||||
[BsonSerializer(typeof(IntDictionarySerializer<Friendship>))]
|
||||
[BsonElement] public Dictionary<int, Friendship> BlackList { get; private set; } = new(); // GameUid why does it use the same proto lol
|
||||
[BsonElement] public Dictionary<int, Friendship> BlackList { get; private set; } = new(); // GameUid why does it use the Friendship proto lol
|
||||
[BsonElement] public HashSet<int> EmojiIdList { get; private set; } = new();
|
||||
|
||||
public SocialManager(Player.Player owner)
|
||||
@ -27,5 +31,74 @@ namespace Weedwacker.GameServer.Systems.Social
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public List<ShowAvatarInfo> GetShowAvatarInfoList()
|
||||
{
|
||||
List<ShowAvatarInfo> showAvatarInfoList = new();
|
||||
|
||||
Player.Player player = Owner;
|
||||
AvatarManager avatars = player.Avatars;
|
||||
|
||||
if (ShowAvatarList != null)
|
||||
{
|
||||
foreach (int avatarId in ShowAvatarList)
|
||||
{
|
||||
Avatar.Avatar avatar = avatars.GetAvatarById(avatarId);
|
||||
showAvatarInfoList.Add(avatar.ToShowAvatarInfoProto());
|
||||
}
|
||||
}
|
||||
return showAvatarInfoList;
|
||||
}
|
||||
|
||||
public SocialDetail GetSocialDetail(int asker)
|
||||
{
|
||||
List<SocialShowAvatarInfo> socialShowAvatarInfoList = new();
|
||||
if (ShowAvatarList != null)
|
||||
{
|
||||
foreach (int avatarId in ShowAvatarList)
|
||||
{
|
||||
var avatar = Owner.Avatars.GetAvatarById(avatarId);
|
||||
socialShowAvatarInfoList.Add(
|
||||
new SocialShowAvatarInfo()
|
||||
{
|
||||
AvatarId = (uint)avatarId,
|
||||
Level = (uint)avatar.Level,
|
||||
CostumeId = (uint)avatar.Costume
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SocialDetail social = new SocialDetail()
|
||||
{
|
||||
Uid = (uint)Owner.GameUid,
|
||||
ProfilePicture = Owner.Profile.HeadImage,
|
||||
Nickname = Owner.Profile.Nickname,
|
||||
Signature = Owner.Profile.Signature,
|
||||
Level = (uint)Owner.PlayerProperties[Enums.PlayerProperty.PROP_PLAYER_LEVEL],
|
||||
Birthday = Owner.Profile.Birthday,
|
||||
WorldLevel = (uint)Owner.PlayerProperties[Enums.PlayerProperty.PROP_PLAYER_WORLD_LEVEL],
|
||||
NameCardId = (uint)Owner.Profile.NameCardId,
|
||||
IsShowAvatar = IsShowAvatar,
|
||||
/* TODO
|
||||
FinishAchievementNum =,
|
||||
AvatarId = ,
|
||||
IsMpModeAvailable = ,
|
||||
FriendEnterHomeOption =,
|
||||
IsChatNoDisturb =,
|
||||
IsFriend =,
|
||||
OnlineId =,
|
||||
IsInBlacklist =,
|
||||
OnlineState =,
|
||||
Param = ,
|
||||
RemarkName = ,
|
||||
TowerFloorIndex = ,
|
||||
TowerLevelIndex = ,
|
||||
*/
|
||||
};
|
||||
social.ShowAvatarInfoList.AddRange(socialShowAvatarInfoList);
|
||||
|
||||
return social;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -134,7 +134,7 @@ namespace Weedwacker.GameServer.Systems.World
|
||||
|
||||
foreach (EquipItem item in Avatar.Equips.Values)
|
||||
{
|
||||
if ((item.ItemData as MaterialData).itemType == ItemType.ITEM_WEAPON)
|
||||
if (item.ItemData.itemType == ItemType.ITEM_WEAPON)
|
||||
{
|
||||
avatarInfo.Weapon = (item as WeaponItem).CreateSceneWeaponInfo();
|
||||
}
|
||||
|
@ -1,7 +1,9 @@
|
||||
using Vim.Math3d;
|
||||
using MongoDB.Driver;
|
||||
using Vim.Math3d;
|
||||
using Weedwacker.GameServer.Data;
|
||||
using Weedwacker.GameServer.Data.BinOut.Scene.Point;
|
||||
using Weedwacker.GameServer.Data.Excel;
|
||||
using Weedwacker.GameServer.Database;
|
||||
using Weedwacker.GameServer.Enums;
|
||||
using Weedwacker.GameServer.Packet;
|
||||
using Weedwacker.GameServer.Packet.Send;
|
||||
@ -21,23 +23,29 @@ namespace Weedwacker.GameServer.Systems.World
|
||||
public readonly HashSet<SpawnInfo> SpawnedEntities;
|
||||
public readonly HashSet<SpawnInfo> DeadSpawnedEntities;
|
||||
public int AutoCloseTime;
|
||||
public int Time { get; private set; }
|
||||
public uint Time { get; private set; }
|
||||
public SceneScriptManager ScriptManager { get; private set; }
|
||||
public readonly ScenePointData PointData;
|
||||
public readonly DungeonData? DungeonData;
|
||||
public int PrevScene; // Id of the previous scene
|
||||
public int PrevScenePoint;
|
||||
public Dictionary<Tuple<int, int>, int> ActiveAreaWeathers; // <areaID1, areaID2> weatherId>
|
||||
public HashSet<uint> SceneTags; // TODO apply based on host's data
|
||||
public Scene(World world, SceneData sceneData)
|
||||
{
|
||||
World = world;
|
||||
SceneData = sceneData;
|
||||
PointData = GameData.ScenePointDataMap["scene" + sceneData.id + "_point.json"];
|
||||
PointData = GameData.ScenePointDataMap["scene" + sceneData.id + "_point"];
|
||||
if (sceneData.type == SceneType.SCENE_DUNGEON)
|
||||
DungeonData = GameData.DungeonDataMap.Where(w => w.Value.sceneId == sceneData.id).First().Value;
|
||||
|
||||
Time = 8 * 60;
|
||||
PrevScene = 3;
|
||||
ScriptManager = new SceneScriptManager(this);
|
||||
|
||||
// Always applied tags?
|
||||
SceneTags = new HashSet<uint>(GameData.SceneTagDataMap.Where(w => w.Value.sceneId == GetId() && (w.Value.cond == null || w.Value.cond.Length == 0)).Select(s => (uint)s.Key));
|
||||
|
||||
//ScriptManager = GameData.SceneScripts[GetId()];
|
||||
}
|
||||
|
||||
public int GetId()
|
||||
@ -51,7 +59,7 @@ namespace Weedwacker.GameServer.Systems.World
|
||||
|
||||
public void ChangeTime(int time)
|
||||
{
|
||||
Time = time % 1440;
|
||||
Time = (uint)time % 1440;
|
||||
}
|
||||
|
||||
public bool IsInScene(GameEntity entity)
|
||||
@ -59,7 +67,13 @@ namespace Weedwacker.GameServer.Systems.World
|
||||
return Entities.ContainsKey(entity.Id);
|
||||
}
|
||||
|
||||
public async Task AddPlayerAsync(Player.Player player, EnterReason reason, Vector3 newPosition, EnterType type = EnterType.Self, int oldSceneId = default, Vector3 oldPos = default)
|
||||
public async Task UpdateActiveAreaWeathersAsync(Tuple<int, int> areaIDs)
|
||||
{
|
||||
//TODO update based on host's weather and quest progression
|
||||
await BroadcastPacketAsync(new PacketSceneAreaWeatherNotify(ClimateType.CLIMATE_SUNNY, 1));
|
||||
}
|
||||
|
||||
public async Task AddPlayerAsync(Player.Player player, EnterReason reason, Vector3 newPosition, EnterType type = EnterType.Self, int oldSceneId = default, Vector3 oldPos = default)
|
||||
{
|
||||
// Check if player already in
|
||||
if (Players.Contains(player))
|
||||
@ -70,7 +84,14 @@ namespace Weedwacker.GameServer.Systems.World
|
||||
// Add
|
||||
Players.Add(player);
|
||||
await player.SetSceneAsync(this);
|
||||
await player.SendPacketAsync(new PacketPlayerEnterSceneNotify(player, EnterType.Self, EnterReason.TeamKick, this, player.Position, oldSceneId, oldPos));
|
||||
player.Position = newPosition;
|
||||
|
||||
// Update Database
|
||||
var filter = Builders<Player.Player>.Filter.Where(w => w.AccountUid == player.AccountUid);
|
||||
var update = Builders<Player.Player>.Update.Set(w => w.PositionArray, player.PositionArray).Set(w => w.RotationArray, player.RotationArray);
|
||||
await DatabaseManager.UpdatePlayerAsync(filter, update);
|
||||
|
||||
await player.SendPacketAsync(new PacketPlayerEnterSceneNotify(player, type, reason, this, newPosition, oldSceneId, oldPos));
|
||||
|
||||
await SetupPlayerAvatarsAsync(player);
|
||||
}
|
||||
@ -82,8 +103,8 @@ namespace Weedwacker.GameServer.Systems.World
|
||||
await player.SetSceneAsync(null);
|
||||
|
||||
// Remove player avatars
|
||||
SortedSet<AvatarEntity> team = player.TeamManager.ActiveTeam;
|
||||
await RemoveEntitiesAsync(team, VisionType.Remove);
|
||||
SortedList<int, AvatarEntity> team = player.TeamManager.ActiveTeam;
|
||||
await RemoveEntitiesAsync(team.Values, VisionType.Remove);
|
||||
team.Clear();
|
||||
|
||||
// Remove player gadgets
|
||||
@ -105,18 +126,14 @@ namespace Weedwacker.GameServer.Systems.World
|
||||
TeamInfo teamInfo = player.TeamManager.GetCurrentTeamInfo();
|
||||
foreach (int avatarId in teamInfo.AvatarInfo.Keys)
|
||||
{
|
||||
if (avatarId == 0) continue;
|
||||
AvatarEntity entity = new AvatarEntity(player.Scene, player.Avatars.GetAvatarById(avatarId));
|
||||
player.TeamManager.ActiveTeam.Add(entity);
|
||||
}
|
||||
|
||||
// Limit character index in case its out of bounds
|
||||
if (player.TeamManager.CurrentCharacterIndex >= player.TeamManager.ActiveTeam.Count || player.TeamManager.CurrentCharacterIndex < 0)
|
||||
{
|
||||
player.TeamManager.CurrentCharacterIndex = player.TeamManager.CurrentCharacterIndex - 1;
|
||||
player.TeamManager.ActiveTeam = new SortedList<int, AvatarEntity>(teamInfo.AvatarInfo.Select(
|
||||
w => new KeyValuePair<int, AvatarEntity>(w.Key, new AvatarEntity(player.Scene, w.Value))).ToDictionary(w => w.Key, w => w.Value));
|
||||
}
|
||||
}
|
||||
|
||||
public async Task SpawnPlayer(Player.Player player)
|
||||
public async Task SpawnPlayerAsync(Player.Player player)
|
||||
{
|
||||
var teamManager = player.TeamManager;
|
||||
if (IsInScene(teamManager.GetCurrentAvatarEntity()))
|
||||
@ -132,7 +149,7 @@ namespace Weedwacker.GameServer.Systems.World
|
||||
await AddEntityAsync(teamManager.GetCurrentAvatarEntity());
|
||||
|
||||
// Notify the client of any extra skill charges
|
||||
teamManager.ActiveTeam.AsParallel().ForAll(async x => await x.Avatar.GetCurSkillDepot().SendAvatarSkillInfoNotify());
|
||||
teamManager.ActiveTeam.AsParallel().ForAll(async x => await x.Value.Avatar.GetCurSkillDepot().SendAvatarSkillInfoNotify());
|
||||
}
|
||||
|
||||
public async Task RespawnPlayerAsync(Player.Player player)
|
||||
@ -140,7 +157,7 @@ namespace Weedwacker.GameServer.Systems.World
|
||||
//player.StaminaManager.stopSustainedStaminaHandler(); // prevent drowning immediately after respawn
|
||||
|
||||
// Revive all team members
|
||||
foreach (AvatarEntity entity in player.TeamManager.ActiveTeam)
|
||||
foreach (AvatarEntity entity in player.TeamManager.ActiveTeam.Values)
|
||||
{
|
||||
entity.FightProps[
|
||||
FightProperty.FIGHT_PROP_CUR_HP] =
|
||||
@ -265,12 +282,16 @@ namespace Weedwacker.GameServer.Systems.World
|
||||
if (attacker != null)
|
||||
{
|
||||
// Check codex
|
||||
if (attacker is ClientGadgetEntity gadgetAttacker) {
|
||||
if (attacker is ClientGadgetEntity gadgetAttacker)
|
||||
{
|
||||
var clientGadgetOwner = Entities[gadgetAttacker.OwnerEntityId];
|
||||
if (clientGadgetOwner is AvatarEntity) {
|
||||
if (clientGadgetOwner is AvatarEntity)
|
||||
{
|
||||
//((ClientGadgetEntity)attacker).Owner.Codex.CheckAnimal(target, CodexAnimalData.CodexAnimalUnlockCondition.CODEX_COUNT_TYPE_KILL);
|
||||
}
|
||||
} else if (attacker is AvatarEntity avatarAttacker) {
|
||||
}
|
||||
else if (attacker is AvatarEntity avatarAttacker)
|
||||
{
|
||||
//avatarAttacker.Avatar.Owner.Codex.CheckAnimal(target, CodexAnimalData.CodexAnimalUnlockCondition.CODEX_COUNT_TYPE_KILL);
|
||||
}
|
||||
}
|
||||
@ -316,7 +337,8 @@ namespace Weedwacker.GameServer.Systems.World
|
||||
{
|
||||
GameEntity entity = Entities[entityId];
|
||||
|
||||
if (entity == null || !(entity is ClientGadgetEntity)) {
|
||||
if (entity == null || !(entity is ClientGadgetEntity))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1,24 +0,0 @@
|
||||
using Weedwacker.GameServer.Enums;
|
||||
using Weedwacker.GameServer.Systems.Script;
|
||||
using Weedwacker.GameServer.Systems.Script.Scene;
|
||||
|
||||
namespace Weedwacker.GameServer.Systems.World
|
||||
{
|
||||
internal class SceneScriptManager
|
||||
{
|
||||
public readonly Scene Scene;
|
||||
public SceneInfo Info;
|
||||
public ScriptMonsterSpawnService ScriptMonsterSpawnService;
|
||||
|
||||
public SceneScriptManager(Scene scene)
|
||||
{
|
||||
Scene = scene;
|
||||
//TODO
|
||||
}
|
||||
|
||||
internal Task CallEvent(EventType eventType, ScriptArgs scriptArgs)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
@ -23,7 +23,6 @@ namespace Weedwacker.GameServer.Systems.World
|
||||
public World(Player.Player owner)
|
||||
{
|
||||
Host = owner;
|
||||
Players.Add(owner);
|
||||
LevelEntityId = GetNextEntityId(EntityIdType.MPLEVEL);
|
||||
WorldLevel = owner.Profile.WorldLevel;
|
||||
GameServer.RegisterWorld(this);
|
||||
@ -109,6 +108,7 @@ namespace Weedwacker.GameServer.Systems.World
|
||||
|
||||
public async Task RemovePlayerAsync(Player.Player player)
|
||||
{
|
||||
if (!Players.Contains(player)) return;
|
||||
// Remove team entities
|
||||
await player.SendPacketAsync(new PacketDelTeamEntityNotify(player.SceneId, player.TeamManager.EntityId));
|
||||
|
||||
@ -152,6 +152,7 @@ namespace Weedwacker.GameServer.Systems.World
|
||||
}
|
||||
|
||||
Scene? oldScene = player.Scene;
|
||||
int oldSceneId = oldScene == null ? 0 : oldScene.GetId();
|
||||
Scene newScene = GetSceneById(sceneId);
|
||||
|
||||
if (oldScene != null)
|
||||
@ -163,12 +164,12 @@ namespace Weedwacker.GameServer.Systems.World
|
||||
|
||||
if (useDefaultBornPosition)
|
||||
{
|
||||
SceneInfo sceneInfo = newScene.ScriptManager.Info;
|
||||
SceneInfo sceneInfo = GameData.SceneScripts[sceneId];
|
||||
teleportTo = sceneInfo.scene_config.born_pos;
|
||||
player.Rotation = sceneInfo.scene_config.born_rot;
|
||||
}
|
||||
|
||||
await newScene.AddPlayerAsync(player, enterReason, teleportTo, enterType, oldScene.GetId(), player.Position);
|
||||
await newScene.AddPlayerAsync(player, enterReason, teleportTo, enterType, oldSceneId, player.Position);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -177,18 +178,18 @@ namespace Weedwacker.GameServer.Systems.World
|
||||
{
|
||||
Players.AsParallel().ForAll(async player =>
|
||||
{
|
||||
// Dont send packets if player is logging in and filter out joining player
|
||||
// Dont send packets if player is logging in and filter out joining player
|
||||
if (!player.HasSentLoginPackets || player == paramPlayer) return;
|
||||
|
||||
|
||||
// Update team of all players since max players has been changed - Probably not the best way to do it
|
||||
// Update team of all players since max players has been changed - Probably not the best way to do it
|
||||
if (IsMultiplayer)
|
||||
{
|
||||
player.TeamManager.MpTeam.CopyFrom(player.TeamManager.MpTeam, player.TeamManager.GetMaxTeamSize());
|
||||
await player.TeamManager.UpdateTeamEntities();
|
||||
}
|
||||
|
||||
// Dont send packets if player is loading into the scene
|
||||
// Dont send packets if player is loading into the scene
|
||||
if (player.SceneLoadState < SceneLoadState.INIT)
|
||||
{
|
||||
await Task.WhenAll(new Task[]
|
||||
@ -204,12 +205,14 @@ namespace Weedwacker.GameServer.Systems.World
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
public async Task BroadcastPacketAsync(BasePacket packet)
|
||||
{
|
||||
// Send to all players - might have to check if player has been sent data packets
|
||||
Players.AsParallel().ForAll(async p => await p.SendPacketAsync(packet));
|
||||
Players.AsParallel().ForAll(async p => await p.SendPacketAsync(packet));
|
||||
}
|
||||
|
||||
// Returns false if there are no players in this world
|
||||
|
Loading…
Reference in New Issue
Block a user