public static Vector3D Deserialize2(int maxBits, BitReader br) { var v = new Vector3D(); // From ReadPackedVector v.NumBits = br.ReadInt32Max(maxBits); Int32 Bias = 1 << (v.NumBits + 1); Int32 Max = v.NumBits + 2; v.DX = br.ReadInt32FromBits(Max); v.DY = br.ReadInt32FromBits(Max); v.DZ = br.ReadInt32FromBits(Max); //float fact = 1; //(float)ScaleFactor; // 1 in our case, doesnt matter //v.X = (float)(static_cast<int32>(DX)-Bias) / fact; // Why bother with the static_cast? Why not make DX an int32 instead of uint32 in the first place? // always integers, hey? v.X = v.DX-Bias; v.Y = v.DY-Bias; v.Z = v.DZ-Bias; return v; }
public static ActorStateProperty Deserialize(IClassNetCache classMap, IDictionary<int, string> objectIndexToName, BitReader br) { var asp = new ActorStateProperty(); var startPosition = br.Position; var maxPropId = classMap.MaxPropertyId; //var idBitLen = Math.Floor(Math.Log10(maxPropId) / Math.Log10(2)) + 1; var className = objectIndexToName[classMap.ObjectIndex]; asp.PropertyId = br.ReadInt32Max(maxPropId + 1);// br.ReadInt32FromBits((int)idBitLen); asp.MaxPropertyId = maxPropId; asp.PropertyName = objectIndexToName[classMap.GetProperty(asp.PropertyId).Index]; asp.Data = new List<object>(); try { switch (asp.PropertyName) { case "TAGame.GameEvent_TA:ReplicatedStateIndex": asp.Data.Add(br.ReadInt32Max(140)); // number is made up, I dont know the max yet asp.IsComplete = true; break; case "TAGame.RBActor_TA:ReplicatedRBState": asp.Data.Add(br.ReadBit()); asp.Data.Add(Vector3D.Deserialize2(20, br)); var rot = Vector3D.DeserializeFixed(br); asp.Data.Add(rot); // Sometimes these two vectors are missing? // Wild guess: They're momentum vectors, and only there when moving? // Well, how do I know they're moving without momentum vectors... hm. if (!(rot.X < -1 && rot.Y < -1 && rot.Z < -1)) { asp.Data.Add(Vector3D.Deserialize2(20, br)); asp.Data.Add(Vector3D.Deserialize2(20, br)); } asp.IsComplete = true; break; case "TAGame.Team_TA:GameEvent": case "TAGame.CrowdActor_TA:ReplicatedOneShotSound": case "TAGame.CrowdManager_TA:ReplicatedGlobalOneShotSound": case "Engine.Actor:Owner": case "TAGame.GameEvent_Soccar_TA:RoundNum": case "Engine.GameReplicationInfo:GameClass": case "TAGame.GameEvent_TA:BotSkill": case "Engine.PlayerReplicationInfo:Team": case "TAGame.CrowdManager_TA:GameEvent": case "Engine.Pawn:PlayerReplicationInfo": //case "TAGame.VehiclePickup_TA:ReplicatedPickupData": asp.Data.Add(br.ReadBit()); asp.Data.Add(br.ReadInt32()); asp.IsComplete = true; break; case "TAGame.CarComponent_TA:Vehicle": // 110101111 // TAGame.CarComponent_Jump_TA // 100111111 // TAGame.CarComponent_FlipCar_TA asp.Data.Add(br.ReadBit()); if (className == "TAGame.CarComponent_Jump_TA" || className == "TAGame.CarComponent_FlipCar_TA" || className == "TAGame.CarComponent_Boost_TA" || className == "TAGame.CarComponent_Dodge_TA" || className == "TAGame.CarComponent_DoubleJump_TA") { asp.Data.Add(br.ReadInt32()); } else { asp.Data.Add(br.ReadByte()); } asp.IsComplete = true; break; case "Engine.PlayerReplicationInfo:PlayerName": case "Engine.GameReplicationInfo:ServerName": asp.Data.Add(br.ReadString()); asp.IsComplete = true; break; case "TAGame.GameEvent_Soccar_TA:SecondsRemaining": case "TAGame.GameEvent_TA:ReplicatedGameStateTimeRemaining": case "TAGame.CrowdActor_TA:ReplicatedCountDownNumber": case "TAGame.CrowdActor_TA:ModifiedNoise": case "TAGame.GameEvent_Team_TA:MaxTeamSize": asp.Data.Add(br.ReadInt32()); asp.IsComplete = true; break; case "TAGame.VehiclePickup_TA:ReplicatedPickupData": // 1011101000000000000000000000000001 // 0111111111111111111111111111111110 // 1111001000000000000000000000000001 // 1000001000000000000000000000000001 // 1111110000000000000000000000000001 // 1101110000000000000000000000000001 // 111111111 // 100000001 // 101001111 var bit1 = br.ReadBit(); var byt = br.ReadByte(); var bit2 = (byt & 0x80) > 0; if (bit1 == bit2) { asp.Data.Add(bit1); asp.Data.Add(byt); } else { asp.Data.Add(bit1); var bytes = new byte[4]; bytes[0] = byt; bytes[1] = br.ReadByte(); bytes[2] = br.ReadByte(); bytes[3] = br.ReadByte(); asp.Data.Add(BitConverter.ToInt32(bytes, 0)); asp.Data.Add(br.ReadBit()); } asp.IsComplete = true; break; case "Engine.Actor:bNetOwner": case "Engine.Actor:bBlockActors": // this doesnt look right... asp.Data.Add(br.ReadBit()); asp.Data.Add(br.ReadBit()); asp.Data.Add(br.ReadBit()); asp.IsComplete = true; break; case "Engine.Pawn:DrivenVehicle": asp.Data.Add(br.ReadInt32()); asp.Data.Add(br.ReadBit()); asp.Data.Add(br.ReadBit()); asp.IsComplete = true; break; case "Engine.Actor:DrawScale": // Might be more properties in this sample data // 100011000000000000010000000001001110010100000001000000000000000000000000000000110000000000000000000100000000010000000001000110000000000010101 // 1011010000000100010000000011001110010100000010000000000000000000000000000011100000000000000001001000000000010000000000100110101100000000101010 // 1011010000000011110000000001111111000100000010000000000000000000000000000001100000000000000000101000000000001000000000001110111111100000000101010 break; case "Engine.PlayerReplicationInfo:Ping": case "TAGame.Vehicle_TA:ReplicatedSteer": case "TAGame.Vehicle_TA:ReplicatedThrottle": case "TAGame.PRI_TA:CameraYaw": case "TAGame.PRI_TA:CameraPitch": asp.Data.Add(br.ReadByte()); asp.IsComplete = true; break; case "Engine.Actor:Location": case "TAGame.CarComponent_Dodge_TA:DodgeTorque": asp.Data.Add(Vector3D.Deserialize(br)); asp.IsComplete = true; break; case "Engine.Actor:bCollideWorld": case "Engine.PlayerReplicationInfo:bReadyToPlay": case "TAGame.Vehicle_TA:bReplicatedHandbrake": case "TAGame.Vehicle_TA:bDriving": //asp.Data.Add(Vector3D.Deserialize(5, br)); asp.Data.Add(br.ReadBit()); asp.IsComplete = true; break; case "TAGame.PRI_TA:bUsingBehindView": case "TAGame.PRI_TA:bUsingSecondaryCamera": asp.Data.Add(br.ReadBit()); asp.IsComplete = true; break; case "TAGame.CarComponent_TA:ReplicatedActive": // example data // 0111111111111111111111111111111110 asp.Data.Add(br.ReadByte()); /* asp.Data.Add(br.ReadBit()); if ( (bool)asp.Data[0]) { asp.Data.Add(br.ReadInt32FromBits(7)); }*/ asp.IsComplete = true; break; case "Engine.Actor:Role": asp.Data.Add(br.ReadInt32FromBits(11)); asp.IsComplete = true; break; /*case "Engine.Actor:RelativeRotation": //SWAG asp.Data.Add(br.ReadBit()); asp.Data.Add(br.ReadByte()); asp.Data.Add(br.ReadInt32()); asp.IsComplete = true; break;*/ case "Engine.PlayerReplicationInfo:UniqueId": asp.Data.Add(br.ReadBit()); asp.Data.Add(br.ReadByte()); asp.IsComplete = true; break; } } catch(Exception) { asp.Data.Add("FAILED"); } finally { asp.KnownBits = br.GetBits(startPosition, br.Position - startPosition); } return asp; }
// This probably belongs in BitReader. This is the only calss that uses it though. static float ReadFixedCompressedFloat(Int32 maxValue, Int32 numBits, BitReader br) { float value = 0; // NumBits = 8: var maxBitValue = (1 << (numBits - 1)) - 1; // 0111 1111 - Max abs value we will serialize var bias = (1 << (numBits - 1)) ; // 1000 0000 - Bias to pivot around (in order to support signed values) var serIntMax = (1 << (numBits - 0)) ; // 1 0000 0000 - What we pass into SerializeInt var maxDelta = (1 << (numBits - 0)) - 1; // 1111 1111 - Max delta is Int32 delta = br.ReadInt32Max(serIntMax); // Could just read 16 bits always, since numBits will always be 16 float unscaledValue = delta - bias; if ( maxValue > maxBitValue ) { // We have to scale down, scale needs to be a float: float invScale = maxValue / (float)maxBitValue; value = unscaledValue * invScale; } else { var scale = maxBitValue / maxValue; float invScale = 1.0f / (float)scale; value = unscaledValue * invScale; } return value; }