Иконка ресурса

FREE QRGenerator : 1.0.0 1.0.0

Нет прав для скачивания
C#:
using Oxide.Game.Rust.Cui;
using System;
using System.Collections.Generic;
using System.Text;
using UnityEngine;

namespace Oxide.Plugins
{
    [Info("QRGenerator", "NINJA WORKS", "1.0.0")]
    [Description("Displays URL with QR code using /qr command")]
    public class QRGenerator : RustPlugin
    {
        #region Constants

        private const string UI_OVERLAY = "QRGenerator_Overlay";
        private const string UI_PANEL = "QRGenerator_Panel";
        private const string UI_QR = "QRGenerator_QR";

        private const string COMMAND_NAME = "qr";

        private const string COLOR_OVERLAY = "0 0 0 0.85";
        private const string COLOR_BACKGROUND = "0.1 0.1 0.1 0.95";
        private const string COLOR_TITLE = "1 1 1 1";
        private const string COLOR_URL = "0.3 0.8 1 1";
        private const string COLOR_HINT = "0.6 0.6 0.6 1";
        private const string COLOR_BUTTON = "0.6 0.2 0.2 1";
        private const string COLOR_QR_MODULE = "0 0 0 1";
        private const string COLOR_QR_BACKGROUND = "1 1 1 1";

        private const float QR_HEIGHT = 0.45f;
        private const float QR_ASPECT_RATIO = 1f;
        private const float QR_BOTTOM = 0.28f;

        private const string MSG_USAGE = "<color=#ff6666>Usage:</color> /qr <URL>";
        private const string MSG_INVALID = "<color=#ff6666>Error:</color> Please enter a valid URL (http:// or https://)";
        private const string MSG_TITLE = "Open URL with QR Code";
        private const string MSG_INSTRUCTION = "Scan the QR code with your smartphone";
        private const string MSG_HINT = "* To copy the URL, press F1 to open the console";
        private const string MSG_CLOSE = "Close";

        #endregion

        #region Hooks

        private void Init()
        {
            cmd.AddChatCommand(COMMAND_NAME, this, nameof(CmdTestURL));
        }

        private void Unload()
        {
            foreach (var player in BasePlayer.activePlayerList)
                CuiHelper.DestroyUi(player, UI_OVERLAY);
        }

        #endregion

        #region Commands

        private void CmdTestURL(BasePlayer player, string command, string[] args)
        {
            if (args.Length == 0)
            {
                player.ChatMessage(MSG_USAGE);
                return;
            }

            string url = args[0];

            if (!url.StartsWith("http://") && !url.StartsWith("https://"))
            {
                player.ChatMessage(MSG_INVALID);
                return;
            }

            ShowUI(player, url);
        }

        [ConsoleCommand("qr.close")]
        private void CmdClose(ConsoleSystem.Arg arg)
        {
            var player = arg.Player();
            if (player != null)
                CuiHelper.DestroyUi(player, UI_OVERLAY);
        }

        #endregion

        #region UI

