diff --git a/FFXIVClassic Map Server/ClientConnection.cs b/FFXIVClassic Map Server/ClientConnection.cs index e2d07e7d..70f86065 100644 --- a/FFXIVClassic Map Server/ClientConnection.cs +++ b/FFXIVClassic Map Server/ClientConnection.cs @@ -21,7 +21,7 @@ namespace FFXIVClassic_Lobby_Server public Socket socket; public byte[] buffer = new byte[0xffff]; public CircularBuffer incomingStream = new CircularBuffer(1024); - public BlockingCollection sendPacketQueue = new BlockingCollection(100); + private BlockingCollection sendPacketQueue = new BlockingCollection(100); //Instance Stuff public uint owner = 0; @@ -68,7 +68,8 @@ namespace FFXIVClassic_Lobby_Server public void disconnect() { - socket.Disconnect(false); + if (socket.Connected) + socket.Disconnect(false); } } } diff --git a/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj b/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj index 666485d5..dd3fc56e 100644 --- a/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj +++ b/FFXIVClassic Map Server/FFXIVClassic Map Server.csproj @@ -82,6 +82,7 @@ + @@ -113,6 +114,7 @@ + @@ -122,6 +124,7 @@ + diff --git a/FFXIVClassic Map Server/PacketProcessor.cs b/FFXIVClassic Map Server/PacketProcessor.cs index 70c68879..0a4be42d 100644 --- a/FFXIVClassic Map Server/PacketProcessor.cs +++ b/FFXIVClassic Map Server/PacketProcessor.cs @@ -17,6 +17,7 @@ using FFXIVClassic_Map_Server.packets.send.login; using FFXIVClassic_Map_Server.packets.send.Actor.inventory; using FFXIVClassic_Map_Server.packets.send.Actor; using FFXIVClassic_Map_Server.packets.send.actor; +using FFXIVClassic_Map_Server; namespace FFXIVClassic_Lobby_Server { @@ -26,6 +27,8 @@ namespace FFXIVClassic_Lobby_Server List mConnections; Boolean isAlive = true; + Zone inn = new Zone(); + public PacketProcessor(Dictionary playerList, List connectionList) { mPlayers = playerList; @@ -64,7 +67,7 @@ namespace FFXIVClassic_Lobby_Server } //Send packets - if (conn != null && conn.sendPacketQueue.Count != 0) + if (conn != null) conn.flushQueuedSendPackets(); } } @@ -110,8 +113,8 @@ namespace FFXIVClassic_Lobby_Server } } - client.sendPacketQueue.Add(init); - client.sendPacketQueue.Add(reply2); + client.queuePacket(init); + client.queuePacket(reply2); break; } @@ -295,6 +298,9 @@ namespace FFXIVClassic_Lobby_Server client.queuePacket(reply10); //client.queuePacket(reply11); client.queuePacket(reply12); + + inn.addActorToZone(player.getActor()); + break; //Chat Received case 0x0003: @@ -304,26 +310,31 @@ namespace FFXIVClassic_Lobby_Server case 0x00CA: UpdatePlayerPositionPacket posUpdate = new UpdatePlayerPositionPacket(subpacket.data); player.updatePlayerActorPosition(posUpdate.x, posUpdate.y, posUpdate.z, posUpdate.rot, posUpdate.moveState); + + List instanceUpdatePackets = player.updateInstance(inn.getActorsAroundActor(player.getActor(), 50)); + foreach (BasePacket bp in instanceUpdatePackets) + client.queuePacket(bp); + break; //Set Target case 0x00CD: subpacket.debugPrintSubPacket(); SetTargetPacket setTarget = new SetTargetPacket(subpacket.data); - player.setTarget(setTarget.actorID); + player.getActor().currentTarget = setTarget.actorID; client.queuePacket(BasePacket.createPacket(SetActorTargetAnimatedPacket.buildPacket(player.actorID, player.actorID, setTarget.actorID), true, false)); break; //Lock Target case 0x00CC: LockTargetPacket lockTarget = new LockTargetPacket(subpacket.data); - player.setLockedTarget(lockTarget.actorID); + player.getActor().currentLockedTarget = lockTarget.actorID; break; //Start Script case 0x012D: subpacket.debugPrintSubPacket(); //StartScriptPacket startScript = new StartScriptPacket(subpacket.data); //client.queuePacket(new BasePacket("./packets/script/bed.bin")); - client.queuePacket(BasePacket.createPacket(ActorDoEmotePacket.buildPacket(player.actorID, player.getTargetedActor(), 137), true, false)); + client.queuePacket(BasePacket.createPacket(ActorDoEmotePacket.buildPacket(player.actorID, player.getActor().currentTarget, 137), true, false)); break; //Script Result case 0x012E: @@ -354,9 +365,9 @@ namespace FFXIVClassic_Lobby_Server { packet.replaceActorID(entry.Value.actorID); if (conn == 1 || conn == 3) - entry.Value.getConnection1().sendPacketQueue.Add(packet); + entry.Value.getConnection1().queuePacket(packet); if (conn == 2 || conn == 3) - entry.Value.getConnection2().sendPacketQueue.Add(packet); + entry.Value.getConnection2().queuePacket(packet); } } diff --git a/FFXIVClassic Map Server/Zone.cs b/FFXIVClassic Map Server/Zone.cs index 546a9d17..7b2a7cd1 100644 --- a/FFXIVClassic Map Server/Zone.cs +++ b/FFXIVClassic Map Server/Zone.cs @@ -10,17 +10,45 @@ namespace FFXIVClassic_Map_Server class Zone { public uint mapId; + public ushort weatherNormal, weatherCommon, weatherRare; + public ushort bgmDay, bgmNight, bgmBattle; public int boundingGridSize = 200; + public int minX = -1000, minY = -1000, maxX = 1000, maxY = 1000; + private int numXBlocks, numYBlocks; + private int halfWidth, halfHeight; + private List[,] actorBlock; - private Dictionary, List> actorBlock = new Dictionary, List>(); + public Zone() + { + numXBlocks = (maxX - minX) / boundingGridSize; + numYBlocks = (maxY - minY) / boundingGridSize; + actorBlock = new List[numXBlocks, numYBlocks]; + halfWidth = numXBlocks / 2; + halfHeight = numYBlocks / 2; + } + + #region Actor Management public void addActorToZone(Actor actor) { int gridX = (int)actor.positionX / boundingGridSize; int gridY = (int)actor.positionY / boundingGridSize; + gridX += halfWidth; + gridY += halfHeight; + + //Boundries + if (gridX < 0) + gridX = 0; + if (gridX >= numXBlocks) + gridX = numXBlocks - 1; + if (gridY < 0) + gridY = 0; + if (gridY >= numYBlocks) + gridY = numYBlocks - 1; + lock (actorBlock) - actorBlock[Tuple.Create(gridX, gridY)].Add(actor); + actorBlock[gridX, gridY].Add(actor); } public void removeActorToZone(Actor actor) @@ -28,8 +56,21 @@ namespace FFXIVClassic_Map_Server int gridX = (int)actor.positionX / boundingGridSize; int gridY = (int)actor.positionY / boundingGridSize; + gridX += halfWidth; + gridY += halfHeight; + + //Boundries + if (gridX < 0) + gridX = 0; + if (gridX >= numXBlocks) + gridX = numXBlocks - 1; + if (gridY < 0) + gridY = 0; + if (gridY >= numYBlocks) + gridY = numYBlocks - 1; + lock (actorBlock) - actorBlock[Tuple.Create(gridX, gridY)].Remove(actor); + actorBlock[gridX, gridY].Remove(actor); } public void updateActorPosition(Actor actor) @@ -37,17 +78,43 @@ namespace FFXIVClassic_Map_Server int gridX = (int)actor.positionX / boundingGridSize; int gridY = (int)actor.positionY / boundingGridSize; + gridX += halfWidth; + gridY += halfHeight; + + //Boundries + if (gridX < 0) + gridX = 0; + if (gridX >= numXBlocks) + gridX = numXBlocks - 1; + if (gridY < 0) + gridY = 0; + if (gridY >= numYBlocks) + gridY = numYBlocks - 1; + int gridOldX = (int)actor.oldPositionX / boundingGridSize; int gridOldY = (int)actor.oldPositionY / boundingGridSize; + gridOldX += halfWidth; + gridOldY += halfHeight; + + //Boundries + if (gridOldX < 0) + gridOldX = 0; + if (gridOldX >= numXBlocks) + gridOldX = numXBlocks - 1; + if (gridOldY < 0) + gridOldY = 0; + if (gridOldY >= numYBlocks) + gridOldY = numYBlocks - 1; + //Still in same block if (gridX == gridOldX && gridY == gridOldY) return; lock (actorBlock) - actorBlock[Tuple.Create(gridOldX, gridOldY)].Remove(actor); + actorBlock[gridOldX, gridOldY].Remove(actor); lock (actorBlock) - actorBlock[Tuple.Create(gridX, gridY)].Add(actor); + actorBlock[gridX, gridY].Add(actor); } public List getActorsAroundPoint(float x, float y, int checkDistance) @@ -55,18 +122,63 @@ namespace FFXIVClassic_Map_Server int gridX = (int)x/boundingGridSize; int gridY = (int)y/boundingGridSize; + gridX += halfWidth; + gridY += halfHeight; + + //Boundries + if (gridX < 0) + gridX = 0; + if (gridX >= numXBlocks) + gridX = numXBlocks - 1; + if (gridY < 0) + gridY = 0; + if (gridY >= numYBlocks) + gridY = numYBlocks - 1; + List result = new List(); for (int gx = gridX - checkDistance; gx <= gridX + checkDistance; gx++) { for (int gy = gridY - checkDistance; gy <= gridY + checkDistance; gy++) { - result.AddRange(actorBlock[Tuple.Create(gx, gy)]); + result.AddRange(actorBlock[gx, gy]); } } return result; } - + + public List getActorsAroundActor(Actor actor, int checkDistance) + { + int gridX = (int)actor.positionX / boundingGridSize; + int gridY = (int)actor.positionY / boundingGridSize; + + gridX += halfWidth; + gridY += halfHeight; + + //Boundries + if (gridX < 0) + gridX = 0; + if (gridX >= numXBlocks) + gridX = numXBlocks - 1; + if (gridY < 0) + gridY = 0; + if (gridY >= numYBlocks) + gridY = numYBlocks - 1; + + List result = new List(); + + for (int gx = gridX - checkDistance; gx <= gridX + checkDistance; gx++) + { + for (int gy = gridY - checkDistance; gy <= gridY + checkDistance; gy++) + { + result.AddRange(actorBlock[gx, gy]); + } + } + + return result; + } + + #endregion } } diff --git a/FFXIVClassic Map Server/dataobjects/Actor.cs b/FFXIVClassic Map Server/dataobjects/Actor.cs index e54b8e4a..93817ea0 100644 --- a/FFXIVClassic Map Server/dataobjects/Actor.cs +++ b/FFXIVClassic Map Server/dataobjects/Actor.cs @@ -41,16 +41,41 @@ namespace FFXIVClassic_Map_Server.dataobjects public uint actorID; - public uint displayNameID; + public bool isNameplateVisible; + public bool isTargetable; + + public uint displayNameID = 0xFFFFFFFF; public string customDisplayName; + public uint nameplateIcon; public uint modelID; public uint[] appearanceIDs = new uint[0x1D]; - public float positionX, positionY, positionZ; - public float oldPositionX, oldPositionY, oldPositionZ; - public float rotation; - public ushort moveState; + public uint currentTarget = 0xC0000000; + public uint currentLockedTarget = 0xC0000000; + + public float positionX, positionY, positionZ, rotation; + public float oldPositionX, oldPositionY, oldPositionZ, oldRotation; + public ushort moveState, oldMoveState; + + public uint currentState = SetActorStatePacket.STATE_PASSIVE; + + public uint currentZoneID; + + //Properties + public ushort curHP, curMP, curTP; + public ushort maxHP, maxMP, maxTP; + + public byte currentJob; + public ushort currentLevel; + + public ushort statSTR, statVIT, statDEX, statINT, statMIN, statPIE; + public ushort statAttack, statDefense, statAccuracy, statAttackMgkPotency, statHealingMgkPotency, statEnchancementMgkPotency, statEnfeeblingMgkPotency, statMgkAccuracy, statMgkEvasion; + public ushort resistFire, resistIce, resistWind, resistEarth, resistLightning, resistWater; + + public uint currentEXP; + + public ushort linkshellcrest; public Actor(uint id) { @@ -94,7 +119,7 @@ namespace FFXIVClassic_Map_Server.dataobjects public SubPacket createStatePacket(uint playerActorID) { - return SetActorStatePacket.buildPacket(playerActorID, actorID, SetActorStatePacket.STATE_PASSIVE); + return SetActorStatePacket.buildPacket(playerActorID, actorID, currentState); } public SubPacket createSpeedPacket(uint playerActorID) @@ -102,5 +127,33 @@ namespace FFXIVClassic_Map_Server.dataobjects return SetActorSpeedPacket.buildPacket(playerActorID, actorID); } + public SubPacket createSpawnPositonPacket(uint playerActorID, uint spawnType) + { + return SetActorPositionPacket.buildPacket(playerActorID, actorID, positionX, positionY, positionZ, rotation, spawnType); + } + + public SubPacket createPositionUpdatePacket(uint playerActorID) + { + return MoveActorToPositionPacket.buildPacket(playerActorID, actorID, positionX, positionY, positionZ, rotation, moveState); + } + + public SubPacket createScriptBindPacket(uint playerActorID) + { + return null; + } + + public BasePacket createActorSpawnPackets(uint playerActorID) + { + List subpackets = new List(); + subpackets.Add(AddActorPacket.buildPacket(playerActorID, actorID)); + subpackets.Add(createSpeedPacket(playerActorID)); + subpackets.Add(createSpawnPositonPacket(playerActorID, 0)); + subpackets.Add(createAppearancePacket(playerActorID)); + subpackets.Add(createNamePacket(playerActorID)); + subpackets.Add(createStatePacket(playerActorID)); + subpackets.Add(createScriptBindPacket(playerActorID)); + return BasePacket.createPacket(subpackets, true, false); + } + } } diff --git a/FFXIVClassic Map Server/dataobjects/Player.cs b/FFXIVClassic Map Server/dataobjects/Player.cs index b995b05d..bc10608f 100644 --- a/FFXIVClassic Map Server/dataobjects/Player.cs +++ b/FFXIVClassic Map Server/dataobjects/Player.cs @@ -1,5 +1,7 @@ using FFXIVClassic_Lobby_Server; using FFXIVClassic_Lobby_Server.dataobjects; +using FFXIVClassic_Lobby_Server.packets; +using FFXIVClassic_Map_Server.packets.send.actor; using System; using System.Collections.Generic; using System.Linq; @@ -15,12 +17,8 @@ namespace FFXIVClassic_Map_Server.dataobjects ClientConnection conn1; ClientConnection conn2; - public uint characterID = 0; public uint actorID = 0; - private uint currentTarget = 0xC0000000; - private uint currentLockedTarget = 0xC0000000; - private uint currentZoneID = 0; List actorInstanceList = new List(); @@ -112,19 +110,28 @@ namespace FFXIVClassic_Map_Server.dataobjects } - public void setTarget(uint actorID) - { - currentTarget = actorID; - } - public void setLockedTarget(uint actorID) - { - currentLockedTarget = actorID; - } + public List updateInstance(List list) + { + List basePackets = new List(); + List posUpdateSubpackets = new List(); - public uint getTargetedActor() - { - return currentTarget; + for (int i = 0; i < list.Count; i++) + { + Actor actor = list[i]; + + if (actor.actorID == playerActor.actorID) + continue; + + if (actorInstanceList.Contains(actor)) + posUpdateSubpackets.Add(actor.createPositionUpdatePacket(playerActor.actorID)); + else + basePackets.Add(actor.createActorSpawnPackets(playerActor.actorID)); + } + + basePackets.Add(BasePacket.createPacket(posUpdateSubpackets, true, false)); + + return basePackets; } } }