Linkshell inviting completed.

This commit is contained in:
Filip Maj 2017-01-08 21:42:43 -05:00
parent 8a0ebe7ec4
commit 108d8be013
22 changed files with 377 additions and 43 deletions

View File

@ -285,8 +285,10 @@
<Compile Include="packets\WorldPackets\Receive\SessionBeginPacket.cs" /> <Compile Include="packets\WorldPackets\Receive\SessionBeginPacket.cs" />
<Compile Include="packets\WorldPackets\Send\Group\CreateLinkshellPacket.cs" /> <Compile Include="packets\WorldPackets\Send\Group\CreateLinkshellPacket.cs" />
<Compile Include="packets\WorldPackets\Send\Group\DeleteLinkshellPacket.cs" /> <Compile Include="packets\WorldPackets\Send\Group\DeleteLinkshellPacket.cs" />
<Compile Include="packets\WorldPackets\Send\Group\LinkshellInviteCancelPacket.cs" />
<Compile Include="packets\WorldPackets\Send\Group\ModifyLinkshellPacket.cs" /> <Compile Include="packets\WorldPackets\Send\Group\ModifyLinkshellPacket.cs" />
<Compile Include="packets\WorldPackets\Send\Group\GroupInviteResultPacket.cs" /> <Compile Include="packets\WorldPackets\Send\Group\GroupInviteResultPacket.cs" />
<Compile Include="packets\WorldPackets\Send\Group\LinkshellInvitePacket.cs" />
<Compile Include="packets\WorldPackets\Send\Group\PartyInvitePacket.cs" /> <Compile Include="packets\WorldPackets\Send\Group\PartyInvitePacket.cs" />
<Compile Include="packets\WorldPackets\Send\Group\PartyLeavePacket.cs" /> <Compile Include="packets\WorldPackets\Send\Group\PartyLeavePacket.cs" />
<Compile Include="packets\WorldPackets\Send\Group\PartyModifyPacket.cs" /> <Compile Include="packets\WorldPackets\Send\Group\PartyModifyPacket.cs" />

View File

@ -678,14 +678,21 @@ namespace FFXIVClassic_Map_Server
Server.GetWorldConnection().QueuePacket(packet, true, false); Server.GetWorldConnection().QueuePacket(packet, true, false);
} }
public bool RequestWorldLinkshellRankChange(Player player, string lsname, string memberName, byte newRank) public void RequestWorldLinkshellRankChange(Player player, string lsname, string memberName, byte newRank)
{ {
return false;
} }
public bool RequestWorldLinkshellAddMember(Player player, string lsname, string memberName) public void RequestWorldLinkshellInviteMember(Player player, string lsname, uint invitedActorId)
{ {
return false; SubPacket packet = LinkshellInvitePacket.BuildPacket(player.playerSession, invitedActorId, lsname);
Server.GetWorldConnection().QueuePacket(packet, true, false);
}
public void RequestWorldLinkshellCancelInvite(Player player)
{
SubPacket packet = LinkshellInviteCancelPacket.BuildPacket(player.playerSession);
Server.GetWorldConnection().QueuePacket(packet, true, false);
} }
public bool RequestWorldLinkshellRemoveMember(Player player, bool wasKicked, string lsname, string memberName) public bool RequestWorldLinkshellRemoveMember(Player player, bool wasKicked, string lsname, string memberName)

View File

@ -363,6 +363,7 @@ namespace FFXIVClassic_Map_Server.lua
((FileSystemScriptLoader)script.Options.ScriptLoader).ModulePaths = FileSystemScriptLoader.UnpackStringPaths("./scripts/?;./scripts/?.lua"); ((FileSystemScriptLoader)script.Options.ScriptLoader).ModulePaths = FileSystemScriptLoader.UnpackStringPaths("./scripts/?;./scripts/?.lua");
script.Globals["GetWorldManager"] = (Func<WorldManager>)Server.GetWorldManager; script.Globals["GetWorldManager"] = (Func<WorldManager>)Server.GetWorldManager;
script.Globals["GetStaticActor"] = (Func<string, Actor>)Server.GetStaticActors; script.Globals["GetStaticActor"] = (Func<string, Actor>)Server.GetStaticActors;
script.Globals["GetStaticActorById"] = (Func<uint, Actor>)Server.GetStaticActors;
script.Globals["GetWorldMaster"] = (Func<Actor>)Server.GetWorldManager().GetActor; script.Globals["GetWorldMaster"] = (Func<Actor>)Server.GetWorldManager().GetActor;
script.Globals["GetItemGamedata"] = (Func<uint, Item>)Server.GetItemGamedata; script.Globals["GetItemGamedata"] = (Func<uint, Item>)Server.GetItemGamedata;

