Skip to content

Commit

Permalink
Merge pull request #71 from Kaioru/feat/quests
Browse files Browse the repository at this point in the history
Implement basic quest handling
  • Loading branch information
Kaioru authored Sep 25, 2023
2 parents 0eb6664 + dd3400c commit 1e28ad5
Show file tree
Hide file tree
Showing 106 changed files with 2,446 additions and 328 deletions.
10 changes: 10 additions & 0 deletions src/app/Edelstein.Application.Server/ProgramHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
using Edelstein.Common.Gameplay.Game.Combat;
using Edelstein.Common.Gameplay.Game.Continents;
using Edelstein.Common.Gameplay.Game.Conversations;
using Edelstein.Common.Gameplay.Game.Quests;
using Edelstein.Common.Gameplay.Login;
using Edelstein.Common.Gameplay.Models.Inventories;
using Edelstein.Common.Gameplay.Packets;
using Edelstein.Common.Gameplay.Shop;
using Edelstein.Common.Gameplay.Shop.Commodities;
Expand All @@ -25,8 +27,10 @@
using Edelstein.Protocol.Gameplay.Game.Contexts;
using Edelstein.Protocol.Gameplay.Game.Continents;
using Edelstein.Protocol.Gameplay.Game.Conversations;
using Edelstein.Protocol.Gameplay.Game.Quests;
using Edelstein.Protocol.Gameplay.Login;
using Edelstein.Protocol.Gameplay.Login.Contexts;
using Edelstein.Protocol.Gameplay.Models.Inventories;
using Edelstein.Protocol.Gameplay.Shop;
using Edelstein.Protocol.Gameplay.Shop.Commodities;
using Edelstein.Protocol.Gameplay.Shop.Contexts;
Expand Down Expand Up @@ -107,6 +111,9 @@ public async Task StartAsync(CancellationToken cancellationToken)
c.Resolve<ITransportAcceptor>(),
stage
)).As<IBootstrap>().SingleInstance();


b.RegisterType<InventoryManager>().As<IInventoryManager>().SingleInstance();

