private async Task <bool> ProcessAnimationsAsync(int fileRequestCount) { 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; } //We can't force load more because if we constantly loop thw webgl main thread has no //way to load the resources we're waiting for. await TaskDelayFactory.Create(1); if (onDemandFetcher.failedRequests > 3) { loadError(); return(false); } } return(true); }
public async Task preloadRegionsAsync(bool flag) { int j = MapIndices.Count; for (int k = 0; k < j; k++) { if (flag || MapIndices[k].isMembers) { setPriority((byte)2, 3, MapIndices[k].ObjectFileId); setPriority((byte)2, 3, MapIndices[k].TerrainId); if (k % 2 == 0) { await TaskDelayFactory.Create(1); } } } }
private async Task DrawFlamesAsync() { Debug.Log($"Starting flame drawing."); drawingFlames = true; while (currentlyDrawingFlames) { flameCycle++; if (ShouldClientRender) { calcFlamesPosition(); calcFlamesPosition(); doFlamesDrawing(); } await TaskDelayFactory.Create(25); } drawingFlames = false; }
//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); }
private async Task AppletRunCoroutine() { Console.WriteLine($"Loading."); drawLoadingText(0, "Loading..."); await StartupCoroutine(); await LoadMediaContentAsync(); await HandlePendingInterfaceUnpackingAsync(); await PostLoadEngineInitializationAsync(); int opos = 0; int ratio = 256; int delay = 1; int count = 0; int intex = 0; for (int otim = 0; otim < 10; otim++) { otims[otim] = TimeService.CurrentTimeInMilliseconds(); } while (gameState >= 0) { if (gameState > 0) { gameState--; if (gameState == 0) { exit(); return; } } int i2 = ratio; int j2 = delay; ratio = 300; delay = 1; long currentTime = TimeService.CurrentTimeInMilliseconds(); if (otims[opos] == 0L) { ratio = i2; delay = j2; } else if (currentTime > otims[opos]) { ratio = (int)(2560 * delayTime / (currentTime - otims[opos])); } if (ratio < 25) { ratio = 25; } if (ratio > 256) { ratio = 256; delay = (int)(delayTime - (currentTime - otims[opos]) / 10L); } if (delay > delayTime) { delay = delayTime; } otims[opos] = currentTime; opos = (opos + 1) % 10; if (delay > 1) { for (int otim = 0; otim < 10; otim++) { if (otims[otim] != 0L) { otims[otim] += delay; } } } if (delay < minDelay) { delay = minDelay; } //Always await, mindelay is at least one ms and that'll be 1 frame minimum for us //if we never yield frame time then critical things in WebGL enviroment can't run await TaskDelayFactory.Create(delay); for (; count < 256; count += ratio) { clickType = eventMouseButton; clickX = eventClickX; clickY = eventClickY; clickTime = eventClickTime; eventMouseButton = 0; await processGameLoop(); readIndex = writeIndex; } count &= 0xff; if (delayTime > 0) { fps = (1000 * ratio) / (delayTime * 256); } processDrawing(); if (debugRequested) { Console.WriteLine("ntime:" + currentTime); for (int i = 0; i < 10; i++) { int otim = ((opos - i - 1) + 20) % 10; Console.WriteLine("otim" + otim + ":" + otims[otim]); } Console.WriteLine("fps:" + fps + " ratio:" + ratio + " count:" + count); Console.WriteLine("del:" + delay + " deltime:" + delayTime + " mindel:" + minDelay); Console.WriteLine("intex:" + intex + " opos:" + opos); debugRequested = false; intex = 0; } } if (gameState == -1) { exit(); } }
internal async Task LoadMediaContentAsync() { Archive archiveMedia = requestArchive(4, "2d graphics", "media", 0, 40); Default317Buffer metadataBuffer = new Default317Buffer(archiveMedia.decompressFile("index.dat")); inventoryBackgroundImage = new IndexedImage(archiveMedia, "invback", 0, metadataBuffer); chatBackgroundImage = new IndexedImage(archiveMedia, "chatback", 0, metadataBuffer); minimapBackgroundImage = new IndexedImage(archiveMedia, "mapback", 0, metadataBuffer); backBase1Image = new IndexedImage(archiveMedia, "backbase1", 0, metadataBuffer); backBase2Image = new IndexedImage(archiveMedia, "backbase2", 0, metadataBuffer); backHmid1Image = new IndexedImage(archiveMedia, "backhmid1", 0, metadataBuffer); for (int icon = 0; icon < 13; icon++) { sideIconImage[icon] = new IndexedImage(archiveMedia, "sideicons", icon, metadataBuffer); } minimapCompassImage = new Sprite(archiveMedia, "compass", 0, metadataBuffer); minimapEdgeImage = new Sprite(archiveMedia, "mapedge", 0, metadataBuffer); minimapEdgeImage.trim(); await TaskDelayFactory.Create(1); try { for (int i = 0; i < 100; i++) { mapSceneImage[i] = new IndexedImage(archiveMedia, "mapscene", i, metadataBuffer); } await TaskDelayFactory.Create(1); } catch (Exception _ex) { signlink.reporterror($"Unexpected Exception: {_ex.Message} \n\n Stack: {_ex.StackTrace}"); } try { for (int i = 0; i < 100; i++) { mapFunctionImage[i] = new Sprite(archiveMedia, "mapfunction", i, metadataBuffer); } await TaskDelayFactory.Create(1); } catch (Exception _ex) { signlink.reporterror($"Unexpected Exception: {_ex.Message} \n\n Stack: {_ex.StackTrace}"); } try { for (int i = 0; i < 20; i++) { hitMarkImage[i] = new Sprite(archiveMedia, "hitmarks", i, metadataBuffer); } await TaskDelayFactory.Create(1); } catch (Exception _ex) { signlink.reporterror($"Unexpected Exception: {_ex.Message} \n\n Stack: {_ex.StackTrace}"); } try { for (int i = 0; i < 20; i++) { headIcons[i] = new Sprite(archiveMedia, "headicons", i, metadataBuffer); } await TaskDelayFactory.Create(1); } catch (Exception _ex) { signlink.reporterror($"Unexpected Exception: {_ex.Message} \n\n Stack: {_ex.StackTrace}"); throw; } mapFlag = new Sprite(archiveMedia, "mapmarker", 0, metadataBuffer); mapMarker = new Sprite(archiveMedia, "mapmarker", 1, metadataBuffer); for (int i = 0; i < 8; i++) { crosses[i] = new Sprite(archiveMedia, "cross", i, metadataBuffer); } mapDotItem = new Sprite(archiveMedia, "mapdots", 0, metadataBuffer); mapDotNPC = new Sprite(archiveMedia, "mapdots", 1, metadataBuffer); mapDotPlayer = new Sprite(archiveMedia, "mapdots", 2, metadataBuffer); mapDotFriend = new Sprite(archiveMedia, "mapdots", 3, metadataBuffer); mapDotTeam = new Sprite(archiveMedia, "mapdots", 4, metadataBuffer); scrollBarUp = new IndexedImage(archiveMedia, "scrollbar", 0, metadataBuffer); scrollBarDown = new IndexedImage(archiveMedia, "scrollbar", 1, metadataBuffer); redStone1 = new IndexedImage(archiveMedia, "redstone1", 0, metadataBuffer); redStone2 = new IndexedImage(archiveMedia, "redstone2", 0, metadataBuffer); redStone3 = new IndexedImage(archiveMedia, "redstone3", 0, metadataBuffer); redStone1_2 = new IndexedImage(archiveMedia, "redstone1", 0, metadataBuffer); redStone1_2.flipHorizontally(); redStone2_2 = new IndexedImage(archiveMedia, "redstone2", 0, metadataBuffer); redStone2_2.flipHorizontally(); redStone1_3 = new IndexedImage(archiveMedia, "redstone1", 0, metadataBuffer); redStone1_3.flipVertically(); redStone2_3 = new IndexedImage(archiveMedia, "redstone2", 0, metadataBuffer); redStone2_3.flipVertically(); redStone3_2 = new IndexedImage(archiveMedia, "redstone3", 0, metadataBuffer); redStone3_2.flipVertically(); redStone1_4 = new IndexedImage(archiveMedia, "redstone1", 0, metadataBuffer); redStone1_4.flipHorizontally(); redStone1_4.flipVertically(); redStone2_4 = new IndexedImage(archiveMedia, "redstone2", 0, metadataBuffer); redStone2_4.flipHorizontally(); redStone2_4.flipVertically(); for (int i = 0; i < 2; i++) { modIcons[i] = new IndexedImage(archiveMedia, "mod_icons", i, metadataBuffer); } await TaskDelayFactory.Create(1); Sprite sprite = new Sprite(archiveMedia, "backleft1", 0, metadataBuffer); backLeftIP1 = CreateNewImageProducer(sprite.width, sprite.height, nameof(backLeftIP1)); sprite.drawInverse(0, 0); sprite = new Sprite(archiveMedia, "backleft2", 0, metadataBuffer); backLeftIP2 = CreateNewImageProducer(sprite.width, sprite.height, nameof(backLeftIP2)); sprite.drawInverse(0, 0); sprite = new Sprite(archiveMedia, "backright1", 0, metadataBuffer); backRightIP1 = CreateNewImageProducer(sprite.width, sprite.height, nameof(backRightIP1)); sprite.drawInverse(0, 0); sprite = new Sprite(archiveMedia, "backright2", 0, metadataBuffer); backRightIP2 = CreateNewImageProducer(sprite.width, sprite.height, nameof(backRightIP2)); sprite.drawInverse(0, 0); sprite = new Sprite(archiveMedia, "backtop1", 0, metadataBuffer); backTopIP1 = CreateNewImageProducer(sprite.width, sprite.height, nameof(backTopIP1)); sprite.drawInverse(0, 0); sprite = new Sprite(archiveMedia, "backvmid1", 0, metadataBuffer); backVmidIP1 = CreateNewImageProducer(sprite.width, sprite.height, nameof(backVmidIP1)); sprite.drawInverse(0, 0); sprite = new Sprite(archiveMedia, "backvmid2", 0, metadataBuffer); backVmidIP2 = CreateNewImageProducer(sprite.width, sprite.height, nameof(backVmidIP2)); sprite.drawInverse(0, 0); sprite = new Sprite(archiveMedia, "backvmid3", 0, metadataBuffer); backVmidIP3 = CreateNewImageProducer(sprite.width, sprite.height, nameof(backVmidIP3)); sprite.drawInverse(0, 0); sprite = new Sprite(archiveMedia, "backhmid2", 0, metadataBuffer); backVmidIP2_2 = CreateNewImageProducer(sprite.width, sprite.height, nameof(backVmidIP2_2)); sprite.drawInverse(0, 0); await TaskDelayFactory.Create(1); int randomRed = (int)(StaticRandomGenerator.Next() * 21D) - 10; int randomGreen = (int)(StaticRandomGenerator.Next() * 21D) - 10; int randomBlue = (int)(StaticRandomGenerator.Next() * 21D) - 10; int randomColour = (int)(StaticRandomGenerator.Next() * 41D) - 20; for (int i = 0; i < 100; i++) { if (mapFunctionImage[i] != null) { mapFunctionImage[i].adjustRGB(randomRed + randomColour, randomGreen + randomColour, randomBlue + randomColour); } if (mapSceneImage[i] != null) { mapSceneImage[i].mixPalette(randomRed + randomColour, randomGreen + randomColour, randomBlue + randomColour); } } }
public async Task 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; return; } 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; return; } 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); drawLogo(); loadTitleScreen(); Archive archiveConfig = requestArchive(2, "config", "config", expectedCRCs[2], 30); 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(false); await TaskDelayFactory.Create(1); if (onDemandFetcher.failedRequests > 3) { loadError(); return; } } drawLoadingText(65, "Requesting animations"); int fileRequestCount = onDemandFetcher.fileCount(1); for (int id = 0; id < fileRequestCount; id++) { onDemandFetcher.request(1, id); } if (!await ProcessAnimationsAsync(fileRequestCount)) { return; } 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(); await TaskDelayFactory.Create(1); } if (caches[0] != null) { drawLoadingText(75, "Requesting maps"); onDemandFetcher.request(3, onDemandFetcher.getMapId(0, 47, 48)); onDemandFetcher.request(3, onDemandFetcher.getMapId(1, 47, 48)); onDemandFetcher.request(3, onDemandFetcher.getMapId(0, 48, 48)); onDemandFetcher.request(3, onDemandFetcher.getMapId(1, 48, 48)); onDemandFetcher.request(3, onDemandFetcher.getMapId(0, 49, 48)); onDemandFetcher.request(3, onDemandFetcher.getMapId(1, 49, 48)); onDemandFetcher.request(3, onDemandFetcher.getMapId(0, 47, 47)); onDemandFetcher.request(3, onDemandFetcher.getMapId(1, 47, 47)); onDemandFetcher.request(3, onDemandFetcher.getMapId(0, 48, 47)); onDemandFetcher.request(3, onDemandFetcher.getMapId(1, 48, 47)); onDemandFetcher.request(3, onDemandFetcher.getMapId(0, 48, 148)); onDemandFetcher.request(3, onDemandFetcher.getMapId(1, 48, 148)); fileRequestCount = onDemandFetcher.immediateRequestCount(); while (onDemandFetcher.immediateRequestCount() > 0) { int remaining = fileRequestCount - onDemandFetcher.immediateRequestCount(); if (remaining > 0) { drawLoadingText(75, "Loading maps - " + (remaining * 100) / fileRequestCount + "%"); } processOnDemandQueue(false); await TaskDelayFactory.Create(1); } } 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); } } //Don't need to even preload. await((WebGLOnDemandFetcher)onDemandFetcher).preloadRegionsAsync(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); } } //We don't unpack media here on WebGL because it //causes memory problems. 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"); //Sound loading disabled in WebGL. byte[] soundData = archiveSounds.decompressFile("sounds.dat"); Effect.load(new Default317Buffer(soundData)); }