View File

@ -0,0 +1,23 @@
using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.dataobjects;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.WorldPackets.Send.Group
{
class LinkshellInviteCancelPacket
{
public const ushort OPCODE = 0x1030;
public const uint PACKET_SIZE = 0x28;
public static SubPacket BuildPacket(Session session)
{
byte[] data = new byte[PACKET_SIZE - 0x20];
return new SubPacket(true, OPCODE, session.id, session.id, data);
}
}
}

View File

@ -0,0 +1,31 @@
using FFXIVClassic.Common;
using FFXIVClassic_Map_Server.dataobjects;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Map_Server.packets.WorldPackets.Send.Group
{
class LinkshellInvitePacket
{
public const ushort OPCODE = 0x1029;
public const uint PACKET_SIZE = 0x48;
public static SubPacket BuildPacket(Session session, uint actorId, string linkshellName)
{
byte[] data = new byte[PACKET_SIZE - 0x20];
using (MemoryStream mem = new MemoryStream(data))
{
using (BinaryWriter binWriter = new BinaryWriter(mem))
{
binWriter.Write((UInt32)actorId);
binWriter.Write(Encoding.ASCII.GetBytes(linkshellName), 0, Encoding.ASCII.GetByteCount(linkshellName) >= 0x20 ? 0x20 : Encoding.ASCII.GetByteCount(linkshellName));
}
}
return new SubPacket(true, OPCODE, session.id, session.id, data);
}
}
}

View File

@ -329,6 +329,11 @@ namespace FFXIVClassic_Map_Server.packets.send
{ {
case 0: case 0:
case 1: case 1:
total += 5;
break;
case 2:
total += 20;
break;
case 6: case 6:
total += 5; total += 5;
break; break;

View File

@ -23,10 +23,10 @@ namespace FFXIVClassic_Map_Server.packets.send.events
{ {
binWriter.Write((UInt32)playerActorId); binWriter.Write((UInt32)playerActorId);
binWriter.Write((UInt32)targetActorId); binWriter.Write((UInt32)targetActorId);
binWriter.Write((Byte)0x5);
binWriter.Write((Byte)0x87); int test = 0;
binWriter.Write((Byte)0xDC);
binWriter.Write((Byte)0x75); binWriter.Write((UInt32)test);
binWriter.Write((UInt32)0x30400000); binWriter.Write((UInt32)0x30400000);
binWriter.Write(Encoding.ASCII.GetBytes(conditionName), 0, Encoding.ASCII.GetByteCount(conditionName) >= 0x20 ? 0x20 : Encoding.ASCII.GetByteCount(conditionName)); binWriter.Write(Encoding.ASCII.GetBytes(conditionName), 0, Encoding.ASCII.GetByteCount(conditionName) >= 0x20 ? 0x20 : Encoding.ASCII.GetByteCount(conditionName));

View File

@ -51,7 +51,7 @@ namespace FFXIVClassic_World_Server.DataObjects.Group
public void AddMember(uint charaId) public void AddMember(uint charaId)
{ {
members.Add(new LinkshellMember(charaId, dbId, 0xa)); members.Add(new LinkshellMember(charaId, dbId, 0x0));
members.Sort(); members.Sort();
} }
@ -84,12 +84,26 @@ namespace FFXIVClassic_World_Server.DataObjects.Group
} }
public override List<GroupMember> BuildMemberList(uint id) public override List<GroupMember> BuildMemberList(uint id)
{
lock (members)
{ {
List<GroupMember> groupMembers = new List<GroupMember>(); List<GroupMember> groupMembers = new List<GroupMember>();
foreach (LinkshellMember member in members) foreach (LinkshellMember member in members)
groupMembers.Add(new GroupMember(member.charaId, -1, 0, false, true, Server.GetServer().GetNameForId(member.charaId))); groupMembers.Add(new GroupMember(member.charaId, -1, 0, false, true, Server.GetServer().GetNameForId(member.charaId)));
return groupMembers; return groupMembers;
} }
}
public uint[] GetMemberIds()
{
lock (members)
{
uint[] memberIds = new uint[members.Count];
for (int i = 0; i < memberIds.Length; i++)
memberIds[i] = members[i].charaId;
return memberIds;
}
}
public override void SendInitWorkValues(Session session) public override void SendInitWorkValues(Session session)
{ {
@ -115,5 +129,34 @@ namespace FFXIVClassic_World_Server.DataObjects.Group
{ {
members = Database.GetLSMembers(this); members = Database.GetLSMembers(this);
} }
public void OnPlayerJoin(Session inviteeSession)
{
for (int i = 0; i < members.Count; i++)
{
Session session = Server.GetServer().GetSession(members[i].charaId);
if (session == null)
continue;
if (inviteeSession.Equals(session))
session.SendGameMessage(25157, 0x20, (object) 0, (object)inviteeSession, name);
else
session.SendGameMessage(25284, 0x20, (object) 0, (object)Server.GetServer().GetNameForId(inviteeSession.sessionId), name);
}
}
public bool HasMember(uint id)
{
lock (members)
{
for (int i = 0; i < members.Count; i++)
{
if (members[i].charaId == id)
return true;
}
return false;
}
}
} }
} }

