Exemple #1
0
        //If using async not handing all approach then we need to call this directly.
        public static void InitializeUnpackFields(Archive streamLoader)
        {
            spriteCache = new Dictionary <long, Sprite>(50000);
            stream      = new Default317Buffer(streamLoader.decompressFile("data"));
            parentId    = -1;
            int interfaceCount = stream.getUnsignedLEShort();

            cache = new RSInterface[interfaceCount];
        }
        //Returns true when finished.
        public async Task HandlePendingInterfaceUnpackingAsync()
        {
            Archive archiveInterface = requestArchive(3, "interface", "interface", 0, 35);
            Archive archiveMedia     = requestArchive(4, "2d graphics", "media", 0, 40);

            GameFont fontFancy = new GameFont("q8_full", archiveTitle, true);

            GameFont[] fonts = new GameFont[] { fontSmall, fontPlain, fontBold, fontFancy };

            drawLoadingText(95, "Unpacking interfaces");

            RSInterface.InitializeUnpackFields(archiveInterface);
            await TaskDelayFactory.Create(1);

            long currentMemory = GC.GetTotalMemory(false);

            //There are so many interfaces that we'd be waiting a minute if we unpacked them 1 per frame.
            for (int i = 0; i < int.MaxValue; i++)
            {
                //This will break us out eventually.
                if (!RSInterface.unpack(archiveInterface, fonts, archiveMedia, false))
                {
                    break;
                }

                //If we've doubled the allocated memory, we should early break from this.
                if (GC.GetTotalMemory(false) > currentMemory * 1.5)
                {
                    await TaskDelayFactory.Create(1);
                }

                if (i % 200 == 0)
                {
                    await TaskDelayFactory.Create(1);
                }
            }

            await TaskDelayFactory.Create(1);
        }
        public IEnumerator StartupCoroutine()
        {
            if (!wasClientStartupCalled)
            {
                wasClientStartupCalled = true;
            }
            else
            {
                throw new InvalidOperationException($"Failed. Cannot call startup on Client multiple times.");
            }

            drawLoadingText(20, "Starting up");

            if (clientRunning)
            {
                rsAlreadyLoaded = true;
                yield break;
            }

            clientRunning = true;
            bool   validHost = true;
            String s         = getDocumentBaseHost();

            if (s.EndsWith("jagex.com"))
            {
                validHost = true;
            }
            if (s.EndsWith("runescape.com"))
            {
                validHost = true;
            }
            if (s.EndsWith("192.168.1.2"))
            {
                validHost = true;
            }
            if (s.EndsWith("192.168.1.229"))
            {
                validHost = true;
            }
            if (s.EndsWith("192.168.1.228"))
            {
                validHost = true;
            }
            if (s.EndsWith("192.168.1.227"))
            {
                validHost = true;
            }
            if (s.EndsWith("192.168.1.226"))
            {
                validHost = true;
            }
            if (s.EndsWith("127.0.0.1"))
            {
                validHost = true;
            }
            if (!validHost)
            {
                genericLoadingError = true;
                yield break;
            }

            if (signlink.cache_dat != null)
            {
                for (int i = 0; i < 5; i++)
                {
                    caches[i] = new FileCache(signlink.cache_dat, signlink.cache_idx[i], i + 1);
                }
            }

            connectServer();
            archiveTitle = requestArchive(1, "title screen", "title", expectedCRCs[1], 25);
            fontSmall    = new GameFont("p11_full", archiveTitle, false);
            fontPlain    = new GameFont("p12_full", archiveTitle, false);
            fontBold     = new GameFont("b12_full", archiveTitle, false);
            GameFont fontFancy = new GameFont("q8_full", archiveTitle, true);

            drawLogo();
            loadTitleScreen();
            Archive archiveConfig    = requestArchive(2, "config", "config", expectedCRCs[2], 30);
            Archive archiveInterface = requestArchive(3, "interface", "interface", expectedCRCs[3], 35);
            Archive archiveMedia     = requestArchive(4, "2d graphics", "media", expectedCRCs[4], 40);
            Archive archiveTextures  = requestArchive(6, "textures", "textures", expectedCRCs[6], 45);
            Archive archiveWord      = requestArchive(7, "chat system", "wordenc", expectedCRCs[7], 50);
            Archive archiveSounds    = requestArchive(8, "sound effects", "sounds", expectedCRCs[8], 55);

            tileFlags       = new byte[4, 104, 104];
            intGroundArray  = CollectionUtilities.Create3DJaggedArray <int>(4, 105, 105);
            worldController = new WorldController(intGroundArray);
            for (int z = 0; z < 4; z++)
            {
                currentCollisionMap[z] = new CollisionMap();
            }

            minimapImage = new Sprite(512, 512);
            Archive archiveVersions = requestArchive(5, "update list", "versionlist", expectedCRCs[5], 60);

            drawLoadingText(60, "Connecting to update server");
            StartOnDemandFetcher(archiveVersions);
            Animation.init(onDemandFetcher.getAnimCount());
            Model.init(onDemandFetcher.fileCount(0), onDemandFetcher);

            songChanging = true;
            onDemandFetcher.request(2, nextSong);
            while (onDemandFetcher.immediateRequestCount() > 0)
            {
                processOnDemandQueue();

                yield return(new WaitForSeconds(0.1f));

                if (onDemandFetcher.failedRequests > 3)
                {
                    loadError();
                    yield break;
                }
            }

            drawLoadingText(65, "Requesting animations");
            int fileRequestCount = onDemandFetcher.fileCount(1);

            for (int id = 0; id < fileRequestCount; id++)
            {
                onDemandFetcher.request(1, id);
            }

            while (onDemandFetcher.immediateRequestCount() > 0)
            {
                int remaining = fileRequestCount - onDemandFetcher.immediateRequestCount();
                if (remaining > 0)
                {
                    drawLoadingText(65, "Loading animations - " + (remaining * 100) / fileRequestCount + "%");
                }

                try
                {
                    processOnDemandQueue();
                }
                catch (Exception e)
                {
                    Console.WriteLine($"Failed to process animation demand queue. Reason: {e.Message} \n Stack: {e.StackTrace}");
                    signlink.reporterror($"Failed to process animation demand queue. Reason: {e.Message} \n Stack: {e.StackTrace}");
                    throw;
                }

                yield return(new WaitForSeconds(0.1f));

                if (onDemandFetcher.failedRequests > 3)
                {
                    loadError();
                    yield break;
                }
            }

            drawLoadingText(70, "Requesting models");
            fileRequestCount = onDemandFetcher.fileCount(0);
            for (int id = 0; id < fileRequestCount; id++)
            {
                int modelId = onDemandFetcher.getModelId(id);
                if ((modelId & 1) != 0)
                {
                    onDemandFetcher.request(0, id);
                }
            }

            fileRequestCount = onDemandFetcher.immediateRequestCount();
            while (onDemandFetcher.immediateRequestCount() > 0)
            {
                int remaining = fileRequestCount - onDemandFetcher.immediateRequestCount();
                if (remaining > 0)
                {
                    drawLoadingText(70, "Loading models - " + (remaining * 100) / fileRequestCount + "%");
                }
                processOnDemandQueue();

                yield return(new WaitForSeconds(0.1f));
            }

            GC.Collect();
            if (caches[0] != null)
            {
                drawLoadingText(75, "Requesting maps");
                onDemandFetcher.request(3, onDemandFetcher.getMapId(0, 47, 48));
                yield return(null);

                onDemandFetcher.request(3, onDemandFetcher.getMapId(1, 47, 48));
                yield return(null);

                onDemandFetcher.request(3, onDemandFetcher.getMapId(0, 48, 48));
                yield return(null);

                onDemandFetcher.request(3, onDemandFetcher.getMapId(1, 48, 48));
                yield return(null);

                onDemandFetcher.request(3, onDemandFetcher.getMapId(0, 49, 48));
                yield return(null);

                onDemandFetcher.request(3, onDemandFetcher.getMapId(1, 49, 48));
                yield return(null);

                onDemandFetcher.request(3, onDemandFetcher.getMapId(0, 47, 47));
                yield return(null);

                onDemandFetcher.request(3, onDemandFetcher.getMapId(1, 47, 47));
                yield return(null);

                onDemandFetcher.request(3, onDemandFetcher.getMapId(0, 48, 47));
                yield return(null);

                onDemandFetcher.request(3, onDemandFetcher.getMapId(1, 48, 47));
                yield return(null);

                onDemandFetcher.request(3, onDemandFetcher.getMapId(0, 48, 148));
                yield return(null);

                onDemandFetcher.request(3, onDemandFetcher.getMapId(1, 48, 148));
                yield return(null);

                fileRequestCount = onDemandFetcher.immediateRequestCount();
                while (onDemandFetcher.immediateRequestCount() > 0)
                {
                    int remaining = fileRequestCount - onDemandFetcher.immediateRequestCount();
                    if (remaining > 0)
                    {
                        drawLoadingText(75, "Loading maps - " + (remaining * 100) / fileRequestCount + "%");
                    }
                    processOnDemandQueue();

                    yield return(new WaitForSeconds(0.1f));
                }
            }

            fileRequestCount = onDemandFetcher.fileCount(0);
            for (int id = 0; id < fileRequestCount; id++)
            {
                int  modelId  = onDemandFetcher.getModelId(id);
                byte priority = 0;
                if ((modelId & 8) != 0)
                {
                    priority = 10;
                }
                else if ((modelId & 0x20) != 0)
                {
                    priority = 9;
                }
                else if ((modelId & 0x10) != 0)
                {
                    priority = 8;
                }
                else if ((modelId & 0x40) != 0)
                {
                    priority = 7;
                }
                else if ((modelId & 0x80) != 0)
                {
                    priority = 6;
                }
                else if ((modelId & 2) != 0)
                {
                    priority = 5;
                }
                else if ((modelId & 4) != 0)
                {
                    priority = 4;
                }
                if ((modelId & 1) != 0)
                {
                    priority = 3;
                }
                if (priority != 0)
                {
                    onDemandFetcher.setPriority(priority, 0, id);
                }
            }

            onDemandFetcher.preloadRegions(membersWorld);

            //Remove low memory check.
            int count = onDemandFetcher.fileCount(2);

            for (int id = 1; id < count; id++)
            {
                if (onDemandFetcher.midiIdEqualsOne(id))
                {
                    onDemandFetcher.setPriority((byte)1, 2, id);
                }
            }

            drawLoadingText(80, "Unpacking media");

            //Default cache can cause some errors, so wecan surpress them here.
            try
            {
                InitializeUnpackedMedia(archiveMedia);
            }
            catch (Exception e)
            {
                Console.WriteLine($"Media Error: {e}");
            }

            drawLoadingText(83, "Unpacking textures");
            Rasterizer.unpackTextures(archiveTextures);
            Rasterizer.calculatePalette(0.80000000000000004D);
            Rasterizer.resetTextures();
            drawLoadingText(86, "Unpacking config");
            AnimationSequence.unpackConfig(archiveConfig);
            GameObjectDefinition.load(archiveConfig);
            FloorDefinition.load(archiveConfig);
            ItemDefinition.load(archiveConfig);
            EntityDefinition.load(archiveConfig);
            IdentityKit.load(archiveConfig);
            SpotAnimation.load(archiveConfig);
            Varp.load(archiveConfig);
            VarBit.load(archiveConfig);
            ItemDefinition.membersWorld = membersWorld;

            //Removed low memory check
            drawLoadingText(90, "Unpacking sounds");
            byte[]           soundData = archiveSounds.decompressFile("sounds.dat");
            Default317Buffer stream    = new Default317Buffer(soundData);

            Effect.load(stream);

            drawLoadingText(95, "Unpacking interfaces");
            GameFont[] fonts = { fontSmall, fontPlain, fontBold, fontFancy };
            RSInterface.unpack(archiveInterface, fonts, archiveMedia);
            drawLoadingText(100, "Preparing game engine");
            for (int _y = 0; _y < 33; _y++)
            {
                int firstXOfLine = 999;
                int lastXOfLine  = 0;
                for (int _x = 0; _x < 34; _x++)
                {
                    if (minimapBackgroundImage.pixels[_x + _y * minimapBackgroundImage.width] == 0)
                    {
                        if (firstXOfLine == 999)
                        {
                            firstXOfLine = _x;
                        }
                        continue;
                    }

                    if (firstXOfLine == 999)
                    {
                        continue;
                    }
                    lastXOfLine = _x;
                    break;
                }

                compassHingeSize[_y] = firstXOfLine;
                compassWidthMap[_y]  = lastXOfLine - firstXOfLine;
            }

            for (int _y = 5; _y < 156; _y++)
            {
                int min = 999;
                int max = 0;
                for (int _x = 25; _x < 172; _x++)
                {
                    if (minimapBackgroundImage.pixels[_x + _y * minimapBackgroundImage.width] == 0 &&
                        (_x > 34 || _y > 34))
                    {
                        if (min == 999)
                        {
                            min = _x;
                        }
                        continue;
                    }

                    if (min == 999)
                    {
                        continue;
                    }
                    max = _x;
                    break;
                }

                minimapLeft[_y - 5]      = min - 25;
                minimapLineWidth[_y - 5] = max - min;
            }

            Rasterizer.setBounds(479, 96);
            chatboxLineOffsets = Rasterizer.lineOffsets;
            Rasterizer.setBounds(190, 261);
            sidebarOffsets = Rasterizer.lineOffsets;
            Rasterizer.setBounds(512, 334);
            viewportOffsets = Rasterizer.lineOffsets;

            int[] ai = new int[9];
            for (int i8 = 0; i8 < 9; i8++)
            {
                int k8 = 128 + i8 * 32 + 15;
                int l8 = 600 + k8 * 3;
                int i9 = Rasterizer.SINE[k8];
                ai[i8] = l8 * i9 >> 16;
            }

            WorldController.setupViewport(500, 800, 512, 334, ai);

            GameObject.clientInstance           = this;
            GameObjectDefinition.clientInstance = this;
            EntityDefinition.clientInstance     = this;

            //TODO: Disabled censor
            //Censor.load(archiveWord);
            mouseDetection = new MouseDetection(this);
            //startRunnable(mouseDetection, 10);
            yield break;
        }
        public static void unpack(Archive streamLoader, GameFont[] fonts, Archive mediaArchive)
        {
            spriteCache = new Cache(50000);
            Default317Buffer stream = new Default317Buffer(streamLoader.decompressFile("data"));
            int parentId            = -1;
            int interfaceCount      = stream.getUnsignedLEShort();

            cache = new RSInterface[interfaceCount];
            while (stream.position < stream.buffer.Length)
            {
                int id = stream.getUnsignedLEShort();
                if (id == 65535)
                {
                    parentId = stream.getUnsignedLEShort();
                    id       = stream.getUnsignedLEShort();
                }

                RSInterface rsInterface = cache[id] = new RSInterface();
                rsInterface.id           = id;
                rsInterface.parentID     = parentId;
                rsInterface.type         = stream.getUnsignedByte();
                rsInterface.actionType   = stream.getUnsignedByte();
                rsInterface.contentType  = stream.getUnsignedLEShort();
                rsInterface.width        = stream.getUnsignedLEShort();
                rsInterface.height       = stream.getUnsignedLEShort();
                rsInterface.alpha        = (byte)stream.getUnsignedByte();
                rsInterface.hoveredPopup = stream.getUnsignedByte();
                if (rsInterface.hoveredPopup != 0)
                {
                    rsInterface.hoveredPopup = (rsInterface.hoveredPopup - 1 << 8) + stream.getUnsignedByte();
                }
                else
                {
                    rsInterface.hoveredPopup = -1;
                }
                int conditionCount = stream.getUnsignedByte();
                if (conditionCount > 0)
                {
                    rsInterface.conditionType  = new int[conditionCount];
                    rsInterface.conditionValue = new int[conditionCount];
                    for (int c = 0; c < conditionCount; c++)
                    {
                        rsInterface.conditionType[c]  = stream.getUnsignedByte();
                        rsInterface.conditionValue[c] = stream.getUnsignedLEShort();
                    }
                }

                int opcodeCount = stream.getUnsignedByte();
                if (opcodeCount > 0)
                {
                    rsInterface.opcodes = new int[opcodeCount][];
                    for (int c = 0; c < opcodeCount; c++)
                    {
                        int subOpcodeCount = stream.getUnsignedLEShort();
                        rsInterface.opcodes[c] = new int[subOpcodeCount];
                        for (int s = 0; s < subOpcodeCount; s++)
                        {
                            rsInterface.opcodes[c][s] = stream.getUnsignedLEShort();
                        }
                    }
                }

                if (rsInterface.type == 0)
                {
                    rsInterface.scrollMax = stream.getUnsignedLEShort();
                    rsInterface.hoverOnly = stream.getUnsignedByte() == 1;
                    int childCount = stream.getUnsignedLEShort();
                    rsInterface.children = new int[childCount];
                    rsInterface.childX   = new int[childCount];
                    rsInterface.childY   = new int[childCount];
                    for (int child = 0; child < childCount; child++)
                    {
                        rsInterface.children[child] = stream.getUnsignedLEShort();
                        rsInterface.childX[child]   = stream.getShort();
                        rsInterface.childY[child]   = stream.getShort();
                    }
                }

                if (rsInterface.type == 1)
                {
                    stream.getUnsignedLEShort();
                    stream.getUnsignedByte();
                }

                if (rsInterface.type == 2)
                {
                    rsInterface.inventoryItemId              = new int[rsInterface.width * rsInterface.height];
                    rsInterface.inventoryStackSize           = new int[rsInterface.width * rsInterface.height];
                    rsInterface.itemSwappable                = stream.getUnsignedByte() == 1;
                    rsInterface.inventory                    = stream.getUnsignedByte() == 1;
                    rsInterface.usableItemInterface          = stream.getUnsignedByte() == 1;
                    rsInterface.itemDeletesDragged           = stream.getUnsignedByte() == 1;
                    rsInterface.inventorySpritePaddingColumn = stream.getUnsignedByte();
                    rsInterface.inventorySpritePaddingRow    = stream.getUnsignedByte();
                    rsInterface.spritesX = new int[20];
                    rsInterface.spritesY = new int[20];
                    rsInterface.sprites  = new Sprite[20];
                    for (int sprite = 0; sprite < 20; sprite++)
                    {
                        int spriteExists = stream.getUnsignedByte();
                        if (spriteExists == 1)
                        {
                            rsInterface.spritesX[sprite] = stream.getShort();
                            rsInterface.spritesY[sprite] = stream.getShort();
                            String name = stream.getString();
                            if (mediaArchive != null && name.Length > 0)
                            {
                                int spriteId = name.LastIndexOf(',');
                                rsInterface.sprites[sprite] = getImage(int.Parse(name.Substring(spriteId + 1)),
                                                                       mediaArchive, name.Substring(0, spriteId));
                            }
                        }
                    }

                    rsInterface.actions = new String[5];
                    for (int action = 0; action < 5; action++)
                    {
                        rsInterface.actions[action] = stream.getString();
                        if (rsInterface.actions[action].Length == 0)
                        {
                            rsInterface.actions[action] = null;
                        }
                    }
                }

                if (rsInterface.type == 3)
                {
                    rsInterface.filled = stream.getUnsignedByte() == 1;
                }
                if (rsInterface.type == 4 || rsInterface.type == 1)
                {
                    rsInterface.textCentred = stream.getUnsignedByte() == 1;
                    int font = stream.getUnsignedByte();
                    if (fonts != null)
                    {
                        rsInterface.textDrawingAreas = fonts[font];
                    }
                    rsInterface.textShadowed = stream.getUnsignedByte() == 1;
                }

                if (rsInterface.type == 4)
                {
                    rsInterface.textDefault = stream.getString();
                    rsInterface.textActive  = stream.getString();
                }

                if (rsInterface.type == 1 || rsInterface.type == 3 || rsInterface.type == 4)
                {
                    rsInterface.colourDefault = stream.getInt();
                }
                if (rsInterface.type == 3 || rsInterface.type == 4)
                {
                    rsInterface.colourActive       = stream.getInt();
                    rsInterface.colourDefaultHover = stream.getInt();
                    rsInterface.colourActiveHover  = stream.getInt();
                }

                if (rsInterface.type == 5)
                {
                    String spriteName = stream.getString();
                    if (mediaArchive != null && spriteName.Length > 0)
                    {
                        int spriteId = spriteName.LastIndexOf(",");
                        rsInterface.spriteDefault = getImage(int.Parse(spriteName.Substring(spriteId + 1)),
                                                             mediaArchive, spriteName.Substring(0, spriteId));
                    }

                    spriteName = stream.getString();
                    if (mediaArchive != null && spriteName.Length > 0)
                    {
                        int spriteId = spriteName.LastIndexOf(",");
                        rsInterface.spriteActive = getImage(int.Parse(spriteName.Substring(spriteId + 1)),
                                                            mediaArchive, spriteName.Substring(0, spriteId));
                    }
                }

                if (rsInterface.type == 6)
                {
                    int interfaceId = stream.getUnsignedByte();
                    if (interfaceId != 0)
                    {
                        rsInterface.modelTypeDefault = 1;
                        rsInterface.modelIdDefault   = (interfaceId - 1 << 8) + stream.getUnsignedByte();
                    }

                    interfaceId = stream.getUnsignedByte();
                    if (interfaceId != 0)
                    {
                        rsInterface.modelTypeActive = 1;
                        rsInterface.modelIdActive   = (interfaceId - 1 << 8) + stream.getUnsignedByte();
                    }

                    interfaceId = stream.getUnsignedByte();
                    if (interfaceId != 0)
                    {
                        rsInterface.animationIdDefault = (interfaceId - 1 << 8) + stream.getUnsignedByte();
                    }
                    else
                    {
                        rsInterface.animationIdDefault = -1;
                    }
                    interfaceId = stream.getUnsignedByte();
                    if (interfaceId != 0)
                    {
                        rsInterface.animationIdActive = (interfaceId - 1 << 8) + stream.getUnsignedByte();
                    }
                    else
                    {
                        rsInterface.animationIdActive = -1;
                    }
                    rsInterface.modelZoom      = stream.getUnsignedLEShort();
                    rsInterface.modelRotationX = stream.getUnsignedLEShort();
                    rsInterface.modelRotationY = stream.getUnsignedLEShort();
                }

                if (rsInterface.type == 7)
                {
                    rsInterface.inventoryItemId    = new int[rsInterface.width * rsInterface.height];
                    rsInterface.inventoryStackSize = new int[rsInterface.width * rsInterface.height];
                    rsInterface.textCentred        = stream.getUnsignedByte() == 1;
                    int font = stream.getUnsignedByte();
                    if (fonts != null)
                    {
                        rsInterface.textDrawingAreas = fonts[font];
                    }
                    rsInterface.textShadowed  = stream.getUnsignedByte() == 1;
                    rsInterface.colourDefault = stream.getInt();
                    rsInterface.inventorySpritePaddingColumn = stream.getShort();
                    rsInterface.inventorySpritePaddingRow    = stream.getShort();
                    rsInterface.inventory = stream.getUnsignedByte() == 1;
                    rsInterface.actions   = new String[5];
                    for (int active = 0; active < 5; active++)
                    {
                        rsInterface.actions[active] = stream.getString();
                        if (rsInterface.actions[active].Length == 0)
                        {
                            rsInterface.actions[active] = null;
                        }
                    }
                }

                if (rsInterface.actionType == 2 || rsInterface.type == 2)
                {
                    rsInterface.selectedActionName = stream.getString();
                    rsInterface.spellName          = stream.getString();
                    rsInterface.spellUsableOn      = stream.getUnsignedLEShort();
                }

                if (rsInterface.type == 8)
                {
                    rsInterface.textDefault = stream.getString();
                }

                if (rsInterface.actionType == 1 || rsInterface.actionType == 4 || rsInterface.actionType == 5 ||
                    rsInterface.actionType == 6)
                {
                    rsInterface.tooltip = stream.getString();
                    if (rsInterface.tooltip.Length == 0)
                    {
                        if (rsInterface.actionType == 1)
                        {
                            rsInterface.tooltip = "Ok";
                        }
                        if (rsInterface.actionType == 4)
                        {
                            rsInterface.tooltip = "Select";
                        }
                        if (rsInterface.actionType == 5)
                        {
                            rsInterface.tooltip = "Select";
                        }
                        if (rsInterface.actionType == 6)
                        {
                            rsInterface.tooltip = "Continue";
                        }
                    }
                }
            }

            spriteCache = null;
        }