From 8687e43191311f70fcb3d7cf6ea4820ce4373486 Mon Sep 17 00:00:00 2001 From: Filip Maj Date: Thu, 11 Jul 2019 12:13:23 -0400 Subject: [PATCH] Fixed actors not being resent on login into already available session due to those actors being in the instance list but not the client. Added chocobo rental code. --- Map Server/Actors/Chara/Player/Player.cs | 53 +++++++++++++++---- .../Player/SetCurrentMountChocoboPacket.cs | 15 +++++- Map Server/Server.cs | 3 ++ Map Server/actors/chara/player/Player.cs | 53 +++++++++++++++---- .../player/SetCurrentMountChocoboPacket.cs | 15 +++++- 5 files changed, 117 insertions(+), 22 deletions(-) diff --git a/Map Server/Actors/Chara/Player/Player.cs b/Map Server/Actors/Chara/Player/Player.cs index 2837e8a8..13016595 100644 --- a/Map Server/Actors/Chara/Player/Player.cs +++ b/Map Server/Actors/Chara/Player/Player.cs @@ -130,9 +130,11 @@ namespace Meteor.Map.Actors //Mount Related public bool hasChocobo; public bool hasGoobbue; - public byte chocoboAppearance; public string chocoboName; - public byte mountState = 0; + public byte mountState = 0; + public byte chocoboAppearance; + public uint rentalExpireTime = 0; + public byte rentalMinLeft = 0; public uint achievementPoints; @@ -370,7 +372,7 @@ namespace Meteor.Map.Actors } if (mountState == 1) - subpackets.Add(SetCurrentMountChocoboPacket.BuildPacket(actorId, chocoboAppearance)); + subpackets.Add(SetCurrentMountChocoboPacket.BuildPacket(actorId, chocoboAppearance, rentalExpireTime, rentalMinLeft)); else if (mountState == 2) subpackets.Add(SetCurrentMountGoobbuePacket.BuildPacket(actorId, 1)); @@ -554,7 +556,8 @@ namespace Meteor.Map.Actors { QueuePacket(SetActorIsZoningPacket.BuildPacket(actorId, false)); QueuePacket(SetDalamudPacket.BuildPacket(actorId, 0)); - QueuePacket(SetMusicPacket.BuildPacket(actorId, zone.bgmDay, 0x01)); + if (spawnType != 0x13 && spawnType != 0x14) + QueuePacket(SetMusicPacket.BuildPacket(actorId, zone.bgmDay, 0x01)); QueuePacket(SetWeatherPacket.BuildPacket(actorId, SetWeatherPacket.WEATHER_CLEAR, 1)); QueuePacket(SetMapPacket.BuildPacket(actorId, zone.regionId, zone.actorId)); @@ -840,7 +843,7 @@ namespace Meteor.Map.Actors public void SendMountAppearance() { if (mountState == 1) - BroadcastPacket(SetCurrentMountChocoboPacket.BuildPacket(actorId, chocoboAppearance), true); + BroadcastPacket(SetCurrentMountChocoboPacket.BuildPacket(actorId, chocoboAppearance, rentalExpireTime, rentalMinLeft), true); else if (mountState == 2) BroadcastPacket(SetCurrentMountGoobbuePacket.BuildPacket(actorId, 1), true); } @@ -1914,6 +1917,17 @@ namespace Meteor.Map.Actors chocoboAppearance = appearanceId; } + public void StartChocoboRental(byte numMins) + { + rentalExpireTime = Utils.UnixTimeStampUTC() + ((uint)numMins * 60); + rentalMinLeft = numMins; + } + + public bool IsChocoboRentalActive() + { + return rentalExpireTime != 0; + } + public Retainer SpawnMyRetainer(Npc bell, int retainerIndex) { Retainer retainer = Database.LoadRetainer(this, retainerIndex); @@ -1948,15 +1962,37 @@ namespace Meteor.Map.Actors public override void Update(DateTime tick) { + + // Chocobo Rental Expirey + if (rentalExpireTime != 0) + { + uint tickUTC = Utils.UnixTimeStampUTC(tick); + + //Rental has expired, dismount + if (rentalExpireTime <= tickUTC) + { + rentalExpireTime = 0; + rentalMinLeft = 0; + ChangeMusic(GetZone().bgmDay); + SetMountState(0); + ChangeSpeed(0.0f, 2.0f, 5.0f, 5.0f); + ChangeState(0); + } + else + { + rentalMinLeft = (byte) ((rentalExpireTime - tickUTC) /60); + } + } + aiContainer.Update(tick); - statusEffects.Update(tick); + statusEffects.Update(tick); } public override void PostUpdate(DateTime tick, List packets = null) { // todo: is this correct? if (this.playerSession.isUpdatesLocked) - return; + return; // todo: should probably add another flag for battleTemp since all this uses reflection packets = new List(); @@ -2005,8 +2041,7 @@ namespace Meteor.Map.Actors updateFlags ^= ActorUpdateFlags.Hotbar; } - - + base.PostUpdate(tick, packets); } diff --git a/Map Server/Packets/Send/Player/SetCurrentMountChocoboPacket.cs b/Map Server/Packets/Send/Player/SetCurrentMountChocoboPacket.cs index 7ad76faa..e42ade02 100644 --- a/Map Server/Packets/Send/Player/SetCurrentMountChocoboPacket.cs +++ b/Map Server/Packets/Send/Player/SetCurrentMountChocoboPacket.cs @@ -19,6 +19,9 @@ along with Project Meteor Server. If not, see . =========================================================================== */ +using System; +using System.IO; + using Meteor.Common; namespace Meteor.Map.packets.send.player @@ -45,10 +48,18 @@ namespace Meteor.Map.packets.send.player public const ushort OPCODE = 0x0197; public const uint PACKET_SIZE = 0x28; - public static SubPacket BuildPacket(uint sourceActorId, int appearanceId) + public static SubPacket BuildPacket(uint sourceActorId, byte chocoboAppearance, uint rentalExpireTime, byte rentalMinLeft) { byte[] data = new byte[PACKET_SIZE - 0x20]; - data[5] = (byte)(appearanceId & 0xFF); + using (MemoryStream mem = new MemoryStream(data)) + { + using (BinaryWriter binWriter = new BinaryWriter(mem)) + { + binWriter.Write((UInt32)rentalExpireTime); + binWriter.Write((Byte)rentalMinLeft); + binWriter.Write((Byte)chocoboAppearance); + } + } return new SubPacket(OPCODE, sourceActorId, data); } } diff --git a/Map Server/Server.cs b/Map Server/Server.cs index c86111d6..aa97403e 100644 --- a/Map Server/Server.cs +++ b/Map Server/Server.cs @@ -124,7 +124,10 @@ namespace Meteor.Map public Session AddSession(uint id) { if (mSessionList.ContainsKey(id)) + { + mSessionList[id].ClearInstance(); return mSessionList[id]; + } Session session = new Session(id); mSessionList.Add(id, session); diff --git a/Map Server/actors/chara/player/Player.cs b/Map Server/actors/chara/player/Player.cs index 2837e8a8..13016595 100644 --- a/Map Server/actors/chara/player/Player.cs +++ b/Map Server/actors/chara/player/Player.cs @@ -130,9 +130,11 @@ namespace Meteor.Map.Actors //Mount Related public bool hasChocobo; public bool hasGoobbue; - public byte chocoboAppearance; public string chocoboName; - public byte mountState = 0; + public byte mountState = 0; + public byte chocoboAppearance; + public uint rentalExpireTime = 0; + public byte rentalMinLeft = 0; public uint achievementPoints; @@ -370,7 +372,7 @@ namespace Meteor.Map.Actors } if (mountState == 1) - subpackets.Add(SetCurrentMountChocoboPacket.BuildPacket(actorId, chocoboAppearance)); + subpackets.Add(SetCurrentMountChocoboPacket.BuildPacket(actorId, chocoboAppearance, rentalExpireTime, rentalMinLeft)); else if (mountState == 2) subpackets.Add(SetCurrentMountGoobbuePacket.BuildPacket(actorId, 1)); @@ -554,7 +556,8 @@ namespace Meteor.Map.Actors { QueuePacket(SetActorIsZoningPacket.BuildPacket(actorId, false)); QueuePacket(SetDalamudPacket.BuildPacket(actorId, 0)); - QueuePacket(SetMusicPacket.BuildPacket(actorId, zone.bgmDay, 0x01)); + if (spawnType != 0x13 && spawnType != 0x14) + QueuePacket(SetMusicPacket.BuildPacket(actorId, zone.bgmDay, 0x01)); QueuePacket(SetWeatherPacket.BuildPacket(actorId, SetWeatherPacket.WEATHER_CLEAR, 1)); QueuePacket(SetMapPacket.BuildPacket(actorId, zone.regionId, zone.actorId)); @@ -840,7 +843,7 @@ namespace Meteor.Map.Actors public void SendMountAppearance() { if (mountState == 1) - BroadcastPacket(SetCurrentMountChocoboPacket.BuildPacket(actorId, chocoboAppearance), true); + BroadcastPacket(SetCurrentMountChocoboPacket.BuildPacket(actorId, chocoboAppearance, rentalExpireTime, rentalMinLeft), true); else if (mountState == 2) BroadcastPacket(SetCurrentMountGoobbuePacket.BuildPacket(actorId, 1), true); } @@ -1914,6 +1917,17 @@ namespace Meteor.Map.Actors chocoboAppearance = appearanceId; } + public void StartChocoboRental(byte numMins) + { + rentalExpireTime = Utils.UnixTimeStampUTC() + ((uint)numMins * 60); + rentalMinLeft = numMins; + } + + public bool IsChocoboRentalActive() + { + return rentalExpireTime != 0; + } + public Retainer SpawnMyRetainer(Npc bell, int retainerIndex) { Retainer retainer = Database.LoadRetainer(this, retainerIndex); @@ -1948,15 +1962,37 @@ namespace Meteor.Map.Actors public override void Update(DateTime tick) { + + // Chocobo Rental Expirey + if (rentalExpireTime != 0) + { + uint tickUTC = Utils.UnixTimeStampUTC(tick); + + //Rental has expired, dismount + if (rentalExpireTime <= tickUTC) + { + rentalExpireTime = 0; + rentalMinLeft = 0; + ChangeMusic(GetZone().bgmDay); + SetMountState(0); + ChangeSpeed(0.0f, 2.0f, 5.0f, 5.0f); + ChangeState(0); + } + else + { + rentalMinLeft = (byte) ((rentalExpireTime - tickUTC) /60); + } + } + aiContainer.Update(tick); - statusEffects.Update(tick); + statusEffects.Update(tick); } public override void PostUpdate(DateTime tick, List packets = null) { // todo: is this correct? if (this.playerSession.isUpdatesLocked) - return; + return; // todo: should probably add another flag for battleTemp since all this uses reflection packets = new List(); @@ -2005,8 +2041,7 @@ namespace Meteor.Map.Actors updateFlags ^= ActorUpdateFlags.Hotbar; } - - + base.PostUpdate(tick, packets); } diff --git a/Map Server/packets/send/player/SetCurrentMountChocoboPacket.cs b/Map Server/packets/send/player/SetCurrentMountChocoboPacket.cs index 7ad76faa..e42ade02 100644 --- a/Map Server/packets/send/player/SetCurrentMountChocoboPacket.cs +++ b/Map Server/packets/send/player/SetCurrentMountChocoboPacket.cs @@ -19,6 +19,9 @@ along with Project Meteor Server. If not, see . =========================================================================== */ +using System; +using System.IO; + using Meteor.Common; namespace Meteor.Map.packets.send.player @@ -45,10 +48,18 @@ namespace Meteor.Map.packets.send.player public const ushort OPCODE = 0x0197; public const uint PACKET_SIZE = 0x28; - public static SubPacket BuildPacket(uint sourceActorId, int appearanceId) + public static SubPacket BuildPacket(uint sourceActorId, byte chocoboAppearance, uint rentalExpireTime, byte rentalMinLeft) { byte[] data = new byte[PACKET_SIZE - 0x20]; - data[5] = (byte)(appearanceId & 0xFF); + using (MemoryStream mem = new MemoryStream(data)) + { + using (BinaryWriter binWriter = new BinaryWriter(mem)) + { + binWriter.Write((UInt32)rentalExpireTime); + binWriter.Write((Byte)rentalMinLeft); + binWriter.Write((Byte)chocoboAppearance); + } + } return new SubPacket(OPCODE, sourceActorId, data); } }