Skip to content

Commit

Permalink
Fixed memory leak with form images
Browse files Browse the repository at this point in the history
  • Loading branch information
kennyvv committed Mar 22, 2022
1 parent 24702bb commit 08ea662
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 32 deletions.
2 changes: 1 addition & 1 deletion src/Alex/Graphics/Models/BoneMatrices.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public void ApplyMovement()

if (posData.IsValid)
{
_positionData = _positionData.WithValues(_position, posData.Target * new Vector3(-1f, 1f, 1f), posData.TargetTime);
_positionData = _positionData.WithValues(_position, posData.Target * new Vector3(1f, 1f, 1f), posData.TargetTime); // (-1, 1, 1) for fixed LBSG npc
_tempPositionData.Reset();
}

Expand Down
13 changes: 12 additions & 1 deletion src/Alex/Gui/Forms/BedrockFormManager.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using Alex.Net;
using Alex.Net.Bedrock;
using Alex.Worlds.Multiplayer.Bedrock;
Expand All @@ -9,7 +10,7 @@

namespace Alex.Gui.Forms
{
public class BedrockFormManager
public class BedrockFormManager : IDisposable
{
private static readonly ILogger Log = LogManager.GetCurrentClassLogger();

Expand Down Expand Up @@ -79,5 +80,15 @@ public void CloseAll()
if (active != null)
Hide(active.FormId);
}

/// <inheritdoc />
public void Dispose()
{
FormImage.ClearCache();

_activeForm?.Dispose();
GuiManager?.Dispose();
InputManager?.Dispose();
}
}
}
101 changes: 73 additions & 28 deletions src/Alex/Gui/Forms/FormImage.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
using System;
using System.Collections.Concurrent;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Alex.Common.Utils;
using Microsoft.Xna.Framework;
using RocketUI;
using NLog;
using SixLabors.ImageSharp.PixelFormats;
Expand All @@ -20,36 +24,77 @@ public class FormImage : RocketControl
public FormImage(string url)
{
Image = url;
}

private bool _didLoad = false;
private SemaphoreSlim _loadingLock = new SemaphoreSlim(1);
/// <inheritdoc />
protected override void OnDraw(GuiSpriteBatch graphics, GameTime gameTime)
{
base.OnDraw(graphics, gameTime);

if (!_didLoad)
{
_ = LoadAsync();
}
}

ThreadPool.QueueUserWorkItem(
(o) =>
private async Task LoadAsync()
{
if (!await _loadingLock.WaitAsync(0))
return;

try
{
var path = Image;
if (!_cache.TryGetValue(path, out var data))
{
try
{
byte[] imageData = _cache.GetOrAdd(
Image, (path) =>
{
using (WebClient wc = new WebClient())
{
var data = wc.DownloadData(path);

return data;
}
});

var image = SixLabors.ImageSharp.Image.Load<Rgba32>(imageData);
TextureUtils.BitmapToTexture2DAsync(
this, Alex.Instance.GraphicsDevice, image, texture =>
{
Background = (TextureSlice2D)texture;
image.Dispose();
}, $"FormImage - {url}");
}
catch (Exception ex)
{
Log.Error(ex, $"Could not convert image!");
}
});
HttpClient httpClient = new HttpClient();
data = await httpClient.GetByteArrayAsync(path);
_cache.TryAdd(path, data);
}

if (data == null)
return;

using (MemoryStream ms = new MemoryStream(data))
{
var image = await SixLabors.ImageSharp.Image.LoadAsync<Rgba32>(ms);

TextureUtils.BitmapToTexture2DAsync(
this, Alex.Instance.GraphicsDevice, image, texture =>
{
Background = (TextureSlice2D) texture;
image?.Dispose();
}, $"FormImage - {path}");
}
}
catch (Exception ex)
{
Log.Error(ex, $"Could not convert image!");
}
finally
{
_didLoad = true;
_loadingLock.Release();
}
}

/// <inheritdoc />
protected override void Dispose(bool disposing)
{
if (disposing)
{
_loadingLock?.Dispose();
_loadingLock = null;
}

base.Dispose(disposing);
}

public static void ClearCache()
{
_cache?.Clear();
}
}
}
2 changes: 1 addition & 1 deletion src/Alex/Net/Bedrock/BedrockClientPacketHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -776,7 +776,7 @@ public void HandleMcpeNetworkChunkPublisherUpdate(McpeNetworkChunkPublisherUpdat
message.coordinates.X, message.coordinates.Y, message.coordinates.Z);

Client.ChunkPublisherRadius = message.radius;
Log.Info($"ChunkPublisherUpdate: radius={message.radius} coordinates={message.coordinates}");
//Log.Info($"ChunkPublisherUpdate: radius={message.radius} coordinates={message.coordinates}");
}

public void HandleMcpeBiomeDefinitionList(McpeBiomeDefinitionList message)
Expand Down
4 changes: 3 additions & 1 deletion src/Alex/Worlds/Multiplayer/BedrockWorldProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,9 @@ protected virtual void OnSpawn() { }
public override void Dispose()
{
//World?.Ticker?.UnregisterTicked(this);

FormManager?.Dispose();
FormManager = null;

base.Dispose();
Client.Dispose();
}
Expand Down

0 comments on commit 08ea662

Please sign in to comment.