// Server public object[] GetNewInformation(List <object[]> oldInformation, out byte[] dataInterp, bool isPlayerOwner) { int bitChoicesLength = getBitChoicesLength(isPlayerOwner); int byteChoicesByteLength = (bitChoicesLength + 7) / 8; int count = 0; dataInterp = new byte[byteChoicesByteLength + 3]; // Copies in ID / Type: Buffer.BlockCopy(BitConverter.GetBytes(objectID), 0, dataInterp, 0, 2); dataInterp[2] = objectType; // Exists is set manually in dataInterp: if (exists) { dataInterp[3] += (1 << 0); } // Sets what needs to be changed: for (int i = 1; i < bitChoicesLength; i++) { for (int x = 0; x < oldInformation.Count; x++) { if (DataInterpret.isObjectDifferent(getObject(i - 1, isPlayerOwner), oldInformation [x] [i - 1])) { count++; dataInterp [3 + i / 8] += (byte)(1 << (i % 8)); break; } } } // It only adds the neccessary objects: object[] returnObjects = new object[count]; count = 0; for (int i = 1; i < bitChoicesLength; i++) { if ((dataInterp[3 + i / 8] & (1 << (i % 8))) != 0) { returnObjects[count++] = getObject(i - 1, isPlayerOwner); } } return(returnObjects); }
// This just passes the full data set in. CLIENT SIDE public object[] getObjects(byte[] data, ref int bytePosition, object[] lastObjects, bool isPlayerOwner, int tickNumber) { int initialIndex = bytePosition; int bitChoicesLength = getBitChoicesLength(isPlayerOwner); int byteChoicesByteLength = (bitChoicesLength + 7) / 8; // The dataInterp is just part of the data: object[] returnObjects = new object[bitChoicesLength - 1]; bytePosition = bytePosition + 3 + byteChoicesByteLength; // Reiterates through the byteChoices: for (int i = 1; i < bitChoicesLength; i++) { if ((data[initialIndex + 3 + i / 8] & (1 << (i % 8))) != 0) { // Acquire each object from data. New types of objects should be created if, for example, different accuracies of Vector3 are wanted to be written / read. returnObjects[i - 1] = DataInterpret.interpretObject(data, ref bytePosition, getObject(i - 1, isPlayerOwner), this, tickNumber, isPlayerOwner); // Last is type. getObject will return the right type. } else { // Adds it anyways: if (lastObjects == null || lastObjects[i - 1] == null) { // If this happens, it's just a throwaway anyway.. should be.. at least.. TODO this is a possible error spot that could happen w/o choke // Well. It is ASSUMED that the current state is the old state in this case. returnObjects[i - 1] = getObject(i - 1, isPlayerOwner); // getObject is most likely not ready for clientSide use currently. (The type will be right, ofc) } else { returnObjects[i - 1] = lastObjects[i - 1]; } } } return(returnObjects); }
// INTERP // Interps between ALL objects: 0 <= percent < 1. // b can be null if percent == 0. b could be null in any case, actually. // a.Length should equal b.Length, of course. public void interp(object[] a, object[] b, float percent, bool isThisFirstTick, bool isThisMine) { // Interp is not used for the first "frame" because interpolation can't be done on "SyncPlayer" because it switches what data it uses.. if (b == null || percent == 0 || !didFirstInterp) { SetInformation(a, a, b, isThisFirstTick, isThisMine); if (!didFirstInterp) { didFirstInterp = true; AfterFirstInterp(); } return; } object[] c = new object[a.Length]; for (int i = 0; i < a.Length; i++) { c[i] = DataInterpret.interp(a[i], b[i], percent); } SetInformation(c, a, b, isThisFirstTick, isThisMine); }
// Certain triggers will have a variable amount of data public override object getTriggerData(byte index, byte[] data, ref int bytePosition, bool isPlayerOwner) { if (!isPlayerOwner) { if (index == HITSCAN) { return(DataInterpret.interpretObject(data, ref bytePosition, new Vector3[] { }, null, -1, false)); } } else { if (index == DAMAGE_NUMBER) { return(new DamageNumber(data, ref bytePosition)); } else if (index == DAMAGE_TAKEN) { return(new DamageNumber(data, ref bytePosition)); } } return(null); }
// Client side: public DamageNumber(byte[] data, ref int bytePosition) { posData = (Vector3)DataInterpret.interpretObject(data, ref bytePosition, Vector3.zero, null, -1, false); damage = (float)DataInterpret.interpretObject(data, ref bytePosition, 1f, null, -1, false); }