Synchronized Random Number Generator
by Danni · 04/17/2011 (5:16 pm) · 2 comments
This code use useful for creating random numbers client side during prediction, then having the server perform the same generation so for example, you can fire hitscans client side spawning bullet puffs on the wall instantly, have the server replicate and send the result to everyone else.
This modification will also send verification of the servers current pointer in the list in the case of a lost packet, etc.
This uses a similar RNG table as Doom II with a few changes and is not intended to be secure or offer a flat distribution. Feel free to upgrade it if you need something different.
File: mods/syncedRandom.hpp
Modification: shapeBase.cpp
Modification: shapeBase.cpp
Modification: shapeBase.cpp (add this somewhere)
Example usage: (NOTE: my T3D is modified to run weapon scripts client and server side; this code won't work with stock but gives an example)
This modification will also send verification of the servers current pointer in the list in the case of a lost packet, etc.
This uses a similar RNG table as Doom II with a few changes and is not intended to be secure or offer a flat distribution. Feel free to upgrade it if you need something different.
File: mods/syncedRandom.hpp
#ifndef __SYNCEDRANDOM_HPP_
#define __SYNCEDRANDOM_HPP_
// Doom2 Inspired static psudorandom number generator.
const static U8 rndtable[256] = {
1, 8, 109, 220, 222, 241, 149, 107, 75, 248, 254, 140, 16, 66,
74, 21, 211, 47, 80, 242, 154, 27, 205, 128, 161, 89, 77, 36,
95, 110, 85, 48, 212, 140, 211, 249, 22, 79, 200, 50, 28, 188,
52, 140, 202, 120, 68, 146, 62, 70, 184, 190, 91, 197, 152, 224,
149, 104, 25, 178, 252, 182, 202, 182, 141, 197, 4, 81, 181, 242,
145, 42, 39, 227, 156, 198, 225, 193, 219, 93, 122, 175, 249, 0,
175, 143, 70, 239, 46, 246, 163, 53, 163, 109, 168, 135, 2, 235,
25, 92, 20, 145, 138, 77, 69, 166, 78, 176, 173, 212, 166, 113,
94, 161, 41, 50, 239, 49, 111, 164, 70, 60, 2, 37, 171, 75,
136, 156, 11, 56, 42, 147, 138, 229, 73, 146, 77, 61, 98, 196,
135, 106, 63, 197, 195, 86, 96, 203, 113, 101, 170, 247, 181, 113,
80, 250, 108, 7, 255, 237, 129, 226, 79, 107, 112, 166, 103, 241,
24, 223, 239, 120, 198, 58, 60, 82, 128, 3, 184, 66, 143, 224,
145, 224, 81, 206, 163, 45, 63, 90, 168, 114, 59, 33, 159, 95,
28, 139, 123, 98, 125, 196, 15, 70, 194, 253, 54, 14, 109, 226,
71, 17, 161, 93, 186, 87, 244, 138, 20, 52, 123, 251, 26, 36,
17, 46, 52, 231, 232, 76, 31, 221, 84, 37, 216, 165, 212, 106,
197, 242, 98, 43, 39, 175, 254, 145, 190, 84, 118, 222, 187, 136,
120, 163, 236, 249
};
class SyncedRandom
{
public:
inline SyncedRandom() { index = 0; dirty = false; };
inline void setPointer(U8 _index) { index = _index; };
inline U8 getPointer() { return index; };
inline U8 getRandom() { dirty = true;
return rndtable[++index]; };
inline bool isDirty() { return dirty; };
private:
U8 index;
bool dirty;
};
#endifModification: shapeBase.cpp
void ShapeBase::unpackUpdate(NetConnection *con, BitStream *stream)
...
if(!stream->writeFlag(mask & (NameMask | DamageMask | SoundMask | MeshHiddenMask |
ThreadMask | ImageMask | HideCloakMask | MountedMask | InvincibleMask |
ShieldMask | SkinMask)))
return retMask;
// [Danni] Client Weapons: Synced Random
if (stream->writeFlag(syncedRandom.isDirty() || mask & InitialUpdateMask))
stream->writeInt(syncedRandom.getPointer(), 8);
// [Danni] END Client Weapons: Synced Random
if (stream->writeFlag(mask & DamageMask)) {
stream->writeFloat(mClampF(mDamage / mDataBlock->maxDamage, 0.f, 1.f), DamageLevelBits);
stream->writeInt(mDamageState,NumDamageStateBits);
stream->writeNormalVector( damageDir, 8 );
}Modification: shapeBase.cpp
void ShapeBase::unpackUpdate(NetConnection *con, BitStream *stream)
...
if(!stream->readFlag())
return;
// [Danni] Client Weapons: Synced Random
if (stream->readFlag())
syncedRandom.setPointer(stream->readInt(8));
// [Danni] END Client Weapons: Synced Random
if (stream->readFlag()) {Modification: shapeBase.cpp (add this somewhere)
// [Danni] Client Weapons: Synced Random
ConsoleMethod(ShapeBase, getRandom, S32, 2,2, "Returns a random number between 0 and 255")
{
return object->syncedRandom.getRandom();
}
// [Danni] END Client Weapons: Synced RandomExample usage: (NOTE: my T3D is modified to run weapon scripts client and server side; this code won't work with stock but gives an example)
for (%i = 0; %i < 20; %i++)
{
%damage = 5*(%obj.getRandom()%3+1);
%muzzzleVector = %obj.getMuzzleVector(%slot);
%muzzzleVector = VectorNormalize(%muzzzleVector);
%yaw = YawFromVector(%muzzzleVector);
%pitch = PitchFromVector(%muzzzleVector);
%yaw += mDegToRad(((((%obj.getRandom()-128) << 19) / 65536.0)/65536.0)*360);
%pitch += mDegToRad(((((%obj.getRandom()-128) << 18) / 65536.0)/65536.0)*360);
%rnd = %rnd @ %yaw @ %pitch;
%muzzzleVector = VectorFromAngles(%yaw, %pitch);
%muzzzleVector = VectorScale(%muzzzleVector, %this.ballisticsRange);
%muzzlePoint = %obj.getMuzzlePoint(%slot);
%distance = VectorAdd(%muzzlePoint, %muzzzleVector);
// Do a "hitscan"
%scanTarg = ContainerRayCast(%muzzlePoint, %distance, %searchMasks, %obj);
if(%scanTarg)
{
%target = firstWord(%scanTarg);
%target.damage(%obj,%pos,%damage,%this.meansOfDeath);
}
}
#2
06/03/2011 (8:08 pm)
It is taken care of server side; client side is purely cosmetic so if they hack it, they are only fooling themselves. 
Torque 3D Owner Entr0py