diff --git a/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj b/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj index 3c275fc0..7db51905 100644 --- a/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj +++ b/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj @@ -93,13 +93,14 @@ + - + diff --git a/FFXIVClassic Map Server/WorldManager.cs b/FFXIVClassic Map Server/WorldManager.cs index 12e82dde..62e9779b 100644 --- a/FFXIVClassic Map Server/WorldManager.cs +++ b/FFXIVClassic Map Server/WorldManager.cs @@ -41,8 +41,10 @@ namespace FFXIVClassic_Map_Server private const int MILIS_LOOPTIME = 10; private Timer mZoneTimer; - //Content Groups + //Zone Server Groups public Dictionary mContentGroups = new Dictionary(); + public Dictionary mRelationGroups = new Dictionary(); + public Dictionary mTradeGroups = new Dictionary(); private Object groupLock = new Object(); public ulong groupIndexId = 1; @@ -712,9 +714,7 @@ namespace FFXIVClassic_Map_Server player.SendInstanceUpdate(); player.playerSession.LockUpdates(false); - - - + LuaEngine.GetInstance().CallLuaFunction(player, contentArea, "onZoneIn", true); } @@ -863,6 +863,160 @@ namespace FFXIVClassic_Map_Server } } + public RelationGroup CreateRelationGroup(Actor inviter, Actor invitee, ulong groupType) + { + lock (groupLock) + { + groupIndexId = groupIndexId | 0x0000000000000000; + + RelationGroup group = new RelationGroup(groupIndexId, inviter.actorId, invitee.actorId, 0, groupType); + mRelationGroups.Add(groupIndexId, group); + groupIndexId++; + + group.SendGroupPacketsAll(inviter.actorId, invitee.actorId); + + return group; + } + } + + public RelationGroup GetRelationGroup(uint actorId) + { + lock (groupLock) + { + foreach (RelationGroup relation in mRelationGroups.Values) + { + if (relation.GetHost() == actorId || relation.GetOther() == actorId) + return relation; + } + return null; + } + } + + public void DeleteRelationGroup(ulong groupid) + { + lock (groupLock) + { + if (mRelationGroups.ContainsKey(groupid)) + mRelationGroups.Remove(groupid); + } + } + + public TradeGroup CreateTradeGroup(Player inviter, Player invitee) + { + lock (groupLock) + { + groupIndexId = groupIndexId | 0x0000000000000000; + + TradeGroup group = new TradeGroup(groupIndexId, inviter.actorId, invitee.actorId); + mTradeGroups.Add(groupIndexId, group); + groupIndexId++; + + group.SendGroupPacketsAll(inviter.actorId, invitee.actorId); + + inviter.SendGameMessage(GetActor(), 25101, 0x20, (object)invitee); //You request to trade with X + invitee.SendGameMessage(GetActor(), 25037, 0x20, (object)inviter); //X wishes to trade with you + + return group; + } + } + + public TradeGroup GetTradeGroup(uint actorId) + { + lock (groupLock) + { + foreach (TradeGroup group in mTradeGroups.Values) + { + if (group.GetHost() == actorId || group.GetOther() == actorId) + return (TradeGroup)group; + } + return null; + } + } + + public void DeleteTradeGroup(ulong groupid) + { + lock (groupLock) + { + if (mTradeGroups.ContainsKey(groupid)) + { + TradeGroup group = mTradeGroups[groupid]; + group.SendDeletePackets(group.GetHost(), group.GetOther()); + mTradeGroups.Remove(groupid); + } + } + } + + public void AcceptTrade(Player invitee) + { + TradeGroup group = GetTradeGroup(invitee.actorId); + + if (group == null) + { + invitee.SendMessage(0x20, "", "MASSIVE ERROR: No tradegroup found!!!"); + return; + } + + Player inviter = (Player)invitee.GetZone().FindActorInArea(group.GetHost()); + + DeleteTradeGroup(group.groupIndex); + } + + public void CancelTradeTooFar(Player inviter) + { + TradeGroup group = GetTradeGroup(inviter.actorId); + + if (group == null) + { + inviter.SendMessage(0x20, "", "MASSIVE ERROR: No tradegroup found!!!"); + return; + } + + Player invitee = (Player)inviter.GetZone().FindActorInArea(group.GetOther()); + + inviter.SendGameMessage(GetActor(), 25042, 0x20); //You cancel the trade. + if (invitee != null) + invitee.SendGameMessage(GetActor(), 25042, 0x20); //The trade has been canceled. + + DeleteTradeGroup(group.groupIndex); + } + + public void CancelTrade(Player inviter) + { + TradeGroup group = GetTradeGroup(inviter.actorId); + + if (group == null) + { + inviter.SendMessage(0x20, "", "MASSIVE ERROR: No tradegroup found!!!"); + return; + } + + Player invitee = (Player)inviter.GetZone().FindActorInArea(group.GetOther()); + + inviter.SendGameMessage(GetActor(), 25041, 0x20); //You cancel the trade. + if (invitee != null) + invitee.SendGameMessage(GetActor(), 25040, 0x20); //The trade has been canceled. + + DeleteTradeGroup(group.groupIndex); + } + + public void RefuseTrade(Player invitee) + { + TradeGroup group = GetTradeGroup(invitee.actorId); + + if (group == null) + { + invitee.SendMessage(0x20, "", "MASSIVE ERROR: No tradegroup found!!!"); + return; + } + + Player inviter = (Player)invitee.GetZone().FindActorInArea(group.GetHost()); + + if (inviter != null) + inviter.SendGameMessage(GetActor(), 25038, 0x20); //Your trade request fails + + DeleteTradeGroup(group.groupIndex); + } + public bool SendGroupInit(Session session, ulong groupId) { if (mContentGroups.ContainsKey(groupId)) @@ -870,6 +1024,11 @@ namespace FFXIVClassic_Map_Server mContentGroups[groupId].SendInitWorkValues(session); return true; } + else if (mTradeGroups.ContainsKey(groupId)) + { + mTradeGroups[groupId].SendInitWorkValues(session); + return true; + } return false; } diff --git a/FFXIVClassic Map Server/actors/group/Relation.cs b/FFXIVClassic Map Server/actors/group/RelationGroup.cs similarity index 94% rename from FFXIVClassic Map Server/actors/group/Relation.cs rename to FFXIVClassic Map Server/actors/group/RelationGroup.cs index 600c8b9c..2d780498 100644 --- a/FFXIVClassic Map Server/actors/group/Relation.cs +++ b/FFXIVClassic Map Server/actors/group/RelationGroup.cs @@ -11,13 +11,13 @@ using System.Threading.Tasks; namespace FFXIVClassic_Map_Server.actors.group { - class Relation : Group + class RelationGroup : Group { public RelationWork work = new RelationWork(); private uint charaOther; private ulong topicGroup; - public Relation(ulong groupIndex, uint host, uint other, uint command, ulong topicGroup) : base (groupIndex) + public RelationGroup(ulong groupIndex, uint host, uint other, uint command, ulong topicGroup) : base (groupIndex) { this.charaOther = other; work._globalTemp.host = ((ulong)host << 32) | (0xc17909); diff --git a/FFXIVClassic Map Server/actors/group/TradeGroup.cs b/FFXIVClassic Map Server/actors/group/TradeGroup.cs new file mode 100644 index 00000000..49741307 --- /dev/null +++ b/FFXIVClassic Map Server/actors/group/TradeGroup.cs @@ -0,0 +1,79 @@ +using FFXIVClassic.Common; +using FFXIVClassic_Map_Server.actors.chara.npc; +using FFXIVClassic_Map_Server.actors.group.Work; +using FFXIVClassic_Map_Server.Actors; +using FFXIVClassic_Map_Server.dataobjects; +using FFXIVClassic_Map_Server.packets.send.group; +using FFXIVClassic_Map_Server.packets.send.groups; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FFXIVClassic_Map_Server.actors.group +{ + class TradeGroup : Group + { + public RelationWork work = new RelationWork(); + private uint charaOther; + private ulong topicGroup; + + public TradeGroup(ulong groupIndex, uint host, uint other) + : base(groupIndex) + { + this.charaOther = other; + work._globalTemp.host = ((ulong)host << 32) | (0xc17909); + work._globalTemp.variableCommand = 30001; + } + + public uint GetHost() + { + return (uint)(((ulong)work._globalTemp.host >> 32) & 0xFFFFFFFF); + } + + public uint GetOther() + { + return charaOther; + } + + public override int GetMemberCount() + { + return 2; + } + + public override uint GetTypeId() + { + return Group.TradeRelationGroup; + } + + public ulong GetTopicGroupIndex() + { + return topicGroup; + } + + public override List BuildMemberList(uint id) + { + List groupMembers = new List(); + + uint hostId = (uint)((work._globalTemp.host >> 32) & 0xFFFFFFFF); + + groupMembers.Add(new GroupMember(hostId, -1, 0, false, Server.GetServer().GetSession(hostId) != null, Server.GetWorldManager().GetActorInWorld(hostId).customDisplayName)); + groupMembers.Add(new GroupMember(charaOther, -1, 0, false, Server.GetServer().GetSession(charaOther) != null, Server.GetWorldManager().GetActorInWorld(charaOther).customDisplayName)); + return groupMembers; + } + + public override void SendInitWorkValues(Session session) + { + SynchGroupWorkValuesPacket groupWork = new SynchGroupWorkValuesPacket(groupIndex); + groupWork.addProperty(this, "work._globalTemp.host"); + groupWork.addProperty(this, "work._globalTemp.variableCommand"); + groupWork.setTarget("/_init"); + + SubPacket test = groupWork.buildPacket(session.id); + test.DebugPrintSubPacket(); + session.QueuePacket(test); + } + + } +} diff --git a/data/scripts/commands/ConfirmTradeCommand.lua b/data/scripts/commands/ConfirmTradeCommand.lua new file mode 100644 index 00000000..109f783c --- /dev/null +++ b/data/scripts/commands/ConfirmTradeCommand.lua @@ -0,0 +1,20 @@ +--[[ + +ConfirmTradeCommand Script + +Handles what happens when you accept/refuse a trade + +--]] + +function onEventStarted(player, actor, triggerName, groupType, result) + + --Accept + if (result == 1) then + GetWorldManager():AcceptTrade(player); + --Refuse + elseif (result == 2) then + GetWorldManager():RefuseTrade(player); + end + player:EndEvent(); + +end \ No newline at end of file diff --git a/data/scripts/commands/TradeOfferCancelCommand.lua b/data/scripts/commands/TradeOfferCancelCommand.lua new file mode 100644 index 00000000..71edd609 --- /dev/null +++ b/data/scripts/commands/TradeOfferCancelCommand.lua @@ -0,0 +1,14 @@ +--[[ + +TradeOfferCommand Script + +Handles what happens a player cancels a trade + +--]] + +function onEventStarted(player, actor, triggerName, commandId, result) + + GetWorldManager():CancelTrade(player); + player:EndEvent(); + +end \ No newline at end of file diff --git a/data/scripts/commands/TradeOfferCommand.lua b/data/scripts/commands/TradeOfferCommand.lua new file mode 100644 index 00000000..8222d7d8 --- /dev/null +++ b/data/scripts/commands/TradeOfferCommand.lua @@ -0,0 +1,26 @@ +--[[ + +TradeOfferCommand Script + +Handles what happens when you invite to trade + +--]] + +function onEventStarted(player, actor, triggerName, name, arg1, arg2, arg3, actorId) + + local otherActor = nil; + + if (name ~= nil) then + otherActor = player:GetZone():FindPCInZone(name); + elseif (actorId ~= nil) then + otherActor = player:GetZone():FindActorInArea(actorId); + end + + if (otherActor ~= nil) then + GetWorldManager():CreateTradeGroup(player, otherActor); + else + end + + player:EndEvent(); + +end \ No newline at end of file