View File

@ -12,13 +12,15 @@ namespace FFXIVClassic_World_Server.DataObjects.Group
class Relation : Group class Relation : Group
{ {
public RelationWork work = new RelationWork(); public RelationWork work = new RelationWork();
public uint charaOther; private uint charaOther;
private ulong topicGroup;
public Relation(ulong groupIndex, uint host, uint other, uint command) : base (groupIndex) public Relation(ulong groupIndex, uint host, uint other, uint command, ulong topicGroup) : base (groupIndex)
{ {
this.charaOther = other; this.charaOther = other;
work._globalTemp.host = ((ulong)host << 32) | (0xc17909); work._globalTemp.host = ((ulong)host << 32) | (0xc17909);
work._globalTemp.variableCommand = command; work._globalTemp.variableCommand = command;
this.topicGroup = topicGroup;
} }
public uint GetHost() public uint GetHost()
@ -41,6 +43,11 @@ namespace FFXIVClassic_World_Server.DataObjects.Group
return Group.GroupInvitationRelationGroup; return Group.GroupInvitationRelationGroup;
} }
public ulong GetTopicGroupIndex()
{
return topicGroup;
}
public override List<GroupMember> BuildMemberList(uint id) public override List<GroupMember> BuildMemberList(uint id)
{ {
List<GroupMember> groupMembers = new List<GroupMember>(); List<GroupMember> groupMembers = new List<GroupMember>();

View File

@ -295,6 +295,10 @@ namespace FFXIVClassic_World_Server.DataObjects
{ {
luaParams.Add(new LuaParam(0x5, null)); luaParams.Add(new LuaParam(0x5, null));
} }
else if (o is Session)
{
luaParams.Add(new LuaParam(0x6, (uint)((Session)o).sessionId));
}
else if (o is Type7Param) else if (o is Type7Param)
{ {
luaParams.Add(new LuaParam(0x7, (Type7Param)o)); luaParams.Add(new LuaParam(0x7, (Type7Param)o));

View File

@ -16,6 +16,7 @@ namespace FFXIVClassic_World_Server.DataObjects
public string characterName; public string characterName;
public uint currentZoneId; public uint currentZoneId;
public uint activeLinkshellIndex = 0;
public readonly ClientConnection clientConnection; public readonly ClientConnection clientConnection;
public readonly Channel type; public readonly Channel type;
@ -30,6 +31,16 @@ namespace FFXIVClassic_World_Server.DataObjects
Database.LoadZoneSessionInfo(this); Database.LoadZoneSessionInfo(this);
} }
public void SendGameMessage(uint actorId, ushort textId, byte log, params object[] msgParams)
{
if (msgParams == null || msgParams.Length == 0)
{
clientConnection.QueuePacket(GameMessagePacket.BuildPacket(0x5FF80001, sessionId, actorId, 0x5FF80001, textId, log), true, false);
}
else
clientConnection.QueuePacket(GameMessagePacket.BuildPacket(0x5FF80001, sessionId, actorId, 0x5FF80001, textId, log, LuaUtils.CreateLuaParamList(msgParams)), true, false);
}
public void SendGameMessage( ushort textId, byte log, params object[] msgParams) public void SendGameMessage( ushort textId, byte log, params object[] msgParams)
{ {
if (msgParams == null || msgParams.Length == 0) if (msgParams == null || msgParams.Length == 0)

View File

@ -78,6 +78,11 @@ namespace FFXIVClassic_World_Server.DataObjects
catch (Exception e) catch (Exception e)
{ Program.Log.Error("Weird case, socket was d/ced: {0}", e); } { Program.Log.Error("Weird case, socket was d/ced: {0}", e); }
} }
else
{
if (Connect())
SendPacket(subpacket);
}
} }
private void ReceiveCallback(IAsyncResult result) private void ReceiveCallback(IAsyncResult result)

