private bool CheckCCP(SteamHelper.DLC_BitMask dlc) { if (dlc == SteamHelper.DLC_BitMask.ModderPack1) { return(true); } if (dlc == SteamHelper.DLC_BitMask.ModderPack2) { return(true); } if (dlc == SteamHelper.DLC_BitMask.ModderPack3) { return(true); } if (dlc == SteamHelper.DLC_BitMask.ModderPack4) { return(true); } if (dlc == SteamHelper.DLC_BitMask.ModderPack5) { return(true); } if (dlc == SteamHelper.DLC_BitMask.ModderPack6) { return(true); } return(false); }
private bool CheckCCP(SteamHelper.DLC_BitMask dlc) { if (dlc == SteamHelper.DLC_BitMask.ModderPack1) { author = "Shroomblaze"; } else if (dlc == SteamHelper.DLC_BitMask.ModderPack2) { author = "GCVos"; } else if (dlc == SteamHelper.DLC_BitMask.ModderPack3) { author = "Avanya"; } else if (dlc == SteamHelper.DLC_BitMask.ModderPack4) { author = "KingLeno"; } else if (dlc == SteamHelper.DLC_BitMask.ModderPack5) { author = "AmiPolizeiFunk"; } else if (dlc == SteamHelper.DLC_BitMask.ModderPack6) { author = "Ryuichi Kaminogi"; } else { return(false); } return(true); }
public static DLCComparison Compare(SteamHelper.DLC_BitMask server, SteamHelper.DLC_BitMask client) { return(new DLCComparison { ServerMissing = ~server & client, ClientMissing = server & ~client, }); }
private void SetDLCSprite(UISprite sprite, SteamHelper.DLC_BitMask dlc) { if (dlc == SteamHelper.DLC_BitMask.None) { return; } sprite.isVisible = true; if (dlc == SteamHelper.DLC_BitMask.DeluxeDLC) { sprite.tooltip = "Deluxe Upgrade Pack"; sprite.spriteName = "DeluxeIcon"; } else if (dlc == SteamHelper.DLC_BitMask.AfterDarkDLC) { sprite.tooltip = "After Dark DLC"; sprite.spriteName = "ADIcon"; } else if (dlc == SteamHelper.DLC_BitMask.SnowFallDLC) { sprite.tooltip = "Snow Fall DLC"; sprite.spriteName = "WWIcon"; } else if (dlc == SteamHelper.DLC_BitMask.NaturalDisastersDLC) { sprite.tooltip = "Natural Disasters DLC"; sprite.spriteName = "NaturalDisastersIcon"; } else if (dlc == SteamHelper.DLC_BitMask.InMotionDLC) { sprite.tooltip = "Mass Transit DLC"; sprite.spriteName = "MassTransitIcon"; } else if (dlc == SteamHelper.DLC_BitMask.GreenCitiesDLC) { sprite.tooltip = "Green Cities DLC"; sprite.spriteName = "GreenCitiesIcon"; } else if (dlc == SteamHelper.DLC_BitMask.ParksDLC) { sprite.tooltip = "Parklife DLC"; sprite.spriteName = "ParkLifeIcon"; } else if (dlc == SteamHelper.DLC_BitMask.IndustryDLC) { sprite.tooltip = "Industries DLC"; sprite.spriteName = "IndustriesIcon"; } else if (dlc == SteamHelper.DLC_BitMask.CampusDLC) { sprite.tooltip = "Campus DLC"; sprite.spriteName = "CampusIcon"; } else if (dlc == SteamHelper.DLC_BitMask.UrbanDLC) { sprite.tooltip = "Sunset Harbor DLC"; sprite.spriteName = "DonutIcon"; } else if (dlc == SteamHelper.DLC_BitMask.Football) { sprite.tooltip = "Match Day DLC"; sprite.spriteName = "MDIcon"; } else if (dlc == SteamHelper.DLC_BitMask.Football2345) { sprite.tooltip = "Stadiums: European Club Pack DLC"; sprite.spriteName = "StadiumsDLCIcon"; } else if (dlc == SteamHelper.DLC_BitMask.OrientalBuildings) { sprite.tooltip = "Pearls from the East DLC"; sprite.spriteName = "ChineseBuildingsTagIcon"; } else if (dlc == SteamHelper.DLC_BitMask.MusicFestival) { sprite.tooltip = "Concerts DLC"; sprite.spriteName = "ConcertsIcon"; } else if (dlc == SteamHelper.DLC_BitMask.ModderPack1) { sprite.tooltip = "Art Deco Content Creator Pack by Shroomblaze"; sprite.spriteName = "ArtDecoIcon"; } else if (dlc == SteamHelper.DLC_BitMask.ModderPack2) { sprite.tooltip = "High-Tech Buildings Content Creator Pack by GCVos"; sprite.spriteName = "HighTechIcon"; } else if (dlc == SteamHelper.DLC_BitMask.ModderPack3) { sprite.tooltip = "European Suburbias Content Creator Pack by Avanya"; sprite.spriteName = "Modderpack3Icon"; } else if (dlc == SteamHelper.DLC_BitMask.ModderPack4) { sprite.tooltip = "University City Content Creator Pack by KingLeno"; sprite.spriteName = "Modderpack4Icon"; } else if (dlc == SteamHelper.DLC_BitMask.ModderPack5) { sprite.tooltip = "Modern City Center Content Creator Pack by AmiPolizeiFunk"; sprite.spriteName = "Modderpack5Icon"; } else if (dlc == SteamHelper.DLC_BitMask.ModderPack6) { sprite.tooltip = "Modern Japan Content Creator Pack by Ryuichi Kaminogi"; sprite.spriteName = "Modderpack6Icon"; } else if (dlc == SteamHelper.DLC_BitMask.ModderPack7) { sprite.tooltip = "Train Stations Content Creator Pack by BadPeanut"; sprite.spriteName = "Modderpack7Icon"; } else if (dlc == SteamHelper.DLC_BitMask.ModderPack8) { sprite.tooltip = "Bridges & Piers Content Creator Pack by Armesto"; sprite.spriteName = "Modderpack8Icon"; } else { sprite.tooltip = "Unknown DLC"; sprite.spriteName = "ToolbarIconHelp"; } }
public override void OnBeforeLoadData() { base.OnBeforeLoadData(); // determine vanilla speed limits and customizable NetInfos SteamHelper.DLC_BitMask dlcMask = SteamHelper.GetOwnedDLCMask(); int numLoaded = PrefabCollection <NetInfo> .LoadedCount(); vanillaLaneSpeedLimitsByNetInfoName.Clear(); customizableNetInfos.Clear(); CustomLaneSpeedLimitIndexByNetInfoName.Clear(); childNetInfoNamesByCustomizableNetInfoName.Clear(); NetInfoByName.Clear(); List <NetInfo> mainNetInfos = new List <NetInfo>(); Log.Info($"SpeedLimitManager.OnBeforeLoadData: {numLoaded} NetInfos loaded."); for (uint i = 0; i < numLoaded; ++i) { NetInfo info = PrefabCollection <NetInfo> .GetLoaded(i); if (info == null || info.m_netAI == null || !(info.m_netAI is RoadBaseAI || info.m_netAI is MetroTrackAI || info.m_netAI is TrainTrackBaseAI) || !(info.m_dlcRequired == 0 || (uint)(info.m_dlcRequired & dlcMask) != 0u)) { if (info == null) { Log.Warning($"SpeedLimitManager.OnBeforeLoadData: NetInfo @ {i} is null!"); } continue; } string infoName = info.name; if (infoName == null) { Log.Warning($"SpeedLimitManager.OnBeforeLoadData: NetInfo name @ {i} is null!"); continue; } if (!vanillaLaneSpeedLimitsByNetInfoName.ContainsKey(infoName)) { if (info.m_lanes == null) { Log.Warning($"SpeedLimitManager.OnBeforeLoadData: NetInfo lanes @ {i} is null!"); continue; } Log.Info($"Loaded road NetInfo: {infoName}"); NetInfoByName[infoName] = info; mainNetInfos.Add(info); float[] vanillaLaneSpeedLimits = new float[info.m_lanes.Length]; for (int k = 0; k < info.m_lanes.Length; ++k) { vanillaLaneSpeedLimits[k] = info.m_lanes[k].m_speedLimit; } vanillaLaneSpeedLimitsByNetInfoName[infoName] = vanillaLaneSpeedLimits; } } mainNetInfos.Sort(delegate(NetInfo a, NetInfo b) { bool aRoad = a.m_netAI is RoadBaseAI; bool bRoad = b.m_netAI is RoadBaseAI; if (aRoad != bRoad) { if (aRoad) { return(-1); } else { return(1); } } bool aTrain = a.m_netAI is TrainTrackBaseAI; bool bTrain = b.m_netAI is TrainTrackBaseAI; if (aTrain != bTrain) { if (aTrain) { return(1); } else { return(-1); } } bool aMetro = a.m_netAI is MetroTrackAI; bool bMetro = b.m_netAI is MetroTrackAI; if (aMetro != bMetro) { if (aMetro) { return(1); } else { return(-1); } } if (aRoad && bRoad) { bool aHighway = ((RoadBaseAI)a.m_netAI).m_highwayRules; bool bHighway = ((RoadBaseAI)b.m_netAI).m_highwayRules; if (aHighway != bHighway) { if (aHighway) { return(1); } else { return(-1); } } } int aNumVehicleLanes = 0; foreach (NetInfo.Lane lane in a.m_lanes) { if ((lane.m_laneType & LANE_TYPES) != NetInfo.LaneType.None) { ++aNumVehicleLanes; } } int bNumVehicleLanes = 0; foreach (NetInfo.Lane lane in b.m_lanes) { if ((lane.m_laneType & LANE_TYPES) != NetInfo.LaneType.None) { ++bNumVehicleLanes; } } int res = aNumVehicleLanes.CompareTo(bNumVehicleLanes); if (res == 0) { return(a.name.CompareTo(b.name)); } else { return(res); } }); // identify parent NetInfos int x = 0; while (x < mainNetInfos.Count) { NetInfo info = mainNetInfos[x]; string infoName = info.name; // find parent with prefix name bool foundParent = false; for (int y = 0; y < mainNetInfos.Count; ++y) { NetInfo parentInfo = mainNetInfos[y]; if (info.m_placementStyle == ItemClass.Placement.Procedural && !infoName.Equals(parentInfo.name) && infoName.StartsWith(parentInfo.name)) { Log.Info($"Identified child NetInfo {infoName} of parent {parentInfo.name}"); List <string> childNetInfoNames; if (!childNetInfoNamesByCustomizableNetInfoName.TryGetValue(parentInfo.name, out childNetInfoNames)) { childNetInfoNamesByCustomizableNetInfoName[parentInfo.name] = childNetInfoNames = new List <string>(); } childNetInfoNames.Add(info.name); NetInfoByName[infoName] = info; foundParent = true; break; } } if (foundParent) { mainNetInfos.RemoveAt(x); } else { ++x; } } customizableNetInfos = mainNetInfos; }
Package.Asset[] GetLoadQueue(HashSet <string> styleBuildings) { Package[] packages = PackageManager.allPackages.ToArray(); Array.Sort(packages, (a, b) => string.Compare(a.packageName, b.packageName)); List <Package.Asset> assets = new List <Package.Asset>(8); List <CustomAssetMetaData> metas = new List <CustomAssetMetaData>(8); // Why this load order? By having related and identical assets close to each other, we get more loader cache hits (of meshes and textures) // in Sharing. We also get faster disk reads. // [0] propvar and prop, citizen [1] prop, tree [2] pillar and elevation and road [3] road // [4] sub-building and building [5] building [6] trailer and vehicle [7] vehicle List <Package.Asset>[] queues = { new List <Package.Asset>(4), new List <Package.Asset>(64), new List <Package.Asset>(4), new List <Package.Asset>(4), new List <Package.Asset>(4), new List <Package.Asset>(64), new List <Package.Asset>(32), new List <Package.Asset>(32) }; SteamHelper.DLC_BitMask notMask = ~SteamHelper.GetOwnedDLCMask(); bool loadEnabled = Settings.settings.loadEnabled, loadUsed = Settings.settings.loadUsed, report = loadUsed && Settings.settings.reportAssets; //PrintPackages(packages); foreach (Package p in packages) { CustomAssetMetaData meta = null; try { assets.Clear(); assets.AddRange(p.FilterAssets(UserAssetType.CustomAssetMetaData)); if (assets.Count == 0) { continue; } if (report) { AssetReport.instance.AddPackage(p); } bool enabled = loadEnabled && IsEnabled(p); if (assets.Count == 1) // the common case { bool want = enabled || styleBuildings.Contains(assets[0].fullName); // Fast exit. if (!want && !(loadUsed && UsedAssets.instance.GotPackage(p.packageName))) { continue; } meta = AssetDeserializer.Instantiate(assets[0]) as CustomAssetMetaData; bool used = loadUsed && UsedAssets.instance.IsUsed(meta); if (used || want && (AssetImporterAssetTemplate.GetAssetDLCMask(meta) & notMask) == 0) { CustomAssetMetaData.Type type = meta.type; int offset = type == CustomAssetMetaData.Type.Trailer || type == CustomAssetMetaData.Type.SubBuilding || type == CustomAssetMetaData.Type.PropVariation || type >= CustomAssetMetaData.Type.RoadElevation ? -1 : 0; AddToQueue(queues, meta, offset, !(enabled | used)); } } else { bool want = enabled; // Fast exit. if (!want) { for (int i = 0; i < assets.Count; i++) { want = want || styleBuildings.Contains(assets[i].fullName); } if (!want && !(loadUsed && UsedAssets.instance.GotPackage(p.packageName))) { continue; } } metas.Clear(); bool used = false; for (int i = 0; i < assets.Count; i++) { meta = AssetDeserializer.Instantiate(assets[i]) as CustomAssetMetaData; metas.Add(meta); want = want && (AssetImporterAssetTemplate.GetAssetDLCMask(meta) & notMask) == 0; used = used || loadUsed && UsedAssets.instance.IsUsed(meta); } if (want | used) { metas.Sort((a, b) => b.type - a.type); // prop variation, sub-building, trailer, elevation, pillar before main asset CustomAssetMetaData.Type type = metas[0].type; int offset = type == CustomAssetMetaData.Type.Trailer || type == CustomAssetMetaData.Type.SubBuilding || type == CustomAssetMetaData.Type.PropVariation || type >= CustomAssetMetaData.Type.RoadElevation ? -1 : 0; bool dontSpawn = !(enabled | used); for (int i = 0; i < metas.Count; i++) { AddToQueue(queues, metas[i], offset, dontSpawn); } } } } catch (Exception e) { AssetFailed(meta?.assetRef?.fullName ?? p.packageName + "." + p.packageMainAsset, e); } } Package.Asset[] queue = new Package.Asset[queues.Select(lst => lst.Count).Sum()]; for (int i = 0, k = 0; i < queues.Length; k += queues[i].Count, i++) { queues[i].CopyTo(queue, k); } return(queue); }
public void HandleOnServer(ConnectionRequestCommand command, NetPeer peer) { Log.Info("Received connection request."); string joiningVersion = command.GameVersion; string appVersion = BuildConfig.applicationVersion; MatchVersionString(ref joiningVersion); MatchVersionString(ref appVersion); // Check to see if the game versions match if (joiningVersion != appVersion) { Log.Info($"Connection rejected: Game versions {joiningVersion} (client) and {appVersion} (server) differ."); Command.SendToClient(peer, new ConnectionResultCommand { Success = false, Reason = $"Client and server have different game versions. Client: {joiningVersion}, Server: {appVersion}." }); return; } // Check to see if the mod version matches Version version = Assembly.GetAssembly(typeof(Client)).GetName().Version; string versionString = $"{version.Major}.{version.Minor}"; if (command.ModVersion != versionString) { Log.Info($"Connection rejected: Mod versions {command.ModVersion} (client) and {versionString} (server) differ."); Command.SendToClient(peer, new ConnectionResultCommand { Success = false, Reason = $"Client and server have different CSM Mod versions. Client: {command.ModVersion}, Server: {versionString}." }); return; } // Check the client username to see if anyone on the server already have a username bool hasExistingPlayer = MultiplayerManager.Instance.PlayerList.Contains(command.Username); if (hasExistingPlayer) { Log.Info($"Connection rejected: Username {command.Username} already in use."); Command.SendToClient(peer, new ConnectionResultCommand { Success = false, Reason = "This username is already in use." }); return; } // Check the password to see if it matches (only if the server has provided a password). if (!string.IsNullOrEmpty(MultiplayerManager.Instance.CurrentServer.Config.Password)) { if (command.Password != MultiplayerManager.Instance.CurrentServer.Config.Password) { Log.Warn("Connection rejected: Invalid password provided!"); Command.SendToClient(peer, new ConnectionResultCommand { Success = false, Reason = "Invalid password for this server." }); return; } } SteamHelper.DLC_BitMask dlcMask = DLCHelper.GetOwnedDLCs(); // Check both client have the same DLCs enabled if (!command.DLCBitMask.Equals(dlcMask)) { Log.Info($"Connection rejected: DLC bit mask {command.DLCBitMask} (client) and {dlcMask} (server) differ."); Command.SendToClient(peer, new ConnectionResultCommand { Success = false, Reason = "DLCs don't match", DLCBitMask = dlcMask }); return; } // Check that no other player is currently connecting bool clientJoining = false; foreach (Player p in MultiplayerManager.Instance.CurrentServer.ConnectedPlayers.Values) { if (p.Status != ClientStatus.Connected) { clientJoining = true; } } if (clientJoining) { Command.SendToClient(peer, new ConnectionResultCommand { Success = false, Reason = "A client is already joining", DLCBitMask = dlcMask }); return; } // Add the new player as a connected player Player newPlayer = new Player(peer, command.Username); MultiplayerManager.Instance.CurrentServer.ConnectedPlayers[peer.Id] = newPlayer; // Send the result command Command.SendToClient(peer, new ConnectionResultCommand { Success = true, ClientId = peer.Id }); PrepareWorldLoad(newPlayer); MultiplayerManager.Instance.CurrentServer.HandlePlayerConnect(newPlayer); }
private static SteamHelper.DLC_BitMask RemoveRadioStations(SteamHelper.DLC_BitMask bitmask) { return(bitmask & ~RadioStations); }
private bool CheckDLCFilters(SteamHelper.DLC_BitMask dlc) { if (dlc != SteamHelper.DLC_BitMask.None && UISearchBox.instance.extraFiltersPanel.DLCDropDownMenu.selectedIndex == (int)UIFilterExtra.DLCDropDownOptions.BaseGame) { return(false); } else if (dlc != SteamHelper.DLC_BitMask.DeluxeDLC && UISearchBox.instance.extraFiltersPanel.DLCDropDownMenu.selectedIndex == (int)UIFilterExtra.DLCDropDownOptions.DeluxeUpgrade) { return(false); } else if (dlc != SteamHelper.DLC_BitMask.AfterDarkDLC && UISearchBox.instance.extraFiltersPanel.DLCDropDownMenu.selectedIndex == (int)UIFilterExtra.DLCDropDownOptions.AfterDark) { return(false); } else if (dlc != SteamHelper.DLC_BitMask.SnowFallDLC && UISearchBox.instance.extraFiltersPanel.DLCDropDownMenu.selectedIndex == (int)UIFilterExtra.DLCDropDownOptions.SnowFall) { return(false); } else if (dlc != SteamHelper.DLC_BitMask.NaturalDisastersDLC && UISearchBox.instance.extraFiltersPanel.DLCDropDownMenu.selectedIndex == (int)UIFilterExtra.DLCDropDownOptions.NaturalDisasters) { return(false); } else if (dlc != SteamHelper.DLC_BitMask.InMotionDLC && UISearchBox.instance.extraFiltersPanel.DLCDropDownMenu.selectedIndex == (int)UIFilterExtra.DLCDropDownOptions.MassTransit) { return(false); } else if (dlc != SteamHelper.DLC_BitMask.GreenCitiesDLC && UISearchBox.instance.extraFiltersPanel.DLCDropDownMenu.selectedIndex == (int)UIFilterExtra.DLCDropDownOptions.GreenCities) { return(false); } else if (dlc != SteamHelper.DLC_BitMask.ParksDLC && UISearchBox.instance.extraFiltersPanel.DLCDropDownMenu.selectedIndex == (int)UIFilterExtra.DLCDropDownOptions.Parklife) { return(false); } else if (dlc != SteamHelper.DLC_BitMask.IndustryDLC && UISearchBox.instance.extraFiltersPanel.DLCDropDownMenu.selectedIndex == (int)UIFilterExtra.DLCDropDownOptions.Industries) { return(false); } else if (dlc != SteamHelper.DLC_BitMask.CampusDLC && UISearchBox.instance.extraFiltersPanel.DLCDropDownMenu.selectedIndex == (int)UIFilterExtra.DLCDropDownOptions.Campus) { return(false); } else if (dlc != SteamHelper.DLC_BitMask.UrbanDLC && UISearchBox.instance.extraFiltersPanel.DLCDropDownMenu.selectedIndex == (int)UIFilterExtra.DLCDropDownOptions.SunsetHarbor) { return(false); } else if (dlc != SteamHelper.DLC_BitMask.Football && UISearchBox.instance.extraFiltersPanel.DLCDropDownMenu.selectedIndex == (int)UIFilterExtra.DLCDropDownOptions.MatchDay) { return(false); } else if (dlc != SteamHelper.DLC_BitMask.Football2345 && UISearchBox.instance.extraFiltersPanel.DLCDropDownMenu.selectedIndex == (int)UIFilterExtra.DLCDropDownOptions.Stadiums) { return(false); } else if (dlc != SteamHelper.DLC_BitMask.OrientalBuildings && UISearchBox.instance.extraFiltersPanel.DLCDropDownMenu.selectedIndex == (int)UIFilterExtra.DLCDropDownOptions.PearlsFromTheEast) { return(false); } else if (dlc != SteamHelper.DLC_BitMask.MusicFestival && UISearchBox.instance.extraFiltersPanel.DLCDropDownMenu.selectedIndex == (int)UIFilterExtra.DLCDropDownOptions.Concerts) { return(false); } else if (dlc != SteamHelper.DLC_BitMask.ModderPack1 && UISearchBox.instance.extraFiltersPanel.DLCDropDownMenu.selectedIndex == (int)UIFilterExtra.DLCDropDownOptions.ArtDeco) { return(false); } else if (dlc != SteamHelper.DLC_BitMask.ModderPack2 && UISearchBox.instance.extraFiltersPanel.DLCDropDownMenu.selectedIndex == (int)UIFilterExtra.DLCDropDownOptions.HighTechBuildings) { return(false); } else if (dlc != SteamHelper.DLC_BitMask.ModderPack3 && UISearchBox.instance.extraFiltersPanel.DLCDropDownMenu.selectedIndex == (int)UIFilterExtra.DLCDropDownOptions.EuropeanSuburbias) { return(false); } else if (dlc != SteamHelper.DLC_BitMask.ModderPack4 && UISearchBox.instance.extraFiltersPanel.DLCDropDownMenu.selectedIndex == (int)UIFilterExtra.DLCDropDownOptions.UniverisityCity) { return(false); } else if (dlc != SteamHelper.DLC_BitMask.ModderPack5 && UISearchBox.instance.extraFiltersPanel.DLCDropDownMenu.selectedIndex == (int)UIFilterExtra.DLCDropDownOptions.ModernCityCenter) { return(false); } else if (dlc != SteamHelper.DLC_BitMask.ModderPack6 && UISearchBox.instance.extraFiltersPanel.DLCDropDownMenu.selectedIndex == (int)UIFilterExtra.DLCDropDownOptions.ModernJapan) { return(false); } else if (dlc != SteamHelper.DLC_BitMask.ModderPack7 && UISearchBox.instance.extraFiltersPanel.DLCDropDownMenu.selectedIndex == (int)UIFilterExtra.DLCDropDownOptions.TrainStations) { return(false); } else if (dlc != SteamHelper.DLC_BitMask.ModderPack8 && UISearchBox.instance.extraFiltersPanel.DLCDropDownMenu.selectedIndex == (int)UIFilterExtra.DLCDropDownOptions.BridgesPiers) { return(false); } return(true); }
public void HandleOnServer(ConnectionRequestCommand command, NetPeer peer) { _logger.Info("Received connection request."); // Check to see if the game versions match if (command.GameVersion != BuildConfig.applicationVersion) { _logger.Info($"Connection rejected: Game versions {command.GameVersion} (client) and {BuildConfig.applicationVersion} (server) differ."); Command.SendToClient(peer, new ConnectionResultCommand { Success = false, Reason = $"Client and server have different game versions. Client: {command.GameVersion}, Server: {BuildConfig.applicationVersion}." }); return; } // Check to see if the mod version matches Version version = Assembly.GetAssembly(typeof(Client)).GetName().Version; string versionString = $"{version.Major}.{version.Minor}"; if (command.ModVersion != versionString) { _logger.Info($"Connection rejected: Mod versions {command.ModVersion} (client) and {versionString} (server) differ."); Command.SendToClient(peer, new ConnectionResultCommand { Success = false, Reason = $"Client and server have different CSM Mod versions. Client: {command.ModVersion}, Server: {versionString}." }); return; } // Check the client username to see if anyone on the server already have a username bool hasExistingPlayer = MultiplayerManager.Instance.PlayerList.Contains(command.Username); if (hasExistingPlayer) { _logger.Info($"Connection rejected: Username {command.Username} already in use."); Command.SendToClient(peer, new ConnectionResultCommand { Success = false, Reason = "This username is already in use." }); return; } // Check the password to see if it matches (only if the server has provided a password). if (!string.IsNullOrEmpty(MultiplayerManager.Instance.CurrentServer.Config.Password)) { if (command.Password != MultiplayerManager.Instance.CurrentServer.Config.Password) { _logger.Warn("Connection rejected: Invalid password provided!"); Command.SendToClient(peer, new ConnectionResultCommand { Success = false, Reason = "Invalid password for this server." }); return; } } SteamHelper.DLC_BitMask dlcMask = DLCHelper.GetOwnedDLCs(); // Check both client have the same DLCs enabled if (!command.DLCBitMask.Equals(dlcMask)) { _logger.Info($"Connection rejected: DLC bit mask {command.DLCBitMask} (client) and {dlcMask} (server) differ."); Command.SendToClient(peer, new ConnectionResultCommand { Success = false, Reason = "DLCs don't match", DLCBitMask = dlcMask }); return; } // Add the new player as a connected player Player newPlayer = new Player(peer, command.Username); MultiplayerManager.Instance.CurrentServer.ConnectedPlayers[peer.Id] = newPlayer; // Get a serialized version of the server world to send to the player. if (command.RequestWorld) { // Get the world byte[] world = WorldManager.GetWorld(); // Send the result command Command.SendToClient(peer, new ConnectionResultCommand { Success = true, ClientId = peer.Id, World = world }); } else { // Send the result command Command.SendToClient(peer, new ConnectionResultCommand { Success = true, ClientId = peer.Id }); } MultiplayerManager.Instance.CurrentServer.HandlePlayerConnect(newPlayer); }
Package.Asset[] GetLoadQueue(HashSet <string> styleBuildings) { Package.AssetType[] customAssets = { UserAssetType.CustomAssetMetaData }; Package[] packages = { }; try { packages = PackageManager.allPackages.Where(p => p.FilterAssets(customAssets).Any()).ToArray(); Array.Sort(packages, PackageComparison); } catch (Exception e) { UnityEngine.Debug.LogException(e); } List <Package.Asset> assets = new List <Package.Asset>(8); List <CustomAssetMetaData> metas = new List <CustomAssetMetaData>(8); // Why this load order? By having related and identical assets close to each other, we get more loader cache hits (of meshes and textures) // in Sharing. We also get faster disk reads. // [0] propvar and prop, tree, citizen [1] prop [2] pillar and elevation and road [3] road // [4] sub-building and building [5] building [6] trailer and vehicle [7] vehicle List <Package.Asset>[] queues = { new List <Package.Asset>(32), new List <Package.Asset>(64), new List <Package.Asset>(4), new List <Package.Asset>(4), new List <Package.Asset>(16), new List <Package.Asset>(64), new List <Package.Asset>(32), new List <Package.Asset>(32) }; SteamHelper.DLC_BitMask notMask = ~SteamHelper.GetOwnedDLCMask(); bool loadEnabled = Settings.settings.loadEnabled, loadUsed = Settings.settings.loadUsed; //PrintPackages(packages); foreach (Package p in packages) { CustomAssetMetaData meta = null; try { assets.Clear(); assets.AddRange(p.FilterAssets(customAssets)); int count = assets.Count; CustomDeserializer.instance.AddPackage(p); bool enabled = loadEnabled && IsEnabled(p); if (count == 1) // the common case { bool want = enabled || styleBuildings.Contains(assets[0].fullName); // Fast exit. if (!want && !(loadUsed && UsedAssets.instance.GotPackage(p.packageName))) { continue; } meta = AssetDeserializer.Instantiate(assets[0]) as CustomAssetMetaData; bool used = loadUsed && UsedAssets.instance.IsUsed(meta); if (used || want && (AssetImporterAssetTemplate.GetAssetDLCMask(meta) & notMask) == 0) { if (reportAssets) { AssetReport.instance.AddPackage(p, meta, want, used); } CustomAssetMetaData.Type type = meta.type; int offset = type == CustomAssetMetaData.Type.Trailer || type == CustomAssetMetaData.Type.SubBuilding || type == CustomAssetMetaData.Type.PropVariation || type >= CustomAssetMetaData.Type.RoadElevation ? -1 : 0; AddToQueue(queues, meta, type, offset, !(enabled | used)); } } else { bool want = enabled; // Fast exit. if (!want) { for (int i = 0; i < count; i++) { want = want || styleBuildings.Contains(assets[i].fullName); } if (!want && !(loadUsed && UsedAssets.instance.GotPackage(p.packageName))) { continue; } } metas.Clear(); bool used = false; for (int i = 0; i < count; i++) { meta = AssetDeserializer.Instantiate(assets[i]) as CustomAssetMetaData; metas.Add(meta); want = want && (AssetImporterAssetTemplate.GetAssetDLCMask(meta) & notMask) == 0; used = used || loadUsed && UsedAssets.instance.IsUsed(meta); } if (want | used) { metas.Sort((a, b) => b.type - a.type); // prop variation, sub-building, trailer, elevation, pillar before main asset CustomAssetMetaData lastmeta = metas[count - 1]; if (reportAssets) { AssetReport.instance.AddPackage(p, lastmeta, want, used); } CustomAssetMetaData.Type type = metas[0].type; int offset = type == CustomAssetMetaData.Type.Trailer || type == CustomAssetMetaData.Type.SubBuilding || type == CustomAssetMetaData.Type.PropVariation || type >= CustomAssetMetaData.Type.RoadElevation ? -1 : 0; bool treeVariations = lastmeta.type == CustomAssetMetaData.Type.Tree, dontSpawn = !(enabled | used); for (int i = 0; i < count; i++) { CustomAssetMetaData m = metas[i]; CustomAssetMetaData.Type t = m.type; if (treeVariations && t == CustomAssetMetaData.Type.PropVariation) { t = CustomAssetMetaData.Type.Tree; } AddToQueue(queues, m, t, offset, dontSpawn); } } } } catch (Exception e) { AssetFailed(meta?.assetRef, p, e); } } CheckSuspects(); for (int i = 0; i < queuedLoads.Length; i++) { queuedLoads[i].Clear(); queuedLoads[i] = null; } queuedLoads = null; Package.Asset[] queue = new Package.Asset[queues.Sum(lst => lst.Count)]; for (int i = 0, k = 0; i < queues.Length; i++) { queues[i].CopyTo(queue, k); k += queues[i].Count; queues[i].Clear(); queues[i] = null; } return(queue); }
public IEnumerator LoadCustomContent() { LoadingManager.instance.m_loadingProfilerMain.BeginLoading("LoadCustomContent"); LoadingManager.instance.m_loadingProfilerCustomContent.Reset(); LoadingManager.instance.m_loadingProfilerCustomAsset.Reset(); LoadingManager.instance.m_loadingProfilerCustomContent.BeginLoading("District Styles"); LoadingManager.instance.m_loadingProfilerCustomAsset.PauseLoading(); hasStarted = true; int i, j; DistrictStyle districtStyle; DistrictStyleMetaData districtStyleMetaData; List <DistrictStyle> districtStyles = new List <DistrictStyle>(); HashSet <string> styleBuildings = new HashSet <string>(); FastList <DistrictStyleMetaData> districtStyleMetaDatas = new FastList <DistrictStyleMetaData>(); FastList <Package> districtStylePackages = new FastList <Package>(); Package.Asset europeanStyles = PackageManager.FindAssetByName("System." + DistrictStyle.kEuropeanStyleName); if (europeanStyles != null && europeanStyles.isEnabled) { districtStyle = new DistrictStyle(DistrictStyle.kEuropeanStyleName, true); Util.InvokeVoid(LoadingManager.instance, "AddChildrenToBuiltinStyle", GameObject.Find("European Style new"), districtStyle, false); Util.InvokeVoid(LoadingManager.instance, "AddChildrenToBuiltinStyle", GameObject.Find("European Style others"), districtStyle, true); districtStyles.Add(districtStyle); } foreach (Package.Asset asset in PackageManager.FilterAssets(UserAssetType.DistrictStyleMetaData)) { try { if (asset != null && asset.isEnabled) { districtStyleMetaData = asset.Instantiate <DistrictStyleMetaData>(); if (districtStyleMetaData != null && !districtStyleMetaData.builtin) { districtStyleMetaDatas.Add(districtStyleMetaData); districtStylePackages.Add(asset.package); if (districtStyleMetaData.assets != null) { for (i = 0; i < districtStyleMetaData.assets.Length; i++) { styleBuildings.Add(districtStyleMetaData.assets[i]); } } } } } catch (Exception ex) { CODebugBase <LogChannel> .Warn(LogChannel.Modding, string.Concat(new object[] { ex.GetType(), ": Loading custom district style failed[", asset, "]\n", ex.Message })); } } LoadingManager.instance.m_loadingProfilerCustomAsset.ContinueLoading(); LoadingManager.instance.m_loadingProfilerCustomContent.EndLoading(); if (loadUsed) { //while (!Profiling.SimulationPaused()) // yield return null; refs = new UsedAssets(); refs.Setup(); } LoadingManager.instance.m_loadingProfilerCustomContent.BeginLoading("Loading Assets First Pass"); notMask = ~SteamHelper.GetOwnedDLCMask(); lastMillis = Profiling.Millis; // Load custom assets: props, trees, trailers foreach (Package.Asset asset in PackageManager.FilterAssets(UserAssetType.CustomAssetMetaData)) { if (asset != null && PropTreeTrailer(asset) && Profiling.Millis - lastMillis > yieldInterval) { lastMillis = Profiling.Millis; yield return(null); } } LoadingManager.instance.m_loadingProfilerCustomContent.EndLoading(); LoadingManager.instance.m_loadingProfilerCustomContent.BeginLoading("Loading Assets Second Pass"); // Load custom assets: buildings and vehicles foreach (Package.Asset asset in PackageManager.FilterAssets(UserAssetType.CustomAssetMetaData)) { if (asset != null && BuildingVehicle(asset, styleBuildings.Contains(asset.fullName)) && Profiling.Millis - lastMillis > yieldInterval) { lastMillis = Profiling.Millis; yield return(null); } } if (loadUsed) { refs.ReportMissingAssets(); } if (reportAssets) { AssetReport.instance.Save(); } LoadingManager.instance.m_loadingProfilerCustomContent.EndLoading(); LoadingManager.instance.m_loadingProfilerCustomContent.BeginLoading("Finalizing District Styles"); LoadingManager.instance.m_loadingProfilerCustomAsset.PauseLoading(); for (i = 0; i < districtStyleMetaDatas.m_size; i++) { try { districtStyleMetaData = districtStyleMetaDatas.m_buffer[i]; districtStyle = new DistrictStyle(districtStyleMetaData.name, false); if (districtStylePackages.m_buffer[i].GetPublishedFileID() != PublishedFileId.invalid) { districtStyle.PackageName = districtStylePackages.m_buffer[i].packageName; } if (districtStyleMetaData.assets != null) { for (j = 0; j < districtStyleMetaData.assets.Length; j++) { BuildingInfo bi = PrefabCollection <BuildingInfo> .FindLoaded(districtStyleMetaData.assets[j] + "_Data"); if (bi != null) { districtStyle.Add(bi); if (districtStyleMetaData.builtin) // this is always false { bi.m_dontSpawnNormally = !districtStyleMetaData.assetRef.isEnabled; } } else { CODebugBase <LogChannel> .Warn(LogChannel.Modding, "Warning: Missing asset (" + districtStyleMetaData.assets[i] + ") in style " + districtStyleMetaData.name); } } districtStyles.Add(districtStyle); } } catch (Exception ex) { CODebugBase <LogChannel> .Warn(LogChannel.Modding, ex.GetType() + ": Loading district style failed\n" + ex.Message); } } Singleton <DistrictManager> .instance.m_Styles = districtStyles.ToArray(); if (Singleton <BuildingManager> .exists) { Singleton <BuildingManager> .instance.InitializeStyleArray(districtStyles.Count); } LoadingManager.instance.m_loadingProfilerCustomAsset.ContinueLoading(); LoadingManager.instance.m_loadingProfilerCustomContent.EndLoading(); if (Singleton <TelemetryManager> .exists) { Singleton <TelemetryManager> .instance.CustomContentInfo(buildingsCount, propsCount, treeCount, vehicleCount); } LoadingManager.instance.m_loadingProfilerMain.EndLoading(); hasFinished = true; }
List <Package.Asset>[] GetLoadQueues(IEnumerable <Package.Asset> assets) { Profiler.Info("Create Load queue for {0} assets", assets.Count()); List <Package.Asset>[] queues = { new List <Package.Asset>(4), new List <Package.Asset>(64), new List <Package.Asset>(4), new List <Package.Asset>(64) }; SteamHelper.DLC_BitMask notMask = ~SteamHelper.GetOwnedDLCMask(); foreach (Package.Asset asset in assets) { string fullName = null; // Profiler.Trace( "Q {0} - {1} - {2} - {3}", asset, loadEnabled, IsEnabled( asset ), styleBuildings.Contains( asset.fullName ) ); //Profiler.Trace( "Q {0} - {1} - {2}", asset, IsEnabled( asset ), styleBuildings); try { //triggers calls to CustomSerialize CustomAssetMetaData assetMetaData = asset.Instantiate <CustomAssetMetaData>(); //Profiler.Trace( "meta {0}", assetMetaData ); // Always remember: assetRef may point to another package because the deserialization method accepts any asset with the same checksum. // Think of identical vehicle trailers in different crp's. // There is a bug in the 1.6.0 game update in this. fullName = asset.package.packageName + "." + assetMetaData.assetRef.name; if ((AssetImporterAssetTemplate.GetAssetDLCMask(assetMetaData) & notMask) == 0) { switch (assetMetaData.type) { case CustomAssetMetaData.Type.Building: if (!IsDuplicate(fullName, loadedBuildings, asset.package)) { queues[3].Add(asset); } break; case CustomAssetMetaData.Type.Prop: if (!IsDuplicate(fullName, loadedProps, asset.package)) { queues[1].Add(asset); } break; case CustomAssetMetaData.Type.Tree: if (!IsDuplicate(fullName, loadedTrees, asset.package)) { queues[1].Add(asset); } break; case CustomAssetMetaData.Type.Vehicle: if (!IsDuplicate(fullName, loadedVehicles, asset.package)) { queues[3].Add(asset); } break; case CustomAssetMetaData.Type.Trailer: if (!IsDuplicate(fullName, loadedVehicles, asset.package)) { queues[1].Add(asset); } break; case CustomAssetMetaData.Type.Unknown: queues[3].Add(asset); break; case CustomAssetMetaData.Type.SubBuilding: if (!IsDuplicate(fullName, loadedBuildings, asset.package)) { queues[2].Add(asset); } break; case CustomAssetMetaData.Type.PropVariation: if (!IsDuplicate(fullName, loadedProps, asset.package)) { queues[0].Add(asset); } break; } } } catch (Exception e) { Profiler.Error("GetLoadQueues", e); StoreFailedAssetName(fullName ?? asset.fullName, e); } } return(queues); }
List <Package.Asset>[] GetLoadQueues(HashSet <string> styleBuildings) { Package.Asset[] assets = FilterAssets(UserAssetType.CustomAssetMetaData); List <Package.Asset>[] queues = { new List <Package.Asset>(4), new List <Package.Asset>(64), new List <Package.Asset>(4), new List <Package.Asset>(64) }; SteamHelper.DLC_BitMask notMask = ~SteamHelper.GetOwnedDLCMask(); for (int i = 0; i < assets.Length; i++) { Package.Asset asset = assets[i]; string fullName = null; try { bool wantThis = loadEnabled && IsEnabled(asset) || styleBuildings.Contains(asset.fullName); // Make the first check fast. if (wantThis || loadUsed && UsedAssets.instance.GotPackage(asset.package.packageName)) { CustomAssetMetaData assetMetaData = asset.Instantiate <CustomAssetMetaData>(); // Always remember: assetRef may point to another package because the deserialization method accepts any asset with the same checksum. // Think of identical vehicle trailers in different crp's. // There is a bug in the 1.6.0 game update in this. fullName = asset.package.packageName + "." + assetMetaData.assetRef.name; if ((AssetImporterAssetTemplate.GetAssetDLCMask(assetMetaData) & notMask) == 0) { switch (assetMetaData.type) { case CustomAssetMetaData.Type.Building: if ((wantThis || loadUsed && UsedAssets.instance.GotBuilding(fullName)) && !IsDuplicate(fullName, loadedBuildings, asset.package)) { queues[3].Add(asset); } break; case CustomAssetMetaData.Type.Prop: if ((wantThis || loadUsed && UsedAssets.instance.GotProp(fullName)) && !IsDuplicate(fullName, loadedProps, asset.package)) { queues[1].Add(asset); } break; case CustomAssetMetaData.Type.Tree: if ((wantThis || loadUsed && UsedAssets.instance.GotTree(fullName)) && !IsDuplicate(fullName, loadedTrees, asset.package)) { queues[1].Add(asset); } break; case CustomAssetMetaData.Type.Vehicle: if ((wantThis || loadUsed && UsedAssets.instance.GotVehicle(fullName)) && !IsDuplicate(fullName, loadedVehicles, asset.package)) { queues[3].Add(asset); } break; case CustomAssetMetaData.Type.Trailer: if ((wantThis || loadUsed && UsedAssets.instance.GotVehicle(fullName)) && !IsDuplicate(fullName, loadedVehicles, asset.package)) { queues[1].Add(asset); } break; case CustomAssetMetaData.Type.Unknown: if (wantThis) { queues[3].Add(asset); } break; case CustomAssetMetaData.Type.SubBuilding: if ((wantThis || loadUsed && UsedAssets.instance.GotBuilding(fullName)) && !IsDuplicate(fullName, loadedBuildings, asset.package)) { queues[2].Add(asset); } break; case CustomAssetMetaData.Type.PropVariation: if ((wantThis || loadUsed && UsedAssets.instance.GotProp(fullName)) && !IsDuplicate(fullName, loadedProps, asset.package)) { queues[0].Add(asset); } break; } } } } catch (Exception e) { AssetFailed(fullName ?? asset.fullName, e); } } return(queues); }