public bool TrySpawnParticle(Vector3D worldPosition, MyTuple<int, ContactPropertyParticleProperties> particle) { if (!MyFakes.ENABLE_DRIVING_PARTICLES) return false; MyWheel wheel = Entity as MyWheel; if(wheel == null) return false; if (MyUtils.GetRandomInt(10) < 8)//spawn only about 20% of particles return false; var speedMultiplier = wheel.GetTopMostParent().Physics.LinearVelocity.Length() / MyGridPhysics.ShipMaxLinearVelocity(); var currentTime = MySandboxGame.TotalGamePlayTimeInMilliseconds; if (currentTime - m_lastEffectCreationTime < 50) return false; MyParticleEffect drivingEffect = null; if (!MyParticlesManager.TryCreateParticleEffect(particle.Item1, out drivingEffect)) return false; m_lastEffectCreationTime = currentTime; m_lastGlobalEffectCreationTime = m_lastEffectCreationTime; drivingEffect.WorldMatrix = MatrixD.CreateTranslation(worldPosition); var speedScaleMultiplier = 1.0f + speedMultiplier * 6.0f; if (particle.Item2 != null) { drivingEffect.UserScale = particle.Item2.SizeMultiplier * speedScaleMultiplier; drivingEffect.UserColorMultiplier = particle.Item2.ColorMultiplier; drivingEffect.SetPreload(particle.Item2.Preload); } return true; }
public MyPhysicalDistributionGroup(MyDefinitionId typeId, MyResourceSourceComponent tempConnectedSource) { SinksByPriority = null; SourcesByPriority = null; SinkSourcePairs = null; FirstEndpoint = null; SinkDataByPriority = null; SourceDataByPriority = null; StockpilingStorage = null; OtherStorage = null; InputOutputData = new MyTuple<MySinkGroupData, MySourceGroupData>(); MaxAvailableResources = 0f; ResourceState = MyResourceStateEnum.NoPower; AllocateData(); InitFromTempConnected(typeId, tempConnectedSource); }
public MyPhysicalDistributionGroup(MyDefinitionId typeId, IMyConveyorEndpointBlock block) { SinksByPriority = null; SourcesByPriority = null; SinkSourcePairs = null; FirstEndpoint = null; SinkDataByPriority = null; SourceDataByPriority = null; StockpilingStorage = null; OtherStorage = null; InputOutputData = new MyTuple<MySinkGroupData, MySourceGroupData>(); MaxAvailableResources = 0f; ResourceState = MyResourceStateEnum.NoPower; AllocateData(); Init(typeId, block); }
public Order(PlaceMessage msg) { asset1 = msg.asset1; asset2 = msg.asset2; user = msg.user_id; price = msg.price; quantity = msg.quantity; buy = msg.buy; id = last_id++; }
public PlaceMessage(byte[] msg) { int len = BitConverter.ToInt32(msg, 4); user_id = System.Text.Encoding.ASCII.GetString(msg, 8, len); price = new MyTuple<long, long>(BitConverter.ToInt64(msg, len + 8), BitConverter.ToInt64(msg, len + 16)); quantity = BitConverter.ToInt64(msg, len + 24); buy = BitConverter.ToInt32(msg, len + 32) > 0; int len2 = BitConverter.ToInt32(msg, len + 36); asset1 = System.Text.Encoding.ASCII.GetString(msg, len + 40, len2); int len3 = BitConverter.ToInt32(msg, len + len2 + 40); asset2 = System.Text.Encoding.ASCII.GetString(msg, len + len2 + 44, len3); }
void ComposePlaceMessage(string user_id, MyTuple<long, long> price, long quantity, bool buy, string asset1, string asset2) { msg.AddRange(BitConverter.GetBytes(2));//Place msg.AddRange(BitConverter.GetBytes(strlen(user_id))); msg.AddRange(System.Text.Encoding.ASCII.GetBytes(user_id)); msg.AddRange(BitConverter.GetBytes(price.Item1)); msg.AddRange(BitConverter.GetBytes(price.Item2)); msg.AddRange(BitConverter.GetBytes(quantity)); msg.AddRange(BitConverter.GetBytes(buy)); msg.AddRange(BitConverter.GetBytes(strlen(asset1))); msg.AddRange(System.Text.Encoding.ASCII.GetBytes(asset1)); msg.AddRange(BitConverter.GetBytes(strlen(asset2))); msg.AddRange(System.Text.Encoding.ASCII.GetBytes(asset2)); }
private static void StartWriting(StreamWriter streamwriter) { //var text = MyTextHelper.Instance.EmploymentHistory; var textInLines = _text.Split('\n'); var tuple = new MyTuple() { Writer = streamwriter, Text = textInLines} ; //Tuple <StreamWriter,string[],int> tuple = new Tuple <StreamWriter,string[],int>(streamwriter,textInLines,0) Timer t = new Timer(TimerCallback1, tuple, 0, _milliseconds); tuple.Time = t; //Timer time = new Timer(seconds * 1000); //foreach (var line in textInLines) //{ // streamwriter.WriteLine("data:" + line + "\n"); // streamwriter.Flush(); // Debug.WriteLine("Sent at: " + DateTime.Now.TimeOfDay + " " + line); // Thread.Sleep(_milliseconds); //} }
/// <summary> /// Recomputes power distribution in subset of all priority groups (in range /// from startPriorityIdx until the end). Passing index 0 recomputes all priority groups. /// </summary> private static MyResourceStateEnum RecomputeResourceDistributionPartial( ref MyDefinitionId typeId, int startPriorityIdx, MySinkGroupData[] sinkDataByPriority, MySourceGroupData[] sourceDataByPriority, ref MyTuple<MySinkGroupData, MySourceGroupData> sinkSourceData, HashSet<MyResourceSinkComponent>[] sinksByPriority, HashSet<MyResourceSourceComponent>[] sourcesByPriority, List<MyTuple<MyResourceSinkComponent, MyResourceSourceComponent>> sinkSourcePairs, List<int> stockpilingStorageList, List<int> otherStorageList, float availableResource) { ProfilerShort.Begin("MyResourceDistributor.RecomputeResourceDistributionPartial"); ProfilerShort.Begin("Non-zero inputs"); float totalAvailableResource = availableResource; int sinkPriorityIndex = startPriorityIdx; // Distribute power over the sinks by priority for (; sinkPriorityIndex < sinksByPriority.Length; ++sinkPriorityIndex) { sinkDataByPriority[sinkPriorityIndex].RemainingAvailableResource = availableResource; if (sinkDataByPriority[sinkPriorityIndex].RequiredInput <= availableResource) { // Run everything in the group at max. availableResource -= sinkDataByPriority[sinkPriorityIndex].RequiredInput; foreach (MyResourceSinkComponent sink in sinksByPriority[sinkPriorityIndex]) sink.SetInputFromDistributor(typeId, sink.RequiredInputByType(typeId), sinkDataByPriority[sinkPriorityIndex].IsAdaptible); } else if (sinkDataByPriority[sinkPriorityIndex].IsAdaptible && availableResource > 0.0f) { // Distribute power in this group based on ratio of its requirement vs. group requirement. foreach (MyResourceSinkComponent sink in sinksByPriority[sinkPriorityIndex]) { float ratio = sink.RequiredInputByType(typeId) / sinkDataByPriority[sinkPriorityIndex].RequiredInput; sink.SetInputFromDistributor(typeId, ratio * availableResource, true); } availableResource = 0.0f; } else { // Not enough power for this group and members can't adapt. // None of the lower priority groups will get any power either. foreach (MyResourceSinkComponent sink in sinksByPriority[sinkPriorityIndex]) sink.SetInputFromDistributor(typeId, 0.0f, sinkDataByPriority[sinkPriorityIndex].IsAdaptible); sinkDataByPriority[sinkPriorityIndex].RemainingAvailableResource = availableResource; ++sinkPriorityIndex; // move on to next group break; } } ProfilerShort.End(); ProfilerShort.Begin("Zero inputs"); // Set remaining data. for (; sinkPriorityIndex < sinkDataByPriority.Length; ++sinkPriorityIndex) { sinkDataByPriority[sinkPriorityIndex].RemainingAvailableResource = 0.0f; foreach (MyResourceSinkComponent sink in sinksByPriority[sinkPriorityIndex]) sink.SetInputFromDistributor(typeId, 0.0f, sinkDataByPriority[sinkPriorityIndex].IsAdaptible); } ProfilerShort.End(); float consumptionForNonStorage = totalAvailableResource - availableResource + (startPriorityIdx != 0 ? sinkDataByPriority[0].RemainingAvailableResource - sinkDataByPriority[startPriorityIdx].RemainingAvailableResource : 0f); // Distribute remaining energy over stockpiling storage float totalAvailableResourcesForStockpiles = Math.Max(totalAvailableResource - consumptionForNonStorage, 0); float availableResourcesForStockpiles = totalAvailableResourcesForStockpiles; if (stockpilingStorageList.Count > 0) { ProfilerShort.Begin("Stockpiles"); float stockpilesRequiredInput = sinkSourceData.Item1.RequiredInputCumulative; if (stockpilesRequiredInput <= availableResourcesForStockpiles) { availableResourcesForStockpiles -= stockpilesRequiredInput; //ToArray = Hotfix for collection modified exception foreach (int pairIndex in stockpilingStorageList.ToArray()) { var sink = sinkSourcePairs[pairIndex].Item1; sink.SetInputFromDistributor(typeId, sink.RequiredInputByType(typeId), true); } sinkSourceData.Item1.RemainingAvailableResource = availableResourcesForStockpiles; } else { //ToArray = Hotfix for collection modified exception foreach (int pairIndex in stockpilingStorageList.ToArray()) { var sink = sinkSourcePairs[pairIndex].Item1; float ratio = sink.RequiredInputByType(typeId) / stockpilesRequiredInput; sink.SetInputFromDistributor(typeId, ratio * totalAvailableResourcesForStockpiles, true); } availableResourcesForStockpiles = 0f; sinkSourceData.Item1.RemainingAvailableResource = availableResourcesForStockpiles; } ProfilerShort.End(); } // Distribute remaining power over non-stockpiling storage float consumptionForStockpiles = totalAvailableResourcesForStockpiles - availableResourcesForStockpiles; float totalAvailableResourcesForStorage = Math.Max(totalAvailableResource - (sinkSourceData.Item2.MaxAvailableResource - sinkSourceData.Item2.MaxAvailableResource * sinkSourceData.Item2.UsageRatio) - consumptionForNonStorage - consumptionForStockpiles, 0); float availableResourcesForStorage = totalAvailableResourcesForStorage; if (otherStorageList.Count > 0) { ProfilerShort.Begin("Non-stockpiling storage"); float ordinaryStorageRequiredInput = sinkSourceData.Item1.RequiredInput - sinkSourceData.Item1.RequiredInputCumulative; if (ordinaryStorageRequiredInput <= availableResourcesForStorage) { availableResourcesForStorage -= ordinaryStorageRequiredInput; foreach (int pairIndex in otherStorageList) { var sink = sinkSourcePairs[pairIndex].Item1; sink.SetInputFromDistributor(typeId, sink.RequiredInputByType(typeId), true); } sinkSourceData.Item1.RemainingAvailableResource = availableResourcesForStorage; } else { foreach (int pairIndex in otherStorageList) { var sink = sinkSourcePairs[pairIndex].Item1; float ratio = sink.RequiredInputByType(typeId) / ordinaryStorageRequiredInput; sink.SetInputFromDistributor(typeId, ratio * availableResourcesForStorage, true); } availableResourcesForStorage = 0f; sinkSourceData.Item1.RemainingAvailableResource = availableResourcesForStorage; } ProfilerShort.End(); } ProfilerShort.Begin("Sources"); float consumptionForStorage = totalAvailableResourcesForStorage - availableResourcesForStorage; float consumptionForNonStorageAndStockpiles = consumptionForStockpiles + consumptionForNonStorage; if (sinkSourceData.Item2.MaxAvailableResource > 0) { float amountToSupply = consumptionForNonStorageAndStockpiles; sinkSourceData.Item2.UsageRatio = Math.Min(1f, amountToSupply/sinkSourceData.Item2.MaxAvailableResource); consumptionForNonStorageAndStockpiles -= Math.Min(amountToSupply, sinkSourceData.Item2.MaxAvailableResource); } else sinkSourceData.Item2.UsageRatio = 0f; sinkSourceData.Item2.ActiveCount = 0; foreach (int pairIndex in otherStorageList) { var source = sinkSourcePairs[pairIndex].Item2; if (!source.Enabled || !source.ProductionEnabledByType(typeId) || !source.HasCapacityRemainingByType(typeId)) continue; ++sinkSourceData.Item2.ActiveCount; ProfilerShort.Begin("Set CurrentOutput"); source.SetOutputByType(typeId, sinkSourceData.Item2.UsageRatio * source.MaxOutputByType(typeId)); ProfilerShort.End(); } int sourcePriorityIndex = 0; float totalRemainingConsumption = consumptionForNonStorageAndStockpiles + consumptionForStorage; for (; sourcePriorityIndex < sourcesByPriority.Length; ++sourcePriorityIndex) { if (sourceDataByPriority[sourcePriorityIndex].MaxAvailableResource > 0f) { float amountToSupply = Math.Max(totalRemainingConsumption, 0f); sourceDataByPriority[sourcePriorityIndex].UsageRatio = Math.Min(1f, amountToSupply/sourceDataByPriority[sourcePriorityIndex].MaxAvailableResource); totalRemainingConsumption -= Math.Min(amountToSupply, sourceDataByPriority[sourcePriorityIndex].MaxAvailableResource); } else sourceDataByPriority[sourcePriorityIndex].UsageRatio = 0f; sourceDataByPriority[sourcePriorityIndex].ActiveCount = 0; foreach (MyResourceSourceComponent source in sourcesByPriority[sourcePriorityIndex]) { if (!source.Enabled || !source.HasCapacityRemainingByType(typeId)) continue; ++sourceDataByPriority[sourcePriorityIndex].ActiveCount; ProfilerShort.Begin("Set CurrentOutput"); source.SetOutputByType(typeId, sourceDataByPriority[sourcePriorityIndex].UsageRatio * source.MaxOutputByType(typeId)); ProfilerShort.End(); } } MyResourceStateEnum resultState; if (totalAvailableResource == 0.0f) resultState = MyResourceStateEnum.NoPower; else if (sinkDataByPriority[m_sinkGroupPrioritiesTotal - 1].RequiredInputCumulative > totalAvailableResource) { MySinkGroupData lastGroup = sinkDataByPriority.Last(); if (lastGroup.IsAdaptible && lastGroup.RemainingAvailableResource != 0.0f) resultState = MyResourceStateEnum.OverloadAdaptible; else resultState = MyResourceStateEnum.OverloadBlackout; } else resultState = MyResourceStateEnum.Ok; ProfilerShort.End(); ProfilerShort.End(); return resultState; }
private static void ComputeInitialDistributionData( ref MyDefinitionId typeId, MySinkGroupData[] sinkDataByPriority, MySourceGroupData[] sourceDataByPriority, ref MyTuple<MySinkGroupData, MySourceGroupData> sinkSourceData, HashSet<MyResourceSinkComponent>[] sinksByPriority, HashSet<MyResourceSourceComponent>[] sourcesByPriority, List<MyTuple<MyResourceSinkComponent, MyResourceSourceComponent>> sinkSourcePairs, List<int> stockpilingStorageList, List<int> otherStorageList, out float maxAvailableResource) { // Clear state of all sources and sinks. Also find out how // much of resource is available for distribution. maxAvailableResource = 0.0f; Debug.Assert(sourceDataByPriority.Length == sourcesByPriority.Length); for (int i = 0; i < sourceDataByPriority.Length; ++i) { var resourceSources = sourcesByPriority[i]; MySourceGroupData sourceGroupData = sourceDataByPriority[i]; sourceGroupData.MaxAvailableResource = 0f; foreach (MyResourceSourceComponent source in resourceSources) { if (!source.Enabled || !source.HasCapacityRemainingByType(typeId)) continue; sourceGroupData.MaxAvailableResource += source.MaxOutputByType(typeId); sourceGroupData.InfiniteCapacity = source.IsInfiniteCapacity; } maxAvailableResource += sourceGroupData.MaxAvailableResource; sourceDataByPriority[i] = sourceGroupData; } float requiredInputCumulative = 0.0f; for (int i = 0; i < sinksByPriority.Length; ++i) { float requiredInput = 0.0f; bool isAdaptible = true; foreach (MyResourceSinkComponent sink in sinksByPriority[i]) { requiredInput += sink.RequiredInputByType(typeId); isAdaptible = isAdaptible && IsAdaptible(sink); } sinkDataByPriority[i].RequiredInput = requiredInput; sinkDataByPriority[i].IsAdaptible = isAdaptible; requiredInputCumulative += requiredInput; sinkDataByPriority[i].RequiredInputCumulative = requiredInputCumulative; } PrepareSinkSourceData(ref typeId, ref sinkSourceData, sinkSourcePairs, stockpilingStorageList, otherStorageList); maxAvailableResource += sinkSourceData.Item2.MaxAvailableResource; }
private static void PrepareSinkSourceData( ref MyDefinitionId typeId, ref MyTuple<MySinkGroupData, MySourceGroupData> sinkSourceData, List<MyTuple<MyResourceSinkComponent, MyResourceSourceComponent>> sinkSourcePairs, List<int> stockpilingStorageList, List<int> otherStorageList) { stockpilingStorageList.Clear(); otherStorageList.Clear(); sinkSourceData.Item1.IsAdaptible = true; sinkSourceData.Item1.RequiredInput = 0f; sinkSourceData.Item1.RequiredInputCumulative = 0f; sinkSourceData.Item2.MaxAvailableResource = 0f; for (int pairIndex = 0; pairIndex < sinkSourcePairs.Count; ++pairIndex) { var sinkSourcePair = sinkSourcePairs[pairIndex]; bool productionEnabled = sinkSourcePair.Item2.ProductionEnabledByType(typeId); bool isStockpiling = sinkSourcePair.Item2.Enabled && !productionEnabled && sinkSourcePair.Item1.RequiredInputByType(typeId) > 0; sinkSourceData.Item1.IsAdaptible = sinkSourceData.Item1.IsAdaptible && IsAdaptible(sinkSourcePair.Item1); sinkSourceData.Item1.RequiredInput += sinkSourcePair.Item1.RequiredInputByType(typeId); if (isStockpiling) sinkSourceData.Item1.RequiredInputCumulative += sinkSourcePair.Item1.RequiredInputByType(typeId); sinkSourceData.Item2.InfiniteCapacity = float.IsInfinity(sinkSourcePair.Item2.RemainingCapacityByType(typeId)); if (isStockpiling) stockpilingStorageList.Add(pairIndex); else { otherStorageList.Add(pairIndex); if (sinkSourcePair.Item2.Enabled && productionEnabled) sinkSourceData.Item2.MaxAvailableResource += sinkSourcePair.Item2.MaxOutputByType(typeId); } } }
public bool CanDoAction(string actionId, out MyTuple<ushort, MyStringHash> message, bool continuous = false) { message = new MyTuple<ushort, MyStringHash>(0, MyStringHash.NullOrEmpty); if (m_scripts == null || m_scripts.Count == 0) return true; bool cannotPerformAction = true; foreach (var script in m_scripts) { MyTuple<ushort, MyStringHash> msg; cannotPerformAction &= !script.CanDoAction(actionId, continuous, out msg); if (msg.Item1 != 0) message = msg; } return !cannotPerformAction; }
public static void HandleSomeEventA (string arg1, object arg2, double arg3, MyTuple mt) { Console.WriteLine ("SomeEvent handler A: " + arg1 + ", " + arg2 + ", " + arg3 + ", " + mt.A + ", " + mt.B); }
public static void AddGPSToEntity(string entityName, string GPSName, string GPSDescription, long playerId = -1) { MyEntity entity; if (MyEntities.TryGetEntityByName(entityName, out entity)) { if (playerId == -1) playerId = GetLocalPlayerId(); MyTuple<string, string> gpsIdentifier = new MyTuple<string, string>(entityName, GPSName); MyGps newGPS = new MyGps { ShowOnHud = true, Name = GPSName, Description = GPSDescription, AlwaysVisible = true }; MySession.Static.Gpss.SendAddGps(playerId, ref newGPS, entity.EntityId); } }
public static void RemoveGPSFromEntity(string entityName, string GPSName, string GPSDescription, long playerId = -1) { MyEntity entity; if (MyEntities.TryGetEntityByName(entityName, out entity)) { if (playerId == -1) playerId = GetLocalPlayerId(); MyTuple<string, string> gpsIdentifier = new MyTuple<string, string>(entityName, GPSName); var gps = MySession.Static.Gpss.GetGpsByName(playerId, GPSName); if (gps != null) MySession.Static.Gpss.SendDelete(playerId, gps.Hash); } }
public static void MUL(MyTuple<long, long> price, long quantity, out long q1, out long q2) { q1 = price.Item1 * quantity + price.Item2 * (quantity / MAGIC) + price.Item2 * (quantity % MAGIC) / MAGIC; q2 = price.Item2 * (quantity % MAGIC) % MAGIC; }
public void AddAsset(string asset, long quantity) { long i = eq[num[asset]].Item1; long r = eq[num[asset]].Item2; i += quantity / MAGIC; r += quantity % MAGIC; if (r >= MAGIC) { r -= MAGIC; ++i; } if (r < 0) { --i; r += MAGIC; } eq[num[asset]] = new MyTuple<long, long>(i, r); }
public bool CanDoAction(string actionId, bool continuous, out MyTuple<ushort, MyStringHash> message) { MyStatAction action; if(!m_statActions.TryGetValue(actionId, out action)) { message = new MyTuple<ushort, MyStringHash>(0, action.StatId); return true; } if (action.CanPerformWithout) { message = new MyTuple<ushort, MyStringHash>(0, action.StatId); return true; } MyEntityStat stat; if(!m_stats.TryGetValue(action.StatId, out stat)) { message = new MyTuple<ushort, MyStringHash>(0, action.StatId); return true; } if (continuous) { if (stat.Value < action.Cost) { message = new MyTuple<ushort, MyStringHash>(STAT_VALUE_TOO_LOW, action.StatId); return false; } } else { if (stat.Value < action.Cost || stat.Value < action.AmountToActivate) { message = new MyTuple<ushort, MyStringHash>(STAT_VALUE_TOO_LOW, action.StatId); Debug.Write(String.Format("value: {0}, cost: {1}, activation: {2}", stat.Value, action.Cost, action.AmountToActivate)); return false; } } message = new MyTuple<ushort, MyStringHash>(0, action.StatId); return true; }
private void VoiceMessageReceived(byte[] data, int dataSize, ulong sender, TimeSpan timestamp) { if (!m_enabled) return; if (!IsCharacterValid(MySession.LocalCharacter)) return; ProcessBuffer(data, dataSize, sender); if (MyFakes.ENABLE_VOICE_CHAT_DEBUGGING) m_debugReceivedVoice[sender] = new MyTuple<int, TimeSpan>(dataSize, timestamp); }
public void AddCurrency(string asset, long quantity, MyTuple<long, long> price) { long q1, q2; MUL(price, quantity, out q1, out q2); long i = eq[num[asset]].Item1; long r = eq[num[asset]].Item2; i += q1; r += q2; if (r >= MAGIC) { r -= MAGIC; ++i; } if (r < 0) { --i; r += MAGIC; } eq[num[asset]] = new MyTuple<long, long>(i, r); }
public static void SetGPSHighlight(string entityName, string GPSName, string GPSDescription, bool enabled = true, int thickness = 1, int pulseTimeInFrames = 120, Color color = default(Color), long playerId = -1) { MyEntity entity; if (MyEntities.TryGetEntityByName(entityName, out entity)) { if (playerId == -1) playerId = GetLocalPlayerId(); MyTuple<string, string> gpsIdentifier = new MyTuple<string, string>(entityName, GPSName); if (enabled) { MyGps newGPS = new MyGps { ShowOnHud = true, Name = GPSName, Description = GPSDescription, AlwaysVisible = true }; MySession.Static.Gpss.SendAddGps(playerId, ref newGPS, entity.EntityId); } else { var gps = MySession.Static.Gpss.GetGpsByName(playerId, GPSName); if (gps != null) MySession.Static.Gpss.SendDelete(playerId, gps.Hash); } SetHighlight(entityName, enabled: enabled, thickness: thickness, pulseTimeInFrames: pulseTimeInFrames, color: color, playerId: playerId); } }
internal Tuple<byte[], List<byte[]>> Place(PlaceMessage pm) { Order o = new Order(pm); Tuple<byte[], List<byte[]>> ans = new Tuple<byte[], List<byte[]>>(BitConverter.GetBytes(o.id), new List<byte[]>()); ans.Item2.Add(o.AddedString()); orders[o.id] = o; if (!users.ContainsKey(pm.user_id)) { //ошибка, юзера нет } if (pm.buy) //покупаем asset2 за asset1 { long q1, q2; User.MUL(pm.price, pm.quantity, out q1, out q2); //проверить хватит ли денег if (users[pm.user_id].eq[User.num[pm.asset1]].CompareTo(new MyTuple<long, long>(q1, q2)) < 0) { //денег не хватило } if (!buy.ContainsKey(pm.asset1)) { buy[pm.asset1] = new Dictionary<string, SortedDictionary<MyTuple<long, long>, List<Order>>>(); } if (!buy[pm.asset1].ContainsKey(pm.asset2)) { buy[pm.asset1][pm.asset2] = new SortedDictionary<MyTuple<long, long>, List<Order>>(); } if (!buy[pm.asset1][pm.asset2].ContainsKey(pm.price)) { buy[pm.asset1][pm.asset2][pm.price] = new List<Order>(); } buy[pm.asset1][pm.asset2][pm.price].Add(o); } else //продаем asset2 за asset1 { //проверить хватит ли денег MyTuple<long, long> T = new MyTuple<long, long>(pm.quantity/User.MAGIC, pm.quantity%User.MAGIC); if (users[pm.user_id].eq[User.num[pm.asset2]].CompareTo(T)<0) ; { //денег не хватило } if (pm.quantity<=0 || pm.price.Item1<0 || pm.price.Item2<0 || (pm.price.Item1)==0 && (pm.price.Item2)==0) { //проверка на отрицательную смму и количество } if (!buy.ContainsKey(pm.asset1)) { buy[pm.asset1] = new Dictionary<string, SortedDictionary<MyTuple<long, long>, List<Order>>>(); } if (!buy[pm.asset1].ContainsKey(pm.asset2)) { buy[pm.asset1][pm.asset2] = new SortedDictionary<MyTuple<long, long>, List<Order>>(); } if (!buy[pm.asset1][pm.asset2].ContainsKey(pm.price)) { buy[pm.asset1][pm.asset2][pm.price] = new List<Order>(); } buy[pm.asset1][pm.asset2][pm.price].Add(o); } while (sell[pm.asset1][pm.asset2].First().Key.CompareTo(buy[pm.asset1][pm.asset2].Last().Key) <= 0) { MyTuple<long, long> price = pm.buy ? sell[pm.asset1][pm.asset2].First().Key : buy[pm.asset1][pm.asset2].First().Key; List<Order> l1 = sell[pm.asset1][pm.asset2].First().Value; List<Order> l2 = buy[pm.asset1][pm.asset2].Last().Value; while (l1.Count > 0 && l2.Count > 0) { long q = Math.Min(l1[0].quantity, l2[0].quantity); users[l1[0].user].AddAsset(pm.asset1, -q); users[l2[0].user].AddAsset(pm.asset1, q); users[l1[0].user].AddCurrency(pm.asset2, q, price); users[l2[0].user].AddCurrency(pm.asset2, -q, price); l1[0].quantity -= q; l2[0].quantity -= q; List<byte> tick = new List<byte>(); tick.AddRange(System.Text.Encoding.ASCII.GetBytes(pm.asset1 + "/" + pm.asset2)); tick.Add(2); tick.AddRange(BitConverter.GetBytes(l1[0].id)); tick.AddRange(BitConverter.GetBytes(l2[0].id)); tick.AddRange(BitConverter.GetBytes(price.Item1)); tick.AddRange(BitConverter.GetBytes(price.Item2)); tick.AddRange(BitConverter.GetBytes(q)); ans.Item2.Add(tick.ToArray()); if (l1[0].quantity == 0) { l1.RemoveAt(0); } if (l2[0].quantity == 0) { l2.RemoveAt(0); } } if (l1.Count == 0) { sell[pm.asset1][pm.asset2].Remove(sell[pm.asset1][pm.asset2].First().Key); } if (l2.Count == 0) { buy[pm.asset1][pm.asset2].Remove(buy[pm.asset1][pm.asset2].Last().Key); } } return ans; }