Exemplo n.º 1
0
        /// <summary>
        /// Attempts to create a definition ID from a definition string, which has the form (using ores as an example) "MyObjectBuilder_Ore/Iron".
        /// The first part must represent an existing type, while the second (the subtype) is not enforced.
        /// </summary>
        /// <param name="id"></param>
        /// <param name="definitionId"></param>
        /// <returns></returns>
        public static bool TryParse(string id, out MyDefinitionId definitionId)
        {
            if (string.IsNullOrEmpty(id))
            {
                definitionId = new MyDefinitionId();
                return(false);
            }

            var slashIndex = id.IndexOf('/');

            if (slashIndex == -1)
            {
                definitionId = new MyDefinitionId();
                return(false);
            }
            var typeId = id.Substring(0, slashIndex).Trim();
            MyObjectBuilderType result;

            if (MyObjectBuilderType.TryParse(typeId, out result))
            {
                var subtypeId = id.Substring(slashIndex + 1).Trim();
                if (subtypeId == "(null)")
                {
                    subtypeId = null;
                }
                definitionId = new MyDefinitionId(result, subtypeId);
                return(true);
            }
            definitionId = new MyDefinitionId();
            return(false);
        }
Exemplo n.º 2
0
        public void AddResearchGroup(ResearchGroup group)
        {
            MyObjectBuilderType typeId;

            if (!MyObjectBuilderType.TryParse(group.ComponentId.TypeId, out typeId))
            {
                return;
            }

            var compDef = new MyDefinitionId(typeId, group.ComponentId.SubtypeId);

            ResearchGroup existing;

            if (!group.OverwriteAllOthers && ResearchGroups.TryGetValue(compDef, out existing))
            {
                foreach (var item in group.BlockDefinitons)
                {
                    if (!existing.BlockDefinitons.Contains(item))
                    {
                        existing.BlockDefinitons.Add(item);
                    }
                }
            }
            else
            {
                ResearchGroups[compDef] = group;
                ResearchGroupList.Add(group);
            }
        }
Exemplo n.º 3
0
        private void SetItemAtSerialized(int i, string serializedItem, MyObjectBuilder_ToolbarItem data)
        {
            if (!m_items.IsValidIndex(i))
            {
                return;
            }

            //old saves
            if (data == null)
            {
                if (String.IsNullOrEmpty(serializedItem))
                {
                    return;
                }

                var split = serializedItem.Split(':');
                MyObjectBuilderType typeId;

                if (!MyObjectBuilderType.TryParse(split[0], out typeId))
                {
                    return;
                }

                string subtypeString = (split.Length == 2) ? split[1] : null;
                var    defId         = new MyDefinitionId(typeId, subtypeString);

                SetItemAtSerializedCompat(i, defId);
            }

            //new saves
            else
            {
                SetItemAtIndexInternal(i, MyToolbarItemFactory.CreateToolbarItem(data), true);
            }
        }
Exemplo n.º 4
0
        internal void LoadData()
        {
            if (Entity.Storage == null)
            {
                // DebugLog.Write("storage is null, exiting loadData().");
                return;
            }
            string Data;

            if (Entity.Storage.TryGetValue(FilterStateGUID, out Data))
            {
                // DebugLog.Write(Data);
                Filterdata loadedfilterdata = new Filterdata();

                var base64 = Convert.FromBase64String(Data);
                loadedfilterdata = MyAPIGateway.Utilities.SerializeFromBinary <Filterdata>(base64);
                // DebugLog.Write($"loaded id: {loadedfilterdata.id}");
                if (loadedfilterdata.id == MyCargoContainer.EntityId)
                {
                    // DebugLog.Write($"Saved state found (id: {loadedfilterdata.id})");
                    MyInventory inventory = (MyInventory)MyCargoContainer.GetInventory();
                    if (loadedfilterdata.FilterItems != null)
                    {
                        for (int i = 0; i < loadedfilterdata.FilterItems.Count(); i++)
                        {
                            // DebugLog.Write($"{loadedfilterdata.FilterItems[i].DisplayName}");
                            FilterController.FilterList.Add(loadedfilterdata.FilterItems[i]);
                            if (loadedfilterdata.FilterItems[i].Type == FilterType.FILTER_TYPE)
                            {
                                MyObjectBuilderType type;
                                if (MyObjectBuilderType.TryParse(loadedfilterdata.FilterItems[i].ParseItem, out type) == true)
                                {
                                    inventory.Constraint.AddObjectBuilderType(type);
                                }
                            }
                            else if (loadedfilterdata.FilterItems[i].Type == FilterType.FILTER_ITEM)
                            {
                                MyDefinitionId Id;
                                if (MyDefinitionId.TryParse(loadedfilterdata.FilterItems[i].ParseItem, out Id) == true)
                                {
                                    inventory.Constraint.Add(Id);
                                }
                            }
                        }
                    }
                    inventory.Constraint.IsWhitelist = loadedfilterdata.FilterMode;
                    FilterController.FilterMode      = loadedfilterdata.FilterMode;
                    inventory.Constraint.Icon        = null;
                }
                else
                {
                    // DebugLog.Write($"Id mismatch - Entity Id: {Entity.EntityId}  MyCargoContainerId: {MyCargoContainer.EntityId}");
                }
            }
        }
Exemplo n.º 5
0
 static ToughNightsMod()
 {
     if (MyObjectBuilderType.TryParse("Block", out var blockType))
     {
         lightEntityDefinitionIds.Add(new MyDefinitionId(blockType, "TorchWall"));
         lightEntityDefinitionIds.Add(new MyDefinitionId(blockType, "TorchStand"));
         lightEntityDefinitionIds.Add(new MyDefinitionId(blockType, "Brazier"));
         lightEntityDefinitionIds.Add(new MyDefinitionId(blockType, "Bonfire"));
         lightEntityDefinitionIds.Add(new MyDefinitionId(blockType, "BedWood"));
     }
 }
Exemplo n.º 6
0
        public MyPlanetEnvironmentMapping(PlanetEnvironmentItemMapping map)
        {
            Rule  = map.Rule;
            Items = new MyMaterialEnvironmentItem[map.Items.Length];
            if (Items.Length <= 0)
            {
                CumulativeIntervals = null;
                TotalFrequency      = 0;
                return;
            }

            TotalFrequency = 0;
            for (int i = 0; i < map.Items.Length; i++)
            {
                var item = map.Items[i];

                MyObjectBuilderType type;
                if (item.TypeId != null && MyObjectBuilderType.TryParse(item.TypeId, out type))
                {
                    if (!typeof(MyObjectBuilder_BotDefinition).IsAssignableFrom((Type)type) && !typeof(MyObjectBuilder_VoxelMapStorageDefinition).IsAssignableFrom((Type)type) && !typeof(MyObjectBuilder_EnvironmentItems).IsAssignableFrom((Type)type))
                    {
                        MyLog.Default.WriteLine(String.Format("Object builder type {0} is not supported for environment items.", item.TypeId));
                        Items[i].Frequency = 0; // This should disable this item
                    }
                    else
                    {
                        Items[i] = new MyMaterialEnvironmentItem()
                        {
                            Definition        = new MyDefinitionId(type, item.SubtypeId),
                            Frequency         = map.Items[i].Density,
                            IsDetail          = map.Items[i].IsDetail,
                            IsBot             = typeof(MyObjectBuilder_BotDefinition).IsAssignableFrom((Type)type),
                            IsVoxel           = typeof(MyObjectBuilder_VoxelMapStorageDefinition).IsAssignableFrom((Type)type),
                            IsEnvironemntItem = typeof(MyObjectBuilder_EnvironmentItems).IsAssignableFrom((Type)type),
                            BaseColor         = map.Items[i].BaseColor,
                            ColorSpread       = map.Items[i].ColorSpread,
                            MaxRoll           = (float)Math.Cos(MathHelper.ToDegrees(map.Items[i].MaxRoll)),
                            Offset            = map.Items[i].Offset,
                            GroupId           = map.Items[i].GroupId,
                            GroupIndex        = map.Items[i].GroupIndex,
                            ModifierId        = map.Items[i].ModifierId,
                            ModifierIndex     = map.Items[i].ModifierIndex
                        };
                    }
                }
                else
                {
                    MyLog.Default.WriteLine(String.Format("Object builder type {0} does not exist.", item.TypeId));
                    Items[i].Frequency = 0; // This should disable this item
                }
            }

            ComputeDistribution();
        }
 public Wave(MyObjectBuilder_BarbarianWaveEventDefinition.WaveDef waveOb)
 {
     foreach (var botDef in waveOb.Bots)
     {
         MyObjectBuilderType botType;
         if (!MyObjectBuilderType.TryParse(botDef.TypeName, out botType))
         {
             botType = typeof(MyObjectBuilder_HumanoidBot);
         }
         Bots.Add(new MyDefinitionId(botType, botDef.SubtypeName));
     }
 }
Exemplo n.º 8
0
 public Wave(MyObjectBuilder_BarbarianWaveEventDefinition.WaveDef waveOb)
 {
     foreach (MyObjectBuilder_BarbarianWaveEventDefinition.BotDef def in waveOb.Bots)
     {
         MyObjectBuilderType type;
         if (!MyObjectBuilderType.TryParse(def.TypeName, out type))
         {
             type = typeof(MyObjectBuilder_HumanoidBot);
         }
         this.Bots.Add(new MyDefinitionId(type, def.SubtypeName));
     }
 }
        public static MyPhysicalItemDefinition GetDefinition(this MyDefinitionManager definitionManager, string typeId, string subtypeName)
        {
            MyPhysicalItemDefinition definition = null;
            MyObjectBuilderType      result;

            if (MyObjectBuilderType.TryParse(typeId, out result))
            {
                var id = new MyDefinitionId(result, subtypeName);
                MyDefinitionManager.Static.TryGetPhysicalItemDefinition(id, out definition);
            }

            return(definition);
        }
Exemplo n.º 10
0
 public MyPlanetEnvironmentMapping(PlanetEnvironmentItemMapping map)
 {
     this.Rule  = map.Rule;
     this.Items = new MyMaterialEnvironmentItem[map.Items.Length];
     if (this.Items.Length == 0)
     {
         this.CumulativeIntervals = null;
         this.TotalFrequency      = 0f;
     }
     else
     {
         this.TotalFrequency = 0f;
         for (int i = 0; i < map.Items.Length; i++)
         {
             MyObjectBuilderType        type;
             MyPlanetEnvironmentItemDef def = map.Items[i];
             if ((def.TypeId == null) || !MyObjectBuilderType.TryParse(def.TypeId, out type))
             {
                 MyLog.Default.WriteLine($"Object builder type {def.TypeId} does not exist.");
                 this.Items[i].Frequency = 0f;
             }
             else if ((!typeof(MyObjectBuilder_BotDefinition).IsAssignableFrom((Type)type) && !typeof(MyObjectBuilder_VoxelMapStorageDefinition).IsAssignableFrom((Type)type)) && !typeof(MyObjectBuilder_EnvironmentItems).IsAssignableFrom((Type)type))
             {
                 MyLog.Default.WriteLine($"Object builder type {def.TypeId} is not supported for environment items.");
                 this.Items[i].Frequency = 0f;
             }
             else
             {
                 MyMaterialEnvironmentItem item1 = new MyMaterialEnvironmentItem();
                 item1.Definition        = new MyDefinitionId(type, def.SubtypeId);
                 item1.Frequency         = map.Items[i].Density;
                 item1.IsDetail          = map.Items[i].IsDetail;
                 item1.IsBot             = typeof(MyObjectBuilder_BotDefinition).IsAssignableFrom((Type)type);
                 item1.IsVoxel           = typeof(MyObjectBuilder_VoxelMapStorageDefinition).IsAssignableFrom((Type)type);
                 item1.IsEnvironemntItem = typeof(MyObjectBuilder_EnvironmentItems).IsAssignableFrom((Type)type);
                 item1.BaseColor         = map.Items[i].BaseColor;
                 item1.ColorSpread       = map.Items[i].ColorSpread;
                 item1.MaxRoll           = (float)Math.Cos((double)MathHelper.ToDegrees(map.Items[i].MaxRoll));
                 item1.Offset            = map.Items[i].Offset;
                 item1.GroupId           = map.Items[i].GroupId;
                 item1.GroupIndex        = map.Items[i].GroupIndex;
                 item1.ModifierId        = map.Items[i].ModifierId;
                 item1.ModifierIndex     = map.Items[i].ModifierIndex;
                 this.Items[i]           = item1;
             }
         }
         this.ComputeDistribution();
     }
 }
