Пример #1
0
 public static Packet MakeAddEntity( byte id, [NotNull] string name, Position pos )
 {
     if( name == null ) throw new ArgumentNullException( "name" );
     Packet packet = new Packet( OpCode.AddEntity );
     packet.Bytes[1] = id;
     Encoding.ASCII.GetBytes( name.PadRight( 64 ), 0, 64, packet.Bytes, 2 );
     ToNetOrder( pos.X, packet.Bytes, 66 );
     ToNetOrder( pos.Z, packet.Bytes, 68 );
     ToNetOrder( pos.Y, packet.Bytes, 70 );
     packet.Bytes[72] = pos.R;
     packet.Bytes[73] = pos.L;
     return packet;
 }
Пример #2
0
 public Map( int width, int length, int height )
 {
     if( width < 16 || width > 2048 || length < 16 || length > 2048 || height < 16 || height > 2048 ) {
         throw new ArgumentException( "Invalid map dimension(s)." );
     }
     Width = width;
     Length = length;
     Height = height;
     Volume = width*length*height;
     WaterLevel = Height/2;
     Blocks = new byte[Volume];
     Spawn = new Position( Width*16, Length*16, Math.Min( Height*32, Int16.MaxValue ) );
 }
Пример #3
0
        public static Map Load( [NotNull] string fileName )
        {
            if( fileName == null ) throw new ArgumentNullException( "fileName" );
            using( FileStream mapStream = File.OpenRead( fileName ) ) {
                byte[] temp = new byte[8];
                Map map = null;

                mapStream.Seek( -4, SeekOrigin.End );
                mapStream.Read( temp, 0, 4 );
                mapStream.Seek( 0, SeekOrigin.Begin );
                int uncompressedLength = BitConverter.ToInt32( temp, 0 );
                byte[] data = new byte[uncompressedLength];
                using( GZipStream reader = new GZipStream( mapStream, CompressionMode.Decompress, true ) ) {
                    reader.Read( data, 0, uncompressedLength );
                }

                for( int i = 0; i < uncompressedLength - 1; i++ ) {
                    if( data[i] != 0xAC || data[i + 1] != 0xED ) continue;

                    // bypassing the header crap
                    int pointer = i + 6;
                    Array.Copy( data, pointer, temp, 0, 2 );
                    pointer += IPAddress.HostToNetworkOrder( BitConverter.ToInt16( temp, 0 ) );
                    pointer += 13;

                    int headerEnd;
                    // find the end of serialization listing
                    for( headerEnd = pointer; headerEnd < data.Length - 1; headerEnd++ ) {
                        if( data[headerEnd] == 0x78 && data[headerEnd + 1] == 0x70 ) {
                            headerEnd += 2;
                            break;
                        }
                    }

                    // start parsing serialization listing
                    int offset = 0;
                    int width = 0, length = 0, height = 0;
                    Position spawn = new Position();
                    while( pointer < headerEnd ) {
                        switch( (char)data[pointer] ) {
                            case 'Z':
                                offset++;
                                break;
                            case 'F':
                            case 'I':
                                offset += 4;
                                break;
                            case 'J':
                                offset += 8;
                                break;
                        }

                        pointer += 1;
                        Array.Copy( data, pointer, temp, 0, 2 );
                        short skip = IPAddress.HostToNetworkOrder( BitConverter.ToInt16( temp, 0 ) );
                        pointer += 2;

                        // look for relevant variables
                        Array.Copy( data, headerEnd + offset - 4, temp, 0, 4 );
                        if( MemCmp( data, pointer, "width" ) ) {
                            width = (ushort)IPAddress.HostToNetworkOrder( BitConverter.ToInt32( temp, 0 ) );
                        } else if( MemCmp( data, pointer, "depth" ) ) {
                            height = (ushort)IPAddress.HostToNetworkOrder( BitConverter.ToInt32( temp, 0 ) );
                        } else if( MemCmp( data, pointer, "height" ) ) {
                            length = (ushort)IPAddress.HostToNetworkOrder( BitConverter.ToInt32( temp, 0 ) );
                        } else if( MemCmp( data, pointer, "xSpawn" ) ) {
                            spawn.X =
                                (short)(IPAddress.HostToNetworkOrder( BitConverter.ToInt32( temp, 0 ) )*32 + 16);
                        } else if( MemCmp( data, pointer, "ySpawn" ) ) {
                            spawn.Z =
                                (short)(IPAddress.HostToNetworkOrder( BitConverter.ToInt32( temp, 0 ) )*32 + 16);
                        } else if( MemCmp( data, pointer, "zSpawn" ) ) {
                            spawn.Y =
                                (short)(IPAddress.HostToNetworkOrder( BitConverter.ToInt32( temp, 0 ) )*32 + 16);
                        }

                        pointer += skip;
                    }

                    map = new Map( width, length, height ) { Spawn = spawn };

                    // find the start of the block array
                    bool foundBlockArray = false;
                    offset = Array.IndexOf<byte>( data, 0x00, headerEnd );
                    while( offset != -1 && offset < data.Length - 2 ) {
                        if( data[offset] == 0x00 && data[offset + 1] == 0x78 && data[offset + 2] == 0x70 ) {
                            foundBlockArray = true;
                            pointer = offset + 7;
                        }
                        offset = Array.IndexOf<byte>( data, 0x00, offset + 1 );
                    }

                    // copy the block array... or fail
                    if( !foundBlockArray ) {
                        throw new Exception( "DatMapConverter: Could not locate block array." );
                    }

                    Array.Copy( data, pointer, map.Blocks, 0, map.Blocks.Length );

                    // Map survivaltest/indev blocktypes to standard/presentation blocktypes
                    map.ConvertBlockTypes( Mapping );

                    if( Config.Physics ) map.EnablePhysics();
                    break;
                }
                if( map == null ) {
                    throw new Exception( "DatMapConverter: Error loading map." );
                }
                return map;
            }
        }
