From 40f58b21c66b1d883bbd0b5992da8098ed31674e Mon Sep 17 00:00:00 2001 From: tontyGH <39193182+tontyGH@users.noreply.github.com> Date: Tue, 26 May 2026 23:21:43 -0400 Subject: [PATCH 1/6] done --- DMCompiler/DMStandard/Types/Atoms/Mob.dm | 5 ++ DMCompiler/DMStandard/Types/Client.dm | 9 +-- OpenDreamRuntime/DreamConnection.cs | 77 ++++++++++++++---------- 3 files changed, 54 insertions(+), 37 deletions(-) diff --git a/DMCompiler/DMStandard/Types/Atoms/Mob.dm b/DMCompiler/DMStandard/Types/Atoms/Mob.dm index d8550a7728..5b3d1f5bdd 100644 --- a/DMCompiler/DMStandard/Types/Atoms/Mob.dm +++ b/DMCompiler/DMStandard/Types/Atoms/Mob.dm @@ -16,5 +16,10 @@ layer = MOB_LAYER proc/Login() + if(!loc) + var/turf/fallback_spawn = locate(1, 1, 1) // TODO: Find nearest non-dense turf + if(fallback_spawn) + loc = fallback_spawn proc/Logout() + del client diff --git a/DMCompiler/DMStandard/Types/Client.dm b/DMCompiler/DMStandard/Types/Client.dm index c07c511036..83e9c75c31 100644 --- a/DMCompiler/DMStandard/Types/Client.dm +++ b/DMCompiler/DMStandard/Types/Client.dm @@ -63,10 +63,11 @@ break if (mob == null) // No existing mob, create a default one - mob = new world.mob(locate(1,1,1)) // TODO: Find nearest non-dense turf - - eye = mob - statobj = mob + var/mob/initial_mob = new world.mob() + + eye = initial_mob + statobj = initial_mob + mob = initial_mob return mob proc/Del() diff --git a/OpenDreamRuntime/DreamConnection.cs b/OpenDreamRuntime/DreamConnection.cs index 52256253f9..03e969bd53 100644 --- a/OpenDreamRuntime/DreamConnection.cs +++ b/OpenDreamRuntime/DreamConnection.cs @@ -37,32 +37,21 @@ public sealed partial class DreamConnection { [ViewVariables] public DreamObjectMob? Mob { get => _mob; set { - if (_mob != value) { - var oldMob = _mob; - value?.IncRef(); - _mob?.DecRef(); - _mob = value; - - if (oldMob != null) { - oldMob.Key = null; - oldMob.Connection = null; - oldMob.SpawnProc("Logout").Dispose(); - } - - StatObj = new(value); - if (Eye != null && Eye == oldMob) { - Eye = value; - } + if (_mob == value) + return; - if (_mob != null) { - // If the mob is already owned by another player, kick them out - _mob.Connection?.Mob = null; + var oldMob = _mob; + var oldConnection = value?.Connection; + SetClientMob(value); - _mob.Connection = this; - _mob.Key = Key; - _mob.SpawnProc("Login", usr: _mob).Dispose(); - } + if(oldConnection is not null) { + oldConnection.HandleDisconnection(); + _mob!.SpawnProc("Logout").Dispose(); } + if(oldMob is not null) + oldMob!.SpawnProc("Logout").Dispose(); + if(_mob is not null) + _mob!.SpawnProc("Login", usr: _mob).Dispose(); } } @@ -125,21 +114,43 @@ public void HandleDisconnection() { _verbSystem?.RemoveConnectionFromRepeatingVerbs(this); Session = null; - if (_mob != null) { - // Don't null out the ckey here - _mob.SpawnProc("Logout").Dispose(); - - if (_mob != null) { // Logout() may have removed our mob - _mob.Connection = null; - _mob = null; - } - } - + Mob = null; Client.DecRef(); Client.Delete(); Client = null; } + /// + /// Sets the connection's mob without any side effects. + /// + private void SetClientMob(DreamObjectMob? newMob) { + if(newMob == _mob) + return; + + var oldMob = _mob; + _mob = newMob; + newMob?.IncRef(); + oldMob?.DecRef(); + + if (oldMob is not null) { + oldMob.Key = null; + oldMob.Connection = null; + } + + StatObj = new(newMob); + if (Eye is not null && Eye == oldMob) { + Eye = newMob; + } + + if (newMob is not null) { + // If the mob is already owned by another player, kick them out + newMob.Connection?.SetClientMob(null); + + newMob.Connection = this; + newMob.Key = Key; + } + } + public void UpdateStat() { if (Session == null || Client == null || _currentlyUpdatingStat) return; From c1ec4dffa3b267edf12fe3a1ef2a539ce64a1de5 Mon Sep 17 00:00:00 2001 From: tontyGH <39193182+tontyGH@users.noreply.github.com> Date: Tue, 26 May 2026 23:35:11 -0400 Subject: [PATCH 2/6] nullables --- OpenDreamRuntime/DreamConnection.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/OpenDreamRuntime/DreamConnection.cs b/OpenDreamRuntime/DreamConnection.cs index 03e969bd53..63115031e4 100644 --- a/OpenDreamRuntime/DreamConnection.cs +++ b/OpenDreamRuntime/DreamConnection.cs @@ -48,10 +48,9 @@ [ViewVariables] public DreamObjectMob? Mob { oldConnection.HandleDisconnection(); _mob!.SpawnProc("Logout").Dispose(); } - if(oldMob is not null) - oldMob!.SpawnProc("Logout").Dispose(); - if(_mob is not null) - _mob!.SpawnProc("Login", usr: _mob).Dispose(); + + oldMob?.SpawnProc("Logout").Dispose(); + _mob?.SpawnProc("Login", usr: _mob).Dispose(); } } From f2d339d98991e756d75eb8cba8c3d1885f93b7f7 Mon Sep 17 00:00:00 2001 From: tontyGH <39193182+tontyGH@users.noreply.github.com> Date: Thu, 28 May 2026 12:41:15 -0400 Subject: [PATCH 3/6] empty commit From 2fb0f4b06cb2eb57cd3e774f98fb158a9616705b Mon Sep 17 00:00:00 2001 From: tontyGH <39193182+tontyGH@users.noreply.github.com> Date: Fri, 5 Jun 2026 18:35:37 -0400 Subject: [PATCH 4/6] Delete the client directly instead of calling HandleDisconnect() --- OpenDreamRuntime/DreamConnection.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenDreamRuntime/DreamConnection.cs b/OpenDreamRuntime/DreamConnection.cs index 63115031e4..6fe1049313 100644 --- a/OpenDreamRuntime/DreamConnection.cs +++ b/OpenDreamRuntime/DreamConnection.cs @@ -45,7 +45,7 @@ [ViewVariables] public DreamObjectMob? Mob { SetClientMob(value); if(oldConnection is not null) { - oldConnection.HandleDisconnection(); + oldConnection.Client?.Delete(); _mob!.SpawnProc("Logout").Dispose(); } From e00e1f744b29d5b235e77a597582b1c3588172d6 Mon Sep 17 00:00:00 2001 From: tontyGH <39193182+tontyGH@users.noreply.github.com> Date: Fri, 12 Jun 2026 14:57:08 -0400 Subject: [PATCH 5/6] Fix that bug --- OpenDreamRuntime/DreamConnection.cs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/OpenDreamRuntime/DreamConnection.cs b/OpenDreamRuntime/DreamConnection.cs index 6fe1049313..b4f2cf5823 100644 --- a/OpenDreamRuntime/DreamConnection.cs +++ b/OpenDreamRuntime/DreamConnection.cs @@ -45,7 +45,7 @@ [ViewVariables] public DreamObjectMob? Mob { SetClientMob(value); if(oldConnection is not null) { - oldConnection.Client?.Delete(); + oldConnection.Client?.Delete(); // TODO: This should tell you why you disconnected _mob!.SpawnProc("Logout").Dispose(); } @@ -113,16 +113,22 @@ public void HandleDisconnection() { _verbSystem?.RemoveConnectionFromRepeatingVerbs(this); Session = null; - Mob = null; + // The client still has a reference to the mob when deleted, so we do this first Client.DecRef(); Client.Delete(); Client = null; + + if(Mob is not null) { + var oldMob = Mob; + SetClientMob(null, true); + oldMob.SpawnProc("Logout").Dispose(); + } } /// /// Sets the connection's mob without any side effects. /// - private void SetClientMob(DreamObjectMob? newMob) { + private void SetClientMob(DreamObjectMob? newMob, bool preserveKey = false) { if(newMob == _mob) return; @@ -132,7 +138,8 @@ private void SetClientMob(DreamObjectMob? newMob) { oldMob?.DecRef(); if (oldMob is not null) { - oldMob.Key = null; + if(!preserveKey) + oldMob.Key = null; oldMob.Connection = null; } @@ -146,7 +153,8 @@ private void SetClientMob(DreamObjectMob? newMob) { newMob.Connection?.SetClientMob(null); newMob.Connection = this; - newMob.Key = Key; + if(!preserveKey) + newMob.Key = Key; } } From 4e162f88b92038d80e345ce8f74f7d1e09875970 Mon Sep 17 00:00:00 2001 From: tontyGH <39193182+tontyGH@users.noreply.github.com> Date: Tue, 16 Jun 2026 12:56:59 -0400 Subject: [PATCH 6/6] "implements" client/Del() it doesn't actually do anything --- DMCompiler/DMStandard/Types/Client.dm | 1 - 1 file changed, 1 deletion(-) diff --git a/DMCompiler/DMStandard/Types/Client.dm b/DMCompiler/DMStandard/Types/Client.dm index 83e9c75c31..7512a31272 100644 --- a/DMCompiler/DMStandard/Types/Client.dm +++ b/DMCompiler/DMStandard/Types/Client.dm @@ -71,7 +71,6 @@ return mob proc/Del() - set opendream_unimplemented = TRUE proc/Topic(href, list/href_list, datum/hsrc) if (hsrc != null)