//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; }