Пример #4
0
        void SendMap()
        {
            // write MapBegin
            //Logger.Log( "Send: MapBegin()" );
            writer.Write( OpCode.MapBegin );

            // grab a compressed copy of the map
            byte[] blockData;
            Map map = Server.Map;
            using( MemoryStream mapStream = new MemoryStream() ) {
                using( GZipStream compressor = new GZipStream( mapStream, CompressionMode.Compress ) ) {
                    int convertedBlockCount = IPAddress.HostToNetworkOrder( map.Volume );
                    compressor.Write( BitConverter.GetBytes( convertedBlockCount ), 0, 4 );
                    byte[] rawData = ( UsesCustomBlocks ? map.Blocks : map.GetFallbackMap() );
                    compressor.Write( rawData, 0, rawData.Length );
                }
                blockData = mapStream.ToArray();
            }

            // Transfer the map copy
            byte[] buffer = new byte[1024];
            int mapBytesSent = 0;
            while( mapBytesSent < blockData.Length ) {
                int chunkSize = blockData.Length - mapBytesSent;
                if( chunkSize > 1024 ) {
                    chunkSize = 1024;
                } else {
                    // CRC fix for ManicDigger
                    for( int i = 0; i < buffer.Length; i++ ) {
                        buffer[i] = 0;
                    }
                }
                Buffer.BlockCopy( blockData, mapBytesSent, buffer, 0, chunkSize );
                byte progress = (byte)( 100 * mapBytesSent / blockData.Length );

                // write in chunks of 1024 bytes or less
                //Logger.Log( "Send: MapChunk({0},{1})", chunkSize, progress );
                writer.Write( OpCode.MapChunk );
                writer.Write( (short)chunkSize );
                writer.Write( buffer, 0, 1024 );
                writer.Write( progress );
                mapBytesSent += chunkSize;
            }

            // write MapEnd
            writer.Write( OpCode.MapEnd );
            writer.Write( (short)map.Width );
            writer.Write( (short)map.Height );
            writer.Write( (short)map.Length );

            // write spawn point
            writer.Write( Packet.MakeAddEntity( 255, Name, map.Spawn ).Bytes );
            writer.Write( Packet.MakeTeleport( 255, map.Spawn ).Bytes );

            lastValidPosition = map.Spawn;
        }