View File

@ -381,7 +381,41 @@ namespace FFXIVClassic_World_Server
public static bool LinkshellAddPlayer(ulong lsId, uint charaId) public static bool LinkshellAddPlayer(ulong lsId, uint charaId)
{ {
throw new NotImplementedException(); string query;
MySqlCommand cmd;
using (MySqlConnection conn = new MySqlConnection(String.Format("Server={0}; Port={1}; Database={2}; UID={3}; Password={4}", ConfigConstants.DATABASE_HOST, ConfigConstants.DATABASE_PORT, ConfigConstants.DATABASE_NAME, ConfigConstants.DATABASE_USERNAME, ConfigConstants.DATABASE_PASSWORD)))
{
try
{
conn.Open();
query = @"
INSERT INTO characters_linkshells
(characterId, linkshellId)
VALUES
(@charaId, @lsId)
";
cmd = new MySqlCommand(query, conn);
cmd.Parameters.AddWithValue("@charaId", charaId);
cmd.Parameters.AddWithValue("@lsId", lsId);
cmd.ExecuteNonQuery();
}
catch (MySqlException e)
{
Program.Log.Error(e.ToString());
conn.Dispose();
return false;
}
finally
{
conn.Dispose();
}
}
return true;
} }
public static bool LinkshellRemovePlayer(ulong lsId, uint charaId) public static bool LinkshellRemovePlayer(ulong lsId, uint charaId)

View File

@ -111,6 +111,8 @@
<Compile Include="Packets\Send\_0x7Packet.cs" /> <Compile Include="Packets\Send\_0x7Packet.cs" />
<Compile Include="Packets\Send\_0x8PingPacket.cs" /> <Compile Include="Packets\Send\_0x8PingPacket.cs" />
<Compile Include="Packets\WorldPackets\Receive\Group\GroupInviteResultPacket.cs" /> <Compile Include="Packets\WorldPackets\Receive\Group\GroupInviteResultPacket.cs" />
<Compile Include="Packets\WorldPackets\Receive\Group\LinkshellInviteCancelPacket.cs" />
<Compile Include="Packets\WorldPackets\Receive\Group\LinkshellInvitePacket.cs" />
<Compile Include="Packets\WorldPackets\Receive\Group\PartyLeavePacket.cs" /> <Compile Include="Packets\WorldPackets\Receive\Group\PartyLeavePacket.cs" />
<Compile Include="Packets\WorldPackets\Receive\Group\PartyInvitePacket.cs" /> <Compile Include="Packets\WorldPackets\Receive\Group\PartyInvitePacket.cs" />
<Compile Include="Packets\WorldPackets\Receive\Group\PartyModifyPacket.cs" /> <Compile Include="Packets\WorldPackets\Receive\Group\PartyModifyPacket.cs" />