Exemplo n.º 11
0
        private void ItemSpawned(string itemtypename, string itemsubtypename, long itemid, int amount, Vector3D position)
        {
            MyObjectBuilderType type;

            if (!MyObjectBuilderType.TryParse(itemtypename, out type))
            {
                return;
            }
            var id = new MyDefinitionId(type, itemsubtypename);

            if (!_generatedAmmos.Contains(id))
            {
                return;
            }
            var ent = MyAPIGateway.Entities.GetEntityById(itemid);

            ent?.Close();
        }
Exemplo n.º 12
0
        internal void AddToFilter(Filterdata filterdata)
        {
            if (filterdata.FilterItems.Length == 0)
            {
                // DebugLog.Write("AddToFilter called with 0 items to add. ignoring...");
                return;
            }

            var inventory = (MyInventory)MyCargoContainer.GetInventory();

            for (int i = 0; i < filterdata.FilterItems.Length; i++)
            {
                if (filterdata.FilterItems[i].Type == FilterType.FILTER_TYPE)
                {
                    MyObjectBuilderType type;
                    if (MyObjectBuilderType.TryParse(filterdata.FilterItems[i].ParseItem, out type) == true)
                    {
                        if (!inventory.Constraint.ConstrainedTypes.Contains(type))
                        {
                            inventory.Constraint.AddObjectBuilderType(type);
                        }
                    }
                }
                if (filterdata.FilterItems[i].Type == FilterType.FILTER_ITEM)
                {
                    MyDefinitionId Id;
                    if (MyDefinitionId.TryParse(filterdata.FilterItems[i].ParseItem, out Id) == true)
                    {
                        if (!inventory.Constraint.ConstrainedIds.Contains(Id))
                        {
                            inventory.Constraint.Add(Id);
                        }
                    }
                }
                if (!FilterController.FilterList.Contains(filterdata.FilterItems[i]))
                {
                    FilterController.FilterList.Add(filterdata.FilterItems[i]);
                }
            }
            inventory.Constraint.Icon = null;
            SaveData();
        }
Exemplo n.º 13
0
        public static MyDefinitionBase GetDefinition(this MyDefinitionManager definitionManager, string typeId, string subtypeName)
        {
            MyObjectBuilderType result;

            if (!MyObjectBuilderType.TryParse(typeId, out result))
            {
                return(null);
            }

            var id = new MyDefinitionId(result, subtypeName);

            try
            {
                return(MyDefinitionManager.Static.GetDefinition(id));
            }
            catch
            {
                // If a item as been removed, like a mod,
                // or the mod has broken and failed to load, this will return null.
                return(null);
            }
        }
