public ItemStack(IEnumerable <IInanimate> thePile) { if (thePile == null || thePile.Count() == 0) { FullStackSize = 0; Description = string.Empty; Item = null; } FullStackSize = thePile.Count(); Item = thePile.First().Template <IInanimateTemplate>(); StringBuilder sb = new StringBuilder(); IInanimate plainItem = thePile.FirstOrDefault(item => item.Qualities == null || item.Qualities.Count() == 0); if (plainItem != null) { sb.AppendFormattedLine("({0}) {1}", thePile.Count(item => item.Qualities == null || item.Qualities.Count() == 0), Item.Name); } foreach (IGrouping <string, IInanimate> currentPair in thePile .Where(item => item.Qualities != null && item.Qualities.Count() > 0) .GroupBy(item => string.Join(",", item.Qualities.Select(quality => string.Format("{0}:{1}", quality.Name, quality.Value))))) { int count = currentPair.Count(); string qualities = currentPair.Key; sb.AppendFormattedLine("({0}) {1} [{2}]", count, Item.Name, qualities); } Description = sb.ToString(); }
/// <summary> /// Execute a sale /// </summary> /// <param name="item">the item in question</param> /// <param name="price">the sale price</param> /// <returns>error or blank</returns> public string MakeSale(IMobile customer, IInanimate item, int price) { string returnString = string.Empty; if (customer == null) { return("Invalid customer"); } if (item == null || !Inventory.Contains(item)) { return("I don't have that item in stock."); } int customerWallet = customer.GetQuality("Bells"); if (customerWallet < price) { return("Insufficient Funds."); } customer.SetQuality(-1 * price, "Bells", true); item.TryMoveTo(customer.GetContainerAsLocation()); return(returnString); }
/// <summary> /// What will the merchant buy this item for /// </summary> /// <param name="item">the item in question</param> /// <returns>the price, -1 indicates they wont buy it</returns> public int HaggleCheck(IInanimate item) { decimal value = -1; if (item != null) { IInanimateTemplate template = item.Template <IInanimateTemplate>(); if (WillPurchase.Any(merch => merch.Item.Id == item.TemplateId)) { DataStructure.Gaia.IEconomy theEconomy = CurrentLocation.CurrentZone.GetWorld().Macroeconomy; if (theEconomy != null) { DataStructure.Gaia.IEconomicBasis priceBasis = theEconomy.Bases.FirstOrDefault(basis => basis.ItemType.Id == item.TemplateId); if (priceBasis != null) { value = priceBasis.Basis * priceBasis.Adjustment; } else { value = theEconomy.MakeValuation(template); } foreach (IQuality quality in item.Qualities) { DataStructure.Gaia.IEconomicTrend trend = theEconomy.Trends.FirstOrDefault(trnd => trnd.Quality.Equals(quality.Name, StringComparison.InvariantCultureIgnoreCase)); if (trend != null) { value += trend.Basis * trend.Adjustment; } else { value += theEconomy.MakeValuation(template); } } decimal myAdjustments = 1; foreach (IMerchandise adjustment in WillPurchase.Where(merch => merch.Item.Id == item.TemplateId)) { if (string.IsNullOrWhiteSpace(adjustment.Quality) || item.Qualities.Any(quality => quality.Name.Equals(adjustment.Quality) && quality.Value.IsBetweenOrEqual(adjustment.QualityRange.Low, adjustment.QualityRange.High))) { myAdjustments += adjustment.MarkRate; } } value += value * myAdjustments; } } } return((int)Math.Truncate(value)); }
/// <summary> /// Check the price this will be sold for /// </summary> /// <param name="item">The item in question</param> /// <returns>the price, -1 indicates it wont be sold or isn't in stock</returns> public int PriceCheck(IInanimate item, bool mustBeInStock) { decimal value = -1; //If we need it in stock but don't have it it's sell price is invalid if (item != null && (!mustBeInStock || Inventory.Contains(item))) { if (WillSell.Any(merch => merch.Item.Id == item.TemplateId)) { DataStructure.Gaia.IEconomy theEconomy = CurrentLocation.CurrentZone.GetWorld().Macroeconomy; if (theEconomy != null) { DataStructure.Gaia.IEconomicBasis priceBasis = theEconomy.Bases.FirstOrDefault(basis => basis.ItemType.Id == item.TemplateId); if (priceBasis != null) { value = priceBasis.Basis * priceBasis.Adjustment; } else { value = theEconomy.MakeValuation(item.Template <IInanimateTemplate>()); } foreach (IQuality quality in item.Qualities) { DataStructure.Gaia.IEconomicTrend trend = theEconomy.Trends.FirstOrDefault(trnd => trnd.Quality.Equals(quality.Name, StringComparison.InvariantCultureIgnoreCase)); if (trend != null) { value += trend.Basis * trend.Adjustment; } else { value += theEconomy.MakeValuation(item.Template <IInanimateTemplate>()); } } decimal myAdjustments = 1; foreach (IMerchandise adjustment in WillSell.Where(merch => merch.Item.Id == item.TemplateId)) { if (string.IsNullOrWhiteSpace(adjustment.Quality) || item.Qualities.Any(quality => quality.Name.Equals(adjustment.Quality) && quality.Value.IsBetweenOrEqual(adjustment.QualityRange.Low, adjustment.QualityRange.High))) { myAdjustments *= adjustment.MarkRate; } } value *= myAdjustments; } } } return((int)Math.Truncate(value)); }
/// <summary> /// Executes this command /// </summary> internal override bool ExecutionBody() { INonPlayerCharacter merchant = (INonPlayerCharacter)Subject; if (merchant == null || !merchant.DoISellThings()) { RenderError("There is no merchant that sells items in that direction."); return(false); } IInanimate thing = (IInanimate)Target; if (Target == null) { RenderError("The merchant does not sell that item."); return(false); } int price = merchant.PriceCheck(thing, true); if (price <= 0) { RenderError("The merchant will not sell that item."); return(false); } string errorMessage = merchant.MakeSale((IMobile)Actor, thing, price); if (!string.IsNullOrWhiteSpace(errorMessage)) { RenderError(errorMessage); } ILexicalParagraph toActor = new LexicalParagraph(string.Format("You purchase a $T$ from $S$ for {0}blz.", price)); ILexicalParagraph toArea = new LexicalParagraph("$A$ makes a purchase from $S$."); //TODO: language outputs Message messagingObject = new Message(toActor) { ToOrigin = new List <ILexicalParagraph> { toArea } }; messagingObject.ExecuteMessaging(Actor, merchant, thing, OriginLocation.CurrentZone, null); return(true); }
/// <summary> /// Move an entity into a named container in this /// </summary> /// <typeparam name="T">the type of the entity to add</typeparam> /// <param name="thing">the entity to add</param> /// <param name="containerName">the name of the container</param> /// <returns>errors</returns> public string MoveInto <T>(T thing, string containerName) { IEnumerable <Type> implimentedTypes = DataUtility.GetAllImplimentingedTypes(typeof(T)); if (implimentedTypes.Contains(typeof(IInanimate))) { IInanimate obj = (IInanimate)thing; if (Inventory.Contains(obj, containerName)) { return("That is already in the container"); } string moveError = MoveInto(obj); if (!string.IsNullOrWhiteSpace(moveError)) { return(moveError); } Inventory.Add(obj, containerName); UpsertToLiveWorldCache(); return(string.Empty); } if (implimentedTypes.Contains(typeof(IMobile))) { IMobile obj = (IMobile)thing; if (MobilesInside.Contains(obj, containerName)) { return("That is already in the container"); } string moveError = MoveInto(obj); if (!string.IsNullOrWhiteSpace(moveError)) { return(moveError); } MobilesInside.Add(obj, containerName); UpsertToLiveWorldCache(); return(string.Empty); } return("Invalid type to move to container."); }
/// <summary> /// Executes this command /// </summary> public override void Execute() { INonPlayerCharacter merchant = (INonPlayerCharacter)Subject; if (merchant == null || !merchant.DoIBuyThings()) { RenderError("There is no merchant that buys items in that direction."); return; } IInanimate thing = (IInanimate)Target; if (Target == null) { RenderError("That item does not exist."); return; } int price = merchant.HaggleCheck(thing); if (price <= 0) { RenderError("The merchant will not buy that item."); return; } string errorMessage = merchant.MakePurchase((IMobile)Actor, thing, price); if (!string.IsNullOrWhiteSpace(errorMessage)) { RenderError(errorMessage); } ILexicalParagraph toActor = new LexicalParagraph(string.Format("You sell a $T$ to $S$ for {0}blz.", price)); ILexicalParagraph toArea = new LexicalParagraph("$A$ sells an item to $S$."); //TODO: language outputs Message messagingObject = new Message(toActor) { ToOrigin = new List <ILexicalParagraph> { toArea } }; messagingObject.ExecuteMessaging(Actor, merchant, thing, OriginLocation.CurrentZone, null); }
/// <summary> /// Execute a purchase /// </summary> /// <param name="item">the item in question</param> /// <param name="price">the sale price</param> /// <returns>error or blank</returns> public string MakePurchase(IMobile customer, IInanimate item, int price) { string returnString = string.Empty; if (customer == null) { return("Invalid customer"); } if (item == null) { return("Invalid item."); } customer.SetQuality(price, "Bells", true); item.TryMoveTo(GetContainerAsLocation()); return(returnString); }
/// <summary> /// Executes this command /// </summary> internal override bool ExecutionBody() { IInanimate thing = (IInanimate)Subject; if (Target == null) { RenderError("There is no merchant in that direction."); return(false); } INonPlayerCharacter merchant = (INonPlayerCharacter)Target; if (merchant == null || (!merchant.DoIBuyThings())) { RenderError("There is no merchant that buys items in that direction."); return(false); } int price = merchant.HaggleCheck(thing); if (price <= 0) { RenderError("The merchant will not buy that item."); return(false); } ILexicalParagraph toActor = new LexicalParagraph(string.Format("The merchant appraises your {0} at {1}blz.", thing.GetDescribableName(Actor), price)); ILexicalParagraph toArea = new LexicalParagraph("$T$ looks very closely at $A$'s $S$."); //TODO: language outputs Message messagingObject = new Message(toActor) { ToOrigin = new List <ILexicalParagraph> { toArea } }; messagingObject.ExecuteMessaging(Actor, thing, merchant, OriginLocation.CurrentZone, null); return(true); }
/// <summary> /// Move an entity out of this' named container /// </summary> /// <typeparam name="T">the type of entity to remove</typeparam> /// <param name="thing">the entity</param> /// <param name="containerName">the name of the container</param> /// <returns>errors</returns> public string MoveFrom <T>(T thing, string containerName) { IEnumerable <Type> implimentedTypes = DataUtility.GetAllImplimentingedTypes(typeof(T)); if (implimentedTypes.Contains(typeof(IInanimate))) { IInanimate obj = (IInanimate)thing; if (!Contents.Contains(obj, containerName)) { return("That is not in the container"); } Contents.Remove(obj, containerName); UpsertToLiveWorldCache(); return(string.Empty); } if (implimentedTypes.Contains(typeof(IMobile))) { IMobile obj = (IMobile)thing; if (!MobilesInside.Contains(obj, containerName)) { return("That is not in the container"); } MobilesInside.Remove(obj, containerName); UpsertToLiveWorldCache(); return(string.Empty); } return("Invalid type to move from container."); }
/// <summary> /// Restores live entity backup from Current /// </summary> /// <returns>Success state</returns> public bool RestoreLiveBackup() { LiveData liveDataAccessor = new LiveData(); string currentBackupDirectory = liveDataAccessor.BaseDirectory + liveDataAccessor.CurrentDirectoryName; //No backup directory? No live data. if (!Directory.Exists(currentBackupDirectory)) { return(false); } LoggingUtility.Log("World restored from current live INITIATED.", LogChannels.Backup, false); try { //dont load players here List <IEntity> entitiesToLoad = new List <IEntity>(); IEnumerable <Type> implimentedTypes = typeof(EntityPartial).Assembly.GetTypes().Where(ty => ty.GetInterfaces().Contains(typeof(IEntity)) && ty.IsClass && !ty.IsAbstract && !ty.GetCustomAttributes <IgnoreAutomatedBackupAttribute>().Any()); foreach (Type type in implimentedTypes.OrderByDescending(type => type == typeof(Gaia) ? 6 : type == typeof(Zone) ? 5 : type == typeof(Locale) ? 3 : type == typeof(Room) ? 3 : type == typeof(Pathway) ? 2 : 0)) { if (!Directory.Exists(currentBackupDirectory + type.Name)) { continue; } DirectoryInfo entityFilesDirectory = new DirectoryInfo(currentBackupDirectory + type.Name); foreach (FileInfo file in entityFilesDirectory.EnumerateFiles()) { entitiesToLoad.Add(liveDataAccessor.ReadEntity(file, type)); } } //Check we found actual data if (!entitiesToLoad.Any(ent => ent.GetType() == typeof(Gaia))) { throw new Exception("No Worlds found, failover."); } if (!entitiesToLoad.Any(ent => ent.GetType() == typeof(Zone))) { throw new Exception("No zones found, failover."); } //Shove them all into the live system first foreach (IEntity entity in entitiesToLoad.OrderBy(ent => ent.Birthdate)) { entity.UpsertToLiveWorldCache(); entity.KickoffProcesses(); } //We need to pick up any places that aren't already live from the file system incase someone added them during the last session\ foreach (IGaiaTemplate thing in TemplateCache.GetAll <IGaiaTemplate>().Where(dt => !entitiesToLoad.Any(ent => ent.TemplateId.Equals(dt.Id) && ent.Birthdate >= dt.LastRevised))) { IGaia entityThing = Activator.CreateInstance(thing.EntityClass, new object[] { thing }) as IGaia; entityThing.SpawnNewInWorld(); } foreach (IZoneTemplate thing in TemplateCache.GetAll <IZoneTemplate>().Where(dt => !entitiesToLoad.Any(ent => ent.TemplateId.Equals(dt.Id) && ent.Birthdate >= dt.LastRevised))) { IZone entityThing = Activator.CreateInstance(thing.EntityClass, new object[] { thing }) as IZone; entityThing.SpawnNewInWorld(); } foreach (ILocaleTemplate thing in TemplateCache.GetAll <ILocaleTemplate>().Where(dt => !entitiesToLoad.Any(ent => ent.TemplateId.Equals(dt.Id) && ent.Birthdate >= dt.LastRevised))) { ILocale entityThing = Activator.CreateInstance(thing.EntityClass, new object[] { thing }) as ILocale; entityThing.ParentLocation = entityThing.ParentLocation.GetLiveInstance(); entityThing.SpawnNewInWorld(); } foreach (IRoomTemplate thing in TemplateCache.GetAll <IRoomTemplate>().Where(dt => !entitiesToLoad.Any(ent => ent.TemplateId.Equals(dt.Id) && ent.Birthdate >= dt.LastRevised))) { IRoom entityThing = Activator.CreateInstance(thing.EntityClass, new object[] { thing }) as IRoom; entityThing.ParentLocation = entityThing.Template <IRoomTemplate>().ParentLocation.GetLiveInstance(); entityThing.SpawnNewInWorld(); } foreach (IPathwayTemplate thing in TemplateCache.GetAll <IPathwayTemplate>().Where(dt => !entitiesToLoad.Any(ent => ent.TemplateId.Equals(dt.Id) && ent.Birthdate >= dt.LastRevised))) { IPathway entityThing = Activator.CreateInstance(thing.EntityClass, new object[] { thing }) as IPathway; entityThing.SpawnNewInWorld(); } //We have the containers contents and the birthmarks from the deserial //I don't know how we can even begin to do this type agnostically since the collections are held on type specific objects without some super ugly reflection foreach (Room entity in entitiesToLoad.Where(ent => ent.GetType() == typeof(Room))) { foreach (IInanimate obj in entity.Contents.EntitiesContained()) { IInanimate fullObj = LiveCache.Get <IInanimate>(new LiveCacheKey(obj)); entity.MoveFrom(obj); entity.MoveInto(fullObj); } foreach (INonPlayerCharacter obj in entity.MobilesInside.EntitiesContained()) { INonPlayerCharacter fullObj = LiveCache.Get <INonPlayerCharacter>(new LiveCacheKey(obj)); entity.MoveFrom(obj); entity.MoveInto(fullObj); } } foreach (NonPlayerCharacter entity in entitiesToLoad.Where(ent => ent.GetType() == typeof(NonPlayerCharacter))) { foreach (IInanimate obj in entity.Inventory.EntitiesContained()) { IInanimate fullObj = LiveCache.Get <IInanimate>(new LiveCacheKey(obj)); entity.MoveFrom(obj); entity.MoveInto(fullObj); } } foreach (Inanimate entity in entitiesToLoad.Where(ent => ent.GetType() == typeof(Inanimate))) { foreach (Tuple <string, IInanimate> obj in entity.Contents.EntitiesContainedByName()) { IInanimate fullObj = LiveCache.Get <IInanimate>(new LiveCacheKey(obj.Item2)); entity.MoveFrom(obj.Item2); entity.MoveInto(fullObj, obj.Item1); } foreach (Tuple <string, IInanimate> obj in entity.Contents.EntitiesContainedByName()) { INonPlayerCharacter fullObj = LiveCache.Get <INonPlayerCharacter>(new LiveCacheKey(obj.Item2)); entity.MoveFrom((INonPlayerCharacter)obj.Item2); entity.MoveInto(fullObj, obj.Item1); } } //We need to poll the WorldMaps here and give all the rooms their coordinates as well as the zones their sub-maps ParseDimension(); LoggingUtility.Log("World restored from current live.", LogChannels.Backup, false); return(true); } catch (Exception ex) { LoggingUtility.LogError(ex); } return(false); }
/// <summary> /// Restores one character from their Current backup /// </summary> /// <param name="accountHandle">Global Account Handle for the account</param> /// <param name="charID">Which character to load</param> /// <returns></returns> public IPlayer RestorePlayer(string accountHandle, IPlayerTemplate chr) { IPlayer newPlayerToLoad = null; try { string currentBackupDirectory = BaseDirectory + accountHandle + "/" + CurrentDirectoryName + chr.Id.ToString() + "/"; //No backup directory? No live data. if (!VerifyDirectory(currentBackupDirectory, false)) { return(null); } DirectoryInfo playerDirectory = new DirectoryInfo(currentBackupDirectory); byte[] fileData = new byte[0]; using (FileStream stream = File.Open(currentBackupDirectory + GetPlayerFilename(chr.Id), FileMode.Open)) { fileData = new byte[stream.Length]; stream.Read(fileData, 0, (int)stream.Length); } //no player file to load, derp if (fileData.Length == 0) { return(null); } IPlayer blankEntity = Activator.CreateInstance(chr.EntityClass) as IPlayer; newPlayerToLoad = (IPlayer)blankEntity.FromBytes(fileData); //bad load, dump it if (newPlayerToLoad == null) { return(null); } //We have the player in live cache now so make it move to the right place newPlayerToLoad.GetFromWorldOrSpawn(); newPlayerToLoad.UpsertToLiveWorldCache(true); //We'll need one of these per container on players if (Directory.Exists(playerDirectory + "Inventory/")) { DirectoryInfo inventoryDirectory = new DirectoryInfo(playerDirectory + "Inventory/"); foreach (FileInfo file in inventoryDirectory.EnumerateFiles()) { IInanimate blankObject = Activator.CreateInstance("NetMud.Data", "NetMud.Data.Game.Inanimate") as IInanimate; IInanimate newObj = (IInanimate)blankObject.FromBytes(ReadFile(file)); newObj.UpsertToLiveWorldCache(true); newObj.TryMoveTo(newPlayerToLoad.GetContainerAsLocation()); } } } catch (Exception ex) { LoggingUtility.LogError(ex); } return(newPlayerToLoad); }
public void DoTheThing(Motivator motivator) { Accomplisher action = Hypothalamus.HowToDo(motivator); bool wander = false; switch (action) { case Accomplisher.Drink: IInanimate waterBottle = Inventory.EntitiesContained().FirstOrDefault(ent => ent.GetQuality("Water") > 0); if (waterBottle != null) { waterBottle.SetQuality(-1, "Water", true); Hypothalamus.ApplyPressure(Motivator.Thirst, -10); Exhaust(-10); } else { wander = true; } break; case Accomplisher.Eat: IInanimate food = Inventory.EntitiesContained().FirstOrDefault(ent => ent.GetQuality("Food") > 0); if (food != null) { //TODO: turn this into an eat command int foodValue = food.GetQuality("Food"); food.Remove(); Hypothalamus.ApplyPressure(Motivator.Hunger, -1 * foodValue); Harm(-1 * foodValue); } else { wander = true; } break; case Accomplisher.Sleep: //Can't sleep yet break; case Accomplisher.Speak: if (CurrentLocation.CurrentZone != null) { CurrentLocation.CurrentZone.BroadcastEvent("$A$ moos.", this); } break; case Accomplisher.Wander: wander = true; break; } if (wander) { Random rand = new Random(); MovementDirectionType direction = (MovementDirectionType)rand.Next(0, 7); //Run the command like anyone else //Interpret.Render(direction.ToString(), this); } }