View File

@ -34,10 +34,11 @@ namespace FFXIVClassic_World_Server
Linkshell newLs = new Linkshell(resultId, mWorldManager.GetGroupIndex(), name, crest, master, 0xa); Linkshell newLs = new Linkshell(resultId, mWorldManager.GetGroupIndex(), name, crest, master, 0xa);
//Add founder to the LS //Add founder to the LS
if (AddMemberToLinkshell(master, newLs.groupIndex)) if (AddMemberToLinkshell(master, newLs.name))
{ {
mLinkshellList.Add(mWorldManager.GetGroupIndex(), newLs); mLinkshellList.Add(mWorldManager.GetGroupIndex(), newLs);
mNameToIdLookup.Add(newLs.name, newLs.groupIndex); mNameToIdLookup.Add(newLs.name, newLs.groupIndex);
mLSIdToIdLookup.Add(newLs.dbId, newLs);
mCurrentWorldGroupsReference.Add(mWorldManager.GetGroupIndex(), newLs); mCurrentWorldGroupsReference.Add(mWorldManager.GetGroupIndex(), newLs);
mWorldManager.IncrementGroupIndex(); mWorldManager.IncrementGroupIndex();
} }
@ -112,10 +113,10 @@ namespace FFXIVClassic_World_Server
} }
//Adds a player to the linkshell //Adds a player to the linkshell
public bool AddMemberToLinkshell(uint charaId, ulong groupId) public bool AddMemberToLinkshell(uint charaId, string LSName)
{ {
//Get the LS //Get the LS
Linkshell ls = GetLinkshell(groupId); Linkshell ls = GetLinkshell(LSName);
if (ls == null) if (ls == null)
return false; return false;
@ -135,10 +136,10 @@ namespace FFXIVClassic_World_Server
} }
//Removes a player from the linkshell //Removes a player from the linkshell
public bool RemoveMemberFromLinkshell(uint charaId, ulong groupId) public bool RemoveMemberFromLinkshell(uint charaId, string LSName)
{ {
//Get the LS //Get the LS
Linkshell ls = GetLinkshell(groupId); Linkshell ls = GetLinkshell(LSName);
if (ls == null) if (ls == null)
return false; return false;
@ -157,7 +158,7 @@ namespace FFXIVClassic_World_Server
} }
} }
//Get a single linkshell group either already instantiated or make one from the db //Get a single linkshell group either already instantiated or make one from the db by Name
public Linkshell GetLinkshell(string name) public Linkshell GetLinkshell(string name)
{ {
if (mNameToIdLookup.ContainsKey(name)) if (mNameToIdLookup.ContainsKey(name))
@ -173,6 +174,7 @@ namespace FFXIVClassic_World_Server
{ {
mLinkshellList.Add(ls.groupIndex, ls); mLinkshellList.Add(ls.groupIndex, ls);
mNameToIdLookup.Add(ls.name, ls.groupIndex); mNameToIdLookup.Add(ls.name, ls.groupIndex);
mLSIdToIdLookup.Add(ls.dbId, ls);
mCurrentWorldGroupsReference.Add(ls.groupIndex, ls); mCurrentWorldGroupsReference.Add(ls.groupIndex, ls);
mWorldManager.IncrementGroupIndex(); mWorldManager.IncrementGroupIndex();
return ls; return ls;
@ -183,11 +185,11 @@ namespace FFXIVClassic_World_Server
} }
} }
//Get a single linkshell group either already instantiated or make one from the db //Get a single linkshell group either already instantiated or make one from the db by ID
public Linkshell GetLinkshell(ulong lsId) public Linkshell GetLinkshell(ulong lsId)
{ {
if (mLSIdToIdLookup.ContainsKey(lsId)) if (mLSIdToIdLookup.ContainsKey(lsId))
return mLSIdToIdLookup[lsId]; return (Linkshell)mCurrentWorldGroupsReference[mLSIdToIdLookup[lsId].groupIndex];
else else
{ {
lock (mGroupLockReference) lock (mGroupLockReference)
@ -204,10 +206,11 @@ namespace FFXIVClassic_World_Server
mWorldManager.IncrementGroupIndex(); mWorldManager.IncrementGroupIndex();
return ls; return ls;
} }
} else
}
return null; return null;
} }
}
}
//Get the linkshells player is part of //Get the linkshells player is part of
public List<Linkshell> GetPlayerLinkshellMembership(uint charaId) public List<Linkshell> GetPlayerLinkshellMembership(uint charaId)

