Browse Source

continued the insanity of getting unity to behave

pull/46/head
Anairkoen Schno 6 years ago
parent
commit
98dfdb69b3
6 changed files with 146 additions and 39 deletions
  1. +1
    -1
      IPA.Tests/updater_test.json
  2. +1
    -0
      IllusionInjector/IllusionInjector.csproj
  3. +70
    -31
      IllusionInjector/Updating/ModsaberML/Updater.cs
  4. +33
    -6
      IllusionInjector/Utilities/BlockingStream.cs
  5. +40
    -0
      IllusionInjector/Utilities/EchoStream.cs
  6. +1
    -1
      IllusionInjector/obj/Debug/IllusionInjector.csproj.CoreCompileInputs.cache

+ 1
- 1
IPA.Tests/updater_test.json View File

@ -40,7 +40,7 @@
"Mono.Cecil.dll": "762fb07e4d81722f0a766460289c6114cd4b7dae", "Mono.Cecil.dll": "762fb07e4d81722f0a766460289c6114cd4b7dae",
"Plugins/SongLoaderPlugin.dll": "f4ab080fbcc5abc6005a868cd965920bac46ddaf" "Plugins/SongLoaderPlugin.dll": "f4ab080fbcc5abc6005a868cd965920bac46ddaf"
}, },
"url": "https://www.modsaber.ml/cdn/song-loader/4.2.2-default.zip"
"url": "file://Z:/Users/aaron/Source/Repos/IPA-Reloaded-BeatSaber/IPA/bin/Debug/Debug.zip"
} }
}, },
"weight": 7, "weight": 7,


+ 1
- 0
IllusionInjector/IllusionInjector.csproj View File

@ -81,6 +81,7 @@
<Compile Include="Updating\Old\ModUpdater.cs" /> <Compile Include="Updating\Old\ModUpdater.cs" />
<Compile Include="Updating\Old\UpdateScript.cs" /> <Compile Include="Updating\Old\UpdateScript.cs" />
<Compile Include="Utilities\BlockingStream.cs" /> <Compile Include="Utilities\BlockingStream.cs" />
<Compile Include="Utilities\EchoStream.cs" />
<Compile Include="Utilities\SimpleJson.cs" /> <Compile Include="Utilities\SimpleJson.cs" />
<Compile Include="Utilities\SteamCheck.cs" /> <Compile Include="Utilities\SteamCheck.cs" />
</ItemGroup> </ItemGroup>


+ 70
- 31
IllusionInjector/Updating/ModsaberML/Updater.cs View File