        private void ShowUI(BasePlayer player, string url)
        {
            CuiHelper.DestroyUi(player, UI_OVERLAY);

            var container = new CuiElementContainer();

            container.Add(new CuiPanel
            {
                Image = { Color = COLOR_OVERLAY },
                RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1" },
                CursorEnabled = true
            }, "Overlay", UI_OVERLAY);

            container.Add(new CuiPanel
            {
                Image = { Color = COLOR_BACKGROUND },
                RectTransform = { AnchorMin = "0.3 0.15", AnchorMax = "0.7 0.85" }
            }, UI_OVERLAY, UI_PANEL);

            container.Add(new CuiLabel
            {
                Text = { Text = MSG_TITLE, FontSize = 20, Align = TextAnchor.MiddleCenter, Color = COLOR_TITLE },
                RectTransform = { AnchorMin = "0 0.9", AnchorMax = "1 0.98" }
            }, UI_PANEL);

            container.Add(new CuiLabel
            {
                Text = { Text = MSG_INSTRUCTION, FontSize = 14, Align = TextAnchor.MiddleCenter, Color = COLOR_HINT },
                RectTransform = { AnchorMin = "0 0.83", AnchorMax = "1 0.9" }
            }, UI_PANEL);

            float qrHeight = QR_HEIGHT;
            float qrWidth = qrHeight * QR_ASPECT_RATIO;
            float qrLeft = 0.5f - (qrWidth / 2f);
            float qrRight = 0.5f + (qrWidth / 2f);
            float qrBottom = QR_BOTTOM;
            float qrTop = qrBottom + qrHeight;

            container.Add(new CuiPanel
            {
                Image = { Color = COLOR_QR_BACKGROUND },
                RectTransform = { AnchorMin = $"{qrLeft} {qrBottom}", AnchorMax = $"{qrRight} {qrTop}" }
            }, UI_PANEL, UI_QR);

            var qrMatrix = QRCodeGen.Generate(url);
            DrawQR(container, qrMatrix);

            container.Add(new CuiLabel
            {
                Text = { Text = url, FontSize = 11, Align = TextAnchor.MiddleCenter, Color = COLOR_URL },
                RectTransform = { AnchorMin = "0.02 0.18", AnchorMax = "0.98 0.26" }
            }, UI_PANEL);

            container.Add(new CuiLabel
            {
                Text = { Text = MSG_HINT, FontSize = 10, Align = TextAnchor.MiddleCenter, Color = COLOR_HINT },
                RectTransform = { AnchorMin = "0 0.1", AnchorMax = "1 0.17" }
            }, UI_PANEL);

            container.Add(new CuiButton
            {
                Button = { Command = "qr.close", Color = COLOR_BUTTON },
                RectTransform = { AnchorMin = "0.35 0.02", AnchorMax = "0.65 0.09" },
                Text = { Text = MSG_CLOSE, FontSize = 14, Align = TextAnchor.MiddleCenter, Color = "1 1 1 1" }
            }, UI_PANEL);

            CuiHelper.AddUi(player, container);
        }

        private void DrawQR(CuiElementContainer container, bool[,] matrix)
        {
            int size = matrix.GetLength(0);
            float moduleSize = 1f / (size + 2);
            float margin = moduleSize;

            for (int y = 0; y < size; y++)
            {
                for (int x = 0; x < size; x++)
                {
                    if (matrix[x, y])
                    {
                        float xMin = margin + (x * moduleSize);
                        float yMin = margin + ((size - 1 - y) * moduleSize);

                        container.Add(new CuiPanel
                        {
                            Image = { Color = COLOR_QR_MODULE },
                            RectTransform = {
                                AnchorMin = $"{xMin} {yMin}",
                                AnchorMax = $"{xMin + moduleSize} {yMin + moduleSize}"
                            }
                        }, UI_QR);
                    }
                }
            }
        }

        #endregion

        #region QR Code Generator

        private static class QRCodeGen
        {
            private static readonly int[] EXP = new int[256];
            private static readonly int[] LOG = new int[256];

            static QRCodeGen()
            {
                int v = 1;
                for (int i = 0; i < 256; i++)
                {
                    EXP[i] = v;
                    LOG[v] = i;
                    v <<= 1;
                    if (v >= 256) v ^= 0x11D;
                }
            }

            public static bool[,] Generate(string text)
            {
                byte[] bytes = Encoding.UTF8.GetBytes(text);
                int ver = GetVersion(bytes.Length);
                byte[] data = Encode(text);
                int size = 17 + ver * 4;

                var matrix = new bool[size, size];
                var reserved = new bool[size, size];

                AddFinders(matrix, reserved, size);
                AddTiming(matrix, reserved, size);
                
                int[] alignPos = GetAlignPositions(ver);
                if (alignPos.Length > 0)
                    AddAlignments(matrix, reserved, alignPos, size);
                
                if (ver >= 7)
                    ReserveVersionArea(reserved, size);
                
                ReserveFormat(reserved, size);
                PlaceData(matrix, reserved, data, size);
                ApplyMask(matrix, reserved, size);
                AddFormat(matrix, size);
                
                if (ver >= 7)
                    AddVersionInfo(matrix, ver, size);

                return matrix;
            }

            private static byte[] Encode(string text)
            {
                byte[] bytes = Encoding.UTF8.GetBytes(text);
                int ver = GetVersion(bytes.Length);
                int charCountBits = ver <= 9 ? 8 : 16;
                
                var bits = new List<bool>();

                AddBits(bits, 4, 4);
                AddBits(bits, bytes.Length, charCountBits);
                foreach (byte b in bytes) AddBits(bits, b, 8);
                int cap = GetCapacity(ver);
                int remaining = cap * 8 - bits.Count;
                AddBits(bits, 0, Math.Min(4, remaining));
                
                while (bits.Count % 8 != 0) bits.Add(false);

                bool tog = true;
                while (bits.Count < cap * 8)
                {
                    AddBits(bits, tog ? 236 : 17, 8);
                    tog = !tog;
                }

                byte[] result = new byte[bits.Count / 8];
                for (int i = 0; i < result.Length; i++)
                    for (int j = 0; j < 8; j++)
                        if (bits[i * 8 + j]) result[i] |= (byte)(128 >> j);

                return AddEC(result, ver);
            }