Exemplo n.º 14
0
        public override void ProcessServer()
        {
            if (!EconomyScript.Instance.ServerConfig.EnableNpcTradezones && !EconomyScript.Instance.ServerConfig.EnablePlayerTradezones)
            {
                MessageClientTextMessage.SendMessage(SenderSteamId, "SELL", "All Trade zones are disabled.");
                return;
            }

            switch (SellAction)
            {
                #region create

            case SellAction.Create:
            {
                EconomyScript.Instance.ServerLogger.WriteVerbose("Action /Sell Create started by Steam Id '{0}'.", SenderSteamId);
                //* Logic:
                //* Get player steam ID
                var sellingPlayer = MyAPIGateway.Players.FindPlayerBySteamId(SenderSteamId);

                MyDefinitionBase    definition = null;
                MyObjectBuilderType result;
                if (MyObjectBuilderType.TryParse(ItemTypeId, out result))
                {
                    var id = new MyDefinitionId(result, ItemSubTypeName);
                    MyDefinitionManager.Static.TryGetDefinition(id, out definition);
                }

                if (definition == null)
                {
                    // Someone hacking, and passing bad data?
                    MessageClientTextMessage.SendMessage(SenderSteamId, "SELL", "Sorry, the item you specified doesn't exist!");
                    EconomyScript.Instance.ServerLogger.WriteVerbose("Definition could not be found for item during '/sell'; '{0}' '{1}'.", ItemTypeId, ItemSubTypeName);
                    return;
                }

                // Do a floating point check on the item item. Tools and components cannot have decimals. They must be whole numbers.
                if (definition.Id.TypeId != typeof(MyObjectBuilder_Ore) && definition.Id.TypeId != typeof(MyObjectBuilder_Ingot))
                {
                    if (ItemQuantity != Math.Truncate(ItemQuantity))
                    {
                        MessageClientTextMessage.SendMessage(SenderSteamId, "SELL", "You must provide a whole number for the quantity of that item.");
                        return;
                    }
                    //ItemQuantity = Math.Round(ItemQuantity, 0);  // Or do we just round the number?
                }

                if (ItemQuantity <= 0)
                {
                    MessageClientTextMessage.SendMessage(SenderSteamId, "SELL", "Invalid quantity, or you dont have any to trade!");
                    EconomyScript.Instance.ServerLogger.WriteVerbose("Action /Sell Create aborted by Steam Id '{0}' -- Invalid quantity.", SenderSteamId);
                    return;
                }

                // Who are we selling to?
                BankAccountStruct accountToBuy;
                if (SellToMerchant)
                {
                    accountToBuy = AccountManager.FindAccount(EconomyConsts.NpcMerchantId);
                }
                else
                {
                    accountToBuy = AccountManager.FindAccount(ToUserName);
                }

                if (accountToBuy == null)
                {
                    MessageClientTextMessage.SendMessage(SenderSteamId, "SELL", "Sorry, player does not exist or have an account!");
                    EconomyScript.Instance.ServerLogger.WriteVerbose("Action /Sell Create aborted by Steam Id '{0}' -- account not found.", SenderSteamId);
                    return;
                }

                if (MarketManager.IsItemBlacklistedOnServer(ItemTypeId, ItemSubTypeName))
                {
                    MessageClientTextMessage.SendMessage(SenderSteamId, "SELL", "Sorry, the item you tried to sell is blacklisted on this server.");
                    EconomyScript.Instance.ServerLogger.WriteVerbose("Action /Sell Create aborted by Steam Id '{0}' -- Item is blacklisted.", SenderSteamId);
                    return;
                }

                // Verify that the items are in the player inventory.
                // TODO: later check trade block, cockpit inventory, cockpit ship inventory, inventory of targeted cube.

                // Get the player's inventory, regardless of if they are in a ship, or a remote control cube.
                var character = sellingPlayer.GetCharacter();
                // TODO: do players in Cryochambers count as a valid trading partner? They should be alive, but the connected player may be offline.
                // I think we'll have to do lower level checks to see if a physical player is Online.
                if (character == null)
                {
                    // Player has no body. Could mean they are dead.
                    // Either way, there is no inventory.
                    MessageClientTextMessage.SendMessage(SenderSteamId, "SELL", "You are dead. You cannot trade while dead.");
                    EconomyScript.Instance.ServerLogger.WriteVerbose("Action /Sell Create aborted by Steam Id '{0}' -- player is dead.", SenderSteamId);
                    return;
                }

                // TODO: is a null check adaqaute?, or do we need to check for IsDead?
                // I don't think the chat console is accessible during respawn, only immediately after death.
                // Is it valid to be able to trade when freshly dead?
                //var identity = payingPlayer.Identity();
                //MyAPIGateway.Utilities.ShowMessage("CHECK", "Is Dead: {0}", identity.IsDead);

                //if (identity.IsDead)
                //{
                //    MessageClientTextMessage.SendMessage(SenderSteamId, "SELL", "You are dead. You cannot trade while dead.");
                //    return;
                //}

                EconomyScript.Instance.ServerLogger.WriteVerbose("Action /Sell finalizing by Steam Id '{0}' -- cataloging cargo cubes.", SenderSteamId);

                // Build list of all cargo blocks that player is attached to as pilot or passenger.
                var cargoBlocks     = new List <MyCubeBlock>();
                var tankBlocks      = new List <MyCubeBlock>();
                var controllingCube = sellingPlayer.Controller.ControlledEntity as IMyCubeBlock;
                if (controllingCube != null)
                {
                    var terminalsys = MyAPIGateway.TerminalActionsHelper.GetTerminalSystemForGrid(controllingCube.CubeGrid);
                    var blocks      = new List <IMyTerminalBlock>();
                    terminalsys.GetBlocksOfType <IMyCargoContainer>(blocks);
                    cargoBlocks.AddRange(blocks.Cast <MyCubeBlock>());

                    terminalsys.GetBlocksOfType <IMyGasTank>(blocks);
                    tankBlocks.AddRange(blocks.Cast <MyCubeBlock>());
                }

                EconomyScript.Instance.ServerLogger.WriteVerbose("Action /Sell finalizing by Steam Id '{0}' -- checking inventory.", SenderSteamId);

                var          position        = ((IMyEntity)character).WorldMatrix.Translation;
                var          playerInventory = character.GetPlayerInventory();
                MyFixedPoint amount          = (MyFixedPoint)ItemQuantity;
                var          storedAmount    = playerInventory.GetItemAmount(definition.Id);

                if (definition.Id.TypeId == typeof(MyObjectBuilder_GasProperties))
                {
                    foreach (MyCubeBlock cubeBlock in tankBlocks)
                    {
                        MyGasTankDefinition gasTankDefintion = cubeBlock.BlockDefinition as MyGasTankDefinition;

                        if (gasTankDefintion == null || gasTankDefintion.StoredGasId != definition.Id)
                        {
                            continue;
                        }

                        var tankLevel = ((IMyGasTank)cubeBlock).FilledRatio;
                        storedAmount += (MyFixedPoint)((decimal)tankLevel * (decimal)gasTankDefintion.Capacity);
                    }
                }
                else
                {
                    foreach (MyCubeBlock cubeBlock in cargoBlocks)
                    {
                        var cubeInventory = cubeBlock.GetInventory();
                        storedAmount += cubeInventory.GetItemAmount(definition.Id);
                    }
                }


                if (amount > storedAmount)
                {
                    // Insufficient items in inventory.
                    // TODO: use of definition.GetDisplayName() isn't localized here.

                    if ((definition.Id.TypeId != typeof(MyObjectBuilder_GasProperties) && cargoBlocks.Count == 0) &&
                        (definition.Id.TypeId == typeof(MyObjectBuilder_GasProperties) && tankBlocks.Count == 0))
                    {
                        MessageClientTextMessage.SendMessage(SenderSteamId, "SELL", "You don't have {0} of '{1}' to sell. You have {2} in your inventory.", ItemQuantity, definition.GetDisplayName(), storedAmount);
                    }
                    else
                    {
                        MessageClientTextMessage.SendMessage(SenderSteamId, "SELL", "You don't have {0} of '{1}' to sell. You have {2} in your player and cargo inventory.", ItemQuantity, definition.GetDisplayName(), storedAmount);
                    }

                    EconomyScript.Instance.ServerLogger.WriteVerbose("Action /Sell Create aborted by Steam Id '{0}' -- inventory doesn't exist.", SenderSteamId);
                    return;
                }

                MarketItemStruct marketItem = null;

                if (SellToMerchant || UseBankBuyPrice)
                {
                    var markets = MarketManager.FindMarketsFromLocation(position);
                    if (markets.Count == 0)         //once again here is were we could put the multi market best price logic..
                    {
                        MessageClientTextMessage.SendMessage(SenderSteamId, "SELL", "Sorry, your are not in range of any markets!");
                        EconomyScript.Instance.ServerLogger.WriteVerbose("Action /Sell Create aborted by Steam Id '{0}' -- no market in range.", SenderSteamId);
                        return;
                    }

                    // TODO: find market with best Buy price that isn't blacklisted.

                    var market = markets.FirstOrDefault();
                    if (market == null)
                    {
                        MessageClientTextMessage.SendMessage(SenderSteamId, "SELL", "Sorry, the market you are accessing does not exist!");
                        EconomyScript.Instance.ServerLogger.WriteVerbose("Action /Sell Create aborted by Steam Id '{0}' -- no market found.", SenderSteamId);
                        return;
                    }

                    accountToBuy = AccountManager.FindAccount(market.MarketId);

                    marketItem = market.MarketItems.FirstOrDefault(e => e.TypeId == ItemTypeId && e.SubtypeName == ItemSubTypeName);
                    if (marketItem == null)
                    {
                        MessageClientTextMessage.SendMessage(SenderSteamId, "SELL", "Sorry, the items you are trying to sell doesn't have a market entry!");
                        // In reality, this shouldn't happen as all markets have their items synced up on start up of the mod.
                        return;
                    }

                    if (marketItem.IsBlacklisted)
                    {
                        MessageClientTextMessage.SendMessage(SenderSteamId, "SELL", "Sorry, the item you tried to sell is blacklisted in this market.");
                        EconomyScript.Instance.ServerLogger.WriteVerbose("Action /Sell Create aborted by Steam Id '{0}' -- item is blacklisted.", SenderSteamId);
                        return;
                    }


                    if (UseBankBuyPrice)
                    {
                        // The player is selling, but the *Market* will *buy* it from the player at this price.
                        // if we are not using price scaling OR the market we are trading with isn't owned by the NPC ID, dont change price. Otherwise scale.
                        if (!EconomyScript.Instance.ServerConfig.PriceScaling || accountToBuy.SteamId != EconomyConsts.NpcMerchantId)
                        {
                            ItemPrice = marketItem.BuyPrice;
                        }
                        else
                        {
                            ItemPrice = EconDataManager.PriceAdjust(marketItem.BuyPrice, marketItem.Quantity, PricingBias.Buy);
                        }
                    }
                    // if we are using price scaling adjust the price before our NPC trade (or check player for subsidy pricing)
                }

                var accountToSell = AccountManager.FindOrCreateAccount(SenderSteamId, SenderDisplayName, SenderLanguage);

                // need fix negative amounts before checking if the player can afford it.
                if (!sellingPlayer.IsAdmin())
                {
                    ItemPrice = Math.Abs(ItemPrice);
                }

                var transactionAmount = ItemPrice * ItemQuantity;

                if (!sellingPlayer.IsAdmin())
                {
                    transactionAmount = Math.Abs(transactionAmount);
                }

                if (SellToMerchant)         // && (merchant has enough money  || !EconomyScript.Instance.ServerConfig.LimitedSupply)
                                            //this is also a quick fix ideally npc should buy what it can afford and the rest is posted as a sell offer
                {
                    if (accountToBuy.SteamId != accountToSell.SteamId)
                    {
                        decimal limit = EconomyScript.Instance.ServerConfig.LimitedSupply ? marketItem.StockLimit - marketItem.Quantity : ItemQuantity;

                        if (limit == 0)
                        {
                            MessageClientTextMessage.SendMessage(SenderSteamId, "SELL", "Sorry, you cannot sell any more {0} into this market.", definition.GetDisplayName());
                            return;
                        }
                        if (ItemQuantity > limit)
                        {
                            MessageClientTextMessage.SendMessage(SenderSteamId, "SELL", "Sorry, you cannot sell any more than {0} of {1} into this market.", limit, definition.GetDisplayName());
                            return;
                        }
                    }

                    if (accountToBuy.BankBalance >= transactionAmount
                        // || !EconomyScript.Instance.ServerConfig.LimitedSupply // I'm not sure why we check limited supply when selling.
                        || accountToBuy.SteamId == accountToSell.SteamId)
                    {
                        // here we look up item price and transfer items and money as appropriate
                        EconomyScript.Instance.ServerLogger.WriteVerbose("Action /Sell finalizing by Steam Id '{0}' -- removing inventory.", SenderSteamId);
                        RemoveInventory(playerInventory, cargoBlocks, tankBlocks, amount, definition.Id);
                        marketItem.Quantity += ItemQuantity;         // increment Market content.

                        if (accountToBuy.SteamId != accountToSell.SteamId)
                        {
                            accountToBuy.BankBalance -= transactionAmount;
                            accountToBuy.Date         = DateTime.Now;

                            accountToSell.BankBalance += transactionAmount;
                            accountToSell.Date         = DateTime.Now;
                            MessageClientTextMessage.SendMessage(SenderSteamId, "SELL", "You just sold {0} {3} worth of {2} ({1} units)", transactionAmount, ItemQuantity, definition.GetDisplayName(), EconomyScript.Instance.ServerConfig.CurrencyName);

                            MessageUpdateClient.SendAccountMessage(accountToBuy);
                            MessageUpdateClient.SendAccountMessage(accountToSell);
                        }
                        else
                        {
                            accountToSell.Date = DateTime.Now;
                            MessageClientTextMessage.SendMessage(SenderSteamId, "BUY", "You just arranged transfer of {0} '{1}' into your market.", ItemQuantity, definition.GetDisplayName());
                        }
                    }
                    else
                    {
                        MessageClientTextMessage.SendMessage(SenderSteamId, "SELL", "NPC can't afford {0} {4} worth of {2} ({1} units) NPC only has {3} funds!", transactionAmount, ItemQuantity, definition.GetDisplayName(), accountToBuy.BankBalance, EconomyScript.Instance.ServerConfig.CurrencyName);
                    }
                    EconomyScript.Instance.ServerLogger.WriteVerbose("Action /Sell Create completed by Steam Id '{0}' -- to NPC market.", SenderSteamId);
                    return;
                }

                if (OfferToMarket)
                {
                    // TODO: Here we post offer to appropriate zone market
                    MessageClientTextMessage.SendMessage(SenderSteamId, "SELL", "Offset to market at price is not yet available!");
                    EconomyScript.Instance.ServerLogger.WriteVerbose("Action /Sell Create aborted by Steam Id '{0}' -- Offer to market at price is not yet available.", SenderSteamId);
                    return;
                }

                // is it a player then?
                if (accountToBuy.SteamId == sellingPlayer.SteamUserId)
                {
                    // commented out for testing with myself.
                    MessageClientTextMessage.SendMessage(SenderSteamId, "SELL", "Sorry, you cannot sell to yourself!");
                    EconomyScript.Instance.ServerLogger.WriteVerbose("Action /Sell Create aborted by Steam Id '{0}' -- can't sell to self.", SenderSteamId);
                    return;
                }

                // check if buying player is online and in range?
                var buyingPlayer = MyAPIGateway.Players.FindPlayerBySteamId(accountToBuy.SteamId);

                if (EconomyScript.Instance.ServerConfig.LimitedRange && !Support.RangeCheck(buyingPlayer, sellingPlayer))
                {
                    MessageClientTextMessage.SendMessage(SenderSteamId, "BUY", "Sorry, you are not in range of that player!");
                    EconomyScript.Instance.ServerLogger.WriteVerbose("Action /Sell Create aborted by Steam Id '{0}' -- target player not in range.", SenderSteamId);
                    return;
                }

                // if other player online, send message.
                if (buyingPlayer == null)
                {
                    // TODO: other player offline.

                    MessageClientTextMessage.SendMessage(SenderSteamId, "SELL", "You cannot sell to offline players at this time.");
                    EconomyScript.Instance.ServerLogger.WriteVerbose("Action /Sell Create aborted by Steam Id '{0}' -- cannot sell to offline player.", SenderSteamId);
                    return;

                    // TODO: we need a way to queue up messages.
                    // While you were gone....
                    // You missed an offer for 4000Kg of Gold for 20,000.
                }
                else
                {
                    // The other player is online.

                    // write to Trade offer table.
                    MarketManager.CreateTradeOffer(SenderSteamId, ItemTypeId, ItemSubTypeName, ItemQuantity, ItemPrice, accountToBuy.SteamId);

                    // remove items from inventory.
                    EconomyScript.Instance.ServerLogger.WriteVerbose("Action /Sell finalizing by Steam Id '{0}' -- removing inventory.", SenderSteamId);
                    RemoveInventory(playerInventory, cargoBlocks, tankBlocks, amount, definition.Id);

                    // Only send message to targeted player if this is the only offer pending for them.
                    // Otherwise it will be sent when the have with previous orders in their order Queue.
                    if (EconomyScript.Instance.Data.OrderBook.Count(e => (e.OptionalId == accountToBuy.SteamId.ToString() && e.TradeState == TradeState.SellDirectPlayer)) == 1)
                    {
                        MessageClientTextMessage.SendMessage(accountToBuy.SteamId, "SELL",
                                                             "You have received an offer from {0} to buy {1} {2} at price {3} {4} each - type '/sell accept' to accept offer (or '/sell deny' to reject and return item to seller)",
                                                             SenderDisplayName, ItemQuantity, definition.GetDisplayName(), ItemPrice, EconomyScript.Instance.ServerConfig.CurrencyName);
                    }

                    // TODO: Improve the message here, to say who were are trading to, and that the item is gone from inventory.
                    // send message to seller to confirm action, "Your Trade offer has been submitted, and the goods removed from you inventory."
                    MessageClientTextMessage.SendMessage(SenderSteamId, "SELL", "Your offer of {0} {1} for {2} {4} each has been sent to {3}.", ItemQuantity, definition.GetDisplayName(), ItemPrice, accountToBuy.NickName, EconomyScript.Instance.ServerConfig.CurrencyName);

                    EconomyScript.Instance.ServerLogger.WriteVerbose("Action /Sell Create completed by Steam Id '{0}' -- to another player.", SenderSteamId);
                    return;
                }
            }

                #endregion

                #region accept

            case SellAction.Accept:
            {
                EconomyScript.Instance.ServerLogger.WriteVerbose("Action /Sell Accept started by Steam Id '{0}'.", SenderSteamId);
                var order = EconomyScript.Instance.Data.OrderBook.FirstOrDefault(e => e.OptionalId == SenderSteamId.ToString() && e.TradeState == TradeState.SellDirectPlayer);
                if (order == null)
                {
                    MessageClientTextMessage.SendMessage(SenderSteamId, "SELL", "There are no outstanding orders to be accepted.");
                    return;
                }

                var payingPlayer = MyAPIGateway.Players.FindPlayerBySteamId(SenderSteamId);

                // get the accounts and check finance.
                var accountToBuy = AccountManager.FindAccount(ulong.Parse(order.OptionalId));

                var transactionAmount = order.Price * order.Quantity;

                // need fix negative amounts before checking if the player can afford it.
                if (!payingPlayer.IsAdmin())
                {
                    transactionAmount = Math.Abs(transactionAmount);
                }

                if (accountToBuy.BankBalance < transactionAmount)
                {
                    MessageClientTextMessage.SendMessage(SenderSteamId, "SELL", "You cannot afford {0} {1} at this time.", transactionAmount, EconomyScript.Instance.ServerConfig.CurrencyName);
                    return;
                }

                var accountToSell = AccountManager.FindAccount(order.TraderId);

                // rebalance accounts.
                accountToBuy.BankBalance -= transactionAmount;
                accountToBuy.Date         = DateTime.Now;

                accountToSell.BankBalance += transactionAmount;
                accountToSell.Date         = DateTime.Now;

                MessageUpdateClient.SendAccountMessage(accountToBuy);
                MessageUpdateClient.SendAccountMessage(accountToSell);

                order.TradeState = TradeState.SellAccepted;

                var definition = MyDefinitionManager.Static.GetDefinition(order.TypeId, order.SubtypeName);

                if (definition == null)
                {
                    // Someone hacking, and passing bad data?
                    MessageClientTextMessage.SendMessage(SenderSteamId, "SELL", "Sorry, the item in your order doesn't exist!");

                    // trade has been finalized, so we can exit safely.
                    EconomyScript.Instance.ServerLogger.WriteVerbose("Definition could not be found for item during '/sell accept'; '{0}' '{1}'.", order.TypeId, order.SubtypeName);
                    return;
                }

                // TODO: Improve the messages.
                // message back "Your Trade offer of xxx to yyy has been accepted. You have recieved zzzz"
                MessageClientTextMessage.SendMessage(accountToSell.SteamId, "SELL", "You just sold {0} {3} worth of {2} ({1} units)", transactionAmount, order.Quantity, definition.GetDisplayName(), EconomyScript.Instance.ServerConfig.CurrencyName);

                var  collectingPlayer    = MyAPIGateway.Players.FindPlayerBySteamId(SenderSteamId);
                var  playerInventory     = collectingPlayer.GetPlayerInventory();
                bool hasAddedToInventory = true;

                if (playerInventory != null)
                {
                    MyFixedPoint amount = (MyFixedPoint)order.Quantity;
                    hasAddedToInventory = Support.InventoryAdd(playerInventory, amount, definition.Id);
                }

                if (hasAddedToInventory)
                {
                    EconomyScript.Instance.Data.OrderBook.Remove(order);         // item has been collected, so the order is finalized.
                    MessageClientTextMessage.SendMessage(SenderSteamId, "SELL", "You just purchased {0} {3} worth of {2} ({1} units) which are now in your player inventory.", transactionAmount, order.Quantity, definition.GetDisplayName(), EconomyScript.Instance.ServerConfig.CurrencyName);
                }
                else
                {
                    MessageClientTextMessage.SendMessage(SenderSteamId, "SELL", "You just purchased {0} {3} worth of {2} ({1} units). Enter '/collect' when you are ready to receive them.", transactionAmount, order.Quantity, definition.GetDisplayName(), EconomyScript.Instance.ServerConfig.CurrencyName);
                }

                // Send message to player if additional offers are pending their attention.
                DisplayNextOrderToAccept(SenderSteamId);

                EconomyScript.Instance.ServerLogger.WriteVerbose("Action /Sell Accept completed by Steam Id '{0}'.", SenderSteamId);
                return;
            }

                #endregion

                #region collect

            case SellAction.Collect:
            {
                EconomyScript.Instance.ServerLogger.WriteVerbose("Action /Sell Collect or /collect started by Steam Id '{0}'.", SenderSteamId);
                var collectableOrders = EconomyScript.Instance.Data.OrderBook.Where(e =>
                                                                                    (e.TraderId == SenderSteamId && e.TradeState == TradeState.SellTimedout) ||
                                                                                    (e.TraderId == SenderSteamId && e.TradeState == TradeState.Holding) ||
                                                                                    (e.TraderId == SenderSteamId && e.TradeState == TradeState.SellRejected) ||
                                                                                    (e.OptionalId == SenderSteamId.ToString() && e.TradeState == TradeState.SellAccepted)).ToArray();

                if (collectableOrders.Length == 0)
                {
                    MessageClientTextMessage.SendMessage(SenderSteamId, "SELL", "There is nothing to collect currently.");
                    return;
                }

                var collectingPlayer = MyAPIGateway.Players.FindPlayerBySteamId(SenderSteamId);

                // TODO: this is just for debugging until the message below are completed....
                //MessageClientTextMessage.SendMessage(SenderSteamId, "SELL", "You are collecting items from {0} order/s.", collectableOrders.Length);

                foreach (var order in collectableOrders)
                {
                    MyDefinitionBase    definition = null;
                    MyObjectBuilderType result;
                    if (MyObjectBuilderType.TryParse(order.TypeId, out result))
                    {
                        var id = new MyDefinitionId(result, order.SubtypeName);
                        MyDefinitionManager.Static.TryGetDefinition(id, out definition);
                    }

                    if (definition == null)
                    {
                        // Someone hacking, and passing bad data?
                        MessageClientTextMessage.SendMessage(SenderSteamId, "SELL", "Sorry, the item in your order doesn't exist!");
                        // TODO: more detail on the item.
                        EconomyScript.Instance.ServerLogger.WriteVerbose("Definition could not be found for item during '/sell collect or /collect'; '{0}' '{1}'.", order.TypeId, order.SubtypeName);
                        continue;
                    }

                    EconomyScript.Instance.ServerLogger.WriteVerbose("Action /Sell finalizing by Steam Id '{0}' -- adding to inventories.", SenderSteamId);
                    var remainingToCollect = MessageSell.AddToInventories(collectingPlayer, order.Quantity, definition.Id);
                    var collected          = order.Quantity - remainingToCollect;

                    if (remainingToCollect == 0)
                    {
                        EconomyScript.Instance.Data.OrderBook.Remove(order);
                        MessageClientTextMessage.SendMessage(SenderSteamId, "SELL", "You just collected {0} worth of {2} ({1} units)", order.Price * collected, collected, definition.GetDisplayName());
                    }
                    else
                    {
                        order.Quantity = remainingToCollect;
                        MessageClientTextMessage.SendMessage(SenderSteamId, "SELL", "You just collected {0} worth of {2} ({1} units). There are {3} remaining.", order.Price * collected, collected, definition.GetDisplayName(), remainingToCollect);
                    }
                }

                EconomyScript.Instance.ServerLogger.WriteVerbose("Action /Sell Collect completed by Steam Id '{0}'.", SenderSteamId);
                return;
            }

                #endregion

                #region cancel

            case SellAction.Cancel:
            {
                EconomyScript.Instance.ServerLogger.WriteVerbose("Action /Sell Cancel started by Steam Id '{0}'.", SenderSteamId);
                var cancellableOrders = EconomyScript.Instance.Data.OrderBook.Where(e =>
                                                                                    (e.TraderId == SenderSteamId && e.TradeState == TradeState.SellDirectPlayer)).OrderByDescending(e => e.Created).ToArray();

                if (cancellableOrders.Length == 0)
                {
                    MessageClientTextMessage.SendMessage(SenderSteamId, "SELL", "There is nothing to cancel currently.");
                }

                // Sellers should be presented with the newest order first, as they will be the most recently created.
                // use of OrderByDescending above assures us that [0] is the most recent order added.
                var order = cancellableOrders[0];
                order.TradeState = TradeState.SellRejected;

                var definition = MyDefinitionManager.Static.GetDefinition(order.TypeId, order.SubtypeName);

                if (definition == null)
                {
                    // Someone hacking, and passing bad data?
                    MessageClientTextMessage.SendMessage(SenderSteamId, "SELL", "Sorry, the item in your order doesn't exist!");

                    // trade has been finalized, so we can exit safely.
                    EconomyScript.Instance.ServerLogger.WriteVerbose("Definition could not be found for item during '/sell cancel'; '{0}' '{1}'.", order.TypeId, order.SubtypeName);
                    return;
                }

                var  transactionAmount   = order.Price * order.Quantity;
                var  collectingPlayer    = MyAPIGateway.Players.FindPlayerBySteamId(SenderSteamId);
                var  inventory           = collectingPlayer.GetPlayerInventory();
                bool hasAddedToInventory = true;

                if (inventory != null)
                {
                    MyFixedPoint amount = (MyFixedPoint)order.Quantity;
                    hasAddedToInventory = Support.InventoryAdd(inventory, amount, definition.Id);
                }

                if (hasAddedToInventory)
                {
                    EconomyScript.Instance.Data.OrderBook.Remove(order);         // item has been collected, so the order is finalized.
                    MessageClientTextMessage.SendMessage(SenderSteamId, "SELL", "You just cancelled the sale of {2} ({1} units) for a total of {0} {3} which are now in your inventory.", transactionAmount, order.Quantity, definition.GetDisplayName(), EconomyScript.Instance.ServerConfig.CurrencyName);
                }
                else
                {
                    MessageClientTextMessage.SendMessage(SenderSteamId, "SELL", "You just cancelled the sale of {2} ({1} units) for a total of {0} {3}. Enter '/sell collect' when you are ready to receive them.", transactionAmount, order.Quantity, definition.GetDisplayName(), EconomyScript.Instance.ServerConfig.CurrencyName);
                }

                cancellableOrders = EconomyScript.Instance.Data.OrderBook.Where(e =>
                                                                                (e.TraderId == SenderSteamId && e.TradeState == TradeState.SellDirectPlayer)).OrderByDescending(e => e.Created).ToArray();

                if (cancellableOrders.Length > 0)
                {
                    // TODO: Inform the player of the next order in the queue that can be cancelled.
                }

                EconomyScript.Instance.ServerLogger.WriteVerbose("Action /Sell Cancel completed by Steam Id '{0}'.", SenderSteamId);
                return;
            }

                #endregion

                #region deny

            case SellAction.Deny:
            {
                EconomyScript.Instance.ServerLogger.WriteVerbose("Action /Sell Deny started by Steam Id '{0}'.", SenderSteamId);
                var buyOrdersForMe = EconomyScript.Instance.Data.OrderBook.Where(e =>
                                                                                 (e.OptionalId == SenderSteamId.ToString() && e.TradeState == TradeState.SellDirectPlayer)).OrderBy(e => e.Created).ToArray();

                if (buyOrdersForMe.Length == 0)
                {
                    MessageClientTextMessage.SendMessage(SenderSteamId, "SELL", "There is nothing to deny currently.");
                }

                // Buyers should be presented with the oldest order first, as they will timout first.
                // use of OrderBy above assures us that [0] is the most oldest order added.
                var order = buyOrdersForMe[0];
                order.TradeState = TradeState.SellRejected;

                var definition = MyDefinitionManager.Static.GetDefinition(order.TypeId, order.SubtypeName);

                if (definition == null)
                {
                    // Someone hacking, and passing bad data?
                    MessageClientTextMessage.SendMessage(SenderSteamId, "SELL", "Sorry, the item in your order doesn't exist!");

                    // trade has been finalized, so we can exit safely.
                    EconomyScript.Instance.ServerLogger.WriteVerbose("Definition could not be found for item during '/sell deny'; '{0}' '{1}'.", order.TypeId, order.SubtypeName);
                    return;
                }

                var transactionAmount = order.Price * order.Quantity;
                var buyerId           = ulong.Parse(order.OptionalId);
                MessageClientTextMessage.SendMessage(buyerId, "SELL", "You just rejected the purchase of {2} ({1} units) for a total of {0} {3}.", transactionAmount, order.Quantity, definition.GetDisplayName(), EconomyScript.Instance.ServerConfig.CurrencyName);

                // TODO: return items to inventory automatically to Trader inventory if there is space.
                MessageClientTextMessage.SendMessage(order.TraderId, "SELL", "{3} has just rejected your offer of {2} ({1} units) for a total of {0} {4}. Enter '/sell collect' when you are ready to receive them.", transactionAmount, order.Quantity, definition.GetDisplayName(), SenderDisplayName, EconomyScript.Instance.ServerConfig.CurrencyName);

                // Send message to player if additional offers are pending their attention.
                DisplayNextOrderToAccept(SenderSteamId);

                EconomyScript.Instance.ServerLogger.WriteVerbose("Action /Sell Deny completed by Steam Id '{0}'.", SenderSteamId);
                return;
            }

                #endregion
            }

            // this is a fall through from the above conditions not yet complete.
            MessageClientTextMessage.SendMessage(SenderSteamId, "SELL", "Not yet complete.");
        }