@ -151,49 +151,76 @@ namespace IllusionInjector.Updating.ModsaberML
} }
} }
class StreamDownloadHandler : DownloadHandlerScript
public class StreamDownloadHandler : DownloadHandlerScript
{ {
public MemoryStream Stream { get; set; }
public BlockingStream Stream { get; set; }
public StreamDownloadHandler(BlockingStream stream)
{
Stream = stream;
}
protected void ReceiveContentLength(long contentLength) protected void ReceiveContentLength(long contentLength)
{ {
Stream.Capacity = (int)contentLength;
//(Stream.BaseStream as MemoryStream).Capacity = (int)contentLength;
Logger.log.Debug($"Got content length: {contentLength}"); Logger.log.Debug($"Got content length: {contentLength}");
} }
protected void OnContentComplete() protected void OnContentComplete()
{ {
Stream.Open = false;
Logger.log.Debug("Download complete"); Logger.log.Debug("Download complete");
} }
protected bool ReceiveData(byte[] data, long dataLength) protected bool ReceiveData(byte[] data, long dataLength)
{ {
Logger.log.Debug("ReceiveData");
if (data == null || data.Length < 1)
{
Logger.log.Debug("CustomWebRequest :: ReceiveData - received a null/empty buffer");
return false;
}
Stream.Write(data, 0, (int)dataLength); Stream.Write(data, 0, (int)dataLength);
return true; return true;
} }
protected override byte[] GetData() { return null; }
protected override float GetProgress()
{
return 0f;
}
public override string ToString()
{
return $"{base.ToString()} ({Stream?.ToString()})";
}
} }
IEnumerator UpdateModCoroutine(string tempdir, UpdateStruct item)
private void DownloadPluginAsync(BlockingStream stream, UpdateStruct item, string tempdir)
{ {
void DownloadPluginAsync(MemoryStream stream)
{ // embedded because i don't think unity likes it in the top level
Logger.log.Debug($"Getting ZIP file for {item.plugin.Plugin.Name}");
//var stream = await httpClient.GetStreamAsync(url);
Logger.log.Debug($"Getting ZIP file for {item.plugin.Plugin.Name}");
//var stream = await httpClient.GetStreamAsync(url);
using (var zipFile = new ZipInputStream(new BlockingStream(stream)))
using (var zipFile = new ZipInputStream(stream))
{
Logger.log.Debug("Streams opened");
ZipEntry entry;
while ((entry = zipFile.GetNextEntry()) != null)
{ {
Logger.log.Debug("Streams opened");
ZipEntry entry;
while ((entry = zipFile.GetNextEntry()) != null)
{
Logger.log.Debug(entry?.FileName);
}
Logger.log.Debug(entry?.FileName ?? "NULL");
} }
Logger.log.Debug("Downloader exited");
} }
Logger.log.Debug("Downloader exited");
}
IEnumerator UpdateModCoroutine(string tempdir, UpdateStruct item)
{
string url; string url;
if (SteamCheck.IsAvailable || item.externInfo.OculusFile == null) if (SteamCheck.IsAvailable || item.externInfo.OculusFile == null)
url = item.externInfo.SteamFile; url = item.externInfo.SteamFile;
@ -201,33 +228,45 @@ namespace IllusionInjector.Updating.ModsaberML
url = item.externInfo.OculusFile; url = item.externInfo.OculusFile;
Logger.log.Debug($"URL = {url}"); Logger.log.Debug($"URL = {url}");
using (var req = UnityWebRequest.Get(url))
using (var memStream = new MemoryStream())
using (var memStream = new EchoStream())
using (var stream = new BlockingStream(memStream))
using (var request = UnityWebRequest.Get(url))
using (var taskTokenSource = new CancellationTokenSource())
{ {
req.downloadHandler = new StreamDownloadHandler
{
Stream = memStream
};
var dlh = new StreamDownloadHandler(stream);
request.downloadHandler = dlh;
var downloadTask = Task.Run(() => var downloadTask = Task.Run(() =>
{ // use slightly more multithreaded approach than coroutines { // use slightly more multithreaded approach than coroutines
DownloadPluginAsync(memStream);
});
DownloadPluginAsync(stream, item, tempdir);
}, taskTokenSource.Token);
Logger.log.Debug("Sending request"); Logger.log.Debug("Sending request");
yield return req.SendWebRequest();
Logger.log.Debug(request?.downloadHandler?.ToString() ?? "DLH==NULL");
yield return request.SendWebRequest();
Logger.log.Debug("Download finished");
if (stream.Open)
{ // anti-hang
Logger.log.Warn("Downloader failed to call DownloadHandler");
stream.Open = false; // no more writing
stream.BaseStream.Write(new byte[] { 0 }, 0, 1);
}
if (req.isNetworkError)
if (request.isNetworkError)
{ {
Logger.log.Error("Network error while trying to update mod"); Logger.log.Error("Network error while trying to update mod");
Logger.log.Error(req.error);
Logger.log.Error(request.error);
taskTokenSource.Cancel();
yield break; yield break;
} }
if (req.isHttpError)
if (request.isHttpError)
{ {
Logger.log.Error($"Server returned an error code while trying to update mod"); Logger.log.Error($"Server returned an error code while trying to update mod");
Logger.log.Error(req.error);
Logger.log.Error(request.error);
taskTokenSource.Cancel();
yield break;
} }
downloadTask.Wait(); // wait for the damn thing to finish downloadTask.Wait(); // wait for the damn thing to finish


+ 33
- 6
IllusionInjector/Utilities/BlockingStream.cs View File

@ -1,5 +1,7 @@
using System;
using IllusionInjector.Logging;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@ -16,11 +18,27 @@ namespace IllusionInjector.Utilities
public Stream BaseStream { get; set; } public Stream BaseStream { get; set; }
public override bool CanRead => BaseStream.CanRead;
private bool _open = true;
public bool Open {
get
{
return CanWrite;
}
set
{
if (!_open)
throw new InvalidOperationException("Blocking stream has already been closed!");
else
_open = value;
}
}
private bool canReadOverride = true;
public override bool CanRead => BaseStream.CanRead && canReadOverride;
public override bool CanSeek => BaseStream.CanSeek; public override bool CanSeek => BaseStream.CanSeek;
public override bool CanWrite => BaseStream.CanWrite;
public override bool CanWrite => BaseStream.CanWrite && _open;
public override long Length => BaseStream.Length; public override long Length => BaseStream.Length;
@ -34,13 +52,17 @@ namespace IllusionInjector.Utilities
public override int Read(byte[] buffer, int offset, int count) public override int Read(byte[] buffer, int offset, int count)
{ {
var read = 0; var read = 0;
do
while (read < count && Open)
{ {
read += BaseStream.Read(buffer, read, count-read); read += BaseStream.Read(buffer, read, count-read);
} }
while (read < count);
return count;
if (read == 0)
{
canReadOverride = false;
}
return read;
} }
public override long Seek(long offset, SeekOrigin origin) public override long Seek(long offset, SeekOrigin origin)
@ -57,5 +79,10 @@ namespace IllusionInjector.Utilities
{ {
BaseStream.Write(buffer, offset, count); BaseStream.Write(buffer, offset, count);
} }
public override string ToString()
{
return $"{base.ToString()} ({BaseStream?.ToString()})";
}
} }
} }

+ 40
- 0
IllusionInjector/Utilities/EchoStream.cs View File

@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace IllusionInjector.Utilities
{
public class EchoStream : MemoryStream
{
private ManualResetEvent m_dataReady = new ManualResetEvent(false);
private byte[] m_buffer;
private int m_offset;
private int m_count;
public override void Write(byte[] buffer, int offset, int count)
{
m_buffer = buffer;
m_offset = offset;
m_count = count;
m_dataReady.Set();
}
public override int Read(byte[] buffer, int offset, int count)
{
if (m_buffer == null)
{
// Block until the stream has some more data.
m_dataReady.Reset();
m_dataReady.WaitOne();
}
Buffer.BlockCopy(m_buffer, m_offset, buffer, offset, (count < m_count) ? count : m_count);
m_buffer = null;
return (count < m_count) ? count : m_count;
}
}
}

+ 1
- 1
IllusionInjector/obj/Debug/IllusionInjector.csproj.CoreCompileInputs.cache View File

@ -1 +1 @@
28cceae1ca85bfd009d7109ef2bb2d8a1412f4b3
c0ee92dfbaba38e571471f2b468aeb2a80b0f76b

Loading…
Cancel
Save