예제 #1
0
 static void SetExtCol(CustomColor col)
 {
     ExtColors[col.Code] = col;
     Player[] players = Server.Players;
     foreach (Player p in players)
     {
         if (!p.Supports(CpeExt.TextColors))
         {
             continue;
         }
         p.Send(Packet.MakeSetTextColor(col));
     }
     SaveExtColors();
 }
예제 #2
0
        bool NegotiateProtocolExtension()
        {
            // write our ExtInfo and ExtEntry packets
            writer.Write(Packet.MakeExtInfo("ProCraft", 30).Bytes);

            writer.Write(Packet.MakeExtEntry(ClickDistanceExtName, 1).Bytes);
            writer.Write(Packet.MakeExtEntry(CustomBlocksExtName, 1).Bytes);
            writer.Write(Packet.MakeExtEntry(HeldBlockExtName, 1).Bytes);

            writer.Write(Packet.MakeExtEntry(TextHotKeyExtName, 1).Bytes);
            writer.Write(Packet.MakeExtEntry(ExtPlayerListExtName, 1).Bytes);
            writer.Write(Packet.MakeExtEntry(EnvColorsExtName, 1).Bytes);

            writer.Write(Packet.MakeExtEntry(SelectionCuboidExtName, 1).Bytes);
            writer.Write(Packet.MakeExtEntry(BlockPermissionsExtName, 1).Bytes);
            writer.Write(Packet.MakeExtEntry(ChangeModelExtName, 1).Bytes);

            writer.Write(Packet.MakeExtEntry(EnvMapAppearanceExtName, 1).Bytes);
            writer.Write(Packet.MakeExtEntry(EnvWeatherTypeExtName, 1).Bytes);
            writer.Write(Packet.MakeExtEntry(HackControlExtName, 1).Bytes);

            writer.Write(Packet.MakeExtEntry(ExtPlayerListExtName, 2).Bytes);
            writer.Write(Packet.MakeExtEntry(PlayerClickExtName, 1).Bytes);
            writer.Write(Packet.MakeExtEntry(MessageTypesExtName, 1).Bytes);

            writer.Write(Packet.MakeExtEntry(EmoteFixExtName, 1).Bytes);
            writer.Write(Packet.MakeExtEntry(LongerMessagesExtName, 1).Bytes);
            writer.Write(Packet.MakeExtEntry(FullCP437ExtName, 1).Bytes);

            writer.Write(Packet.MakeExtEntry(BlockDefinitionsExtName, 1).Bytes);
            writer.Write(Packet.MakeExtEntry(BlockDefinitionsExtExtName, 2).Bytes);
            writer.Write(Packet.MakeExtEntry(BulkBlockUpdateExtName, 1).Bytes);

            writer.Write(Packet.MakeExtEntry(TextColorsExtName, 1).Bytes);
            writer.Write(Packet.MakeExtEntry(EnvMapAspectExtName, 1).Bytes);
            writer.Write(Packet.MakeExtEntry(ExtPlayerPositionsExtName, 1).Bytes);

            writer.Write(Packet.MakeExtEntry(EntityPropertyExtName, 1).Bytes);
            writer.Write(Packet.MakeExtEntry(TwoWayPingExtName, 1).Bytes);
            writer.Write(Packet.MakeExtEntry(InventoryOrderExtName, 1).Bytes);

            writer.Write(Packet.MakeExtEntry(InstantMOTDExtName, 1).Bytes);
            writer.Write(Packet.MakeExtEntry(FastMapExtName, 1).Bytes);

            // Fix for ClassiCube Client which violates the spec -
            // If server supports version > 1 but client version 1, client should reply with version 1.
            // ClassiCube just doesn't reply at all in that case.
            writer.Write(Packet.MakeExtEntry(EnvMapAppearanceExtName, 2).Bytes);

            // Expect ExtInfo reply from the client
            OpCode extInfoReply = reader.ReadOpCode();

            //Logger.Log(LogType.Debug, "Expected: {0} / Received: {1}", OpCode.ExtInfo, extInfoReply );
            if (extInfoReply != OpCode.ExtInfo)
            {
                Logger.Log(LogType.Debug, "Player {0}: Unexpected ExtInfo reply ({1})", Info.Name, extInfoReply);
                return(false);
            }
            ClientName = reader.ReadString();
            int expectedEntries = reader.ReadInt16();

            // wait for client to send its ExtEntries
            for (int i = 0; i < expectedEntries; i++)
            {
                // Expect ExtEntry replies (0 or more)
                OpCode extEntryReply = reader.ReadOpCode();
                if (extEntryReply != OpCode.ExtEntry)
                {
                    Logger.Log(LogType.Warning, "Player {0} from {1}: Unexpected ExtEntry reply ({2})", Name, IP,
                               extInfoReply);
                    return(false);
                }
                string extName = reader.ReadString();
                int    version = reader.ReadInt32();
                CpeExt ext     = CpeExt.None;

                switch (extName)
                {
                case CustomBlocksExtName:
                    if (version == 1)
                    {
                        ext = CpeExt.CustomBlocks;
                    }
                    break;

                case BlockPermissionsExtName:
                    if (version == 1)
                    {
                        ext = CpeExt.BlockPermissions;
                    }
                    break;

                case ClickDistanceExtName:
                    if (version == 1)
                    {
                        ext = CpeExt.ClickDistance;
                    }
                    break;

                case EnvColorsExtName:
                    if (version == 1)
                    {
                        ext = CpeExt.EnvColors;
                    }
                    break;

                case ChangeModelExtName:
                    if (version == 1)
                    {
                        ext = CpeExt.ChangeModel;
                    }
                    break;

                case EnvMapAppearanceExtName:
                    if (version == 1)
                    {
                        ext = CpeExt.EnvMapAppearance;
                    }
                    if (version == 2)
                    {
                        ext = CpeExt.EnvMapAppearance2;
                    }
                    break;

                case EnvWeatherTypeExtName:
                    if (version == 1)
                    {
                        ext = CpeExt.EnvWeatherType;
                    }
                    break;

                case HeldBlockExtName:
                    if (version == 1)
                    {
                        ext = CpeExt.HeldBlock;
                    }
                    break;

                case ExtPlayerListExtName:
                    if (version == 1)
                    {
                        ext = CpeExt.ExtPlayerList;
                        if (Supports(CpeExt.ExtPlayerList2))
                        {
                            ext = CpeExt.ExtPlayerList2;
                        }
                    }
                    else if (version == 2)
                    {
                        ext = CpeExt.ExtPlayerList2;
                        if (Supports(CpeExt.ExtPlayerList))
                        {
                            supportedExts.Remove(CpeExt.ExtPlayerList);
                        }
                    }
                    break;

                case SelectionCuboidExtName:
                    if (version == 1)
                    {
                        ext = CpeExt.SelectionCuboid;
                    }
                    break;

                case MessageTypesExtName:
                    if (version == 1)
                    {
                        ext = CpeExt.MessageType;
                    }
                    break;

                case HackControlExtName:
                    if (version == 1)
                    {
                        ext = CpeExt.HackControl;
                    }
                    break;

                case EmoteFixExtName:
                    if (version == 1)
                    {
                        ext = CpeExt.EmoteFix;
                    }
                    break;

                case TextHotKeyExtName:
                    if (version == 1)
                    {
                        ext = CpeExt.TextHotKey;
                    }
                    break;

                case PlayerClickExtName:
                    if (version == 1)
                    {
                        ext = CpeExt.PlayerClick;
                    }
                    break;

                case LongerMessagesExtName:
                    if (version == 1)
                    {
                        ext = CpeExt.LongerMessages;
                    }
                    break;

                case FullCP437ExtName:
                    if (version == 1)
                    {
                        ext = CpeExt.FullCP437;
                    }
                    break;

                case BlockDefinitionsExtName:
                    if (version == 1)
                    {
                        ext = CpeExt.BlockDefinitions;
                    }
                    break;

                case BlockDefinitionsExtExtName:
                    if (version == 1)
                    {
                        ext = CpeExt.BlockDefinitionsExt;
                    }
                    if (version == 2)
                    {
                        ext = CpeExt.BlockDefinitionsExt2;
                    }
                    break;

                case BulkBlockUpdateExtName:
                    if (version == 1)
                    {
                        ext = CpeExt.BulkBlockUpdate;
                    }
                    break;

                case TextColorsExtName:
                    if (version == 1)
                    {
                        ext = CpeExt.TextColors;
                    }
                    break;

                case EnvMapAspectExtName:
                    if (version == 1)
                    {
                        ext = CpeExt.EnvMapAspect;
                    }
                    break;

                case ExtPlayerPositionsExtName:
                    if (version == 1)
                    {
                        ext = CpeExt.ExtPlayerPositions;
                    }
                    supportsExtPositions = true;
                    break;

                case EntityPropertyExtName:
                    if (version == 1)
                    {
                        ext = CpeExt.EntityProperty;
                    }
                    break;

                case TwoWayPingExtName:
                    if (version == 1)
                    {
                        ext = CpeExt.TwoWayPing;
                    }
                    break;

                case InventoryOrderExtName:
                    if (version == 1)
                    {
                        ext = CpeExt.InventoryOrder;
                    }
                    break;

                case InstantMOTDExtName:
                    if (version == 1)
                    {
                        ext = CpeExt.InstantMOTD;
                    }
                    break;

                case FastMapExtName:
                    if (version == 1)
                    {
                        ext = CpeExt.FastMap;
                    }
                    break;
                }
                if (ext != CpeExt.None)
                {
                    supportedExts.Add(ext);
                }
            }
            supportsCustomBlocks = Supports(CpeExt.CustomBlocks);
            supportsBlockDefs    = Supports(CpeExt.BlockDefinitions);

            // log client's capabilities
            if (supportedExts.Count > 0)
            {
                Logger.Log(LogType.Debug, "Player {0} is using \"{1}\", supporting: {2}",
                           Info.Name, ClientName, supportedExts.JoinToString(", "));
            }
            else if (supportedExts.Count == 0)
            {
                Kick("Please use the ClassicalSharp client", LeaveReason.InvalidOpcodeKick);
            }

            // if client also supports CustomBlockSupportLevel, figure out what level to use

            // Send CustomBlockSupportLevel
            writer.Write(Packet.MakeCustomBlockSupportLevel(CustomBlocksLevel).Bytes);

            if (Supports(CpeExt.TextColors))
            {
                for (int i = 0; i < Color.ExtColors.Length; i++)
                {
                    if (Color.ExtColors[i].Undefined)
                    {
                        continue;
                    }
                    writer.Write(Packet.MakeSetTextColor(Color.ExtColors[i]).Bytes);
                }
            }

            return(true);
        }