Exemplo n.º 15
0
        public override void ProcessServer()
        {
            var player = MyAPIGateway.Players.FindPlayerBySteamId(SenderSteamId);

            // Only Admin can change Npc Market prices.
            if (!player.IsAdmin() && MarketId == EconomyConsts.NpcMerchantId)
            {
                EconomyScript.Instance.ServerLogger.WriteWarning("A Player without Admin \"{0}\" {1} attempted to set Default Market characteristics of item {2}/{3} to Quantity={4}.", SenderDisplayName, SenderSteamId, ItemTypeId, ItemSubTypeName, ItemQuantity);
                return;
            }

            // Only Player can change their own Market prices.
            if (SenderSteamId != MarketId && MarketId != EconomyConsts.NpcMerchantId)
            {
                EconomyScript.Instance.ServerLogger.WriteWarning("A Player \"{0}\" {1} attempted to set another Market characteristics of item {2}/{3} to Quantity={4}.", SenderDisplayName, SenderSteamId, ItemTypeId, ItemSubTypeName, ItemQuantity);
                return;
            }

            // TODO: do we check range to market?

            MyDefinitionBase    definition = null;
            MyObjectBuilderType result;

            if (MyObjectBuilderType.TryParse(ItemTypeId, out result))
            {
                var id = new MyDefinitionId(result, ItemSubTypeName);
                MyDefinitionManager.Static.TryGetDefinition(id, out definition);
            }

            if (definition == null)
            {
                // Passing bad data?
                MessageClientTextMessage.SendMessage(SenderSteamId, "SET", "Sorry, the item you specified doesn't exist!");
                return;
            }

            if (SetType.HasFlag(SetMarketItemType.Quantity))
            {
                // Do a floating point check on the item item. Tools and components cannot have decimals. They must be whole numbers.
                if (definition.Id.TypeId != typeof(MyObjectBuilder_Ore) && definition.Id.TypeId != typeof(MyObjectBuilder_Ingot))
                {
                    if (ItemQuantity != Math.Truncate(ItemQuantity))
                    {
                        MessageClientTextMessage.SendMessage(SenderSteamId, "SET", "You must provide a whole number for the quantity of that item.");
                        return;
                    }
                    //ItemQuantity = Math.Round(ItemQuantity, 0);  // Or do we just round the number?
                }

                if (ItemQuantity <= 0)
                {
                    MessageClientTextMessage.SendMessage(SenderSteamId, "SET", "Invalid quantity specified");
                    return;
                }
            }

            // Find the specified market.
            List <MarketStruct> markets;

            if (string.IsNullOrEmpty(MarketZone))
            {
                var character = player.GetCharacter();

                if (character == null)
                {
                    // Player has no body. Could mean they are dead.
                    MessageClientTextMessage.SendMessage(SenderSteamId, "SET", "There is no market at your location to set.");
                    return;
                }

                var position = ((IMyEntity)character).WorldMatrix.Translation;
                markets = MarketManager.FindMarketsFromLocation(position).Where(m => m.MarketId == MarketId).ToList();
            }
            else
            {
                markets = EconomyScript.Instance.Data.Markets.Where(m => m.MarketId == MarketId && (MarketZone == "*" || m.DisplayName.Equals(MarketZone, StringComparison.InvariantCultureIgnoreCase))).ToList();
            }

            if (markets.Count == 0)
            {
                MessageClientTextMessage.SendMessage(SenderSteamId, "SET", "Sorry, you are not near any markets currently or the market does not exist!");
                return;
            }

            var msg = new StringBuilder();

            msg.AppendFormat("Applying changes to : '{0}' {1}/{2}\r\n\r\n", definition.GetDisplayName(), ItemTypeId, ItemSubTypeName);

            foreach (var market in markets)
            {
                msg.AppendFormat("Market: '{0}'\r\n", market.DisplayName);

                var marketItem = market.MarketItems.FirstOrDefault(e => e.TypeId == ItemTypeId && e.SubtypeName == ItemSubTypeName);
                if (marketItem == null)
                {
                    msg.AppendLine("Sorry, the items you are trying to set doesn't have a market entry!");
                    // In reality, this shouldn't happen as all markets have their items synced up on start up of the mod.
                    continue;
                }

                if (SetType.HasFlag(SetMarketItemType.Quantity))
                {
                    marketItem.Quantity = ItemQuantity;
                    msg.AppendFormat("Stock on hand to {0} units", ItemQuantity);
                }

                // Validation to prevent admins setting prices too low for items.
                if (SetType.HasFlag(SetMarketItemType.BuyPrice))
                {
                    if (ItemBuyPrice >= 0)
                    {
                        marketItem.BuyPrice = ItemBuyPrice;
                        msg.AppendFormat("Buy price to {0}", ItemBuyPrice);
                    }
                    else
                    {
                        msg.AppendFormat("Could not set buy price to less than 0.");
                    }
                }

                // Validation to prevent admins setting prices too low for items.
                if (SetType.HasFlag(SetMarketItemType.SellPrice))
                {
                    if (ItemSellPrice >= 0)
                    {
                        marketItem.SellPrice = ItemSellPrice;
                        msg.AppendFormat("Sell price to {0}", ItemSellPrice);
                    }
                    else
                    {
                        msg.AppendFormat("Could not set sell price to less than 0.");
                    }
                }

                if (SetType.HasFlag(SetMarketItemType.Blacklisted))
                {
                    marketItem.IsBlacklisted = !marketItem.IsBlacklisted;
                    msg.AppendFormat("Blacklist to {0}", marketItem.IsBlacklisted ? "On" : "Off");
                }
                msg.AppendLine();
                msg.AppendLine();
            }

            #region update config for the item

            MarketItemStruct configItem = null;
            if (player.IsAdmin() && MarketId == EconomyConsts.NpcMerchantId)
            {
                configItem = EconomyScript.Instance.ServerConfig.DefaultPrices.FirstOrDefault(e => e.TypeId == ItemTypeId && e.SubtypeName == ItemSubTypeName);
            }

            if (configItem != null)
            {
                if (SetType.HasFlag(SetMarketItemType.BuyPrice))
                {
                    if (ItemBuyPrice >= 0)
                    {
                        configItem.BuyPrice = ItemBuyPrice;
                        msg.AppendFormat("Config updated Buy price to {0}", ItemBuyPrice);
                    }
                }

                // Validation to prevent admins setting prices too low for items.
                if (SetType.HasFlag(SetMarketItemType.SellPrice))
                {
                    if (ItemSellPrice >= 0)
                    {
                        configItem.SellPrice = ItemSellPrice;
                        msg.AppendFormat("Config updated Sell price to {0}", ItemSellPrice);
                    }
                }

                if (SetType.HasFlag(SetMarketItemType.Blacklisted))
                {
                    configItem.IsBlacklisted = !configItem.IsBlacklisted;
                    msg.AppendFormat("Config updated Blacklist to {0}", configItem.IsBlacklisted ? "On" : "Off");

                    // If config blacklisted, then all markets should be updated.
                    if (configItem.IsBlacklisted)
                    {
                        int counter = 0;
                        foreach (var market in EconomyScript.Instance.Data.Markets)
                        {
                            var marketItem = market.MarketItems.FirstOrDefault(e => e.TypeId == ItemTypeId && e.SubtypeName == ItemSubTypeName);
                            if (marketItem != null && !marketItem.IsBlacklisted)
                            {
                                counter++;
                                marketItem.IsBlacklisted = true;
                            }
                        }

                        msg.AppendFormat("Config updated {0} Markets to also Blacklist to {1}.", counter, configItem.IsBlacklisted ? "On" : "Off");
                    }
                }
            }

            #endregion

            MessageClientDialogMessage.SendMessage(SenderSteamId, "SET", " ", msg.ToString());
        }