            private static void AddBits(List<bool> bits, int val, int cnt)
            {
                for (int i = cnt - 1; i >= 0; i--)
                    bits.Add(((val >> i) & 1) == 1);
            }

            private static int GetVersion(int dataLen)
            {
                if (dataLen <= 17) return 1;
                if (dataLen <= 32) return 2;
                if (dataLen <= 53) return 3;
                if (dataLen <= 78) return 4;
                if (dataLen <= 106) return 5;
                if (dataLen <= 134) return 6;
                if (dataLen <= 154) return 7;
                if (dataLen <= 192) return 8;
                if (dataLen <= 230) return 9;
                if (dataLen <= 271) return 10;
                if (dataLen <= 321) return 11;
                if (dataLen <= 367) return 12;
                if (dataLen <= 425) return 13;
                if (dataLen <= 458) return 14;
                if (dataLen <= 520) return 15;
                if (dataLen <= 586) return 16;
                if (dataLen <= 644) return 17;
                if (dataLen <= 718) return 18;
                if (dataLen <= 792) return 19;
                if (dataLen <= 858) return 20;
                return 20;
            }

            private static int GetCapacity(int ver)
            {
                int[] caps = { 0, 19, 34, 55, 80, 108, 136, 156, 194, 232, 274, 324, 370, 428, 461, 523, 589, 647, 721, 795, 861 };
                return ver < caps.Length ? caps[ver] : caps[caps.Length - 1];
            }

            private static int[] GetAlignPositions(int ver)
            {
                if (ver == 1) return new int[0];
                
                int[][] positions = {
                    null,
                    new int[0],
                    new int[] { 6, 18 },
                    new int[] { 6, 22 },
                    new int[] { 6, 26 },
                    new int[] { 6, 30 },
                    new int[] { 6, 34 },
                    new int[] { 6, 22, 38 },
                    new int[] { 6, 24, 42 },
                    new int[] { 6, 26, 46 },
                    new int[] { 6, 28, 50 },
                    new int[] { 6, 30, 54 },
                    new int[] { 6, 32, 58 },
                    new int[] { 6, 34, 62 },
                    new int[] { 6, 26, 46, 66 },
                    new int[] { 6, 26, 48, 70 },
                    new int[] { 6, 26, 50, 74 },
                    new int[] { 6, 30, 54, 78 },
                    new int[] { 6, 30, 56, 82 },
                    new int[] { 6, 30, 58, 86 },
                    new int[] { 6, 34, 62, 90 },
                };
                
                return ver < positions.Length ? positions[ver] : positions[positions.Length - 1];
            }

            private static byte[] AddEC(byte[] data, int ver)
            {
                int cap = GetCapacity(ver);
                byte[] padded = new byte[cap];
                Array.Copy(data, padded, Math.Min(data.Length, cap));

                int[] blockInfo = GetBlockInfo(ver);
                int numBlocks1 = blockInfo[0];
                int dataPerBlock1 = blockInfo[1];
                int numBlocks2 = blockInfo[2];
                int dataPerBlock2 = blockInfo[3];
                int ecPerBlock = blockInfo[4];

                var dataBlocks = new List<byte[]>();
                var ecBlocks = new List<byte[]>();
                int offset = 0;

                for (int i = 0; i < numBlocks1; i++)
                {
                    byte[] block = new byte[dataPerBlock1];
                    Array.Copy(padded, offset, block, 0, dataPerBlock1);
                    offset += dataPerBlock1;
                    dataBlocks.Add(block);
                    ecBlocks.Add(CalculateEC(block, ecPerBlock));
                }

                for (int i = 0; i < numBlocks2; i++)
                {
                    byte[] block = new byte[dataPerBlock2];
                    Array.Copy(padded, offset, block, 0, dataPerBlock2);
                    offset += dataPerBlock2;
                    dataBlocks.Add(block);
                    ecBlocks.Add(CalculateEC(block, ecPerBlock));
                }

                var result = new List<byte>();
                int maxDataLen = Math.Max(dataPerBlock1, dataPerBlock2);
                
                for (int i = 0; i < maxDataLen; i++)
                {
                    foreach (var block in dataBlocks)
                    {
                        if (i < block.Length)
                            result.Add(block[i]);
                    }
                }

                for (int i = 0; i < ecPerBlock; i++)
                {
                    foreach (var block in ecBlocks)
                    {
                        result.Add(block[i]);
                    }
                }

                return result.ToArray();
            }