switch (stage)
{
Expand Down Expand Up @@ -167,6 +174,9 @@ public async Task StartAsync(CancellationToken cancellationToken)
b.RegisterType<ContiMoveManager>().As<IContiMoveManager>().SingleInstance();
b.RegisterType<ScriptedConversationManager>().As<INamedConversationManager>().SingleInstance();
b.RegisterType<SkillManager>().As<ISkillManager>().SingleInstance();
b.RegisterType<ModifiedQuestTimeManager>().As<IModifiedQuestTimeManager>().SingleInstance();
b.RegisterType<QuestManager>().As<IQuestManager>().SingleInstance();
b.RegisterType<MobQuestCacheManager>().As<IMobQuestCacheManager>().SingleInstance();

b
.RegisterAssemblyTypes(Assembly.GetAssembly(typeof(GameStage))!)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
using Edelstein.Protocol.Gameplay.Game.Conversations;
using Edelstein.Protocol.Gameplay.Game.Conversations.Speakers;
using Edelstein.Protocol.Gameplay.Game.Objects.User;

namespace Edelstein.Common.Gameplay.Game.Conversations;

public class FallbackConversation : IConversation
{
private readonly string _name;
private readonly IFieldUser _user;

public FallbackConversation(string name) => _name = name;

public Task Start(IConversationContext ctx, IConversationSpeaker self, IConversationSpeaker target)
public FallbackConversation(string name, IFieldUser user)
{
self.Say($"The scripted conversation '{_name}' is not available");
return Task.CompletedTask;
_name = name;
_user = user;
}

public Task Start(IConversationContext ctx, IConversationSpeaker self, IConversationSpeaker target)
=> _user.Message($"The scripted conversation '{_name}' is not available");
}
2 changes: 1 addition & 1 deletion src/common/Edelstein.Common.Gameplay.Game/Field.cs
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ public async Task Leave(IFieldObject obj, Func<IPacket>? getLeavePacket)
{
if (obj is IFieldSplitObserver observer)
foreach (var split in observer.Observing.ToImmutableList())
await split.Unobserve(observer);
await split.Unobserve(observer, true);
await obj.FieldSplit.Leave(obj, getLeavePacket: getLeavePacket);
}

Expand Down
11 changes: 6 additions & 5 deletions src/common/Edelstein.Common.Gameplay.Game/FieldSplit.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,15 +109,16 @@ await Task.WhenAll(Objects
await UpdateControllableObjects();
}

public async Task Unobserve(IFieldSplitObserver observer)
public async Task Unobserve(IFieldSplitObserver observer, bool quiet = false)
{
_observers.Remove(observer);
observer.Observing.Remove(this);

await Task.WhenAll(Objects
.Where(o => o != observer)
.Where(o => o.IsVisibleTo(observer))
.Select(o => observer.Dispatch(o.GetLeaveFieldPacket())));
if (!quiet)
await Task.WhenAll(Objects
.Where(o => o != observer)
.Where(o => o.IsVisibleTo(observer))
.Select(o => observer.Dispatch(o.GetLeaveFieldPacket())));
await UpdateControllableObjects();
}

Expand Down
66 changes: 10 additions & 56 deletions src/common/Edelstein.Common.Gameplay.Game/GameStage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,69 +50,23 @@ await user.Context.Services.Friend.UpdateProfile(new FriendUpdateProfileRequest(
await field.Enter(fieldUser);
await base.Enter(user);

var funcKeyMappedInitPacket = new PacketWriter(PacketSendOperations.FuncKeyMappedInit);

funcKeyMappedInitPacket.WriteBool(user.Character.FuncKeys.Records.Count == 0);
if (user.Character.FuncKeys.Records.Count > 0)
{
for (byte i = 0; i < 90; i++)
{
if (user.Character.FuncKeys.Records.TryGetValue(i, out var value))
{
funcKeyMappedInitPacket.WriteByte(value.Type);
funcKeyMappedInitPacket.WriteInt(value.Action);
}
else
{
funcKeyMappedInitPacket.WriteByte(0);
funcKeyMappedInitPacket.WriteInt(0);
}
}
}
await fieldUser.Dispatch(funcKeyMappedInitPacket.Build());

var quickslotMappedInitPacket = new PacketWriter(PacketSendOperations.QuickslotMappedInit);

quickslotMappedInitPacket.WriteBool(user.Character.QuickslotKeys.Records.Count > 0);
if (user.Character.QuickslotKeys.Records.Count > 0)
for (byte i = 0; i < 8; i++)
quickslotMappedInitPacket.WriteInt(user.Character.QuickslotKeys.Records.TryGetValue(i, out var value)
? value
: 0
);
await fieldUser.Dispatch(quickslotMappedInitPacket.Build());

if (user.Friends != null)
{
var friendPacket = new PacketWriter(PacketSendOperations.FriendResult);

friendPacket.WriteByte((byte)FriendResultOperations.LoadFriend_Done);
friendPacket.WriteByte((byte)user.Friends.Records.Count);
foreach (var record in user.Friends.Records.Values)
friendPacket.WriteFriendInfo(record);
foreach (var _ in user.Friends.Records.Values)
friendPacket.WriteInt(0);
await fieldUser.Dispatch(friendPacket.Build());
await user.Context.Services.Friend.UpdateChannel(new FriendUpdateChannelRequest(
user.Character.ID,
user.Context.Options.ChannelID
));
}
await user.DispatchInitFuncKeys();
await user.DispatchInitQuickSlotKeys();
await user.DispatchInitFriends();
await user.DispatchInitParty();
await user.DispatchInitQuestTime();

_ = user.Context.Services.Friend.UpdateChannel(new FriendUpdateChannelRequest(
user.Character.ID,
user.Context.Options.ChannelID
));
if (user.Party != null)
{
var partyPacket = new PacketWriter(PacketSendOperations.PartyResult);
partyPacket.WriteByte((byte)PartyResultOperations.LoadPartyDone);
partyPacket.WriteInt(user.Party.ID);
partyPacket.WritePartyInfo(user.Party);
await fieldUser.Dispatch(partyPacket.Build());
await user.Context.Services.Party.UpdateChannelOrField(new PartyUpdateChannelOrFieldRequest(
_ = user.Context.Services.Party.UpdateChannelOrField(new PartyUpdateChannelOrFieldRequest(
user.Party.ID,
user.Character.ID,
user.Context.Options.ChannelID,
field.ID
));
}
}

public new async Task Leave(IGameStageUser user)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
using Edelstein.Common.Gameplay.Packets;
using Edelstein.Common.Gameplay.Social;
using Edelstein.Common.Utilities.Packets;
using Edelstein.Protocol.Gameplay.Game;
using Edelstein.Protocol.Services.Social.Contracts;

namespace Edelstein.Common.Gameplay.Game;

public static class GameStageUserExtensions
{
public static Task DispatchInitFuncKeys(this IGameStageUser user)
{
var p = new PacketWriter(PacketSendOperations.FuncKeyMappedInit);

p.WriteBool(user.Character?.FuncKeys.Records.Count == 0);
if (user.Character?.FuncKeys.Records.Count > 0)
{
for (byte i = 0; i < 90; i++)
{
if (user.Character.FuncKeys.Records.TryGetValue(i, out var value))
{
p.WriteByte(value.Type);
p.WriteInt(value.Action);
}
else
{
p.WriteByte(0);
p.WriteInt(0);
}
}
}

return user.Dispatch(p.Build());
}

public static Task DispatchInitQuickSlotKeys(this IGameStageUser user)
{
var p = new PacketWriter(PacketSendOperations.QuickslotMappedInit);

p.WriteBool(user.Character?.QuickslotKeys.Records.Count > 0);
if (user.Character?.QuickslotKeys.Records.Count > 0)
for (byte i = 0; i < 8; i++)
p.WriteInt(user.Character.QuickslotKeys.Records.TryGetValue(i, out var value)
? value
: 0
);
return user.Dispatch(p.Build());
}

public async static Task DispatchInitFriends(this IGameStageUser user)
{
if (user.Friends != null)
{
var p = new PacketWriter(PacketSendOperations.FriendResult);

p.WriteByte((byte)FriendResultOperations.LoadFriend_Done);
p.WriteByte((byte)user.Friends.Records.Count);
foreach (var record in user.Friends.Records.Values)
p.WriteFriendInfo(record);
foreach (var _ in user.Friends.Records.Values)
p.WriteInt(0);
await user.Dispatch(p.Build());
}
}

public async static Task DispatchInitParty(this IGameStageUser user)
{
if (user.Party != null)
{
var p = new PacketWriter(PacketSendOperations.PartyResult);
p.WriteByte((byte)PartyResultOperations.LoadPartyDone);
p.WriteInt(user.Party.ID);
p.WritePartyInfo(user.Party);
await user.Dispatch(p.Build());
}
}

public async static Task DispatchInitQuestTime(this IGameStageUser user)
{
var records = await user.Context.Managers.QuestTime.RetrieveAll();
var p = new PacketWriter(PacketSendOperations.SetQuestTime);

p.WriteByte((byte)records.Count);
foreach (var record in records)
{
p.WriteInt(record.ID);
p.WriteDateTime(record.DateStart);
p.WriteDateTime(record.DateEnd);
}
await user.Dispatch(p.Build());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public FieldGeneratorNPCUnit(IField field, IFieldTemplateLife life, INPCTemplate

NPC = new FieldNPC(
_template,
_life.Position,
_field.Template.Footholds.FindByID(_life.FootholdID)?.Line.AtX(_life.Position.X) ?? _life.Position,
_field.Template.Footholds.FindByID(_life.FootholdID),
_life.Bounds,
_life.IsFacingLeft
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
namespace Edelstein.Common.Gameplay.Game.Handlers;

public class PartyRequestHandler : AbstractFieldHandler
{
{
private readonly ILogger _logger;

public PartyRequestHandler(ILogger<PartyRequestHandler> logger) => _logger = logger;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using Edelstein.Common.Gameplay.Packets;
using Edelstein.Common.Utilities.Packets;
using Edelstein.Protocol.Gameplay.Game.Contracts;
using Edelstein.Protocol.Gameplay.Game.Objects.User;
using Edelstein.Protocol.Utilities.Packets;
using Edelstein.Protocol.Utilities.Pipelines;

namespace Edelstein.Common.Gameplay.Game.Handlers;

public class UserPortalScriptRequestHandler : AbstractPipedFieldHandler<FieldOnPacketUserPortalScriptRequest>
{

public UserPortalScriptRequestHandler(IPipeline<FieldOnPacketUserPortalScriptRequest> pipeline) : base(pipeline)
{
}

public override short Operation => (short)PacketRecvOperations.UserPortalScriptRequest;

protected override FieldOnPacketUserPortalScriptRequest? Serialize(IFieldUser user, IPacketReader reader)
=> new(
user,
reader.Skip(1).ReadString(),
reader.ReadPoint2D()
);
}
Loading

0 comments on commit 1e28ad5

Please sign in to comment.