Exemplo n.º 16
0
        public override void ProcessServer()
        {
            var player = MyAPIGateway.Players.FindPlayerBySteamId(SenderSteamId);

            // Only Admin can change Npc Market prices.
            if (!player.IsAdmin() && MarketId == EconomyConsts.NpcMerchantId)
            {
                EconomyScript.Instance.ServerLogger.WriteWarning("A Player without Admin \"{0}\" {1} attempted to set Default Market characteristics of item {2}/{3} to Quantity={4}.", SenderDisplayName, SenderSteamId, ItemTypeId, ItemSubTypeName, ItemQuantity);
                return;
            }

            // Only Player can change their own Market prices.
            if (SenderSteamId != MarketId && MarketId != EconomyConsts.NpcMerchantId)
            {
                EconomyScript.Instance.ServerLogger.WriteWarning("A Player \"{0}\" {1} attempted to set another Market characteristics of item {2}/{3} to Quantity={4}.", SenderDisplayName, SenderSteamId, ItemTypeId, ItemSubTypeName, ItemQuantity);
                return;
            }

            // TODO: do we check range to market?

            MyPhysicalItemDefinition definition = null;
            MyObjectBuilderType      result;

            if (MyObjectBuilderType.TryParse(ItemTypeId, out result))
            {
                var id = new MyDefinitionId(result, ItemSubTypeName);
                MyDefinitionManager.Static.TryGetPhysicalItemDefinition(id, out definition);
            }

            if (definition == null)
            {
                // Passing bad data?
                MessageClientTextMessage.SendMessage(SenderSteamId, "SET", "Sorry, the item you specified doesn't exist!");
                return;
            }

            if (SetType.HasFlag(SetMarketItemType.Quantity))
            {
                // Do a floating point check on the item item. Tools and components cannot have decimals. They must be whole numbers.
                if (definition.Id.TypeId != typeof(MyObjectBuilder_Ore) && definition.Id.TypeId != typeof(MyObjectBuilder_Ingot))
                {
                    if (ItemQuantity != Math.Truncate(ItemQuantity))
                    {
                        MessageClientTextMessage.SendMessage(SenderSteamId, "SET", "You must provide a whole number for the quantity of that item.");
                        return;
                    }
                    //ItemQuantity = Math.Round(ItemQuantity, 0);  // Or do we just round the number?
                }

                if (ItemQuantity <= 0)
                {
                    MessageClientTextMessage.SendMessage(SenderSteamId, "SET", "Invalid quantity spectified");
                    return;
                }
            }

            // Find the specified market.
            var market = EconomyScript.Instance.Data.Markets.FirstOrDefault(m => m.MarketId == MarketId);

            if (market == null)
            {
                MessageClientTextMessage.SendMessage(SenderSteamId, "SET", "Sorry, the market you are accessing does not exist!");
                return;
            }

            var marketItem = market.MarketItems.FirstOrDefault(e => e.TypeId == ItemTypeId && e.SubtypeName == ItemSubTypeName);

            if (marketItem == null)
            {
                MessageClientTextMessage.SendMessage(SenderSteamId, "SET", "Sorry, the items you are trying to set doesn't have a market entry!");
                // In reality, this shouldn't happen as all markets have their items synced up on start up of the mod.
                return;
            }

            MarketItemStruct configItem = null;

            if (player.IsAdmin() && MarketId == EconomyConsts.NpcMerchantId)
            {
                configItem = EconomyScript.Instance.Config.DefaultPrices.FirstOrDefault(e => e.TypeId == ItemTypeId && e.SubtypeName == ItemSubTypeName);
            }

            var msg = new StringBuilder();

            msg.AppendFormat("You just set '{0}'", definition.GetDisplayName());

            if (SetType.HasFlag(SetMarketItemType.Quantity))
            {
                marketItem.Quantity = ItemQuantity;
                msg.AppendFormat(", stock on hand to {0} units", ItemQuantity);
            }

            // Validation to prevent admins setting prices too low for items.
            if (SetType.HasFlag(SetMarketItemType.BuyPrice))
            {
                if (ItemBuyPrice >= 0)
                {
                    marketItem.BuyPrice = ItemBuyPrice;
                    msg.AppendFormat(", buy price to {0}", ItemBuyPrice);

                    if (configItem != null)
                    {
                        configItem.BuyPrice = ItemBuyPrice;
                        msg.AppendFormat("; config updated.");
                    }
                }
                else
                {
                    msg.AppendFormat(", could not set buy price to less than 0.");
                }
            }

            // Validation to prevent admins setting prices too low for items.
            if (SetType.HasFlag(SetMarketItemType.SellPrice))
            {
                if (ItemSellPrice >= 0)
                {
                    marketItem.SellPrice = ItemSellPrice;
                    msg.AppendFormat(", sell price to {0}", ItemSellPrice);

                    if (configItem != null)
                    {
                        configItem.SellPrice = ItemSellPrice;
                        msg.AppendFormat("; config updated.");
                    }
                }
                else
                {
                    msg.AppendFormat(", could not set sell price to less than 0.");
                }
            }

            if (SetType.HasFlag(SetMarketItemType.Blacklisted))
            {
                marketItem.IsBlacklisted = !marketItem.IsBlacklisted;
                msg.AppendFormat(", blacklist to {0}", marketItem.IsBlacklisted ? "On" : "Off");

                if (configItem != null)
                {
                    configItem.IsBlacklisted = marketItem.IsBlacklisted;
                    msg.AppendFormat("; config updated.");
                }
            }

            MessageClientTextMessage.SendMessage(SenderSteamId, "SET", msg.ToString());
        }
        public override void ProcessServer()
        {
            // update our own timestamp here
            AccountManager.UpdateLastSeen(SenderSteamId, SenderLanguage);
            EconomyScript.Instance.ServerLogger.WriteVerbose("Price List Request for from '{0}'", SenderSteamId);

            var player    = MyAPIGateway.Players.FindPlayerBySteamId(SenderSteamId);
            var character = player.GetCharacter();

            if (character == null)
            {
                MessageClientTextMessage.SendMessage(SenderSteamId, "PRICELIST", "You are dead. You get market items values while dead.");
                return;
            }

            List <MarketStruct> markets;

            if (string.IsNullOrEmpty(FindMarket))
            {
                var position = ((IMyEntity)character).WorldMatrix.Translation;
                markets = MarketManager.FindMarketsFromLocation(position);
            }
            else
            {
                markets = MarketManager.FindMarketsFromName(FindMarket);
            }

            if (markets.Count == 0)
            {
                MessageClientTextMessage.SendMessage(SenderSteamId, "PRICELIST", "Sorry, your are not in range of any markets!");
                return;
            }

            // TODO: combine multiple markets to list best Buy and Sell prices that isn't blacklisted.


            var market = markets.FirstOrDefault();

            if (market == null) //hmmm looks like market name parameter checking was started but never done
            {
                MessageClientTextMessage.SendMessage(SenderSteamId, "PRICELIST", "That market does not exist.");
                return;  //as I understand it this would only trigger if no markets are defined?
                //in which case should it read no markets exist?  but in that case
                // wont the count check above halt execution before this if statement???
                // remove these comments once read :)
            }

            string reply = null;

            MyAPIGateway.Parallel.StartBackground(delegate()
                                                  // Background processing occurs within this block.
            {
                try
                {
                    bool showAll = !ShowOre && !ShowIngot && !ShowComponent && !ShowAmmo && !ShowTools && !ShowGasses;

                    var orderedList = new Dictionary <MarketItemStruct, string>();
                    foreach (var marketItem in market.MarketItems)
                    {
                        if (marketItem.IsBlacklisted)
                        {
                            continue;
                        }

                        MyObjectBuilderType result;
                        if (MyObjectBuilderType.TryParse(marketItem.TypeId, out result))
                        {
                            var id      = new MyDefinitionId(result, marketItem.SubtypeName);
                            var content = Support.ProducedType(id);

                            // Cannot check the Type of the item, without having to use MyObjectBuilderSerializer.CreateNewObject().

                            if (showAll ||
                                (ShowOre && content is MyObjectBuilder_Ore) ||
                                (ShowIngot && content is MyObjectBuilder_Ingot) ||
                                (ShowComponent && content is MyObjectBuilder_Component) ||
                                (ShowAmmo && content is MyObjectBuilder_AmmoMagazine) ||
                                (ShowTools && content is MyObjectBuilder_PhysicalGunObject) ||   // guns, welders, hand drills, grinders.
                                (ShowGasses && content is MyObjectBuilder_GasContainerObject) || // aka gas bottle.
                                (ShowGasses && content is MyObjectBuilder_GasProperties))
                            // Type check here allows mods that inherit from the same type to also appear in the lists.
                            {
                                var definition = MyDefinitionManager.Static.GetDefinition(marketItem.TypeId, marketItem.SubtypeName);
                                var name       = definition == null ? marketItem.SubtypeName : definition.GetDisplayName();
                                orderedList.Add(marketItem, name);
                            }
                        }
                    }

                    orderedList = orderedList.OrderBy(kvp => kvp.Value).ToDictionary(kvp => kvp.Key, kvp => kvp.Value);

                    var str = new SeTextBuilder();
                    str.AppendLine("Market: {0}\r\n", market.DisplayName);
                    str.AddLeftTrim(550, "Item");
                    str.AddRightText(650, "Buy at");
                    str.AddRightText(850, "Sell at");
                    str.AppendLine();

                    foreach (var kvp in orderedList)
                    {
                        decimal showBuy  = kvp.Key.BuyPrice;
                        decimal showSell = kvp.Key.SellPrice;
                        if ((EconomyScript.Instance.ServerConfig.PriceScaling) && (market.MarketId == EconomyConsts.NpcMerchantId))
                        {
                            showBuy  = EconDataManager.PriceAdjust(kvp.Key.BuyPrice, kvp.Key.Quantity, PricingBias.Buy);
                            showSell = EconDataManager.PriceAdjust(kvp.Key.SellPrice, kvp.Key.Quantity, PricingBias.Sell);
                        }
                        // TODO: formatting of numbers, and currency name.
                        str.AddLeftTrim(550, kvp.Value);
                        str.AddRightText(650, showBuy.ToString("0.00", EconomyScript.ServerCulture));
                        str.AddRightText(850, showSell.ToString("0.00", EconomyScript.ServerCulture));
                        str.AppendLine();
                    }
                    reply = str.ToString();
                }
                catch (Exception ex)
                {
                    EconomyScript.Instance.ServerLogger.WriteException(ex);
                    MessageClientTextMessage.SendMessage(SenderSteamId, "PRICELIST", "Failed and died. Please contact the administrator.");
                }
            }, delegate()
                                                  // when the background processing is finished, this block will run foreground.
            {
                if (reply != null)
                {
                    try
                    {
                        MessageClientDialogMessage.SendMessage(SenderSteamId, "PRICELIST", " ", reply);
                    }
                    catch (Exception ex)
                    {
                        EconomyScript.Instance.ServerLogger.WriteException(ex);
                        MessageClientTextMessage.SendMessage(SenderSteamId, "PRICELIST", "Failed and died. Please contact the administrator.");
                    }
                }
            });
        }