            private static int[] GetBlockInfo(int ver)
            {
                int[][] info = {
                    null,
                    new[] { 1, 19, 0, 0, 7 },
                    new[] { 1, 34, 0, 0, 10 },
                    new[] { 1, 55, 0, 0, 15 },
                    new[] { 1, 80, 0, 0, 20 },
                    new[] { 1, 108, 0, 0, 26 },
                    new[] { 2, 68, 0, 0, 18 },
                    new[] { 2, 78, 0, 0, 20 },
                    new[] { 2, 97, 0, 0, 24 },
                    new[] { 2, 116, 0, 0, 30 },
                    new[] { 2, 68, 2, 69, 18 },
                    new[] { 4, 81, 0, 0, 20 },
                    new[] { 2, 92, 2, 93, 24 },
                    new[] { 4, 107, 0, 0, 26 },
                    new[] { 3, 115, 1, 116, 30 },
                    new[] { 5, 87, 1, 88, 22 },
                    new[] { 5, 98, 1, 99, 24 },
                    new[] { 1, 107, 5, 108, 28 },
                    new[] { 5, 120, 1, 121, 30 },
                    new[] { 3, 113, 4, 114, 28 },
                    new[] { 3, 107, 5, 108, 28 },
                };
                return ver < info.Length ? info[ver] : info[info.Length - 1];
            }

            private static byte[] CalculateEC(byte[] data, int ecCount)
            {
                int[] gen = GetGenerator(ecCount);
                int[] msg = new int[data.Length + ecCount];
                for (int i = 0; i < data.Length; i++) msg[i] = data[i];

                for (int i = 0; i < data.Length; i++)
                {
                    int c = msg[i];
                    if (c != 0)
                        for (int j = 0; j < gen.Length; j++)
                            msg[i + j] ^= Mul(gen[j], c);
                }

                byte[] result = new byte[ecCount];
                for (int i = 0; i < ecCount; i++)
                    result[i] = (byte)msg[data.Length + i];

                return result;
            }

            private static int[] GetGenerator(int deg)
            {
                int[] r = { 1 };
                for (int i = 0; i < deg; i++)
                {
                    int[] t = new int[r.Length + 1];
                    for (int j = 0; j < r.Length; j++)
                    {
                        t[j] ^= r[j];
                        t[j + 1] ^= Mul(r[j], EXP[i]);
                    }
                    r = t;
                }
                return r;
            }

            private static int Mul(int a, int b)
            {
                if (a == 0 || b == 0) return 0;
                return EXP[(LOG[a] + LOG[b]) % 255];
            }

            private static void AddFinders(bool[,] m, bool[,] r, int s)
            {
                int[] offsets = { 0, s - 7 };
                foreach (int ox in new[] { 0, s - 7 })
                {
                    foreach (int oy in new[] { 0, s - 7 })
                    {
                        if (ox != 0 && oy != 0) continue;
                        for (int dy = -1; dy <= 7; dy++)
                        {
                            for (int dx = -1; dx <= 7; dx++)
                            {
                                int x = ox + dx, y = oy + dy;
                                if (x < 0 || y < 0 || x >= s || y >= s) continue;

                                bool blk = dx >= 0 && dx <= 6 && dy >= 0 && dy <= 6 &&
                                    (dx == 0 || dx == 6 || dy == 0 || dy == 6 ||
                                    (dx >= 2 && dx <= 4 && dy >= 2 && dy <= 4));

                                m[x, y] = blk;
                                r[x, y] = true;
                            }
                        }
                    }
                }
            }

            private static void AddTiming(bool[,] m, bool[,] r, int s)
            {
                for (int i = 8; i < s - 8; i++)
                {
                    bool blk = i % 2 == 0;
                    m[i, 6] = blk; m[6, i] = blk;
                    r[i, 6] = true; r[6, i] = true;
                }
            }

