diff --git a/FFXIVClassic Map Server/ClientConnection.cs b/FFXIVClassic Map Server/ClientConnection.cs index e00b073e..5d2087a3 100644 --- a/FFXIVClassic Map Server/ClientConnection.cs +++ b/FFXIVClassic Map Server/ClientConnection.cs @@ -19,12 +19,13 @@ namespace FFXIVClassic_Lobby_Server //Connection stuff public Blowfish blowfish; public Socket socket; - public byte[] buffer = new byte[0xfffff]; + public byte[] buffer; private BlockingCollection sendPacketQueue = new BlockingCollection(1000); + public int lastPartialSize = 0; //Instance Stuff public uint owner = 0; - public uint connType = 0; + public int connType = 0; public void queuePacket(BasePacket packet) { @@ -46,7 +47,7 @@ namespace FFXIVClassic_Lobby_Server BasePacket packet = sendPacketQueue.Take(); byte[] packetBytes = packet.getPacketBytes(); - byte[] buffer = new byte[0xfffff]; + byte[] buffer = new byte[0xFFFF]; Array.Copy(packetBytes, buffer, packetBytes.Length); try { diff --git a/FFXIVClassic Map Server/Database.cs b/FFXIVClassic Map Server/Database.cs index fa00e80a..91574d7e 100644 --- a/FFXIVClassic Map Server/Database.cs +++ b/FFXIVClassic Map Server/Database.cs @@ -455,6 +455,9 @@ namespace FFXIVClassic_Lobby_Server player.inventories[Inventory.NORMAL].initList(getInventory(player, 0, Inventory.NORMAL)); player.inventories[Inventory.KEYITEMS].initList(getInventory(player, 0, Inventory.KEYITEMS)); player.inventories[Inventory.CURRANCY].initList(getInventory(player, 0, Inventory.CURRANCY)); + player.inventories[Inventory.BAZAAR].initList(getInventory(player, 0, Inventory.BAZAAR)); + player.inventories[Inventory.MELDREQUEST].initList(getInventory(player, 0, Inventory.MELDREQUEST)); + player.inventories[Inventory.LOOT].initList(getInventory(player, 0, Inventory.LOOT)); } catch (MySqlException e) diff --git a/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj b/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj index 6cd62949..f6f00e66 100644 --- a/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj +++ b/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj @@ -121,6 +121,7 @@ + diff --git a/FFXIVClassic Map Server/PacketProcessor.cs b/FFXIVClassic Map Server/PacketProcessor.cs index 12cf82a8..8ad84b8f 100644 --- a/FFXIVClassic Map Server/PacketProcessor.cs +++ b/FFXIVClassic Map Server/PacketProcessor.cs @@ -353,6 +353,12 @@ namespace FFXIVClassic_Lobby_Server case 0x01D4: client.queuePacket(BasePacket.createPacket(GMTicketPacket.buildPacket(player.actorID, "This is a GM Ticket Title", "This is a GM Ticket Body."), true, false)); break; + //GM Ticket Sent + case 0x01D5: + GMSupportTicketPacket gmTicket = new GMSupportTicketPacket(subpacket.data); + Log.info("Got GM Ticket: \n" + gmTicket.ticketTitle + "\n" + gmTicket.ticketBody); + client.queuePacket(BasePacket.createPacket(GMTicketSentResponsePacket.buildPacket(player.actorID, true), true, false)); + break; //Request to end ticket case 0x01D6: client.queuePacket(BasePacket.createPacket(EndGMTicketPacket.buildPacket(player.actorID), true, false)); diff --git a/FFXIVClassic Map Server/Server.cs b/FFXIVClassic Map Server/Server.cs index 34d0e9c9..00e426be 100644 --- a/FFXIVClassic Map Server/Server.cs +++ b/FFXIVClassic Map Server/Server.cs @@ -23,7 +23,7 @@ namespace FFXIVClassic_Lobby_Server class Server { public const int FFXIV_MAP_PORT = 54992; - public const int BUFFER_SIZE = 0x400; + public const int BUFFER_SIZE = 0xFFFF; //Max basepacket size is 0xFFFF public const int BACKLOG = 100; public const string STATIC_ACTORS_PATH = "./staticactors.bin"; @@ -163,12 +163,29 @@ namespace FFXIVClassic_Lobby_Server /// private void receiveCallback(IAsyncResult result) { - ClientConnection conn = (ClientConnection)result.AsyncState; + ClientConnection conn = (ClientConnection)result.AsyncState; + + //Check if disconnected + if ((conn.socket.Poll(1, SelectMode.SelectRead) && conn.socket.Available == 0)) + { + if (mConnectedPlayerList.ContainsKey(conn.owner)) + mConnectedPlayerList.Remove(conn.owner); + lock (mConnectionList) + { + mConnectionList.Remove(conn); + } + if (conn.connType == BasePacket.TYPE_ZONE) + Log.conn(String.Format("{0} has disconnected.", conn.owner == 0 ? conn.getAddress() : "User " + conn.owner)); + return; + } try { int bytesRead = conn.socket.EndReceive(result); - if (bytesRead > 0) + + bytesRead += conn.lastPartialSize; + + if (bytesRead >= 0) { int offset = 0; @@ -176,6 +193,7 @@ namespace FFXIVClassic_Lobby_Server while(true) { BasePacket basePacket = buildPacket(ref offset, conn.buffer, bytesRead); + //If can't build packet, break, else process another if (basePacket == null) break; @@ -184,9 +202,13 @@ namespace FFXIVClassic_Lobby_Server } //Not all bytes consumed, transfer leftover to beginning - if (offset < bytesRead) + if (offset < bytesRead) Array.Copy(conn.buffer, offset, conn.buffer, 0, bytesRead - offset); + Array.Clear(conn.buffer, bytesRead - offset, conn.buffer.Length - (bytesRead - offset)); + + conn.lastPartialSize = bytesRead - offset; + //Build any queued subpackets into basepackets and send conn.flushQueuedSendPackets(); @@ -424,6 +446,27 @@ namespace FFXIVClassic_Lobby_Server } } + private void giveItem(ConnectedPlayer client, uint itemId, int quantity, ushort type) + { + if (client != null) + { + Player p = client.getActor(); + + if (p.inventories.ContainsKey(type)) + p.inventories[type].addItem(itemId, quantity, 1); + } + else + { + foreach (KeyValuePair entry in mConnectedPlayerList) + { + Player p = entry.Value.getActor(); + + if (p.inventories.ContainsKey(type)) + p.inventories[type].addItem(itemId, quantity, 1); + } + } + } + private void removeItem(ConnectedPlayer client, uint itemId, int quantity) { if (client != null) @@ -441,6 +484,27 @@ namespace FFXIVClassic_Lobby_Server } } + private void removeItem(ConnectedPlayer client, uint itemId, int quantity, ushort type) + { + if (client != null) + { + Player p = client.getActor(); + + if (p.inventories.ContainsKey(type)) + p.inventories[type].removeItem(itemId, quantity); + } + else + { + foreach (KeyValuePair entry in mConnectedPlayerList) + { + Player p = entry.Value.getActor(); + + if (p.inventories.ContainsKey(type)) + p.inventories[type].removeItem(itemId, quantity); + } + } + } + private void giveCurrancy(ConnectedPlayer client, uint itemId, int quantity) { if (client != null) @@ -562,6 +626,8 @@ namespace FFXIVClassic_Lobby_Server giveItem(client, UInt32.Parse(split[1]), 1); else if (split.Length == 3) giveItem(client, UInt32.Parse(split[1]), Int32.Parse(split[2])); + else if (split.Length == 4) + giveItem(client, UInt32.Parse(split[1]), Int32.Parse(split[2]), UInt16.Parse(split[3])); } catch (Exception e) { @@ -579,6 +645,8 @@ namespace FFXIVClassic_Lobby_Server removeItem(client, UInt32.Parse(split[1]), 1); else if (split.Length == 3) removeItem(client, UInt32.Parse(split[1]), Int32.Parse(split[2])); + else if (split.Length == 4) + removeItem(client, UInt32.Parse(split[1]), Int32.Parse(split[2]), UInt16.Parse(split[3])); } catch (Exception e) { diff --git a/FFXIVClassic Map Server/actors/chara/player/Player.cs b/FFXIVClassic Map Server/actors/chara/player/Player.cs index 5f3f8308..d76349b8 100644 --- a/FFXIVClassic Map Server/actors/chara/player/Player.cs +++ b/FFXIVClassic Map Server/actors/chara/player/Player.cs @@ -98,6 +98,9 @@ namespace FFXIVClassic_Map_Server.Actors inventories[Inventory.NORMAL] = new Inventory(this, MAXSIZE_INVENTORY_NORMAL, Inventory.NORMAL); inventories[Inventory.KEYITEMS] = new Inventory(this, MAXSIZE_INVENTORY_KEYITEMS, Inventory.KEYITEMS); inventories[Inventory.CURRANCY] = new Inventory(this, MAXSIZE_INVENTORY_CURRANCY, Inventory.CURRANCY); + inventories[Inventory.MELDREQUEST] = new Inventory(this, MAXSIZE_INVENTORY_MELDREQUEST, Inventory.MELDREQUEST); + inventories[Inventory.BAZAAR] = new Inventory(this, MAXSIZE_INVENTORY_BAZAAR, Inventory.BAZAAR); + inventories[Inventory.LOOT] = new Inventory(this, MAXSIZE_INVENTORY_LOOT, Inventory.LOOT); charaWork.property[0] = 1; charaWork.property[1] = 1; @@ -433,6 +436,9 @@ namespace FFXIVClassic_Map_Server.Actors inventories[Inventory.NORMAL].sendFullInventory(); inventories[Inventory.CURRANCY].sendFullInventory(); inventories[Inventory.KEYITEMS].sendFullInventory(); + inventories[Inventory.BAZAAR].sendFullInventory(); + inventories[Inventory.MELDREQUEST].sendFullInventory(); + inventories[Inventory.LOOT].sendFullInventory(); #region equipsetup // EquipmentListX08Packet initialEqupmentPacket = new EquipmentListX08Packet(); // initialEqupmentPacket.setItem(EquipmentListX08Packet.SLOT_BODY, 5); diff --git a/FFXIVClassic Map Server/dataobjects/ConnectedPlayer.cs b/FFXIVClassic Map Server/dataobjects/ConnectedPlayer.cs index f25f3025..c90ee4a8 100644 --- a/FFXIVClassic Map Server/dataobjects/ConnectedPlayer.cs +++ b/FFXIVClassic Map Server/dataobjects/ConnectedPlayer.cs @@ -32,6 +32,7 @@ namespace FFXIVClassic_Map_Server.dataobjects public void setConnection(int type, ClientConnection conn) { + conn.connType = type; switch (type) { case BasePacket.TYPE_ZONE: diff --git a/FFXIVClassic Map Server/packets/receive/supportdesk/GMSupportTicketPacket.cs b/FFXIVClassic Map Server/packets/receive/supportdesk/GMSupportTicketPacket.cs new file mode 100644 index 00000000..cab46175 --- /dev/null +++ b/FFXIVClassic Map Server/packets/receive/supportdesk/GMSupportTicketPacket.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FFXIVClassic_Map_Server.packets.receive.supportdesk +{ + class GMSupportTicketPacket + { + public bool invalidPacket = false; + public string ticketTitle, ticketBody; + public uint ticketIssueIndex; + public uint langCode; + + public GMSupportTicketPacket(byte[] data) + { + using (MemoryStream mem = new MemoryStream(data)) + { + using (BinaryReader binReader = new BinaryReader(mem)) + { + try + { + langCode = binReader.ReadUInt32(); + ticketIssueIndex = binReader.ReadUInt32(); + ticketTitle = Encoding.ASCII.GetString(binReader.ReadBytes(0x80)).Trim(new[] { '\0' }); + ticketBody = Encoding.ASCII.GetString(binReader.ReadBytes(0x800)).Trim(new[] { '\0' }); + } + catch (Exception){ + invalidPacket = true; + } + } + } + } + + } +}