Exemplo n.º 18
0
        public override void ProcessServer()
        {
            // update our own timestamp here
            AccountManager.UpdateLastSeen(SenderSteamId, SenderLanguage);
            EconomyScript.Instance.ServerLogger.WriteVerbose("Price List Request for from '{0}'", SenderSteamId);

            var player    = MyAPIGateway.Players.FindPlayerBySteamId(SenderSteamId);
            var character = player.GetCharacter();

            if (character == null)
            {
                MessageClientTextMessage.SendMessage(SenderSteamId, "PRICELIST", "You are dead. You get market items values while dead.");
                return;
            }
            var position = ((IMyEntity)character).WorldMatrix.Translation;

            var markets = MarketManager.FindMarketsFromLocation(position);

            if (markets.Count == 0)
            {
                MessageClientTextMessage.SendMessage(SenderSteamId, "PRICELIST", "Sorry, your are not in range of any markets!");
                return;
            }

            // TODO: combine multiple markets to list best Buy and Sell prices that isn't blacklisted.

            var market = markets.FirstOrDefault();

            if (market == null)
            {
                MessageClientTextMessage.SendMessage(SenderSteamId, "PRICELIST", "That market does not exist.");
                return;
            }

            string reply = null;

            MyAPIGateway.Parallel.StartBackground(delegate()
                                                  // Background processing occurs within this block.
            {
                try
                {
                    bool showAll = !ShowOre && !ShowIngot && !ShowComponent && !ShowAmmo && !ShowTools;

                    var orderedList = new Dictionary <MarketItemStruct, string>();
                    foreach (var marketItem in market.MarketItems)
                    {
                        if (marketItem.IsBlacklisted)
                        {
                            continue;
                        }

                        MyObjectBuilderType result;
                        if (MyObjectBuilderType.TryParse(marketItem.TypeId, out result))
                        {
                            var id      = new MyDefinitionId(result, marketItem.SubtypeName);
                            var content = Support.ProducedType(id);

                            // Cannot check the Type of the item, without having to use MyObjectBuilderSerializer.CreateNewObject().

                            if (showAll ||
                                (ShowOre && content is MyObjectBuilder_Ore) ||
                                (ShowIngot && content is MyObjectBuilder_Ingot) ||
                                (ShowComponent && content is MyObjectBuilder_Component) ||
                                (ShowAmmo && content is MyObjectBuilder_AmmoMagazine) ||
                                (ShowTools && content is MyObjectBuilder_PhysicalGunObject) ||
                                (ShowTools && content is MyObjectBuilder_GasContainerObject)) // Type check here allows mods that inherit from the same type to also appear in the lists.
                            {
                                var definition = MyDefinitionManager.Static.GetDefinition(marketItem.TypeId, marketItem.SubtypeName);
                                var name       = definition == null ? marketItem.SubtypeName : definition.GetDisplayName();
                                orderedList.Add(marketItem, name);
                            }
                        }
                    }

                    orderedList = orderedList.OrderBy(kvp => kvp.Value).ToDictionary(kvp => kvp.Key, kvp => kvp.Value);

                    var str = new SeTextBuilder();
                    str.AppendLine("Market: {0}\r\n", market.DisplayName);
                    str.AddLeftTrim(550, "Item");
                    str.AddRightText(650, "Buy at");
                    str.AddRightText(850, "Sell at");
                    str.AppendLine();

                    foreach (var kvp in orderedList)
                    {
                        // TODO: formatting of numbers, and currency name.
                        str.AddLeftTrim(550, kvp.Value);
                        str.AddRightText(650, kvp.Key.BuyPrice.ToString("0.00", EconomyScript.ServerCulture));
                        str.AddRightText(850, kvp.Key.SellPrice.ToString("0.00", EconomyScript.ServerCulture));
                        str.AppendLine();
                    }
                    reply = str.ToString();
                }
                catch (Exception ex)
                {
                    EconomyScript.Instance.ServerLogger.WriteException(ex);
                    MessageClientTextMessage.SendMessage(SenderSteamId, "PRICELIST", "Failed and died. Please contact the administrator.");
                }
            }, delegate()
                                                  // when the background processing is finished, this block will run foreground.
            {
                if (reply != null)
                {
                    try
                    {
                        MessageClientDialogMessage.SendMessage(SenderSteamId, "PRICELIST", " ", reply);
                    }
                    catch (Exception ex)
                    {
                        EconomyScript.Instance.ServerLogger.WriteException(ex);
                        MessageClientTextMessage.SendMessage(SenderSteamId, "PRICELIST", "Failed and died. Please contact the administrator.");
                    }
                }
            });
        }
