bool SendRawMapCore(Level oldLevel, Level level)
        {
            if (level.blocks == null)
            {
                return(false);
            }
            bool success = true;

            useCheckpointSpawn  = false;
            lastCheckpointIndex = -1;

            AFKCooldown = DateTime.UtcNow.AddSeconds(2);
            SendMapMotd();
            AccessResult access = level.BuildAccess.Check(this);

            AllowBuild = access == AccessResult.Whitelisted || access == AccessResult.Allowed;

            try {
                Send(Packet.LevelInitalise());

                if (hasBlockDefs)
                {
                    if (oldLevel != null && oldLevel != level)
                    {
                        RemoveOldLevelCustomBlocks(oldLevel);
                    }
                    BlockDefinition.SendLevelCustomBlocks(this);

                    if (Supports(CpeExt.InventoryOrder))
                    {
                        BlockDefinition.SendLevelInventoryOrder(this);
                    }
                }

                using (LevelChunkStream s = new LevelChunkStream(this))
                    LevelChunkStream.CompressMap(this, s);

                // Force players to read the MOTD (clamped to 3 seconds at most)
                if (level.Config.LoadDelay > 0)
                {
                    System.Threading.Thread.Sleep(level.Config.LoadDelay);
                }

                byte[] buffer = Packet.LevelFinalise(level.Width, level.Height, level.Length);
                Send(buffer);
                Loading = false;

                OnJoinedLevelEvent.Call(this, oldLevel, level);
            } catch (Exception ex) {
                success = false;
                PlayerActions.ChangeMap(this, Server.mainLevel);
                SendMessage("There was an error sending the map data, you have been sent to the main level.");
                Logger.LogError(ex);
            } finally {
                Server.DoGC();
            }
            return(success);
        }
        bool SendRawMapCore(Level prev, Level level)
        {
            bool success = true;

            try {
                if (level.blocks == null)
                {
                    throw new InvalidOperationException("Tried to join unloaded level");
                }

                useCheckpointSpawn  = false;
                lastCheckpointIndex = -1;

                AFKCooldown = DateTime.UtcNow.AddSeconds(2);
                ZoneIn      = null;
                SendMapMotd();
                AllowBuild = level.BuildAccess.CheckAllowed(this);

                int volume = level.blocks.Length;
                if (Supports(CpeExt.FastMap))
                {
                    Send(Packet.LevelInitaliseExt(volume));
                }
                else
                {
                    Send(Packet.LevelInitalise());
                }

                if (hasBlockDefs)
                {
                    if (prev != null && prev != level)
                    {
                        RemoveOldLevelCustomBlocks(prev);
                    }
                    BlockDefinition.SendLevelCustomBlocks(this);

                    if (Supports(CpeExt.InventoryOrder))
                    {
                        BlockDefinition.SendLevelInventoryOrder(this);
                    }
                }

                using (LevelChunkStream dst = new LevelChunkStream(this))
                    using (Stream stream = LevelChunkStream.CompressMapHeader(this, volume, dst))
                    {
                        if (level.MightHaveCustomBlocks())
                        {
                            LevelChunkStream.CompressMap(this, stream, dst);
                        }
                        else
                        {
                            LevelChunkStream.CompressMapSimple(this, stream, dst);
                        }
                    }

                // Force players to read the MOTD (clamped to 3 seconds at most)
                if (level.Config.LoadDelay > 0)
                {
                    System.Threading.Thread.Sleep(level.Config.LoadDelay);
                }

                byte[] buffer = Packet.LevelFinalise(level.Width, level.Height, level.Length);
                Send(buffer);
                Loading = false;

                OnSentMapEvent.Call(this, prev, level);
            } catch (Exception ex) {
                success = false;
                PlayerActions.ChangeMap(this, Server.mainLevel);
                Message("&WThere was an error sending the map, you have been sent to the main level.");
                Logger.LogError(ex);
            } finally {
                Server.DoGC();
            }
            return(success);
        }