            private static void AddAlignments(bool[,] m, bool[,] r, int[] positions, int size)
            {
                if (positions.Length == 0) return;
                
                foreach (int cy in positions)
                {
                    foreach (int cx in positions)
                    {
                        if ((cx <= 8 && cy <= 8) ||
                            (cx <= 8 && cy >= size - 9) ||
                            (cx >= size - 9 && cy <= 8))
                            continue;
                        
                        for (int dy = -2; dy <= 2; dy++)
                        {
                            for (int dx = -2; dx <= 2; dx++)
                            {
                                int x = cx + dx;
                                int y = cy + dy;
                                if (x < 0 || y < 0 || x >= size || y >= size) continue;
                                
                                bool blk = dx == -2 || dx == 2 || dy == -2 || dy == 2 || (dx == 0 && dy == 0);
                                m[x, y] = blk;
                                r[x, y] = true;
                            }
                        }
                    }
                }
            }

            private static void ReserveFormat(bool[,] r, int s)
            {
                for (int i = 0; i < 9; i++) { r[i, 8] = true; r[8, i] = true; }
                for (int i = 0; i < 8; i++) { r[s - 1 - i, 8] = true; r[8, s - 1 - i] = true; }
                r[8, s - 8] = true;
            }

            private static void ReserveVersionArea(bool[,] r, int s)
            {
                for (int i = 0; i < 6; i++)
                {
                    for (int j = 0; j < 3; j++)
                    {
                        r[s - 11 + j, i] = true;
                        r[i, s - 11 + j] = true;
                    }
                }
            }

            private static void AddVersionInfo(bool[,] m, int ver, int s)
            {
                int[] versionBits = {
                    0, 0, 0, 0, 0, 0, 0,
                    0x07C94, 0x085BC, 0x09A99, 0x0A4D3, 0x0BBF6, 0x0C762, 0x0D847, 0x0E60D,
                    0x0F928, 0x10B78, 0x1145D, 0x12A17, 0x13532, 0x149A6
                };
                
                if (ver < 7 || ver >= versionBits.Length) return;
                
                int bits = versionBits[ver];
                
                for (int i = 0; i < 18; i++)
                {
                    bool bit = ((bits >> i) & 1) == 1;
                    int row = i / 3;
                    int col = i % 3;
                    
                    m[s - 11 + col, row] = bit;
                    m[row, s - 11 + col] = bit;
                }
            }

            private static void PlaceData(bool[,] m, bool[,] r, byte[] d, int s)
            {
                int bi = 0, total = d.Length * 8;
                bool upward = true;
                
                for (int col = s - 1; col >= 1; col -= 2)
                {
                    if (col == 6) col = 5;
                    
                    for (int i = 0; i < s; i++)
                    {
                        int row = upward ? (s - 1 - i) : i;
                        
                        for (int c = 0; c < 2; c++)
                        {
                            int x = col - c;
                            int y = row;
                            
                            if (!r[x, y] && bi < total)
                            {
                                m[x, y] = ((d[bi / 8] >> (7 - bi % 8)) & 1) == 1;
                                bi++;
                            }
                        }
                    }
                    upward = !upward;
                }
            }

            private static void ApplyMask(bool[,] m, bool[,] r, int s)
            {
                for (int y = 0; y < s; y++)
                    for (int x = 0; x < s; x++)
                        if (!r[x, y] && (x + y) % 2 == 0)
                            m[x, y] = !m[x, y];
            }

            private static void AddFormat(bool[,] m, int s)
            {
                int fmt = 0x77C4;
                int[] hp = { 0, 1, 2, 3, 4, 5, 7, 8 };
                int[] vp = { 8, 7, 5, 4, 3, 2, 1, 0 };

                for (int i = 0; i < 8; i++)
                {
                    bool b = ((fmt >> (14 - i)) & 1) == 1;
                    m[hp[i], 8] = b;
                    m[8, s - 1 - i] = b;
                }
                for (int i = 0; i < 7; i++)
                {
                    bool b = ((fmt >> (6 - i)) & 1) == 1;
                    m[8, vp[i]] = b;
                    m[s - 8 + i, 8] = b;
                }
                m[8, s - 8] = true;
            }
        }

        #endregion
    }
}

Автор
15FPS
Скачиваний
0
Просмотры
1
Первый выпуск
Обновление
Оценка
0.00 звёзд 0 оценок
Сверху