Exemplo n.º 19
0
        public static void ProcessLcdBlock(IMyTextPanel textPanel)
        {
            //counter++;

            var writer = TextPanelWriter.Create(textPanel);

            // Use the update interval on the LCD Panel to determine how often the display is updated.
            // It can only go as fast as the timer calling this code is.
            float interval;

            try
            {
                interval = Math.Max((float)EconomyScript.Instance.ServerConfig.MinimumLcdDisplayInterval, textPanel.GetValueFloat("ChangeIntervalSlider"));
            }
            catch (Exception ex)
            {
                // The game may generate an exception from the GetValueFloat(GetValue) call.
                EconomyScript.Instance.ServerLogger.WriteException(ex, UpdateCrashMessage);
                EconomyScript.Instance.ClientLogger.WriteException(ex, UpdateCrashMessage);
                // We can't safely ignore this one if it doesn't work, because this can affect the display timing.
                return;
            }
            if (writer.LastUpdate > DateTime.Now.AddSeconds(-interval))
            {
                return;
            }

            var       checkArray    = textPanel.GetPublicTitle().Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
            var       showAll       = false;
            bool      showOre       = false;
            bool      showIngot     = false;
            bool      showComponent = false;
            bool      showAmmo      = false;
            bool      showTools     = false;
            bool      showGasses    = false;
            bool      showStock     = false;
            bool      showPrices    = true;
            bool      showTest1     = false;
            bool      showTest2     = false;
            StartFrom startFrom     = StartFrom.None; //if # is specified eg #20  then run the start line logic
            int       startLine     = 0;              //this is where our start line placeholder sits
            int       pageNo        = 1;

            // removed Linq, to reduce the looping through the array. This should only have to do one loop through all items in the array.
            foreach (var str in checkArray)
            {
                if (str.Equals("stock", StringComparison.InvariantCultureIgnoreCase))
                {
                    showStock = true;
                }
                if (str.Contains("#"))
                {
                    string[] lineNo = str.Split(new char[] { '#' }, StringSplitOptions.RemoveEmptyEntries);
                    if (lineNo.Length != 0 && int.TryParse(lineNo[0], out startLine))
                    {
                        //this only runs if they put a number in
                        startFrom = StartFrom.Line;
                    }
                }
                if (str.StartsWith("P", StringComparison.InvariantCultureIgnoreCase))
                {
                    if (int.TryParse(str.Substring(1), out pageNo))
                    {
                        startFrom = StartFrom.Page;
                    }
                }
                if (str.Equals("*", StringComparison.InvariantCultureIgnoreCase))
                {
                    showAll = true;
                }
                if (!showAll)
                {
                    if (str.Equals("test1", StringComparison.InvariantCultureIgnoreCase))
                    {
                        showTest1 = true;
                    }
                    else if (str.Equals("test2", StringComparison.InvariantCultureIgnoreCase))
                    {
                        showTest2 = true;
                    }
                    else if (str.StartsWith("ore", StringComparison.InvariantCultureIgnoreCase))
                    {
                        showOre = true;
                    }
                    else if (str.StartsWith("ingot", StringComparison.InvariantCultureIgnoreCase))
                    {
                        showIngot = true;
                    }
                    else if (str.StartsWith("component", StringComparison.InvariantCultureIgnoreCase))
                    {
                        showComponent = true;
                    }
                    else if (str.StartsWith("ammo", StringComparison.InvariantCultureIgnoreCase))
                    {
                        showAmmo = true;
                    }
                    else if (str.StartsWith("tool", StringComparison.InvariantCultureIgnoreCase))
                    {
                        showTools = true;
                    }
                    else if (str.StartsWith("gas", StringComparison.InvariantCultureIgnoreCase))
                    {
                        showGasses = true;
                    }
                }
            }

            bool showHelp = !showAll && !showOre && !showIngot && !showComponent && !showAmmo && !showTools && !showGasses;



            showPrices = !showStock || writer.IsWide;

            if (showTest1)
            {
                Test1(writer);
                writer.UpdatePublic();
                return;
            }
            if (showTest2)
            {
                Test2(writer);
                writer.UpdatePublic();
                return;
            }

            if (showHelp)
            {
                writer.AddPublicLine("Please add a tag to the private or public title.");
                writer.AddPublicLine("ie., * ingot ore component ammo tools.");
                writer.UpdatePublic();
                return;
            }

            var buyColumn   = TextPanelWriter.LcdLineWidth - 180;
            var sellColumn  = TextPanelWriter.LcdLineWidth - 0;
            var stockColumn = TextPanelWriter.LcdLineWidth - 0;

            if (showPrices && showStock)
            {
                buyColumn   = TextPanelWriter.LcdLineWidth - 280;
                sellColumn  = TextPanelWriter.LcdLineWidth - 180;
                stockColumn = TextPanelWriter.LcdLineWidth - 0;
            }

            // This might be a costly operation to run.
            var markets = MarketManager.FindMarketsFromLocation(textPanel.WorldMatrix.Translation);

            if (markets.Count == 0)
            {
                writer.AddPublicCenterLine(TextPanelWriter.LcdLineWidth / 2f, "« {0} »", EconomyScript.Instance.ServerConfig.TradeNetworkName);
                writer.AddPublicCenterLine(TextPanelWriter.LcdLineWidth / 2f, "« No market in range »");
            }
            else
            {
                // TODO: not sure if we should display all markets, the cheapest market item, or the closet market.
                // LOGIC summary: it needs to show the cheapest in stock(in range) sell(to player) price, and the highest (in range) has funds buy(from player) price
                // but this logic depends on the buy/sell commands defaulting to the same buy/sell rules as above.
                // where buy /sell commands run out of funds or supply in a given market and need to pull from the next market
                //it will either have to stop at each price change and notify the player, and/or prompt to keep transacting at each new price, or blindly keep buying until the
                //order is filled, the market runs out of stock, or the money runs out. Blindly is probably not optimal unless we are using stockmarket logic (buy orders/offers)
                //so the prompt option is the safer
                var market = markets.FirstOrDefault();

                // Build a list of the items, so we can get the name so we can the sort the items by name.
                var list = new Dictionary <MarketItemStruct, string>();

                writer.AddPublicCenterLine(TextPanelWriter.LcdLineWidth / 2f, market.DisplayName);

                if (startFrom == StartFrom.Page)
                {
                    // convert the page to lines required.
                    if (pageNo < 1)
                    {
                        pageNo = 1;
                    }
                    startLine = ((writer.DisplayLines - 2) * (pageNo - 1));
                    startFrom = StartFrom.Line;
                }

                string fromLine = " (From item #" + startLine + ".)";
                writer.AddPublicText("« Market List");
                if (startLine >= 1)
                {
                    writer.AddPublicText(fromLine);
                }
                else
                {
                    startLine = 1; // needed for truncating end line.
                }
                if (showPrices && showStock)
                {
                    writer.AddPublicRightText(buyColumn, "Buy");
                    writer.AddPublicRightText(sellColumn, "Sell");
                    writer.AddPublicRightLine(stockColumn, "Stock »");
                }
                else if (showStock)
                {
                    writer.AddPublicRightLine(stockColumn, "Stock »");
                }
                else if (showPrices)
                {
                    writer.AddPublicRightText(buyColumn, "Buy");
                    writer.AddPublicRightLine(sellColumn, "Sell »");
                }

                foreach (var marketItem in market.MarketItems)
                {
                    if (marketItem.IsBlacklisted)
                    {
                        continue;
                    }

                    MyObjectBuilderType result;
                    if (MyObjectBuilderType.TryParse(marketItem.TypeId, out result))
                    {
                        var id      = new MyDefinitionId(result, marketItem.SubtypeName);
                        var content = Support.ProducedType(id);

                        //if (((Type)id.TypeId).IsSubclassOf(typeof(MyObjectBuilder_GasContainerObject))) // TODO: Not valid call yet.

                        // Cannot check the Type of the item, without having to use MyObjectBuilderSerializer.CreateNewObject().

                        if (showAll ||
                            (showOre && content is MyObjectBuilder_Ore) ||
                            (showIngot && content is MyObjectBuilder_Ingot) ||
                            (showComponent && content is MyObjectBuilder_Component) ||
                            (showAmmo && content is MyObjectBuilder_AmmoMagazine) ||
                            (showTools && content is MyObjectBuilder_PhysicalGunObject) ||   // guns, welders, hand drills, grinders.
                            (showGasses && content is MyObjectBuilder_GasContainerObject) || // aka gas bottle.
                            (showGasses && content is MyObjectBuilder_GasProperties))        // Type check here allows mods that inherit from the same type to also appear in the lists.
                        {
                            MyDefinitionBase definition;
                            if (MyDefinitionManager.Static.TryGetDefinition(id, out definition))
                            {
                                list.Add(marketItem, definition == null ? marketItem.TypeId + "/" + marketItem.SubtypeName : definition.GetDisplayName());
                            }
                        }
                    }
                }
                int line = 0;
                foreach (var kvp in list.OrderBy(k => k.Value))
                {
                    line++;
                    if (startFrom == StartFrom.Line && line < startLine) //if we have a start line specified skip all lines up to that
                    {
                        continue;
                    }
                    if (startFrom == StartFrom.Line && line - startLine >= writer.WholeDisplayLines - 2) // counts 2 lines of headers.
                    {
                        break;                                                                           // truncate the display and don't display the text on the bottom edge of the display.
                    }
                    writer.AddPublicLeftTrim(buyColumn - 120, kvp.Value);

                    decimal showBuy  = kvp.Key.BuyPrice;
                    decimal showSell = kvp.Key.SellPrice;
                    if ((EconomyScript.Instance.ServerConfig.PriceScaling) && (market.MarketId == EconomyConsts.NpcMerchantId))
                    {
                        showBuy  = EconDataManager.PriceAdjust(kvp.Key.BuyPrice, kvp.Key.Quantity, PricingBias.Buy);
                        showSell = EconDataManager.PriceAdjust(kvp.Key.SellPrice, kvp.Key.Quantity, PricingBias.Sell);
                    }

                    if (showPrices && showStock)
                    {
                        writer.AddPublicRightText(buyColumn, showBuy.ToString("\t0.000", EconomyScript.ServerCulture));
                        writer.AddPublicRightText(sellColumn, showSell.ToString("\t0.000", EconomyScript.ServerCulture));

                        // TODO: components and tools should be displayed as whole numbers. Will be hard to align with other values.
                        writer.AddPublicRightText(stockColumn, kvp.Key.Quantity.ToString("\t0.0000", EconomyScript.ServerCulture)); // TODO: recheck number of decimal places.
                    }
                    else if (showStock)                                                                                             //does this ever actually run? seems to already be in the above?
                    {
                        // TODO: components and tools should be displayed as whole numbers. Will be hard to align with other values.

                        writer.AddPublicRightText(stockColumn, kvp.Key.Quantity.ToString("\t0.0000", EconomyScript.ServerCulture)); // TODO: recheck number of decimal places.
                    }
                    else if (showPrices)
                    {
                        writer.AddPublicRightText(buyColumn, showBuy.ToString("\t0.000", EconomyScript.ServerCulture));
                        writer.AddPublicRightText(sellColumn, showSell.ToString("\t0.000", EconomyScript.ServerCulture));
                    }
                    writer.AddPublicLine();
                }
            }

            writer.UpdatePublic();
        }
Exemplo n.º 20
0
        public override void ProcessServer()
        {
            EconomyScript.Instance.ServerLogger.WriteVerbose("Action /Buy started by Steam Id '{0}'.", SenderSteamId);

            // Get player steam ID
            var buyingPlayer = MyAPIGateway.Players.FindPlayerBySteamId(SenderSteamId);

            MyPhysicalItemDefinition definition = null;
            MyObjectBuilderType      result;

            if (MyObjectBuilderType.TryParse(ItemTypeId, out result))
            {
                var id = new MyDefinitionId(result, ItemSubTypeName);
                MyDefinitionManager.Static.TryGetPhysicalItemDefinition(id, out definition);
            }

            if (definition == null)
            {
                // Someone hacking, and passing bad data?
                MessageClientTextMessage.SendMessage(SenderSteamId, "BUY", "Sorry, the item you specified doesn't exist!");
                EconomyScript.Instance.ServerLogger.WriteVerbose("Action /Buy aborted by Steam Id '{0}' -- item doesn't exist.", SenderSteamId);
                return;
            }

            // Do a floating point check on the item item. Tools and components cannot have decimals. They must be whole numbers.
            if (definition.Id.TypeId != typeof(MyObjectBuilder_Ore) && definition.Id.TypeId != typeof(MyObjectBuilder_Ingot))
            {
                if (ItemQuantity != Math.Truncate(ItemQuantity))
                {
                    MessageClientTextMessage.SendMessage(SenderSteamId, "BUY", "You must provide a whole number for the quantity to buy that item.");
                    EconomyScript.Instance.ServerLogger.WriteVerbose("Action /Buy aborted by Steam Id '{0}' -- invalid qantity.", SenderSteamId);
                    return;
                }
                //ItemQuantity = Math.Round(ItemQuantity, 0);  // Or do we just round the number?
            }

            if (ItemQuantity <= 0)
            {
                MessageClientTextMessage.SendMessage(SenderSteamId, "BUY", "You must provide a valid quantity to buy.");
                EconomyScript.Instance.ServerLogger.WriteVerbose("Action /Buy aborted by Steam Id '{0}' -- invalid qantity.", SenderSteamId);
                return;
            }

            // Who are we buying to?
            BankAccountStruct accountToSell;

            if (BuyFromMerchant)
            {
                accountToSell = AccountManager.FindAccount(EconomyConsts.NpcMerchantId);
            }
            else
            {
                accountToSell = AccountManager.FindAccount(FromUserName);
            }

            if (accountToSell == null)
            {
                MessageClientTextMessage.SendMessage(SenderSteamId, "BUY", "Sorry, player does not exist or have an account!");
                EconomyScript.Instance.ServerLogger.WriteVerbose("Action /Buy aborted by Steam Id '{0}' -- no account.", SenderSteamId);
                return;
            }

            if (MarketManager.IsItemBlacklistedOnServer(ItemTypeId, ItemSubTypeName))
            {
                MessageClientTextMessage.SendMessage(SenderSteamId, "BUY", "Sorry, the item you tried to buy is blacklisted on this server.");
                EconomyScript.Instance.ServerLogger.WriteVerbose("Action /Buy aborted by Steam Id '{0}' -- item blacklisted.", SenderSteamId);
                return;
            }

            // Get the player's inventory, regardless of if they are in a ship, or a remote control cube.
            var character = buyingPlayer.GetCharacter();

            // TODO: do players in Cryochambers count as a valid trading partner? They should be alive, but the connected player may be offline.
            // I think we'll have to do lower level checks to see if a physical player is Online.
            if (character == null)
            {
                // Player has no body. Could mean they are dead.
                // Either way, there is no inventory.
                MessageClientTextMessage.SendMessage(SenderSteamId, "BUY", "You are dead. You cannot trade while dead.");
                EconomyScript.Instance.ServerLogger.WriteVerbose("Action /Buy aborted by Steam Id '{0}' -- player is dead.", SenderSteamId);
                return;
            }

            // TODO: is a null check adaqaute?, or do we need to check for IsDead?
            // I don't think the chat console is accessible during respawn, only immediately after death.
            // Is it valid to be able to trade when freshly dead?
            //var identity = buyingPlayer.Identity();
            //MyAPIGateway.Utilities.ShowMessage("CHECK", "Is Dead: {0}", identity.IsDead);

            //if (identity.IsDead)
            //{
            //    MessageClientTextMessage.SendMessage(SenderSteamId, "BUY", "You are dead. You cannot trade while dead.");
            //    return;
            //}

            var position = ((IMyEntity)character).WorldMatrix.Translation;

            MarketItemStruct marketItem = null;

            if (BuyFromMerchant || UseBankSellPrice)
            {
                var markets = MarketManager.FindMarketsFromLocation(position);
                if (markets.Count == 0)
                {
                    MessageClientTextMessage.SendMessage(SenderSteamId, "BUY", "Sorry, your are not in range of any markets!");
                    EconomyScript.Instance.ServerLogger.WriteVerbose("Action /Buy aborted by Steam Id '{0}' -- no market in range.", SenderSteamId);
                    return;
                }

                // TODO: find market with best Sell price that isn't blacklisted.

                var market = markets.FirstOrDefault();
                if (market == null)
                {
                    MessageClientTextMessage.SendMessage(SenderSteamId, "BUY", "Sorry, the market you are accessing does not exist!");
                    EconomyScript.Instance.ServerLogger.WriteVerbose("Action /Buy aborted by Steam Id '{0}' -- no market found.", SenderSteamId);
                    return;
                }

                marketItem = market.MarketItems.FirstOrDefault(e => e.TypeId == ItemTypeId && e.SubtypeName == ItemSubTypeName);
                if (marketItem == null)
                {
                    MessageClientTextMessage.SendMessage(SenderSteamId, "BUY", "Sorry, the items you are trying to buy doesn't have a market entry!");
                    // In reality, this shouldn't happen as all markets have their items synced up on start up of the mod.
                    return;
                }

                if (marketItem.IsBlacklisted)
                {
                    MessageClientTextMessage.SendMessage(SenderSteamId, "BUY", "Sorry, the item you tried to buy is blacklisted in this market.");
                    EconomyScript.Instance.ServerLogger.WriteVerbose("Action /Buy aborted by Steam Id '{0}' -- item is blacklisted in market.", SenderSteamId);
                    return;
                }

                // Verify that the items are in the player inventory.
                // TODO: later check trade block, cockpit inventory, cockpit ship inventory, inventory of targeted cube.

                if (UseBankSellPrice)
                {
                    // The player is buying, but the *Market* will *sell* it to the player at this price.
                    ItemPrice = marketItem.SellPrice;
                }
            }

            var accountToBuy      = AccountManager.FindOrCreateAccount(SenderSteamId, SenderDisplayName, SenderLanguage);
            var transactionAmount = ItemPrice * ItemQuantity;

            // need fix negative amounts before checking if the player can afford it.
            if (!buyingPlayer.IsAdmin())
            {
                transactionAmount = Math.Abs(transactionAmount);
            }

            // TODO: admin check on ability to afford it?
            //[maybe later, our pay and reset commands let us steal money from npc anyway best to keep admin abuse features to minimum]
            //[we could put an admin check on blacklist however, allow admins to spawn even blacklisted gear]
            if (accountToBuy.BankBalance < transactionAmount)
            {
                MessageClientTextMessage.SendMessage(SenderSteamId, "BUY", "Sorry, you cannot afford {0} {1}!", transactionAmount, EconomyScript.Instance.Config.CurrencyName);
                EconomyScript.Instance.ServerLogger.WriteVerbose("Action /Buy aborted by Steam Id '{0}' -- not enough money.", SenderSteamId);
                return;
            }

            if (BuyFromMerchant) // and supply is not exhausted, or unlimited mode is not on.
                                 //This is a quick fix, ideally it should do a partial buy of what is left and post a buy offer for remainder
            {
                // here we look up item price and transfer items and money as appropriate
                if (marketItem.Quantity >= ItemQuantity || !EconomyScript.Instance.Config.LimitedSupply)
                {
                    marketItem.Quantity -= ItemQuantity; // reduce Market content.
                    EconomyScript.Instance.ServerLogger.WriteVerbose("Action /Buy finalizing by Steam Id '{0}' -- adding to inventory.", SenderSteamId);
                    var remainingToCollect = MessageSell.AddToInventories(buyingPlayer, ItemQuantity, definition.Id);

                    //EconomyScript.Instance.Config.LimitedSupply

                    accountToSell.BankBalance += transactionAmount;
                    accountToSell.Date         = DateTime.Now;

                    accountToBuy.BankBalance -= transactionAmount;
                    accountToBuy.Date         = DateTime.Now;
                    MessageClientTextMessage.SendMessage(SenderSteamId, "BUY", "You just purchased {1} '{2}' for {0} {3}", transactionAmount, ItemQuantity, definition.GetDisplayName(), EconomyScript.Instance.Config.CurrencyName);

                    if (remainingToCollect > 0)
                    {
                        MarketManager.CreateStockHeld(buyingPlayer.SteamUserId, ItemTypeId, ItemSubTypeName, remainingToCollect, ItemPrice);
                        // TODO: there should be a common command to collect items. Not use /sell.
                        MessageClientTextMessage.SendMessage(SenderSteamId, "BUY", "There are {0} remaining to collect. Use '/sell collect'", remainingToCollect);
                    }
                    EconomyScript.Instance.ServerLogger.WriteVerbose("Action /Buy complete by Steam Id '{0}' -- items bought.", SenderSteamId);
                }
                else
                {
                    MessageClientTextMessage.SendMessage(SenderSteamId, "BUY", "There isn't '{0}' of {1} available to purchase! Only {2} available to buy!", ItemQuantity, definition.GetDisplayName(), marketItem.Quantity);
                    EconomyScript.Instance.ServerLogger.WriteVerbose("Action /Buy aborted by Steam Id '{0}' -- not enough stock.", SenderSteamId);
                }

                return;
            }
            else if (FindOnMarket)
            {
                // TODO: Here we find the best offer on the zone market

                return;
            }
            else
            {
                // is it a player then?
                if (accountToSell.SteamId == buyingPlayer.SteamUserId)
                {
                    MessageClientTextMessage.SendMessage(SenderSteamId, "BUY", "Sorry, you cannot buy from yourself!");
                    return;
                }

                // check if selling player is online and in range?
                var payingPlayer = MyAPIGateway.Players.FindPlayerBySteamId(accountToSell.SteamId);

                if (EconomyScript.Instance.Config.LimitedRange && !Support.RangeCheck(buyingPlayer, payingPlayer))
                {
                    MessageClientTextMessage.SendMessage(SenderSteamId, "BUY", "Sorry, you are not in range of that player!");
                    return;
                }

                if (payingPlayer == null)
                {
                    // TODO: other player offline.
                }
                else
                {
                    // TODO: other player is online.
                }
            }

            // this is a fall through from the above conditions not yet complete.
            MessageClientTextMessage.SendMessage(SenderSteamId, "BUY", "Not yet complete.");
        }
