diff --git a/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj b/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj
index 99ceaa98..bbd8c616 100644
--- a/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj
+++ b/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj
@@ -294,6 +294,7 @@
+
diff --git a/FFXIVClassic Map Server/PacketProcessor.cs b/FFXIVClassic Map Server/PacketProcessor.cs
index 9877856a..fab006e6 100644
--- a/FFXIVClassic Map Server/PacketProcessor.cs
+++ b/FFXIVClassic Map Server/PacketProcessor.cs
@@ -88,6 +88,11 @@ namespace FFXIVClassic_Map_Server
PartySyncPacket partySyncPacket = new PartySyncPacket(subpacket.data);
Server.GetWorldManager().PartyMemberListRecieved(partySyncPacket);
break;
+ //World Server - Linkshell Creation Result
+ case 0x1025:
+ LinkshellResultPacket lsResult = new LinkshellResultPacket(subpacket.data);
+ LuaEngine.GetInstance().OnSignal("ls_result", lsResult.resultCode);
+ break;
//Ping
case 0x0001:
//subpacket.DebugPrintSubPacket();
diff --git a/FFXIVClassic Map Server/lua/LuaEngine.cs b/FFXIVClassic Map Server/lua/LuaEngine.cs
index eadf697e..d72a0e1f 100644
--- a/FFXIVClassic Map Server/lua/LuaEngine.cs
+++ b/FFXIVClassic Map Server/lua/LuaEngine.cs
@@ -91,7 +91,7 @@ namespace FFXIVClassic_Map_Server.lua
}
}
- public void OnSignal(string signal)
+ public void OnSignal(string signal, params object[] args)
{
List mToAwake = new List();
@@ -103,7 +103,7 @@ namespace FFXIVClassic_Map_Server.lua
foreach (Coroutine key in mToAwake)
{
- DynValue value = key.Resume();
+ DynValue value = key.Resume(args);
ResolveResume(null, key, value);
}
}
diff --git a/FFXIVClassic Map Server/packets/WorldPackets/Receive/LinkshellResultPacket.cs b/FFXIVClassic Map Server/packets/WorldPackets/Receive/LinkshellResultPacket.cs
new file mode 100644
index 00000000..abbd75d2
--- /dev/null
+++ b/FFXIVClassic Map Server/packets/WorldPackets/Receive/LinkshellResultPacket.cs
@@ -0,0 +1,35 @@
+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.Receive
+{
+ class LinkshellResultPacket
+ {
+ public int resultCode;
+
+ public bool invalidPacket = false;
+
+ public LinkshellResultPacket(byte[] data)
+ {
+ using (MemoryStream mem = new MemoryStream(data))
+ {
+ using (BinaryReader binReader = new BinaryReader(mem))
+ {
+ try
+ {
+ resultCode = binReader.ReadInt32();
+ }
+ catch (Exception)
+ {
+ invalidPacket = true;
+ }
+ }
+ }
+
+ }
+ }
+}
diff --git a/FFXIVClassic Map Server/packets/WorldPackets/Send/Group/CreateLinkshellPacket.cs b/FFXIVClassic Map Server/packets/WorldPackets/Send/Group/CreateLinkshellPacket.cs
index 5a64741f..bd50318a 100644
--- a/FFXIVClassic Map Server/packets/WorldPackets/Send/Group/CreateLinkshellPacket.cs
+++ b/FFXIVClassic Map Server/packets/WorldPackets/Send/Group/CreateLinkshellPacket.cs
@@ -20,6 +20,7 @@ namespace FFXIVClassic_Map_Server.packets.WorldPackets.Send.Group
using (BinaryWriter binWriter = new BinaryWriter(mem))
{
binWriter.Write(Encoding.ASCII.GetBytes(name), 0, Encoding.ASCII.GetByteCount(name) >= 0x20 ? 0x20 : Encoding.ASCII.GetByteCount(name));
+ binWriter.BaseStream.Seek(0x20, SeekOrigin.Begin);
binWriter.Write((UInt16)crest);
binWriter.Write((UInt32)master);
}
diff --git a/FFXIVClassic World Server/Database.cs b/FFXIVClassic World Server/Database.cs
index 36c7df4b..5f595adf 100644
--- a/FFXIVClassic World Server/Database.cs
+++ b/FFXIVClassic World Server/Database.cs
@@ -529,5 +529,35 @@ namespace FFXIVClassic_World_Server
}
return success;
}
+
+ public static bool LinkshellIsBannedName(string name)
+ {
+ return false;
+ }
+
+ public static bool LinkshellExists(string name)
+ {
+ bool hasLS = false;
+ 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();
+ MySqlCommand cmd = new MySqlCommand("SELECT * FROM server_linkshells WHERE name = @lsName", conn);
+ cmd.Parameters.AddWithValue("@lsName", name);
+ object result = cmd.ExecuteScalar();
+ hasLS = result != null && ((uint)result > 0);
+ }
+ catch (MySqlException e)
+ {
+ Program.Log.Error(e.ToString());
+ }
+ finally
+ {
+ conn.Dispose();
+ }
+ }
+ return hasLS;
+ }
}
}
diff --git a/FFXIVClassic World Server/FFXIVClassic World Server.csproj b/FFXIVClassic World Server/FFXIVClassic World Server.csproj
index 61cbdd46..1de518b5 100644
--- a/FFXIVClassic World Server/FFXIVClassic World Server.csproj
+++ b/FFXIVClassic World Server/FFXIVClassic World Server.csproj
@@ -146,6 +146,7 @@
+
diff --git a/FFXIVClassic World Server/LinkshellManager.cs b/FFXIVClassic World Server/LinkshellManager.cs
index e6423c11..9c937af8 100644
--- a/FFXIVClassic World Server/LinkshellManager.cs
+++ b/FFXIVClassic World Server/LinkshellManager.cs
@@ -23,8 +23,22 @@ namespace FFXIVClassic_World_Server
mCurrentWorldGroupsReference = worldGroupList;
}
+ //Checks if the LS name is in use or banned
+ public int CanCreateLinkshell(string name)
+ {
+ bool nameBanned = Database.LinkshellIsBannedName(name);
+ bool alreadyExists = Database.LinkshellExists(name);
+
+ if (nameBanned)
+ return 2;
+ if (alreadyExists)
+ return 1;
+ else
+ return 0;
+ }
+
//Creates a new linkshell and adds it to the list
- public ulong CreateLinkshell(string name, ushort crest, uint master)
+ public Linkshell CreateLinkshell(string name, ushort crest, uint master)
{
lock (mGroupLockReference)
{
@@ -32,18 +46,19 @@ namespace FFXIVClassic_World_Server
if (resultId >= 0)
{
Linkshell newLs = new Linkshell(resultId, mWorldManager.GetGroupIndex(), name, crest, master, 0xa);
+
+ mLinkshellList.Add(mWorldManager.GetGroupIndex(), newLs);
+ mNameToIdLookup.Add(newLs.name, newLs.groupIndex);
+ mLSIdToIdLookup.Add(newLs.dbId, newLs);
+ mCurrentWorldGroupsReference.Add(mWorldManager.GetGroupIndex(), newLs);
+ mWorldManager.IncrementGroupIndex();
//Add founder to the LS
- if (AddMemberToLinkshell(master, newLs.name))
- {
- mLinkshellList.Add(mWorldManager.GetGroupIndex(), newLs);
- mNameToIdLookup.Add(newLs.name, newLs.groupIndex);
- mLSIdToIdLookup.Add(newLs.dbId, newLs);
- mCurrentWorldGroupsReference.Add(mWorldManager.GetGroupIndex(), newLs);
- mWorldManager.IncrementGroupIndex();
- }
+ AddMemberToLinkshell(master, newLs.name);
+
+ return newLs;
}
- return resultId;
+ return null;
}
}
diff --git a/FFXIVClassic World Server/Packets/WorldPackets/Send/LinkshellResultPacket.cs b/FFXIVClassic World Server/Packets/WorldPackets/Send/LinkshellResultPacket.cs
new file mode 100644
index 00000000..21cd06a1
--- /dev/null
+++ b/FFXIVClassic World Server/Packets/WorldPackets/Send/LinkshellResultPacket.cs
@@ -0,0 +1,32 @@
+using FFXIVClassic.Common;
+using FFXIVClassic_World_Server.DataObjects;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace FFXIVClassic_World_Server.Packets.WorldPackets.Send
+{
+ class LinkshellResultPacket
+ {
+ public const ushort OPCODE = 0x1025;
+ public const uint PACKET_SIZE = 0x24;
+
+ public static SubPacket BuildPacket(Session session, int result)
+ {
+ byte[] data = new byte[PACKET_SIZE - 0x20];
+
+ using (MemoryStream mem = new MemoryStream(data))
+ {
+ using (BinaryWriter binWriter = new BinaryWriter(mem))
+ {
+ binWriter.Write((Int32)result);
+ }
+ }
+
+ return new SubPacket(true, OPCODE, session.sessionId, data);
+ }
+ }
+}
diff --git a/FFXIVClassic World Server/Server.cs b/FFXIVClassic World Server/Server.cs
index efc7a6e6..dda5501b 100644
--- a/FFXIVClassic World Server/Server.cs
+++ b/FFXIVClassic World Server/Server.cs
@@ -5,6 +5,7 @@ using FFXIVClassic_World_Server.Packets.Receive.Subpackets;
using FFXIVClassic_World_Server.Packets.Send.Subpackets.Groups;
using FFXIVClassic_World_Server.Packets.WorldPackets.Receive;
using FFXIVClassic_World_Server.Packets.WorldPackets.Receive.Group;
+using FFXIVClassic_World_Server.Packets.WorldPackets.Send;
using System;
using System.Collections.Generic;
using System.Net;
@@ -282,7 +283,22 @@ namespace FFXIVClassic_World_Server
//Linkshell create request
case 0x1025:
CreateLinkshellPacket createLinkshellPacket = new CreateLinkshellPacket(subpacket.data);
- mWorldManager.GetLinkshellManager().CreateLinkshell(createLinkshellPacket.name, createLinkshellPacket.crestid, createLinkshellPacket.master);
+
+ Linkshell newLs = null;
+ int lsError = mWorldManager.GetLinkshellManager().CanCreateLinkshell(createLinkshellPacket.name);
+
+ if (lsError == 0)
+ {
+ newLs = mWorldManager.GetLinkshellManager().CreateLinkshell(createLinkshellPacket.name, createLinkshellPacket.crestid, createLinkshellPacket.master);
+
+ if (newLs != null)
+ newLs.SendGroupPackets(session);
+ else
+ lsError = 3;
+ }
+
+ SubPacket resultPacket = LinkshellResultPacket.BuildPacket(session, lsError);
+ zoneServer.SendPacket(resultPacket);
break;
//Linkshell modify request
case 0x1026: