public void DecodeFrom( CompressedBlock block ) { const int INVALID_ADJ = 15; const int TERMINATOR = 128; Install install = block.Parent.Install; byte[] data = block.Data; for ( int i=0; i<IDTABLE_SIZE; ++i ) idTable[i] = ushort.MaxValue; int index = 0; idCount = -1; // Get a list of province ids do { ++idCount; idTable[idCount] = (ushort)(data[idCount<<1] + ((data[(idCount<<1)+1]&127) << 8)); index += 2; } while ( data[(idCount<<1)+1] < TERMINATOR ); ++idCount; // Normalize the IDs... Basically, we're stripping some of that data away which we don't need (mainly to do with borders). for ( int i=0; i<idCount; ++i ) { if ( idTable[i] <= Province.MaxID ) continue; ushort id = idTable[((idTable[i]>>9) & 63)-4]; if( id > Province.MaxID ) id = install.Provinces.TerraIncognita.ID; else { int river = (idTable[i]>>5) & 15; if ( river != INVALID_ADJ ) id = install.Provinces[id].GetNeighbor( river ).ID; idTable[i] = id; } } // Build the tree. DecompressorState decompstate = new DecompressorState( index, ref data ); BuildTree( root, decompstate, 5 ); index = decompstate.GetFinalNodeIndex(); // Define ownership and colors tables int numLeaves = decompstate.NumOfLeaves; int sizeLeaves = decompstate.SizeOfLeaves; byte[] colors = new byte[decompstate.SizeOfLeaves + (4-(decompstate.SizeOfLeaves % 4))]; ushort[] ownership = null; decompstate = null; if ( idCount == 1 ) { ownership = new ushort[numLeaves]; for ( int i=0; i<numLeaves; ++i ) ownership[i] = idTable[0]; } else if ( idCount == 2 ) { ownership = new ushort[numLeaves + (8-(numLeaves % 8))]; for ( int i=0; i<numLeaves; ++index ) { ownership[i++] = idTable[(data[index] >> 0) & 1]; ownership[i++] = idTable[(data[index] >> 1) & 1]; ownership[i++] = idTable[(data[index] >> 2) & 1]; ownership[i++] = idTable[(data[index] >> 3) & 1]; ownership[i++] = idTable[(data[index] >> 4) & 1]; ownership[i++] = idTable[(data[index] >> 5) & 1]; ownership[i++] = idTable[(data[index] >> 6) & 1]; ownership[i++] = idTable[(data[index] >> 7) & 1]; } } else if ( idCount <= 4 ) { ownership = new ushort[numLeaves + (4-(numLeaves % 4))]; for ( int i=0; i<numLeaves; ++index ) { ownership[i++] = idTable[(data[index] >> 0) & 3]; ownership[i++] = idTable[(data[index] >> 2) & 3]; ownership[i++] = idTable[(data[index] >> 4) & 3]; ownership[i++] = idTable[(data[index] >> 6) & 3]; } } else if ( idCount <= 16 ) { ownership = new ushort[numLeaves + (2-(numLeaves % 2))]; for ( int i=0; i<numLeaves; index++ ) { ownership[i++] = idTable[(data[index] >> 0) & 15]; ownership[i++] = idTable[(data[index] >> 4) & 15]; } } else if ( idCount > 16 ) { ownership = new ushort[numLeaves]; for ( int i=0; i<ownership.Length; ++i, ++index ) ownership[i] = idTable[data[index]]; } // Read in color table // Finally, read the leaf data. This part contains the "color" data for each leaf. for ( int i=0; i<sizeLeaves; ) { colors[i++] = (byte)(data[index] & 63); colors[i++] = (byte)((data[index] >> 6 | data[index+1] << 2) & 63); colors[i++] = (byte)((data[index+1] >> 4 | data[index+2] << 4) & 63); colors[i++] = (byte)(data[index+2] >> 2); index += 3; } // Fill them into the tree PopulatorState popstate = new PopulatorState( ref ownership, ref colors ); PopulateTree( root, popstate ); }
private void PopulateTree( Node currentNode, PopulatorState state ) { if ( currentNode == null ) return; if ( !currentNode.IsLeaf() ) { // Walk over the tree in a breath-first manner PopulateTree( currentNode.BottomRightChild, state ); PopulateTree( currentNode.BottomLeftChild, state ); PopulateTree( currentNode.TopRightChild, state ); PopulateTree( currentNode.TopLeftChild, state ); } else { currentNode.Owner = state.CurrentOwner; currentNode.Color = state.CurrentColor; state.NextLeaf(); } }