Index: binary-improvements/7dtd-server-fixes/src/API.cs
===================================================================
--- binary-improvements/7dtd-server-fixes/src/API.cs	(revision 358)
+++ binary-improvements/7dtd-server-fixes/src/API.cs	(revision 369)
@@ -1,9 +1,9 @@
 using System.Collections.Generic;
 using AllocsFixes.PersistentData;
-using System;
+using Platform.Steam;
 
 namespace AllocsFixes {
 	public class API : IModApi {
-		public void InitMod () {
+		public void InitMod (Mod _modInstance) {
 			ModEvents.GameStartDone.RegisterHandler (GameAwake);
 			ModEvents.GameShutdown.RegisterHandler (GameShutdown);
@@ -16,64 +16,44 @@
 
 		public void GameAwake () {
-			try {
-				PersistentContainer.Load ();
-			} catch (Exception e) {
-				Log.Out ("Error in StateManager.Awake: " + e);
-			}
+			PersistentContainer.Load ();
 		}
 
 		public void GameShutdown () {
-			try {
-				Log.Out ("Server shutting down!");
-				PersistentContainer.Instance.Save ();
-			} catch (Exception e) {
-				Log.Out ("Error in StateManager.Shutdown: " + e);
-			}
 		}
 
 		public void SavePlayerData (ClientInfo _cInfo, PlayerDataFile _playerDataFile) {
-			try {
-				PersistentContainer.Instance.Players [_cInfo.playerId, true].Update (_playerDataFile);
-			} catch (Exception e) {
-				Log.Out ("Error in GM_SavePlayerData: " + e);
-			}
+			PersistentContainer.Instance.Players [_cInfo.PlatformId, true].Update (_playerDataFile);
 		}
 
 		public void PlayerSpawning (ClientInfo _cInfo, int _chunkViewDim, PlayerProfile _playerProfile) {
-			try {
-				Log.Out ("Player connected" +
-					", entityid=" + _cInfo.entityId +
-					", name=" + _cInfo.playerName +
-					", steamid=" + _cInfo.playerId +
-					", steamOwner=" + _cInfo.ownerId +
-					", ip=" + _cInfo.ip
-				);
-			} catch (Exception e) {
-				Log.Out ("Error in AllocsLogFunctions.RequestToSpawnPlayer: " + e);
+			string owner = null;
+			if (_cInfo.PlatformId is UserIdentifierSteam identifierSteam) {
+				owner = identifierSteam.OwnerId.ToString ();
 			}
+
+			Log.Out ("Player connected" +
+			         ", entityid=" + _cInfo.entityId +
+			         ", name=" + _cInfo.playerName +
+			         ", pltfmid=" + (_cInfo.PlatformId?.CombinedString ?? "<unknown>") +
+			         ", crossid=" + (_cInfo.CrossplatformId?.CombinedString ?? "<unknown/none>") +
+			         ", steamOwner=" + (owner ?? "<unknown/none>") +
+			         ", ip=" + _cInfo.ip
+			);
 		}
 
 		public void PlayerDisconnected (ClientInfo _cInfo, bool _bShutdown) {
-			try {
-				Player p = PersistentContainer.Instance.Players [_cInfo.playerId, false];
-				if (p != null) {
-					p.SetOffline ();
-				} else {
-					Log.Out ("Disconnected player not found in client list...");
-				}
+			Player p = PersistentContainer.Instance.Players [_cInfo.PlatformId, false];
+			if (p != null) {
+				p.SetOffline ();
+			} else {
+				Log.Out ("Disconnected player not found in client list...");
+			}
 
-				PersistentContainer.Instance.Save ();
-			} catch (Exception e) {
-				Log.Out ("Error in AllocsLogFunctions.PlayerDisconnected: " + e);
-			}
+			PersistentContainer.Instance.Save ();
 		}
 
 		public void PlayerSpawned (ClientInfo _cInfo, RespawnType _respawnReason, Vector3i _spawnPos) {
-			try {
-				PersistentContainer.Instance.Players [_cInfo.playerId, true].SetOnline (_cInfo);
-				PersistentContainer.Instance.Save ();
-			} catch (Exception e) {
-				Log.Out ("Error in AllocsLogFunctions.PlayerSpawnedInWorld: " + e);
-			}
+			PersistentContainer.Instance.Players [_cInfo.PlatformId, true].SetOnline (_cInfo);
+			PersistentContainer.Instance.Save ();
 		}
 
@@ -88,5 +68,5 @@
 
 			if (_cInfo != null) {
-				Log.Out ("Sent chat hook reply to {0}", _cInfo.playerId);
+				Log.Out ("Sent chat hook reply to {0}", _cInfo.InternalId);
 				_cInfo.SendPackage (NetPackageManager.GetPackage<NetPackageChat> ().Setup (EChatType.Whisper, -1, ANSWER, "", false, null));
 			} else {
Index: binary-improvements/7dtd-server-fixes/src/LandClaimList.cs
===================================================================
--- binary-improvements/7dtd-server-fixes/src/LandClaimList.cs	(revision 358)
+++ binary-improvements/7dtd-server-fixes/src/LandClaimList.cs	(revision 369)
@@ -4,5 +4,5 @@
 
 namespace AllocsFixes {
-	public class LandClaimList {
+	public static class LandClaimList {
 		public delegate bool OwnerFilter (Player _owner);
 
@@ -41,7 +41,7 @@
 
 			foreach (KeyValuePair<PersistentPlayerData, List<Vector3i>> kvp in owners) {
-				Player p = PersistentContainer.Instance.Players [kvp.Key.PlayerId, false];
+				Player p = PersistentContainer.Instance.Players [kvp.Key.UserIdentifier, false];
 				if (p == null) {
-					p = new Player (kvp.Key.PlayerId);
+					p = new Player (kvp.Key.UserIdentifier);
 				}
 
@@ -67,6 +67,6 @@
 		}
 
-		public static OwnerFilter SteamIdFilter (string _steamId) {
-			return _p => _p.SteamID.Equals (_steamId);
+		public static OwnerFilter UserIdFilter (PlatformUserIdentifierAbs _userId) {
+			return _p => _p.PlatformId.Equals (_userId);
 		}
 
Index: binary-improvements/7dtd-server-fixes/src/PersistentData/PersistentContainer.cs
===================================================================
--- binary-improvements/7dtd-server-fixes/src/PersistentData/PersistentContainer.cs	(revision 358)
+++ binary-improvements/7dtd-server-fixes/src/PersistentData/PersistentContainer.cs	(revision 369)
@@ -46,5 +46,5 @@
 
 		public void Save () {
-			Stream stream = File.Open (GameUtils.GetSaveGameDir () + "/AllocsPeristentData.bin", FileMode.Create);
+			Stream stream = File.Open (GameIO.GetSaveGameDir () + "/AllocsPeristentData.bin", FileMode.Create);
 			BinaryFormatter bFormatter = new BinaryFormatter ();
 			bFormatter.Serialize (stream, this);
@@ -53,5 +53,5 @@
 
 		public static bool Load () {
-			if (!File.Exists (GameUtils.GetSaveGameDir () + "/AllocsPeristentData.bin")) {
+			if (!File.Exists (GameIO.GetSaveGameDir () + "/AllocsPeristentData.bin")) {
 				return false;
 			}
@@ -59,5 +59,5 @@
 			try {
 				PersistentContainer obj;
-				Stream stream = File.Open (GameUtils.GetSaveGameDir () + "/AllocsPeristentData.bin", FileMode.Open);
+				Stream stream = File.Open (GameIO.GetSaveGameDir () + "/AllocsPeristentData.bin", FileMode.Open);
 				BinaryFormatter bFormatter = new BinaryFormatter ();
 				obj = (PersistentContainer) bFormatter.Deserialize (stream);
Index: binary-improvements/7dtd-server-fixes/src/PersistentData/Player.cs
===================================================================
--- binary-improvements/7dtd-server-fixes/src/PersistentData/Player.cs	(revision 358)
+++ binary-improvements/7dtd-server-fixes/src/PersistentData/Player.cs	(revision 369)
@@ -1,4 +1,3 @@
 using System;
-using System.Runtime.Serialization;
 using UnityEngine;
 
@@ -6,5 +5,5 @@
 	[Serializable]
 	public class Player {
-		private readonly string steamId;
+		private readonly PlatformUserIdentifierAbs platformId;
 		private int entityId;
 		private string name;
@@ -12,65 +11,34 @@
 		private long totalPlayTime;
 
-		[OptionalField] private DateTime lastOnline;
+		private DateTime lastOnline;
 
 		private Inventory inventory;
 
-		[OptionalField] private int lastPositionX, lastPositionY, lastPositionZ;
+		private int lastPositionX, lastPositionY, lastPositionZ;
 
-		[OptionalField] [Obsolete ("experience no longer available, use level and expToNextLevel instead")]
-		private uint experience;
-
-		[OptionalField] private bool chatMuted;
-		[OptionalField] private int maxChatLength;
-		[OptionalField] private string chatColor;
-		[OptionalField] private bool chatName;
-		[OptionalField] private uint expToNextLevel;
-		[OptionalField] private int level;
+		private bool chatMuted;
+		private int maxChatLength;
+		private string chatColor;
+		private bool chatName;
+		private uint expToNextLevel;
+		private int level;
 
 		[NonSerialized] private ClientInfo clientInfo;
 
-		public string SteamID {
-			get { return steamId; }
-		}
+		public PlatformUserIdentifierAbs PlatformId => platformId;
 
-        public int EntityID {
-            get { return entityId; }
-        }
+		public int EntityID => entityId;
 
-		public string Name {
-			get { return name == null ? string.Empty : name; }
-		}
+		public string Name => name ?? string.Empty;
 
-		public string IP {
-			get { return ip == null ? string.Empty : ip; }
-		}
+		public string IP => ip ?? string.Empty;
 
-		public Inventory Inventory {
-			get {
-				if (inventory == null) {
-					inventory = new Inventory ();
-				}
+		public Inventory Inventory => inventory ?? (inventory = new Inventory ());
 
-				return inventory;
-			}
-		}
+		public bool IsOnline => clientInfo != null;
 
-		public bool IsOnline {
-			get { return clientInfo != null; }
-		}
+		public ClientInfo ClientInfo => clientInfo;
 
-		public ClientInfo ClientInfo {
-			get { return clientInfo; }
-		}
-
-		public EntityPlayer Entity {
-			get {
-				if (IsOnline) {
-					return GameManager.Instance.World.Players.dict [clientInfo.entityId];
-				}
-
-				return null;
-			}
-		}
+		public EntityPlayer Entity => IsOnline ? GameManager.Instance.World.Players.dict [clientInfo.entityId] : null;
 
 		public long TotalPlayTime {
@@ -84,43 +52,15 @@
 		}
 
-		public DateTime LastOnline {
-			get {
-				if (IsOnline) {
-					return DateTime.Now;
-				}
+		public DateTime LastOnline => IsOnline ? DateTime.Now : lastOnline;
 
-				return lastOnline;
-			}
-		}
+		public Vector3i LastPosition => IsOnline ? new Vector3i (Entity.GetPosition ()) : new Vector3i (lastPositionX, lastPositionY, lastPositionZ);
 
-		public Vector3i LastPosition {
-			get {
-				if (IsOnline) {
-					return new Vector3i (Entity.GetPosition ());
-				}
+		public bool LandProtectionActive =>
+			GameManager.Instance.World.IsLandProtectionValidForPlayer (GameManager.Instance
+				.GetPersistentPlayerList ().GetPlayerData (PlatformId));
 
-				return new Vector3i (lastPositionX, lastPositionY, lastPositionZ);
-			}
-		}
-
-		public bool LandProtectionActive {
-			get {
-				return GameManager.Instance.World.IsLandProtectionValidForPlayer (GameManager.Instance
-					.GetPersistentPlayerList ().GetPlayerData (SteamID));
-			}
-		}
-
-		public float LandProtectionMultiplier {
-			get {
-				return GameManager.Instance.World.GetLandProtectionHardnessModifierForPlayer (GameManager.Instance
-					.GetPersistentPlayerList ().GetPlayerData (SteamID));
-			}
-		}
-
-
-		[Obsolete ("Experience no longer available, use Level instead")]
-		public uint Experience {
-			get { return 0; }
-		}
+		public float LandProtectionMultiplier =>
+			GameManager.Instance.World.GetLandProtectionHardnessModifierForPlayer (GameManager.Instance
+				.GetPersistentPlayerList ().GetPlayerData (PlatformId));
 
 		public float Level {
@@ -135,6 +75,6 @@
 
 		public bool IsChatMuted {
-			get { return chatMuted; }
-			set { chatMuted = value; }
+			get => chatMuted;
+			set => chatMuted = value;
 		}
 
@@ -147,10 +87,10 @@
 				return maxChatLength;
 			}
-			set { maxChatLength = value; }
+			set => maxChatLength = value;
 		}
 
 		public string ChatColor {
 			get {
-				if (chatColor == null || chatColor == "") {
+				if (string.IsNullOrEmpty (chatColor)) {
 					chatColor = "";
 				}
@@ -159,15 +99,14 @@
 			}
 
-			set { chatColor = value; }
+			set => chatColor = value;
 		}
 
 		public bool ChatName {
-			get { return chatName; }
-
-			set { chatName = value; }
+			get => chatName;
+			set => chatName = value;
 		}
 
-		public Player (string _steamId) {
-			steamId = _steamId;
+		public Player (PlatformUserIdentifierAbs _platformId) {
+			platformId = _platformId;
 			inventory = new Inventory ();
 		}
@@ -178,5 +117,5 @@
 			}
 
-			Log.Out ("Player set to offline: " + steamId);
+			Log.Out ("Player set to offline: " + platformId);
 			lastOnline = DateTime.Now;
 			try {
@@ -194,5 +133,5 @@
 
 		public void SetOnline (ClientInfo _ci) {
-			Log.Out ("Player set to online: " + steamId);
+			Log.Out ("Player set to online: " + platformId);
 			clientInfo = _ci;
             entityId = _ci.entityId;
@@ -222,4 +161,5 @@
 			}
 		}
+
 	}
 }
Index: binary-improvements/7dtd-server-fixes/src/PersistentData/Players.cs
===================================================================
--- binary-improvements/7dtd-server-fixes/src/PersistentData/Players.cs	(revision 358)
+++ binary-improvements/7dtd-server-fixes/src/PersistentData/Players.cs	(revision 369)
@@ -2,57 +2,45 @@
 using System.Collections.Generic;
 using System.Text.RegularExpressions;
+using Platform.Steam;
 
 namespace AllocsFixes.PersistentData {
 	[Serializable]
 	public class Players {
-		public readonly Dictionary<string, Player> Dict = new Dictionary<string, Player> (StringComparer.OrdinalIgnoreCase);
+		public readonly Dictionary<PlatformUserIdentifierAbs, Player> Dict = new Dictionary<PlatformUserIdentifierAbs, Player> ();
 
-		public Player this [string _steamId, bool _create] {
+		public Player this [PlatformUserIdentifierAbs _platformId, bool _create] {
 			get {
-				if (string.IsNullOrEmpty (_steamId)) {
+				if (_platformId == null) {
 					return null;
 				}
 
-				if (Dict.ContainsKey (_steamId)) {
-					return Dict [_steamId];
+				if (Dict.TryGetValue (_platformId, out Player pOld)) {
+					return pOld;
 				}
 
-				if (!_create || _steamId.Length != 17) {
+				if (!_create) {
 					return null;
 				}
 
-				Log.Out ("Created new player entry for ID: " + _steamId);
-				Player p = new Player (_steamId);
-				Dict.Add (_steamId, p);
+				Log.Out ("Created new player entry for ID: " + _platformId);
+				Player p = new Player (_platformId);
+				Dict.Add (_platformId, p);
 				return p;
 			}
 		}
 
-		public int Count {
-			get { return Dict.Count; }
-		}
+		public int Count => Dict.Count;
 
-//		public Player GetPlayerByNameOrId (string _nameOrId, bool _ignoreColorCodes)
-//		{
-//			string sid = GetSteamID (_nameOrId, _ignoreColorCodes);
-//			if (sid != null)
-//				return this [sid];
-//			else
-//				return null;
-//		}
-
-		public string GetSteamID (string _nameOrId, bool _ignoreColorCodes) {
-			if (_nameOrId == null || _nameOrId.Length == 0) {
+		public PlatformUserIdentifierAbs GetSteamID (string _nameOrId, bool _ignoreColorCodes) {
+			if (string.IsNullOrEmpty (_nameOrId)) {
 				return null;
 			}
 
-			long tempLong;
-			if (_nameOrId.Length == 17 && long.TryParse (_nameOrId, out tempLong)) {
-				return _nameOrId;
+			if (PlatformUserIdentifierAbs.TryFromCombinedString (_nameOrId, out PlatformUserIdentifierAbs userId)) {
+				return userId;
 			}
 
-			int entityId;
-			if (int.TryParse (_nameOrId, out entityId)) {
-				foreach (KeyValuePair<string, Player> kvp in Dict) {
+			if (int.TryParse (_nameOrId, out int entityId)) {
+				foreach (KeyValuePair<PlatformUserIdentifierAbs, Player> kvp in Dict) {
 					if (kvp.Value.IsOnline && kvp.Value.EntityID == entityId) {
 						return kvp.Key;
@@ -61,5 +49,5 @@
 			}
 
-			foreach (KeyValuePair<string, Player> kvp in Dict) {
+			foreach (KeyValuePair<PlatformUserIdentifierAbs, Player> kvp in Dict) {
 				string name = kvp.Value.Name;
 				if (_ignoreColorCodes) {