View File

@ -329,6 +329,8 @@ namespace FFXIVClassic_World_Server.Packets.Send.Subpackets
{ {
case 0: case 0:
case 1: case 1:
total += 5;
break;
case 2: case 2:
total += 1 + 0x20; total += 1 + 0x20;
break; break;

View File

@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace FFXIVClassic_World_Server.Packets.WorldPackets.Receive.Group
{
class LinkshellInviteCancelPacket
{
public bool invalidPacket = false;
public string lsName;
public uint actorId;
public LinkshellInviteCancelPacket(byte[] data)
{
using (MemoryStream mem = new MemoryStream(data))
{
using (BinaryReader binReader = new BinaryReader(mem))
{
try
{
}
catch (Exception)
{
invalidPacket = true;
}
}
}
}
}
}

View File

@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace FFXIVClassic_World_Server.Packets.WorldPackets.Receive.Group
{
class LinkshellInvitePacket
{
public bool invalidPacket = false;
public string lsName;
public uint actorId;
public LinkshellInvitePacket(byte[] data)
{
using (MemoryStream mem = new MemoryStream(data))
{
using (BinaryReader binReader = new BinaryReader(mem))
{
try
{
actorId = binReader.ReadUInt32();
lsName = Encoding.ASCII.GetString(binReader.ReadBytes(0x20)).Trim(new[] { '\0' });
}
catch (Exception)
{
invalidPacket = true;
}
}
}
}
}
}

View File

@ -19,16 +19,7 @@ namespace FFXIVClassic_World_Server
{ {
// set up logging // set up logging
Log = LogManager.GetCurrentClassLogger(); Log = LogManager.GetCurrentClassLogger();
#if DEBUG
TextWriterTraceListener myWriter = new TextWriterTraceListener(System.Console.Out);
Debug.Listeners.Add(myWriter);
if (System.Diagnostics.Debugger.IsAttached)
{
System.Threading.Thread.Sleep(15000);
}
#endif
bool startServer = true; bool startServer = true;
Log.Info("=================================="); Log.Info("==================================");
@ -36,6 +27,17 @@ namespace FFXIVClassic_World_Server
Log.Info("Version: 0.0.1"); Log.Info("Version: 0.0.1");
Log.Info("=================================="); Log.Info("==================================");
#if DEBUG
TextWriterTraceListener myWriter = new TextWriterTraceListener(System.Console.Out);
Debug.Listeners.Add(myWriter);
if (System.Diagnostics.Debugger.IsAttached)
{
System.Threading.Thread.Sleep(5000);
}
#endif
//Load Config //Load Config
if (!ConfigConstants.Load()) if (!ConfigConstants.Load())
startServer = false; startServer = false;

View File

@ -19,12 +19,12 @@ namespace FFXIVClassic_World_Server
mCurrentWorldGroupsReference = worldGroupList; mCurrentWorldGroupsReference = worldGroupList;
} }
public Relation CreatePartyRelationGroup(uint hostCharaId, uint otherCharaId) public Relation CreatePartyRelationGroup(ulong topicGroupId, uint hostCharaId, uint otherCharaId)
{ {
lock (mGroupLockReference) lock (mGroupLockReference)
{ {
ulong groupIndex = mWorldManager.GetGroupIndex(); ulong groupIndex = mWorldManager.GetGroupIndex();
Relation relation = new Relation(groupIndex, hostCharaId, otherCharaId, 10001); Relation relation = new Relation(groupIndex, hostCharaId, otherCharaId, 10001, topicGroupId);
mPartyRelationList.Add(groupIndex, relation); mPartyRelationList.Add(groupIndex, relation);
mCurrentWorldGroupsReference.Add(groupIndex, relation); mCurrentWorldGroupsReference.Add(groupIndex, relation);
mWorldManager.IncrementGroupIndex(); mWorldManager.IncrementGroupIndex();
@ -32,12 +32,12 @@ namespace FFXIVClassic_World_Server
} }
} }
public Relation CreateLinkshellRelationGroup(uint hostCharaId, uint otherCharaId) public Relation CreateLinkshellRelationGroup(ulong topicGroupId, uint hostCharaId, uint otherCharaId)
{ {
lock (mGroupLockReference) lock (mGroupLockReference)
{ {
ulong groupIndex = mWorldManager.GetGroupIndex(); ulong groupIndex = mWorldManager.GetGroupIndex();
Relation relation = new Relation(groupIndex, hostCharaId, otherCharaId, 10002); Relation relation = new Relation(groupIndex, hostCharaId, otherCharaId, 10002, topicGroupId);
mLinkshellRelationList.Add(groupIndex, relation); mLinkshellRelationList.Add(groupIndex, relation);
mCurrentWorldGroupsReference.Add(groupIndex, relation); mCurrentWorldGroupsReference.Add(groupIndex, relation);
mWorldManager.IncrementGroupIndex(); mWorldManager.IncrementGroupIndex();

View File

@ -249,6 +249,9 @@ namespace FFXIVClassic_World_Server
case 0x2711: case 0x2711:
mWorldManager.ProcessPartyInviteResult(GetSession(subpacket.header.sourceId), groupInviteResultPacket.result); mWorldManager.ProcessPartyInviteResult(GetSession(subpacket.header.sourceId), groupInviteResultPacket.result);
break; break;
case 0x2712:
mWorldManager.ProcessLinkshellInviteResult(GetSession(subpacket.header.sourceId), groupInviteResultPacket.result);
break;
} }
break; break;
@ -282,6 +285,16 @@ namespace FFXIVClassic_World_Server
SetActiveLinkshellPacket setActiveLinkshellPacket = new SetActiveLinkshellPacket(subpacket.data); SetActiveLinkshellPacket setActiveLinkshellPacket = new SetActiveLinkshellPacket(subpacket.data);
//Linkshell ls = mWorldManager.GetLinkshellManager().GetLinkshell(); //Linkshell ls = mWorldManager.GetLinkshellManager().GetLinkshell();
break; break;
//Linkshell invite member
case 0x1029:
LinkshellInvitePacket linkshellInvitePacket = new LinkshellInvitePacket(subpacket.data);
mWorldManager.ProcessLinkshellInvite(GetSession(subpacket.header.sourceId), linkshellInvitePacket.lsName, linkshellInvitePacket.actorId);
break;
//Linkshell cancel invite
case 0x1030:
LinkshellInviteCancelPacket linkshellInviteCancelPacket = new LinkshellInviteCancelPacket(subpacket.data);
mWorldManager.ProcessLinkshellInviteCancel(GetSession(subpacket.header.sourceId));
break;
} }
} }
else if (mZoneSessionList.ContainsKey(sessionId)) else if (mZoneSessionList.ContainsKey(sessionId))

