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/4] 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/4] 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/4] 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/4] 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(); }