Пример #5
0
        void ProcessMovementPacket()
        {
            reader.ReadByte();
            Position newPos = new Position {
                X = reader.ReadInt16(),
                Z = reader.ReadInt16(),
                Y = reader.ReadInt16(),
                R = reader.ReadByte(),
                L = reader.ReadByte()
            };
            Position oldPos = Position;

            // calculate difference between old and new positions
            Position delta = new Position {
                X = (short)( newPos.X - oldPos.X ),
                Y = (short)( newPos.Y - oldPos.Y ),
                Z = (short)( newPos.Z - oldPos.Z ),
                R = (byte)Math.Abs( newPos.R - oldPos.R ),
                L = (byte)Math.Abs( newPos.L - oldPos.L )
            };

            bool posChanged = ( delta.X != 0 ) || ( delta.Y != 0 ) || ( delta.Z != 0 );
            bool rotChanged = ( delta.R != 0 ) || ( delta.L != 0 );

            // skip everything if player hasn't moved
            if( !posChanged && !rotChanged ) return;

            // only reset the timer if player rotated
            // if player is just pushed around, rotation does not change (and timer should not reset)
            if( rotChanged ) ResetIdleTimer();

            if( !IsOp && !Config.AllowSpeedHack || IsOp && !Config.OpAllowSpeedHack ) {
                int distSquared = delta.X * delta.X + delta.Y * delta.Y + delta.Z * delta.Z;
                // speedhack detection
                if( DetectMovementPacketSpam() ) return;
                if( ( distSquared - delta.Z * delta.Z > AntiSpeedMaxDistanceSquared ||
                    delta.Z > AntiSpeedMaxJumpDelta ) && speedHackDetectionCounter >= 0 ) {

                    if( speedHackDetectionCounter == 0 ) {
                        lastValidPosition = Position;
                    } else if( speedHackDetectionCounter > 1 ) {
                        DenyMovement();
                        speedHackDetectionCounter = 0;
                        return;
                    }
                    speedHackDetectionCounter++;

                } else {
                    speedHackDetectionCounter = 0;
                }
            }

            BroadcastMovementChange( newPos, delta );
        }
Пример #6
0
        void BroadcastMovementChange( Position newPos, Position delta )
        {
            Position = newPos;

            bool posChanged = ( delta.X != 0 ) || ( delta.Y != 0 ) || ( delta.Z != 0 );
            bool rotChanged = ( delta.R != 0 ) || ( delta.L != 0 );

            Packet packet;
            // create the movement packet
            if( delta.FitsIntoMoveRotatePacket && positionSyncCounter < PositionSyncInterval ) {
                if( posChanged && rotChanged ) {
                    // incremental position + rotation update
                    packet = Packet.MakeMoveRotate( Id, new Position {
                        X = delta.X,
                        Y = delta.Y,
                        Z = delta.Z,
                        R = newPos.R,
                        L = newPos.L
                    } );

                } else if( posChanged ) {
                    // incremental position update
                    packet = Packet.MakeMove( Id, delta );

                } else if( rotChanged ) {
                    // absolute rotation update
                    packet = Packet.MakeRotate( Id, newPos );
                } else {
                    return;
                }

            } else {
                // full (absolute position + rotation) update
                packet = Packet.MakeTeleport( Id, newPos );
            }

            positionSyncCounter++;
            if( positionSyncCounter >= PositionSyncInterval ) {
                positionSyncCounter = 0;
            }

            Server.Players.Send( this, packet );
        }
Пример #7
0
 public static Packet MakeTeleport( byte id, Position pos )
 {
     Packet packet = new Packet( OpCode.Teleport );
     packet.Bytes[1] = id;
     ToNetOrder( pos.X, packet.Bytes, 2 );
     ToNetOrder( pos.Z, packet.Bytes, 4 );
     ToNetOrder( pos.Y, packet.Bytes, 6 );
     packet.Bytes[8] = pos.R;
     packet.Bytes[9] = pos.L;
     return packet;
 }
Пример #8
0
 public static Packet MakeSelfTeleport( Position pos )
 {
     return MakeTeleport( 255, pos.GetFixed() );
 }
Пример #9
0
 public static Packet MakeRotate( int id, Position pos )
 {
     Packet packet = new Packet( OpCode.Rotate );
     packet.Bytes[1] = (byte)id;
     packet.Bytes[2] = pos.R;
     packet.Bytes[3] = pos.L;
     return packet;
 }
Пример #10
0
 public static Packet MakeMoveRotate( int id, Position pos )
 {
     Packet packet = new Packet( OpCode.MoveRotate );
     packet.Bytes[1] = (byte)id;
     packet.Bytes[2] = (byte)( pos.X & 0xFF );
     packet.Bytes[3] = (byte)( pos.Z & 0xFF );
     packet.Bytes[4] = (byte)( pos.Y & 0xFF );
     packet.Bytes[5] = pos.R;
     packet.Bytes[6] = pos.L;
     return packet;
 }
Пример #11
0
 public static Packet MakeMove( int id, Position pos )
 {
     Packet packet = new Packet( OpCode.Move );
     packet.Bytes[1] = (byte)id;
     packet.Bytes[2] = (byte)pos.X;
     packet.Bytes[3] = (byte)pos.Z;
     packet.Bytes[4] = (byte)pos.Y;
     return packet;
 }