public static void Init() { if (!TransportLineMod.TryLoadData(out TransportLineMod._lineData)) { Utils.Log((object)"Loading default transport line data."); NetManager instance1 = Singleton <NetManager> .instance; TransportManager instance2 = Singleton <TransportManager> .instance; int length = instance2.m_lines.m_buffer.Length; for (ushort index = 0; index < length; ++index) { if (instance2.m_lines.m_buffer[index].Complete) { TransportLineMod._lineData[index].TargetVehicleCount = TransportLineMod.CountLineActiveVehicles(index); } else { TransportLineMod._lineData[index].TargetVehicleCount = OptionsWrapper <Settings> .Options.DefaultVehicleCount; } TransportLineMod._lineData[index].BudgetControl = OptionsWrapper <Settings> .Options.BudgetControl; TransportLineMod._lineData[index].Depot = TransportLineMod.GetClosestDepot((ushort)index, instance1.m_nodes.m_buffer[(int)instance2.m_lines.m_buffer[index].GetStop(0)].m_position); TransportLineMod._lineData[index].Unbunching = OptionsWrapper <Settings> .Options.Unbunching; } } SerializableDataExtension.instance.EventSaveData += new SerializableDataExtension.SaveDataEventHandler(TransportLineMod.OnSaveData); Redirector <TransportLineMod> .Deploy(); TransportLineMod._init = true; }
public static void DequeueVehicle(ushort lineID) { if (TransportLineMod._lineData[(int)lineID].QueuedVehicles == null) { return; } TransportLineMod.DecreaseTargetVehicleCount(lineID); TransportLineMod.Dequeue(lineID); }
//based off code in the SimulationStep public static void RemoveActiveVehicle(ushort lineID, bool descreaseTargetVehicleCount, int activeVehiclesCount) { ushort activeVehicle = GetActiveVehicle(ref Singleton <TransportManager> .instance.m_lines.m_buffer[(int)lineID], Singleton <SimulationManager> .instance.m_randomizer.Int32((uint)activeVehiclesCount)); if ((int)activeVehicle != 0) { TransportLineMod.RemoveVehicle(lineID, activeVehicle, descreaseTargetVehicleCount); } }
private static void OnSaveData() { FastList <byte> data = new FastList <byte>(); try { SerializableDataExtension.WriteString(TransportLineMod._dataVersion, data); for (ushort lineID = 0; (int)lineID < 256; ++lineID) { SerializableDataExtension.AddToData( BitConverter.GetBytes(TransportLineMod.GetTargetVehicleCount(lineID)), data); SerializableDataExtension.AddToData( BitConverter.GetBytes(Mathf.Max( TransportLineMod.GetNextSpawnTime(lineID) - SimHelper.SimulationTime, 0.0f)), data); SerializableDataExtension.AddToData( BitConverter.GetBytes(TransportLineMod.GetBudgetControlState(lineID)), data); SerializableDataExtension.AddToData(BitConverter.GetBytes(TransportLineMod.GetDepot(lineID)), data); int num = 0; HashSet <string> prefabs = TransportLineMod.GetPrefabs(lineID); if (prefabs != null) { num = prefabs.Count; } SerializableDataExtension.AddToData(BitConverter.GetBytes(num), data); if (num > 0) { foreach (string s in prefabs) { SerializableDataExtension.WriteString(s, data); } } string[] enqueuedVehicles = TransportLineMod.GetEnqueuedVehicles(lineID); SerializableDataExtension.AddToData(BitConverter.GetBytes(enqueuedVehicles.Length), data); if (enqueuedVehicles.Length != 0) { foreach (string s in enqueuedVehicles) { SerializableDataExtension.WriteString(s, data); } } SerializableDataExtension.WriteBool(TransportLineMod.GetUnbunchingState(lineID), data); } SerializableDataExtension.instance.SerializableData.SaveData(TransportLineMod._dataID, data.ToArray()); } catch (Exception ex) { string msg = "Error while saving transport line data! " + ex.Message + " " + (object)ex.InnerException; Utils.LogError((object)msg); CODebugBase <LogChannel> .Log(LogChannel.Modding, msg, ErrorLevel.Error); } }
public static void EnqueueVehicle(ushort lineID, string prefabName, bool inscreaseVehicleCount = true) { if (TransportLineMod._lineData[(int)lineID].QueuedVehicles == null) { TransportLineMod._lineData[(int)lineID].QueuedVehicles = new Queue <string>(); } if (inscreaseVehicleCount) { TransportLineMod.IncreaseTargetVehicleCount(lineID); } lock (TransportLineMod._lineData[(int)lineID].QueuedVehicles) TransportLineMod._lineData[(int)lineID].QueuedVehicles.Enqueue(prefabName); }
//based off code in the SimulationStep public static void RemoveVehicle(ushort lineID, ushort vehicleID, bool descreaseTargetVehicleCount) { VehicleManager instance = Singleton <VehicleManager> .instance; if ((instance.m_vehicles.m_buffer[(int)vehicleID].m_flags & Vehicle.Flags.GoingBack) == ~(Vehicle.Flags.Created | Vehicle.Flags.Deleted | Vehicle.Flags.Spawned | Vehicle.Flags.Inverted | Vehicle.Flags.TransferToTarget | Vehicle.Flags.TransferToSource | Vehicle.Flags.Emergency1 | Vehicle.Flags.Emergency2 | Vehicle.Flags.WaitingPath | Vehicle.Flags.Stopped | Vehicle.Flags.Leaving | Vehicle.Flags.Arriving | Vehicle.Flags.Reversed | Vehicle.Flags.TakingOff | Vehicle.Flags.Flying | Vehicle.Flags.Landing | Vehicle.Flags.WaitingSpace | Vehicle.Flags.WaitingCargo | Vehicle.Flags.GoingBack | Vehicle.Flags.WaitingTarget | Vehicle.Flags.Importing | Vehicle.Flags.Exporting | Vehicle.Flags.Parking | Vehicle.Flags.CustomName | Vehicle.Flags.OnGravel | Vehicle.Flags.WaitingLoading | Vehicle.Flags.Congestion | Vehicle.Flags.DummyTraffic | Vehicle.Flags.Underground | Vehicle.Flags.Transition | Vehicle.Flags.InsideBuilding | Vehicle.Flags.LeftHandDrive)) { if (descreaseTargetVehicleCount) { TransportLineMod.DecreaseTargetVehicleCount(lineID); } instance.m_vehicles.m_buffer[(int)vehicleID].Info.m_vehicleAI.SetTransportLine(vehicleID, ref instance.m_vehicles.m_buffer[(int)vehicleID], (ushort)0); } }
public static bool ValidateDepot(ushort lineID, ref ushort depotID, ref TransportInfo transportInfo) { if (depotID != 0 && DepotUtil.IsValidDepot(ref Singleton <BuildingManager> .instance.m_buildings.m_buffer[depotID], ref transportInfo, out _, out _, out _)) { return(true); } depotID = TransportLineMod.GetClosestDepot(lineID, Singleton <NetManager> .instance.m_nodes .m_buffer[Singleton <TransportManager> .instance.m_lines.m_buffer[lineID].GetStop(0)] .m_position); TransportLineMod._lineData[lineID].Depot = depotID; return(depotID != 0); }
public static void DequeueVehicles(ushort lineID, int[] indexes, bool descreaseVehicleCount = true) { lock (TransportLineMod._lineData[(int)lineID].QueuedVehicles) { List <string> stringList = new List <string>( (IEnumerable <string>)TransportLineMod._lineData[(int)lineID].QueuedVehicles); for (int index = indexes.Length - 1; index >= 0; --index) { stringList.RemoveAt(indexes[index]); if (descreaseVehicleCount) { TransportLineMod.DecreaseTargetVehicleCount(lineID); } } TransportLineMod._lineData[(int)lineID].QueuedVehicles = new Queue <string>((IEnumerable <string>)stringList); } }
public override bool CanLeave(ushort vehicleID, ref Vehicle vehicleData) { if ((int)vehicleData.m_leadingVehicle == 0 && (int)vehicleData.m_waitCounter < 12 || !base.CanLeave(vehicleID, ref vehicleData)) { //begin mod(+): track if unbunching happens VehicleManagerMod.m_cachedVehicleData[(int)vehicleID].IsUnbunchingInProgress = false; //end mod return(false); } //begin mod(+): no unbunching for evac buses or if only 1 bus on line! if (vehicleData.Info?.m_class?.m_service == ItemClass.Service.Disaster || (vehicleData.m_nextLineVehicle == 0 && Singleton <TransportManager> .instance.m_lines .m_buffer[(int)vehicleData.m_transportLine].m_vehicles == vehicleID)) { VehicleManagerMod.m_cachedVehicleData[vehicleID].IsUnbunchingInProgress = false; return(true); } //end mod if ((int)vehicleData.m_leadingVehicle == 0 && (int)vehicleData.m_transportLine != 0) { //begin mod(+): Check if unbunching enabled for this line & stop. track if unbunching happens. Don't divide m_waitCounter by 2^4 ushort currentStop = VehicleManagerMod.m_cachedVehicleData[vehicleID].CurrentStop; if (currentStop != 0 && NetManagerMod.m_cachedNodeData[currentStop].Unbunching && TransportLineMod.GetUnbunchingState(vehicleData.m_transportLine)) { var canLeaveStop = Singleton <TransportManager> .instance.m_lines .m_buffer[(int)vehicleData.m_transportLine] .CanLeaveStop(vehicleData.m_targetBuilding, (int)vehicleData.m_waitCounter); VehicleManagerMod.m_cachedVehicleData[vehicleID].IsUnbunchingInProgress = !canLeaveStop; return(canLeaveStop); } //end mod } //begin mod(+): track if unbunching happens VehicleManagerMod.m_cachedVehicleData[vehicleID].IsUnbunchingInProgress = false; //end mod return(true); }
public static bool TryLoadData(out LineData[] data) { data = new LineData[256]; byte[] data1 = SerializableDataExtension.instance.SerializableData.LoadData(TransportLineMod._dataID); if (data1 == null) { return(false); } int index1 = 0; ushort lineID = 0; string empty = string.Empty; try { Utils.Log((object)"Try to load transport line data."); string str = SerializableDataExtension.ReadString(data1, ref index1); if (string.IsNullOrEmpty(str) || str.Length != 4) { Utils.LogWarning((object)"Unknown data found."); return(false); } Utils.Log((object)("Found transport line data version: " + str)); NetManager instance1 = Singleton <NetManager> .instance; TransportManager instance2 = Singleton <TransportManager> .instance; while (index1 < data1.Length) { if (instance2.m_lines.m_buffer[(int)lineID].Complete) { int int32 = BitConverter.ToInt32(data1, index1); data[(int)lineID].TargetVehicleCount = int32; } index1 += 4; float num = Mathf.Min(BitConverter.ToSingle(data1, index1), (float)OptionsWrapper <Settings> .Options.SpawnTimeInterval); if ((double)num > 0.0) { data[(int)lineID].NextSpawnTime = SimHelper.SimulationTime + num; } index1 += 4; bool boolean = BitConverter.ToBoolean(data1, index1); data[(int)lineID].BudgetControl = boolean; ++index1; ushort uint16 = BitConverter.ToUInt16(data1, index1); data[(int)lineID].Depot = (int)uint16 != 0 ? uint16 : TransportLineMod.GetClosestDepot(lineID, instance1.m_nodes.m_buffer[(int)instance2.m_lines.m_buffer[(int)lineID].GetStop(0)] .m_position); index1 += 2; if (str == "v001") { string name = SerializableDataExtension.ReadString(data1, ref index1); if (name != "Random") { if (data[(int)lineID].Prefabs == null) { data[(int)lineID].Prefabs = new HashSet <string>(); } if ((UnityEngine.Object)PrefabCollection <VehicleInfo> .FindLoaded(name) != (UnityEngine.Object)null) { data[(int)lineID].Prefabs.Add(name); } } } else { int int32 = BitConverter.ToInt32(data1, index1); index1 += 4; for (int index2 = 0; index2 < int32; ++index2) { string name = SerializableDataExtension.ReadString(data1, ref index1); if (data[(int)lineID].Prefabs == null) { data[(int)lineID].Prefabs = new HashSet <string>(); } if ((UnityEngine.Object)PrefabCollection <VehicleInfo> .FindLoaded(name) != (UnityEngine.Object)null) { data[(int)lineID].Prefabs.Add(name); } } } if (str != "v001") { int int32 = BitConverter.ToInt32(data1, index1); index1 += 4; for (int index2 = 0; index2 < int32; ++index2) { string name = SerializableDataExtension.ReadString(data1, ref index1); if (!boolean) { if (data[(int)lineID].QueuedVehicles == null) { data[(int)lineID].QueuedVehicles = new Queue <string>(); } if ((UnityEngine.Object)PrefabCollection <VehicleInfo> .FindLoaded(name) != (UnityEngine.Object)null) { lock (data[(int)lineID].QueuedVehicles) data[(int)lineID].QueuedVehicles.Enqueue(name); } } } } if (str == "v003") { ++index1; } data[(int)lineID].Unbunching = str != "v004" ? OptionsWrapper <Settings> .Options.Unbunching : SerializableDataExtension.ReadBool(data1, ref index1); ++lineID; } return(true); } catch (Exception ex) { Utils.LogWarning((object)("Could not load transport line data. " + ex.Message)); data = new LineData[256]; return(false); } }
private static void HandleVehicleSpawn(ushort lineID, TransportInfo info, int targetVehicleCount, int activeVehicleCount, TransferManager.TransferOffer offer) { var itemClass = info.m_class; if ((double)SimHelper.SimulationTime >= (double)TransportLineMod._lineData[(int)lineID].NextSpawnTime || itemClass.m_service == ItemClass.Service.Disaster) { ushort depot = TransportLineMod._lineData[(int)lineID].Depot; if (TransportLineMod.ValidateDepot(lineID, ref depot, info)) { BuildingManager instance2 = Singleton <BuildingManager> .instance; if (TransportLineMod.CanAddVehicle(depot, ref instance2.m_buildings.m_buffer[(int)depot], info)) { string prefabName; if (TransportLineMod.EnqueuedVehiclesCount(lineID) > 0) { prefabName = TransportLineMod.Dequeue(lineID); } else { int diffToTarget = targetVehicleCount - activeVehicleCount; for (int index2 = 0; index2 < diffToTarget; ++index2) { TransportLineMod.EnqueueVehicle(lineID, TransportLineMod.GetRandomPrefab(lineID), false); } prefabName = TransportLineMod.Dequeue(lineID); } if (prefabName == "") { instance2.m_buildings.m_buffer[(int)depot] .Info.m_buildingAI .StartTransfer(depot, ref instance2.m_buildings.m_buffer[(int)depot], info.m_vehicleReason, offer); } else { DepotAIMod.StartTransfer(depot, ref instance2.m_buildings.m_buffer[(int)depot], info.m_vehicleReason, offer, prefabName); } TransportLineMod._lineData[(int)lineID].NextSpawnTime = SimHelper.SimulationTime + (float)OptionsWrapper <Settings> .Options.SpawnTimeInterval; } else { TransportLineMod.ClearEnqueuedVehicles(lineID); } } else { TransportLineMod.ClearEnqueuedVehicles(lineID); } } }
public static void SimulationStep(ref TransportLine thisLine, ushort lineID) { //begin mod(+): change for initialization if (!TransportLineMod._init) { return; } //end mod TransportInfo info = thisLine.Info; if (thisLine.Complete) { //begin mod(*): moved this section to a separate method int num2 = CountLineActiveVehicles(lineID); //end mod bool flag1 = !Singleton <SimulationManager> .instance.m_isNightTime ? (thisLine.m_flags & TransportLine.Flags.DisabledDay) == TransportLine.Flags.None : (thisLine.m_flags & TransportLine.Flags.DisabledNight) == TransportLine.Flags.None; uint range = 0; float num5 = 0.0f; int num6 = 0; bool flag2 = false; if ((int)thisLine.m_stops != 0) { NetManager instance = Singleton <NetManager> .instance; ushort stops = thisLine.m_stops; ushort num3 = stops; int num4 = 0; while ((int)num3 != 0) { ushort num7 = 0; if (flag1) { instance.m_nodes.m_buffer[(int)num3].m_flags &= NetNode.Flags.OneWayOutTrafficLights | NetNode.Flags.UndergroundTransition | NetNode.Flags.Created | NetNode.Flags.Deleted | NetNode.Flags.Original | NetNode.Flags.End | NetNode.Flags.Middle | NetNode.Flags.Bend | NetNode.Flags.Junction | NetNode.Flags.Moveable | NetNode.Flags.Untouchable | NetNode.Flags.Outside | NetNode.Flags.Temporary | NetNode.Flags.Double | NetNode.Flags.Fixed | NetNode.Flags.OnGround | NetNode.Flags.Ambiguous | NetNode.Flags.Water | NetNode.Flags.Sewage | NetNode.Flags.ForbidLaneConnection | NetNode.Flags.LevelCrossing | NetNode.Flags.OneWayIn | NetNode.Flags.Heating | NetNode.Flags.Electricity | NetNode.Flags.Collapsed | NetNode.Flags.DisableOnlyMiddle | NetNode.Flags.AsymForward | NetNode.Flags.AsymBackward | NetNode.Flags.CustomTrafficLights; } else { instance.m_nodes.m_buffer[(int)num3].m_flags |= NetNode.Flags.Disabled; } for (int index = 0; index < 8; ++index) { ushort segment = instance.m_nodes.m_buffer[(int)num3].GetSegment(index); if ((int)segment != 0 && (int)instance.m_segments.m_buffer[(int)segment].m_startNode == (int)num3) { num6 += Mathf.Max((int)instance.m_segments.m_buffer[(int)segment].m_trafficLightState0, (int)instance.m_segments.m_buffer[(int)segment].m_trafficLightState1); num5 += instance.m_segments.m_buffer[(int)segment].m_averageLength; num7 = instance.m_segments.m_buffer[(int)segment].m_endNode; if ((instance.m_segments.m_buffer[(int)segment].m_flags & NetSegment.Flags.PathLength) == NetSegment.Flags.None) { flag2 = true; break; } break; } } ++range; num3 = num7; if ((int)num3 != (int)stops) { if (++num4 >= 32768) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + System.Environment.StackTrace); break; } } else { break; } } } if (!flag2) { thisLine.m_totalLength = num5; } if ((int)range != 0) { thisLine.m_averageInterval = (byte)Mathf.Min((float)byte.MaxValue, (float)(((long)num6 + (long)(range >> 1)) / (long)range)); } //begin mod(-): let's count maintenance once a week //end mod TransferManager.TransferReason vehicleReason = info.m_vehicleReason; if (vehicleReason != TransferManager.TransferReason.None) { //begin mod: calculate target vehicle count or read saved value int num3 = 0; if (TransportLineMod._lineData[(int)lineID].BudgetControl || info.m_class.m_service == ItemClass.Service.Disaster) { num3 = !flag1 ? 0 : (!flag2 ? thisLine.CalculateTargetVehicleCount() : num2); TransportLineMod._lineData[(int)lineID].TargetVehicleCount = num3; } else if (flag1) { num3 = TransportLineMod._lineData[(int)lineID].TargetVehicleCount; } //end mod if (range != 0 && num2 < num3) { ushort stop = thisLine.GetStop(Singleton <SimulationManager> .instance.m_randomizer .Int32((uint)thisLine.CountStops(lineID))); if (info.m_vehicleReason != TransferManager.TransferReason.None && (int)stop != 0) { //begin mod(+): save offer as variable and directly invoke spawn if it's not evac line TransferManager.TransferOffer offer = new TransferManager.TransferOffer { Priority = num3 - num2 + 1, TransportLine = lineID, Position = Singleton <NetManager> .instance.m_nodes.m_buffer[(int)stop] .m_position, Amount = 1, Active = false }; if (info.m_class.m_service == ItemClass.Service.Disaster) { Singleton <TransferManager> .instance.AddIncomingOffer(vehicleReason, offer); } else { HandleVehicleSpawn(lineID, info, num3, num2, offer); } //end mod } } else if (num2 > num3) { //begin mod(*): encapsulate into method TransportLineMod.RemoveActiveVehicle(lineID, false, num2); //end mod } } } if ((Singleton <SimulationManager> .instance.m_currentFrameIndex & 4095U) < 3840U) { return; } thisLine.m_passengers.Update(); Singleton <TransportManager> .instance.m_passengers[(int)info.m_transportType].Add(ref thisLine.m_passengers); thisLine.m_passengers.Reset(); //begin mod(+): update statistics + fetch maintenance costs if (thisLine.Complete) { ushort stops1 = thisLine.m_stops; ushort stop1 = stops1; do { NetManagerMod.m_cachedNodeData[(int)stop1].StartNewWeek(); stop1 = TransportLine.GetNextStop(stop1); } while ((int)stops1 != (int)stop1 && (int)stop1 != 0); var itemClass = info.m_class; PrefabData[] prefabs = VehiclePrefabs.instance.GetPrefabs(itemClass.m_service, itemClass.m_subService, itemClass.m_level); int amount = 0; CountLineActiveVehicles(lineID, (num3) => { Vehicle vehicle = VehicleManager.instance.m_vehicles.m_buffer[num3]; PrefabData prefabData = Array.Find(prefabs, item => item.PrefabDataIndex == vehicle.Info.m_prefabDataIndex); if (prefabData != null) { amount += prefabData.MaintenanceCost; VehicleManagerMod.m_cachedVehicleData[num3].StartNewWeek(prefabData.MaintenanceCost); } }); if (amount != 0) { Singleton <EconomyManager> .instance.FetchResource(EconomyManager.Resource.Maintenance, amount, info.m_class); } //end mod } }