internal set => SetField(ref _namePlateId, value);
}
- private byte HatSequenceId { get; set; } = 0;
+ internal byte HatSequenceId { get; set; } = 0;
- private byte PetSequenceId { get; set; } = 0;
+ internal byte PetSequenceId { get; set; } = 0;
- private byte SkinSequenceId { get; set; } = 0;
+ internal byte SkinSequenceId { get; set; } = 0;
- private byte VisorSequenceId { get; set; } = 0;
+ internal byte VisorSequenceId { get; set; } = 0;
- private byte NamePlateSequenceId { get; set; } = 0;
+ internal byte NamePlateSequenceId { get; set; } = 0;
/// <summary>
/// Gets a value indicating whether a player outfit is complete or whether it needs to receive additional cosmetics.
{
public static class Rpc39SetHatStr
{
- public static void Serialize(IMessageWriter writer, string hat)
+ public static void Serialize(IMessageWriter writer, string hat, byte nextRpcSequenceId)
{
writer.Write(hat);
+ writer.Write(nextRpcSequenceId);
}
- public static void Deserialize(IMessageReader reader, out string hat)
+ public static void Deserialize(IMessageReader reader, out string hat, out byte nextRpcSequenceId)
{
hat = reader.ReadString();
+ nextRpcSequenceId = reader.ReadByte();
}
}
}
{
public static class Rpc40SetSkinStr
{
- public static void Serialize(IMessageWriter writer, string skin)
+ public static void Serialize(IMessageWriter writer, string skin, byte nextRpcSequenceId)
{
writer.Write(skin);
+ writer.Write(nextRpcSequenceId);
}
- public static void Deserialize(IMessageReader reader, out string skin)
+ public static void Deserialize(IMessageReader reader, out string skin, out byte nextRpcSequenceId)
{
skin = reader.ReadString();
+ nextRpcSequenceId = reader.ReadByte();
}
}
}
{
public static class Rpc41SetPetStr
{
- public static void Serialize(IMessageWriter writer, string pet)
+ public static void Serialize(IMessageWriter writer, string pet, byte nextRpcSequenceId)
{
writer.Write(pet);
+ writer.Write(nextRpcSequenceId);
}
- public static void Deserialize(IMessageReader reader, out string pet)
+ public static void Deserialize(IMessageReader reader, out string pet, out byte nextRpcSequenceId)
{
pet = reader.ReadString();
+ nextRpcSequenceId = reader.ReadByte();
}
}
}
{
public static class Rpc42SetVisorStr
{
- public static void Serialize(IMessageWriter writer, string visor)
+ public static void Serialize(IMessageWriter writer, string visor, byte nextRpcSequenceId)
{
writer.Write(visor);
+ writer.Write(nextRpcSequenceId);
}
- public static void Deserialize(IMessageReader reader, out string visor)
+ public static void Deserialize(IMessageReader reader, out string visor, out byte nextRpcSequenceId)
{
visor = reader.ReadString();
+ nextRpcSequenceId = reader.ReadByte();
}
}
}
{
public static class Rpc43SetNamePlateStr
{
- public static void Serialize(IMessageWriter writer, string namePlate)
+ public static void Serialize(IMessageWriter writer, string namePlate, byte nextRpcSequenceId)
{
writer.Write(namePlate);
+ writer.Write(nextRpcSequenceId);
}
- public static void Deserialize(IMessageReader reader, out string namePlate)
+ public static void Deserialize(IMessageReader reader, out string namePlate, out byte nextRpcSequenceId)
{
namePlate = reader.ReadString();
+ nextRpcSequenceId = reader.ReadByte();
}
}
}
{
PlayerInfo.CurrentOutfit.HatId = hatId;
- using var writer = Game.StartRpc(NetId, RpcCalls.SetHat);
- Rpc39SetHatStr.Serialize(writer, hatId);
+ using var writer = Game.StartRpc(NetId, RpcCalls.SetHatStr);
+ Rpc39SetHatStr.Serialize(writer, hatId, PlayerInfo.GetNextRpcSequenceId(RpcCalls.SetHatStr));
await Game.FinishRpcAsync(writer);
}
{
PlayerInfo.CurrentOutfit.PetId = petId;
- using var writer = Game.StartRpc(NetId, RpcCalls.SetPet);
- Rpc41SetPetStr.Serialize(writer, petId);
+ using var writer = Game.StartRpc(NetId, RpcCalls.SetPetStr);
+ Rpc41SetPetStr.Serialize(writer, petId, PlayerInfo.GetNextRpcSequenceId(RpcCalls.SetPetStr));
await Game.FinishRpcAsync(writer);
}
{
PlayerInfo.CurrentOutfit.SkinId = skinId;
- using var writer = Game.StartRpc(NetId, RpcCalls.SetSkin);
- Rpc40SetSkinStr.Serialize(writer, skinId);
+ using var writer = Game.StartRpc(NetId, RpcCalls.SetSkinStr);
+ Rpc40SetSkinStr.Serialize(writer, skinId, PlayerInfo.GetNextRpcSequenceId(RpcCalls.SetSkinStr));
+ await Game.FinishRpcAsync(writer);
+ }
+
+ public async ValueTask SetVisorAsync(string visorId)
+ {
+ PlayerInfo.CurrentOutfit.VisorId = visorId;
+
+ using var writer = Game.StartRpc(NetId, RpcCalls.SetVisorStr);
+ Rpc42SetVisorStr.Serialize(writer, visorId, PlayerInfo.GetNextRpcSequenceId(RpcCalls.SetVisorStr));
+ await Game.FinishRpcAsync(writer);
+ }
+
+ public async ValueTask SetNamePlateAsync(string nameplateId)
+ {
+ PlayerInfo.CurrentOutfit.NamePlateId = nameplateId;
+
+ using var writer = Game.StartRpc(NetId, RpcCalls.SetNamePlateStr);
+ Rpc43SetNamePlateStr.Serialize(writer, nameplateId, PlayerInfo.GetNextRpcSequenceId(RpcCalls.SetNamePlateStr));
await Game.FinishRpcAsync(writer);
}
return false;
}
- Rpc39SetHatStr.Deserialize(reader, out var hat);
- return await HandleSetHat(sender, hat);
+ Rpc39SetHatStr.Deserialize(reader, out var hat, out var nextRpcSequenceId);
+ return await HandleSetHat(sender, hat, nextRpcSequenceId);
}
case RpcCalls.SetSkinStr:
return false;
}
- Rpc40SetSkinStr.Deserialize(reader, out var skin);
- return await HandleSetSkin(sender, skin);
+ Rpc40SetSkinStr.Deserialize(reader, out var skin, out var nextRpcSequenceId);
+ return await HandleSetSkin(sender, skin, nextRpcSequenceId);
}
case RpcCalls.SetVisorStr:
return false;
}
- Rpc42SetVisorStr.Deserialize(reader, out var visor);
- return await HandleSetVisor(sender, visor);
+ Rpc42SetVisorStr.Deserialize(reader, out var visor, out var nextRpcSequenceId);
+ return await HandleSetVisor(sender, visor, nextRpcSequenceId);
}
case RpcCalls.SetNamePlateStr:
return false;
}
- Rpc43SetNamePlateStr.Deserialize(reader, out var namePlate);
- return await HandleSetNamePlate(sender, namePlate);
+ Rpc43SetNamePlateStr.Deserialize(reader, out var namePlate, out var nextRpcSequenceId);
+ return await HandleSetNamePlate(sender, namePlate, nextRpcSequenceId);
}
case RpcCalls.SetLevel:
return false;
}
- Rpc41SetPetStr.Deserialize(reader, out var pet);
- return await HandleSetPet(sender, pet);
+ Rpc41SetPetStr.Deserialize(reader, out var pet, out var nextRpcSequenceId);
+ return await HandleSetPet(sender, pet, nextRpcSequenceId);
}
case RpcCalls.SetStartCounter:
return true;
}
- private async ValueTask<bool> HandleSetHat(ClientPlayer sender, string hat)
+ private async ValueTask<bool> HandleSetHat(ClientPlayer sender, string hat, byte nextRpcSequenceId)
{
if (Game.GameState == GameStates.Started &&
- await sender.Client.ReportCheatAsync(RpcCalls.SetHat, CheatCategory.GameFlow, "Client tried to change hat while not in lobby"))
+ await sender.Client.ReportCheatAsync(RpcCalls.SetHatStr, CheatCategory.GameFlow, "Client tried to change hat while not in lobby"))
{
return false;
}
PlayerInfo.CurrentOutfit.HatId = hat;
+ PlayerInfo.CurrentOutfit.HatSequenceId = nextRpcSequenceId;
return true;
}
- private async ValueTask<bool> HandleSetSkin(ClientPlayer sender, string skin)
+ private async ValueTask<bool> HandleSetSkin(ClientPlayer sender, string skin, byte nextRpcSequenceId)
{
if (Game.GameState == GameStates.Started &&
- await sender.Client.ReportCheatAsync(RpcCalls.SetSkin, CheatCategory.GameFlow, "Client tried to change skin while not in lobby"))
+ await sender.Client.ReportCheatAsync(RpcCalls.SetSkinStr, CheatCategory.GameFlow, "Client tried to change skin while not in lobby"))
{
return false;
}
PlayerInfo.CurrentOutfit.SkinId = skin;
+ PlayerInfo.CurrentOutfit.SkinSequenceId = nextRpcSequenceId;
return true;
}
- private async ValueTask<bool> HandleSetVisor(ClientPlayer sender, string visor)
+ private async ValueTask<bool> HandleSetVisor(ClientPlayer sender, string visor, byte nextRpcSequenceId)
{
if (Game.GameState == GameStates.Started &&
- await sender.Client.ReportCheatAsync(RpcCalls.SetVisor, CheatCategory.GameFlow, "Client tried to change visor while not in lobby"))
+ await sender.Client.ReportCheatAsync(RpcCalls.SetVisorStr, CheatCategory.GameFlow, "Client tried to change visor while not in lobby"))
{
return false;
}
PlayerInfo.CurrentOutfit.VisorId = visor;
+ PlayerInfo.CurrentOutfit.VisorSequenceId = nextRpcSequenceId;
return true;
}
- private async ValueTask<bool> HandleSetNamePlate(ClientPlayer sender, string skin)
+ private async ValueTask<bool> HandleSetNamePlate(ClientPlayer sender, string namePlate, byte nextRpcSequenceId)
{
if (Game.GameState == GameStates.Started &&
- await sender.Client.ReportCheatAsync(RpcCalls.SetNamePlate, CheatCategory.GameFlow, "Client tried to change skin while not in lobby"))
+ await sender.Client.ReportCheatAsync(RpcCalls.SetNamePlateStr, CheatCategory.GameFlow, "Client tried to change skin while not in lobby"))
{
return false;
}
- PlayerInfo.CurrentOutfit.NamePlateId = skin;
+ PlayerInfo.CurrentOutfit.NamePlateId = namePlate;
+ PlayerInfo.CurrentOutfit.NamePlateSequenceId = nextRpcSequenceId;
return true;
}
await _eventManager.CallAsync(new PlayerStartMeetingEvent(Game, Game.GetClientPlayer(this.OwnerId)!, this, deadPlayer));
}
- private async ValueTask<bool> HandleSetPet(ClientPlayer sender, string pet)
+ private async ValueTask<bool> HandleSetPet(ClientPlayer sender, string pet, byte nextRpcSequenceId)
{
if (Game.GameState == GameStates.Started &&
- await sender.Client.ReportCheatAsync(RpcCalls.SetPet, CheatCategory.GameFlow, "Client tried to change pet while not in lobby"))
+ await sender.Client.ReportCheatAsync(RpcCalls.SetPetStr, CheatCategory.GameFlow, "Client tried to change pet while not in lobby"))
{
return false;
}
PlayerInfo.CurrentOutfit.PetId = pet;
+ PlayerInfo.CurrentOutfit.PetSequenceId = nextRpcSequenceId;
return true;
}
Tasks.Add(new TaskInfo(this, _eventManager, taskId++, taskType));
}
}
+
+ public byte GetNextRpcSequenceId(RpcCalls rpc)
+ {
+ var defaultOutfit = this.Outfits[PlayerOutfitType.Default];
+
+ byte nextRpcSequenceId = 0;
+ const byte SequenceIdAddition = 5;
+
+ // ReSharper disable once SwitchStatementHandlesSomeKnownEnumValuesWithDefault
+ switch (rpc)
+ {
+ case RpcCalls.SetHatStr:
+ defaultOutfit.HatSequenceId += SequenceIdAddition;
+ nextRpcSequenceId = defaultOutfit.HatSequenceId;
+ break;
+ case RpcCalls.SetSkinStr:
+ defaultOutfit.SkinSequenceId += SequenceIdAddition;
+ nextRpcSequenceId = defaultOutfit.SkinSequenceId;
+ break;
+ case RpcCalls.SetPetStr:
+ defaultOutfit.PetSequenceId += SequenceIdAddition;
+ nextRpcSequenceId = defaultOutfit.PetSequenceId;
+ break;
+ case RpcCalls.SetVisorStr:
+ defaultOutfit.VisorSequenceId += SequenceIdAddition;
+ nextRpcSequenceId = defaultOutfit.VisorSequenceId;
+ break;
+ case RpcCalls.SetNamePlateStr:
+ defaultOutfit.NamePlateSequenceId += SequenceIdAddition;
+ nextRpcSequenceId = defaultOutfit.NamePlateSequenceId;
+ break;
+ default:
+ _logger.LogError(
+ "{NextRpcSequenceIdName} was called for an RPC it doesn\'t know how to handle: {Rpc}",
+ nameof(GetNextRpcSequenceId),
+ rpc);
+ break;
+ }
+
+ return nextRpcSequenceId;
+ }
}
}