fix memory leaks caused by world not being properly disposed

This commit is contained in:
RandomityGuy 2023-10-01 14:06:36 +05:30
parent ef6c3a0146
commit 74d444a835
5 changed files with 50 additions and 12 deletions

View file

@ -159,6 +159,10 @@ class Console {
} else { } else {
error("Expected one argument, got " + (cmdSplit.length - 1)); error("Expected one argument, got " + (cmdSplit.length - 1));
} }
} else if (cmdType == "dumpmem") {
#if sys
hl.Gc.dumpMemory();
#end
} else { } else {
error("Unknown command"); error("Unknown command");
} }

View file

@ -1032,6 +1032,7 @@ class DtsObject extends GameObject {
public override function dispose() { public override function dispose() {
super.dispose(); super.dispose();
this.level = null;
this.dtsResource.release(); this.dtsResource.release();
} }
} }

View file

@ -19,16 +19,25 @@ import h3d.scene.Mesh;
import h3d.scene.MeshBatch; import h3d.scene.MeshBatch;
import src.MarbleGame; import src.MarbleGame;
typedef MeshBatchInfo = { @:publicFields
class MeshBatchInfo {
var instances:Array<MeshInstance>; var instances:Array<MeshInstance>;
var meshbatch:MeshBatch; var meshbatch:MeshBatch;
var ?transparencymeshbatch:MeshBatch; var transparencymeshbatch:MeshBatch;
var mesh:Mesh; var mesh:Mesh;
public function new() {}
} }
typedef MeshInstance = { @:publicFields
class MeshInstance {
var emptyObj:Object; var emptyObj:Object;
var gameObject:GameObject; var gameObject:GameObject;
public function new(eo, go) {
this.emptyObj = eo;
this.gameObject = go;
}
} }
class InstanceManager { class InstanceManager {
@ -122,7 +131,7 @@ class InstanceManager {
var objs = getAllChildren(object); var objs = getAllChildren(object);
var minfos = objects[objectMap.get(object.identifier)]; // objects.get(object.identifier); var minfos = objects[objectMap.get(object.identifier)]; // objects.get(object.identifier);
for (i in 0...objs.length) { for (i in 0...objs.length) {
minfos[i].instances.push({emptyObj: objs[i], gameObject: object}); minfos[i].instances.push(new MeshInstance(objs[i], object));
} }
} else { } else {
// First time appending the thing so bruh // First time appending the thing so bruh
@ -131,11 +140,11 @@ class InstanceManager {
var minfos = []; var minfos = [];
for (obj in objs) { for (obj in objs) {
var isMesh = obj is Mesh; var isMesh = obj is Mesh;
var minfo:MeshBatchInfo = { var minfo:MeshBatchInfo = new MeshBatchInfo();
instances: [{emptyObj: obj, gameObject: object}], minfo.instances = [new MeshInstance(obj, object)];
meshbatch: isMesh ? new MeshBatch(cast(cast(obj, Mesh).primitive), cast(cast(obj, Mesh)).material.clone(), scene) : null, minfo.meshbatch = isMesh ? new MeshBatch(cast(cast(obj, Mesh).primitive), cast(cast(obj, Mesh)).material.clone(), scene) : null;
mesh: isMesh ? cast obj : null minfo.mesh = isMesh ? cast obj : null;
}
if (isMesh) { if (isMesh) {
var mat = cast(obj, Mesh).material; var mat = cast(obj, Mesh).material;
var dtsshader = mat.mainPass.getShader(DtsTexture); var dtsshader = mat.mainPass.getShader(DtsTexture);

View file

@ -226,7 +226,8 @@ class MarbleGame {
world.setCursorLock(false); world.setCursorLock(false);
exitGameDlg = new ExitGameDlg((sender) -> { exitGameDlg = new ExitGameDlg((sender) -> {
canvas.popDialog(exitGameDlg); canvas.popDialog(exitGameDlg);
if (world.isRecording) { var w = getWorld();
if (w.isRecording) {
MarbleGame.canvas.pushDialog(new ReplayNameDlg(() -> { MarbleGame.canvas.pushDialog(new ReplayNameDlg(() -> {
quitMission(); quitMission();
})); }));
@ -236,10 +237,12 @@ class MarbleGame {
}, (sender) -> { }, (sender) -> {
canvas.popDialog(exitGameDlg); canvas.popDialog(exitGameDlg);
paused = !paused; paused = !paused;
world.setCursorLock(true); var w = getWorld();
w.setCursorLock(true);
}, (sender) -> { }, (sender) -> {
canvas.popDialog(exitGameDlg); canvas.popDialog(exitGameDlg);
world.restart(true); var w = getWorld();
w.restart(true);
// world.setCursorLock(true); // world.setCursorLock(true);
paused = !paused; paused = !paused;
}); });
@ -254,6 +257,11 @@ class MarbleGame {
} }
} }
public function getWorld() {
// So that we don't actually store this somewhere in any closure stack
return world;
}
public function quitMission() { public function quitMission() {
Console.log("Quitting mission"); Console.log("Quitting mission");
world.setCursorLock(false); world.setCursorLock(false);

View file

@ -1950,28 +1950,44 @@ class MarbleWorld extends Scheduler {
for (interior in this.interiors) { for (interior in this.interiors) {
interior.dispose(); interior.dispose();
} }
interiors = null;
for (pathedInteriors in this.pathedInteriors) { for (pathedInteriors in this.pathedInteriors) {
pathedInteriors.dispose(); pathedInteriors.dispose();
} }
pathedInteriors = null;
for (marble in this.marbles) { for (marble in this.marbles) {
marble.dispose(); marble.dispose();
} }
marbles = null;
for (dtsObject in this.dtsObjects) { for (dtsObject in this.dtsObjects) {
dtsObject.dispose(); dtsObject.dispose();
} }
dtsObjects = null;
for (trigger in this.triggers) { for (trigger in this.triggers) {
trigger.dispose(); trigger.dispose();
} }
triggers = null;
for (soundResource in this.soundResources) { for (soundResource in this.soundResources) {
soundResource.release(); soundResource.release();
} }
for (textureResource in this.textureResources) { for (textureResource in this.textureResources) {
textureResource.release(); textureResource.release();
} }
gems = null;
if (sky != null) if (sky != null)
sky.dispose(); sky.dispose();
instanceManager = null;
collisionWorld = null;
particleManager = null;
namedObjects = null;
shapeOrTriggerInside = null;
shapeImmunity = null;
currentCheckpoint = null;
checkpointCollectedGems = null;
marble = null;
this._disposed = true; this._disposed = true;
AudioManager.stopAllSounds(); AudioManager.stopAllSounds();
AudioManager.playShell(); AudioManager.playShell();