diff --git a/CHANGELOG.md b/CHANGELOG.md
index 62554a26..583052ea 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -50,6 +50,9 @@ This is the rolling changelog for TShock for Terraria. Use past tense when addin
* `OnPlaceTileEntity`: The check was newly added.
* `OnPlaceItemFrame`: The check was newly added.
* `OnFoodPlatterTryPlacing`: The check was newly added.
+* Fixed errors on startup not being reported to console. (@bartico6)
+* The server now correctly disconnects players with missing groups instead of throwing an exception, stalling the connection (@bartico6)
+* The server now rejects login attempts from players who would end up with a missing group. (@bartico6)
## TShock 4.5.4
* Fixed ridiculous typo in `GetDataHandlers` which caused TShock to read the wrong field in the packet for `usingBiomeTorches`. (@hakusaro, @Arthri)
diff --git a/TShockAPI/Commands.cs b/TShockAPI/Commands.cs
index 55d281c3..195ed2e2 100644
--- a/TShockAPI/Commands.cs
+++ b/TShockAPI/Commands.cs
@@ -832,10 +832,16 @@ namespace TShockAPI
(usingUUID && account.UUID == args.Player.UUID && !TShock.Config.Settings.DisableUUIDLogin &&
!String.IsNullOrWhiteSpace(args.Player.UUID)))
{
- args.Player.PlayerData = TShock.CharacterDB.GetPlayerData(args.Player, account.ID);
-
var group = TShock.Groups.GetGroupByName(account.Group);
+ if (!TShock.Groups.AssertGroupValid(args.Player, group, false))
+ {
+ args.Player.SendErrorMessage("Login attempt failed - see the message above.");
+ return;
+ }
+
+ args.Player.PlayerData = TShock.CharacterDB.GetPlayerData(args.Player, account.ID);
+
args.Player.Group = group;
args.Player.tempGroup = null;
args.Player.Account = account;
diff --git a/TShockAPI/DB/GroupManager.cs b/TShockAPI/DB/GroupManager.cs
index 3bb50881..750dc7a2 100644
--- a/TShockAPI/DB/GroupManager.cs
+++ b/TShockAPI/DB/GroupManager.cs
@@ -200,6 +200,45 @@ namespace TShockAPI.DB
LoadPermisions();
Group.DefaultGroup = GetGroupByName(TShock.Config.Settings.DefaultGuestGroupName);
+
+ AssertCoreGroupsPresent();
+ }
+
+ internal void AssertCoreGroupsPresent()
+ {
+ if (!GroupExists(TShock.Config.Settings.DefaultGuestGroupName))
+ {
+ TShock.Log.ConsoleError("The guest group could not be found. This may indicate a typo in the configuration file, or that the group was renamed or deleted.");
+ throw new Exception("The guest group could not be found.");
+ }
+
+ if (!GroupExists(TShock.Config.Settings.DefaultRegistrationGroupName))
+ {
+ TShock.Log.ConsoleError("The default usergroup could not be found. This may indicate a typo in the configuration file, or that the group was renamed or deleted.");
+ throw new Exception("The default usergroup could not be found.");
+ }
+ }
+
+ ///
+ /// Asserts that the group reference can be safely assigned to the player object.
+ /// If this assertion fails, and is true, the player is disconnected. If is false, the player will receive an error message.
+ ///
+ /// The player in question
+ /// The group we want to assign them
+ /// Whether or not failing this check disconnects the player.
+ ///
+ public bool AssertGroupValid(TSPlayer player, Group group, bool kick)
+ {
+ if (group == null)
+ {
+ if (kick)
+ player.Disconnect("Your account's group could not be loaded. Please contact server administrators about this.");
+ else
+ player.SendErrorMessage("Your account's group could not be loaded. Please contact server administrators about this.");
+ return false;
+ }
+
+ return true;
}
private void AddDefaultGroup(string name, string parent, string permissions)
diff --git a/TShockAPI/GetDataHandlers.cs b/TShockAPI/GetDataHandlers.cs
index 3bed28b2..2a0fbfe8 100644
--- a/TShockAPI/GetDataHandlers.cs
+++ b/TShockAPI/GetDataHandlers.cs
@@ -2456,10 +2456,13 @@ namespace TShockAPI
args.Player.State = 2;
NetMessage.SendData((int)PacketTypes.WorldInfo, args.Player.Index);
- args.Player.PlayerData = TShock.CharacterDB.GetPlayerData(args.Player, account.ID);
-
var group = TShock.Groups.GetGroupByName(account.Group);
+ if (!TShock.Groups.AssertGroupValid(args.Player, group, true))
+ return true;
+
+ args.Player.PlayerData = TShock.CharacterDB.GetPlayerData(args.Player, account.ID);
+
args.Player.Group = group;
args.Player.tempGroup = null;
args.Player.Account = account;
@@ -3037,6 +3040,9 @@ namespace TShockAPI
var group = TShock.Groups.GetGroupByName(account.Group);
+ if (!TShock.Groups.AssertGroupValid(args.Player, group, true))
+ return true;
+
args.Player.Group = group;
args.Player.tempGroup = null;
args.Player.Account = account;
diff --git a/TShockAPI/TShock.cs b/TShockAPI/TShock.cs
index 16fc1cb9..958d6507 100644
--- a/TShockAPI/TShock.cs
+++ b/TShockAPI/TShock.cs
@@ -386,8 +386,8 @@ namespace TShockAPI
}
catch (Exception ex)
{
- Log.Error("Fatal Startup Exception");
- Log.Error(ex.ToString());
+ Log.ConsoleError("Fatal Startup Exception");
+ Log.ConsoleError(ex.ToString());
Environment.Exit(1);
}
}