Exemplo n.º 21
0
        private static void ProcessLcdBlock(IMyTextPanel textPanel)
        {
            //counter++;

            var  checkArray    = (textPanel.GetPublicTitle() + " " + textPanel.GetPrivateTitle()).Split(new Char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
            var  showAll       = false;
            bool showOre       = false;
            bool showIngot     = false;
            bool showComponent = false;
            bool showAmmo      = false;
            bool showTools     = false;
            bool showStock     = false;
            bool showPrices    = true;
            bool showTest1     = false;
            bool showTest2     = false;

            // removed Linq, to reduce the looping through the array. This should only have to do one loop through all items in the array.
            foreach (var str in checkArray)
            {
                if (str.Equals("stock", StringComparison.InvariantCultureIgnoreCase))
                {
                    showStock = true;
                }
                if (str.Equals("*", StringComparison.InvariantCultureIgnoreCase))
                {
                    showAll = true;
                }
                if (!showAll)
                {
                    if (str.Equals("test1", StringComparison.InvariantCultureIgnoreCase))
                    {
                        showTest1 = true;
                    }
                    if (str.Equals("test2", StringComparison.InvariantCultureIgnoreCase))
                    {
                        showTest2 = true;
                    }
                    if (str.Equals("ore", StringComparison.InvariantCultureIgnoreCase))
                    {
                        showOre = true;
                    }
                    if (str.Equals("ingot", StringComparison.InvariantCultureIgnoreCase))
                    {
                        showIngot = true;
                    }
                    if (str.Equals("component", StringComparison.InvariantCultureIgnoreCase))
                    {
                        showComponent = true;
                    }
                    if (str.Equals("ammo", StringComparison.InvariantCultureIgnoreCase))
                    {
                        showAmmo = true;
                    }
                    if (str.Equals("tools", StringComparison.InvariantCultureIgnoreCase))
                    {
                        showTools = true;
                    }
                }
            }

            bool showHelp = !showAll && !showOre && !showIngot && !showComponent && !showAmmo && !showTools;

            var writer = TextPanelWriter.Create(textPanel);

            // Use the update interval on the LCD Panel to determine how often the display is updated.
            // It can only go as fast as the timer calling this code is.
            var interval = Math.Max(1f, textPanel.GetValueFloat("ChangeIntervalSlider"));

            if (writer.LastUpdate > DateTime.Now.AddSeconds(-interval))
            {
                return;
            }

            showPrices = !showStock || writer.IsWide;

            if (showTest1)
            {
                Test1(writer);
                writer.UpdatePublic();
                return;
            }
            if (showTest2)
            {
                Test2(writer);
                writer.UpdatePublic();
                return;
            }

            if (showHelp)
            {
                writer.AddPublicLine("Please add a tag to the private or public title.");
                writer.AddPublicLine("ie., * ingot ore component ammo tools.");
                writer.UpdatePublic();
                return;
            }

            var buyColumn   = TextPanelWriter.LcdLineWidth - 180;
            var sellColumn  = TextPanelWriter.LcdLineWidth - 0;
            var stockColumn = TextPanelWriter.LcdLineWidth - 0;

            if (showPrices && showStock)
            {
                buyColumn   = TextPanelWriter.LcdLineWidth - 280;
                sellColumn  = TextPanelWriter.LcdLineWidth - 180;
                stockColumn = TextPanelWriter.LcdLineWidth - 0;
            }

            // This might be a costly operation to run.
            var markets = MarketManager.FindMarketsFromLocation(textPanel.WorldMatrix.Translation);

            if (markets.Count == 0)
            {
                writer.AddPublicCenterLine(TextPanelWriter.LcdLineWidth / 2f, "« {0} »", EconomyScript.Instance.Config.TradeNetworkName);
                writer.AddPublicCenterLine(TextPanelWriter.LcdLineWidth / 2f, "« No market in range »");
            }
            else
            {
                // TODO: not sure if we should display all markets, the cheapest market item, or the closet market.
                var market = markets.FirstOrDefault();

                // Build a list of the items, so we can get the name so we can the sort the items by name.
                var list = new Dictionary <MarketItemStruct, string>();

                writer.AddPublicCenterLine(TextPanelWriter.LcdLineWidth / 2f, market.DisplayName);

                writer.AddPublicText("« Market List");

                if (showPrices && showStock)
                {
                    writer.AddPublicRightText(buyColumn, "Buy");
                    writer.AddPublicRightText(sellColumn, "Sell");
                    writer.AddPublicRightLine(stockColumn, "Stock »");
                }
                else if (showStock)
                {
                    writer.AddPublicRightLine(stockColumn, "Stock »");
                }
                else if (showPrices)
                {
                    writer.AddPublicRightText(buyColumn, "Buy");
                    writer.AddPublicRightLine(sellColumn, "Sell »");
                }

                foreach (var marketItem in market.MarketItems)
                {
                    if (marketItem.IsBlacklisted)
                    {
                        continue;
                    }

                    MyObjectBuilderType result;
                    if (MyObjectBuilderType.TryParse(marketItem.TypeId, out result))
                    {
                        var id      = new MyDefinitionId(result, marketItem.SubtypeName);
                        var content = Support.ProducedType(id);

                        // Cannot check the Type of the item, without having to use MyObjectBuilderSerializer.CreateNewObject().

                        if (showAll ||
                            (showOre && content is MyObjectBuilder_Ore) ||
                            (showIngot && content is MyObjectBuilder_Ingot) ||
                            (showComponent && content is MyObjectBuilder_Component) ||
                            (showAmmo && content is MyObjectBuilder_AmmoMagazine) ||
                            (showTools && content is MyObjectBuilder_PhysicalGunObject) ||
                            (showTools && content is MyObjectBuilder_GasContainerObject))  // Type check here allows mods that inherit from the same type to also appear in the lists.
                        {
                            MyPhysicalItemDefinition definition = null;
                            if (MyDefinitionManager.Static.TryGetPhysicalItemDefinition(id, out definition))
                            {
                                list.Add(marketItem, definition == null ? marketItem.TypeId + "/" + marketItem.SubtypeName : definition.GetDisplayName());
                            }
                        }
                    }
                }

                foreach (var kvp in list.OrderBy(k => k.Value))
                {
                    writer.AddPublicLeftTrim(buyColumn - 120, kvp.Value);
                    if (showPrices && showStock)
                    {
                        writer.AddPublicRightText(buyColumn, kvp.Key.BuyPrice.ToString("0.00", EconomyScript.ServerCulture));
                        writer.AddPublicRightText(sellColumn, kvp.Key.SellPrice.ToString("0.00", EconomyScript.ServerCulture));

                        // TODO: components and tools should be displayed as whole numbers. Will be hard to align with other values.
                        writer.AddPublicRightText(stockColumn, kvp.Key.Quantity.ToString("0.000000", EconomyScript.ServerCulture)); // TODO: recheck number of decimal places.
                    }
                    else if (showStock)
                    {
                        // TODO: components and tools should be displayed as whole numbers. Will be hard to align with other values.

                        writer.AddPublicRightText(stockColumn, kvp.Key.Quantity.ToString("0.000000", EconomyScript.ServerCulture)); // TODO: recheck number of decimal places.
                    }
                    else if (showPrices)
                    {
                        writer.AddPublicRightText(buyColumn, kvp.Key.BuyPrice.ToString("0.00", EconomyScript.ServerCulture));
                        writer.AddPublicRightText(sellColumn, kvp.Key.SellPrice.ToString("0.00", EconomyScript.ServerCulture));
                    }
                    writer.AddPublicLine();
                }
            }

            writer.UpdatePublic();
        }