В .NET 4.5 этот шифр отлично работал на 32-битной и 64-битной архитектуре. Переключение проекта на .NET 4.6 полностью разрывает этот шифр в 64-разрядной версии, а в 32-разрядной версии исправляется нечетный.
В моем методе "DecodeSkill", SkillLevel - единственная часть, которая ломается на .NET 4.6. Используемые здесь переменные считываются из сетевого потока и кодируются.
DecodeSkill (всегда возвращает правильное декодированное значение для SkillLevel)
private void DecodeSkill()
{
SkillId = (ushort) (ExchangeShortBits((SkillId ^ ObjectId ^ 0x915d), 13) + 0x14be);
SkillLevel = ((ushort) ((byte)SkillLevel ^ 0x21));
TargetObjectId = (ExchangeLongBits(TargetObjectId, 13) ^ ObjectId ^ 0x5f2d2463) + 0x8b90b51a;
PositionX = (ushort) (ExchangeShortBits((PositionX ^ ObjectId ^ 0x2ed6), 15) + 0xdd12);
PositionY = (ushort) (ExchangeShortBits((PositionY ^ ObjectId ^ 0xb99b), 11) + 0x76de);
}
ExchangeShortBits
private static uint ExchangeShortBits(uint data, int bits)
{
data &= 0xffff;
return (data >> bits | data << (16 - bits)) & 65535;
}
DecodeSkill (исправлено для .NET 4.6 32-бит, заметьте "var patch = SkillLevel" )
private void DecodeSkill()
{
SkillId = (ushort) (ExchangeShortBits((SkillId ^ ObjectId ^ 0x915d), 13) + 0x14be);
var patch = SkillLevel = ((ushort) ((byte)SkillLevel ^ 0x21));
TargetObjectId = (ExchangeLongBits(TargetObjectId, 13) ^ ObjectId ^ 0x5f2d2463) + 0x8b90b51a;
PositionX = (ushort) (ExchangeShortBits((PositionX ^ ObjectId ^ 0x2ed6), 15) + 0xdd12);
PositionY = (ushort) (ExchangeShortBits((PositionY ^ ObjectId ^ 0xb99b), 11) + 0x76de);
}
Назначение переменной как SkillLevel, только в 32-битных, приведет к тому, что SkillLevel всегда будет правильным значением. Удалите этот патч, и значение всегда неверно. В 64-битном случае это всегда неверно даже с патчем.
Я пробовал использовать MethodImplOptions.NoOptimization и MethodImplOptions.NoInlining по методу декодирования, думая, что это будет иметь значение.
Любые идеи, что могло бы вызвать это?
Изменить: Меня попросили привести пример ввода, хорошего вывода и плохого вывода. Это из фактического сценария использования, значения были отправлены от клиента и правильно декодированы сервером, используя "patch" на .NET 4.6.
Input:
ObjectId = 1000001
TargetObjectId = 2778236265
PositionX = 32409
PositionY = 16267
SkillId = 28399
SkillLevel = 8481
Хороший вывод
TargetObjectId = 0
PositionX = 302
PositionY = 278
SkillId = 1115
SkillLevel = 0
Плохой вывод
TargetObjectId = 0
PositionX = 302
PositionY = 278
SkillId = 1115
SkillLevel = 34545
Изменить # 2:
Я должен включить эту часть, определенно важную роль в этом.
EncodeSkill ( Timestamp - Environment.TickCount)
private void EncodeSkill()
{
SkillId = (ushort) (ExchangeShortBits(ObjectId - 0x14be, 3) ^ ObjectId ^ 0x915d);
SkillLevel = (ushort) ((SkillLevel + 0x100*(Timestamp%0x100)) ^ 0x3721);
Arg1 = MathUtils.BitFold32(SkillId, SkillLevel);
TargetObjectId = ExchangeLongBits(((TargetObjectId - 0x8b90b51a) ^ ObjectId ^ 0x5f2d2463u), 19);
PositionX = (ushort) (ExchangeShortBits((uint) PositionX - 0xdd12, 1) ^ ObjectId ^ 0x2ed6);
PositionY = (ushort) (ExchangeShortBits((uint) PositionY - 0x76de, 5) ^ ObjectId ^ 0xb99b);
}
BitFold32
public static int BitFold32(int lower16, int higher16)
{
return (lower16) | (higher16 << 16);
}
ExchangeLongBits
private static uint ExchangeLongBits(uint data, int bits)
{
return data >> bits | data << (32 - bits);
}