View File

@ -298,7 +298,7 @@ namespace FFXIVClassic_World_Server
else else
{ {
Session inviteeSession = mServer.GetSession(invitee); Session inviteeSession = mServer.GetSession(invitee);
Relation inviteRelation = mRelationGroupManager.CreatePartyRelationGroup(requestSession.sessionId, invitee); Relation inviteRelation = mRelationGroupManager.CreatePartyRelationGroup(mPartyManager.GetParty(requestSession.sessionId).groupIndex, requestSession.sessionId, invitee);
inviteRelation.SendGroupPacketsAll(requestSession.sessionId, invitee); inviteRelation.SendGroupPacketsAll(requestSession.sessionId, invitee);
inviteeSession.SendGameMessage(30430, 0x20, (object)mServer.GetNameForId(requestSession.sessionId)); //X Invited you inviteeSession.SendGameMessage(30430, 0x20, (object)mServer.GetNameForId(requestSession.sessionId)); //X Invited you
requestSession.SendGameMessage(30433, 0x20, (object)mServer.GetNameForId(inviteeSession.sessionId)); //You invite X requestSession.SendGameMessage(30433, 0x20, (object)mServer.GetNameForId(inviteeSession.sessionId)); //You invite X
@ -335,6 +335,79 @@ namespace FFXIVClassic_World_Server
} }
public void ProcessLinkshellInvite(Session inviterSession, string lsName, uint invitee)
{
if (mServer.GetSession(invitee) == null)
{
inviterSession.SendGameMessage(30544, 0x20);
}
else if (mRelationGroupManager.GetLinkshellRelationGroup(inviterSession.sessionId) != null)
{
Session inviteeSession = mServer.GetSession(invitee);
inviterSession.SendGameMessage(25196, 0x20, (object)inviteeSession); //Unable to invite X another pending
}
else if (mLinkshellManager.GetLinkshell(lsName).HasMember(invitee))
{
Session inviteeSession = mServer.GetSession(invitee);
inviterSession.SendGameMessage(25155, 0x20, (object)inviteeSession, 1); //X already belongs to
}
else
{
Session inviteeSession = mServer.GetSession(invitee);
Relation inviteRelation = mRelationGroupManager.CreateLinkshellRelationGroup(mLinkshellManager.GetLinkshell(lsName).groupIndex, inviterSession.sessionId, invitee);
inviteRelation.SendGroupPacketsAll(inviterSession.sessionId, invitee);
inviteeSession.SendGameMessage(25150, 0x20, (object)1, (object)lsName, (object)inviterSession); //X Offers you
inviterSession.SendGameMessage(25151, 0x20, (object)1, null, (object)inviteeSession); //You offer X
}
}
public void ProcessLinkshellInviteResult(Session inviteeSession, uint resultCode)
{
Relation relation = mRelationGroupManager.GetLinkshellRelationGroup(inviteeSession.sessionId);
Session inviterSession = mServer.GetSession(relation.GetHost());
//Accept
if (resultCode == 1)
{
Linkshell newLS;
if (mCurrentWorldGroups.ContainsKey(relation.groupIndex))
newLS = (Linkshell) mCurrentWorldGroups[relation.GetTopicGroupIndex()];
else
{
//Error???
return;
}
mLinkshellManager.AddMemberToLinkshell(inviteeSession.sessionId, newLS.name);
newLS.SendGroupPacketsAll(newLS.GetMemberIds());
newLS.OnPlayerJoin(inviteeSession);
}
else //Refuse
{
inviteeSession.SendGameMessage(25189, 0x20); //You decline the linkpearl offer.
inviterSession.SendGameMessage(25190, 0x20); //Your linkpearl offer is declined.
}
//Delete the relation
mRelationGroupManager.DeleteRelationGroup(relation.groupIndex);
relation.SendDeletePackets(inviterSession.sessionId, inviteeSession.sessionId);
}
public void ProcessLinkshellInviteCancel(Session inviterSession)
{
Relation relation = mRelationGroupManager.GetLinkshellRelationGroup(inviterSession.sessionId);
Session inviteeSession = mServer.GetSession(relation.GetOther());
inviterSession.SendGameMessage(25191, 0x20); //You cancel the linkpearl offer.
inviteeSession.SendGameMessage(25192, 0x20); //The linkpearl offer has been canceled.
//Delete the relation
mRelationGroupManager.DeleteRelationGroup(relation.groupIndex);
relation.SendDeletePackets(inviterSession.sessionId, inviteeSession.sessionId);
}
public void IncrementGroupIndex() public void IncrementGroupIndex()
{ {
mRunningGroupIndex++; mRunningGroupIndex++;