Beispiel #3
0
        bool SendRawMapCore(Level oldLevel, Level level)
        {
            if (level.blocks == null)
            {
                return(false);
            }
            bool success = true;

            useCheckpointSpawn  = false;
            lastCheckpointIndex = -1;

            LevelAccess access = level.BuildAccess.Check(this);

            AllowBuild = access == LevelAccess.Whitelisted || access == LevelAccess.Allowed;

            try {
                if (hasBlockDefs)
                {
                    if (oldLevel != null && oldLevel != level)
                    {
                        RemoveOldLevelCustomBlocks(oldLevel);
                    }
                    BlockDefinition.SendLevelCustomBlocks(this);
                }

                SendRaw(Opcode.LevelInitialise);
                using (LevelChunkStream s = new LevelChunkStream(this))
                    LevelChunkStream.CompressMap(this, s);

                byte[] buffer = new byte[7];
                buffer[0] = Opcode.LevelFinalise;
                NetUtils.WriteI16((short)level.Width, buffer, 1);
                NetUtils.WriteI16((short)level.Height, buffer, 3);
                NetUtils.WriteI16((short)level.Length, buffer, 5);
                Send(buffer);
                AFKCooldown = DateTime.UtcNow.AddSeconds(2);
                Loading     = false;

                if (HasCpeExt(CpeExt.EnvWeatherType))
                {
                    Send(Packet.EnvWeatherType((byte)level.Weather));
                }
                if (HasCpeExt(CpeExt.EnvColors))
                {
                    SendCurrentEnvColors();
                }
                SendCurrentMapAppearance();
                if (HasCpeExt(CpeExt.BlockPermissions))
                {
                    SendCurrentBlockPermissions();
                }

                if (OnSendMap != null)
                {
                    OnSendMap(this, buffer);
                }
                if (!level.guns && aiming)
                {
                    aiming = false;
                    ClearBlockchange();
                }
            } catch (Exception ex) {
                success = false;
                PlayerActions.ChangeMap(this, Server.mainLevel);
                SendMessage("There was an error sending the map data, you have been sent to the main level.");
                Server.ErrorLog(ex);
            } finally {
                GC.Collect();
                GC.WaitForPendingFinalizers();
            }
            return(success);
        }
Beispiel #4
0
        public unsafe static void CompressMap(Player p, LevelChunkStream dst)
        {
            const int bufferSize = 64 * 1024;

            byte[] buffer = new byte[bufferSize];
            int    bIndex = 0;

            // Store on stack instead of performing function call for every block in map
            byte *conv    = stackalloc byte[256];
            byte *convCPE = stackalloc byte[256];

            for (int i = 0; i < 256; i++)
            {
                conv[i] = Block.Convert((byte)i);
            }

            if (!p.hasCustomBlocks)
            {
                for (int i = 0; i < 256; i++)
                {
                    convCPE[i] = Block.ConvertCPE((byte)i);
                    conv[i]    = Block.ConvertCPE(conv[i]);
                }
            }

            Level lvl          = p.level;
            bool  hasBlockDefs = p.hasBlockDefs;

            using (GZipStream gs = new GZipStream(dst, CompressionMode.Compress, true)) {
                byte[] blocks = lvl.blocks;
                NetUtils.WriteI32(blocks.Length, buffer, 0);
                gs.Write(buffer, 0, sizeof(int));
                dst.length = blocks.Length;

                // compress the map data in 64 kb chunks
                if (p.hasCustomBlocks)
                {
                    for (int i = 0; i < blocks.Length; ++i)
                    {
                        byte block = blocks[i];
                        if (block == Block.custom_block)
                        {
                            buffer[bIndex] = hasBlockDefs ? lvl.GetExtTile(i) : lvl.GetFallbackExtTile(i);
                        }
                        else
                        {
                            buffer[bIndex] = conv[block];
                        }

                        bIndex++;
                        if (bIndex == bufferSize)
                        {
                            dst.position = i;
                            gs.Write(buffer, 0, bufferSize); bIndex = 0;
                        }
                    }
                }
                else
                {
                    for (int i = 0; i < blocks.Length; ++i)
                    {
                        byte block = blocks[i];
                        if (block == Block.custom_block)
                        {
                            block          = hasBlockDefs ? lvl.GetExtTile(i) : lvl.GetFallbackExtTile(i);
                            buffer[bIndex] = convCPE[block];
                        }
                        else
                        {
                            buffer[bIndex] = conv[block];
                        }

                        bIndex++;
                        if (bIndex == bufferSize)
                        {
                            dst.position = i;
                            gs.Write(buffer, 0, bufferSize); bIndex = 0;
                        }
                    }
                }
                if (bIndex > 0)
                {
                    gs.Write(buffer, 0, bIndex);
                }
            }
        }