public static MudLikeOperationBuilder AddWorldDate(this MudLikeOperationBuilder builder, DateTime dateTime) { return(builder .StartContainer("dateview") .AddTextLine(dateTime.ToString("D"), TextColor.Fuschia, TextSize.Small) .EndContainer("dateview")); }
private async Task HandleMapChanged(Object sender, IMapChangeEvent e) { if (e.OldMap != null) { await e.OldMap.RemovePlayerAsync(e.Player); await Game.Network.RemovePlayerFromMapGroupAsync(e.Player, e.OldMap); e.OldMap.PlayersChanged -= MapPlayersChanged; e.OldMap.ItemsChanged -= MapItemsChanged; e.OldMap.EntitiesChanged -= MapEntitiesChanged; var playersLeftBehind = e.OldMap.Players.Except(e.Player); var leftBehindNotification = MudLikeOperationBuilder.Start("playerlist") .AddPlayers(playersLeftBehind) .Build(); await Game.Network.SendViewCommandsToMapAsync(e.OldMap, MudLikeViewBuilder.Start().AddOperation(leftBehindNotification).Build()); } var map = (GridMap)e.NewMap; await Game.Network.AddPlayerToMapGroupAsync(e.Player, map); map.PlayersChanged += MapPlayersChanged; map.ItemsChanged += MapItemsChanged;; map.EntitiesChanged += MapEntitiesChanged;; var player = e.Player; var lookView = MudLikeOperationBuilder.Start() .AddWorldDate(Game.World.Time.WorldTime) .AddMap(map) .Build(); await Game.Network.SendViewCommandsToPlayerAsync(player, MudLikeViewBuilder.Start().AddOperation(lookView).Build()); // update the map with a new playerslist var playersUpdate = MudLikeOperationBuilder.Start("playerlist").AddPlayers(map.Players) .Build(); var itemsUpdate = MudLikeOperationBuilder.Start("itemlist").AddItems(map.Items) .Build(); var entitiesUpdate = MudLikeOperationBuilder.Start(MudContainers.EntityList.ToString()).AddEntities(map.Entities) .Build(); var update = MudLikeViewBuilder.Start().AddOperation(playersUpdate).AddOperation(itemsUpdate).AddOperation(entitiesUpdate).Build(); await Game.Network.SendViewCommandsToMapAsync(map, update); }
private async Task SpawnerSpawned(ISpawnable spawned, IMap map) { if (spawned.GetType() == typeof(GridEntity)) { var entity = (GridEntity)spawned; entity.Died += EntityDied; } else { var itemsUpdate = MudLikeOperationBuilder.Start("itemlist").AddItems(map.Items) .Build(); await Game.Network.SendViewCommandsToMapAsync(map, MudLikeViewBuilder.Start().AddOperation(itemsUpdate).Build()); } }
private Task ProcessItemPickupAsync(IProcessorData <CommandModel> request, IPlayer player) { request.Handled = true; Parser.Default.ParseArguments <ItemPickupParserOptions>(request.Data.StringFrom(2).Split(' ')) .WithParsed(async(parsed) => { var itemName = string.Join(" ", parsed.Name); // take each matching item up to the quantity we requested var mapItems = ( parsed.PickupAny ? player.Map.Items : player.Map.Items.Where(mi => mi.Name.IndexOf(itemName, StringComparison.OrdinalIgnoreCase) >= 0)) .Take(parsed.Quantity) .ToList(); if (mapItems.Count == 0) { await Game.Network.SendMessageToPlayerAsync(player, "Matching item not found"); return; } itemName = mapItems[0].Name; await Game.Network.SendMessageToPlayerAsync(player, $"Looting {itemName} | quantity {mapItems.Count}"); foreach (var i in mapItems) { // double check one last time the item wasn't picked up elsewhere in the time we've been picking up others if (player.Map.Items.Contains(i)) { await player.PickupItemAsync(Game, i); } } var itemView = MudLikeViewBuilder.Start() .AddOperation( MudLikeOperationBuilder.Start("itemlist").AddItems(player.Map.Items).Build()) .Build(); await Game.Network.SendViewCommandsToMapAsync(player.Map, itemView); }) .WithNotParsed(async(issues) => { await Game.Network.SendMessageToPlayerAsync(player, "invalid command(pickup) - for help type item help"); }); return(Task.CompletedTask); }
public override async Task IntervalTick(object sender, EventArgs e) { await base.IntervalTick(sender, e); var worldTime = ((GridWorld)Game.World).Time.WorldTime; if (lastRunWorldDate.Day != worldTime.Day) { lastRunWorldDate = worldTime; var viewUpdate = MudLikeOperationBuilder.Start("dateview") .AddWorldDate(worldTime) .Build(); await Game.Network.SendViewCommandsToPlayersAsync(Game.Players, MudLikeViewBuilder.Start().AddOperation(viewUpdate).Build()); } }
public static MudLikeOperationBuilder AddMap(this MudLikeOperationBuilder builder, GridMap map, bool includePlayers = false) { builder .StartContainer("mapdata") .AddText($"{map.Id} ", TextColor.Gray, TextSize.Small) .AddTextLine(map.Name, color: TextColor.Aqua, size: TextSize.Strong) .AddTextLine(map.Description, size: TextSize.Strong) .AddText("Exits ") .AddTextLine(string.Join(",", map.Exits.Select(o => o.ToString().ToLower())), TextColor.Green) .EndContainer("mapdata"); if (includePlayers) { builder.AddPlayers(map.Players); } return(builder); }
private async Task HandleNewEncounter(IEncounter encounter) { encounter.ActionExecuted += Encounter_ActionExecuted; encounter.Ended += Encounter_Ended; var map = ((GridPlayer)encounter.Combatants.First().Key).Map; await Game.Network.SendViewCommandsToMapAsync(map, MudLikeViewBuilder.Start() .AddOperation( MudLikeOperationBuilder.Start($"enc_{encounter.Id}") .StartContainer($"enc_{encounter.Id}") .AddTextLine("Combat Starting") .EndContainer($"enc_{encounter.Id}") .Build() ) .Build()); }
private async Task ProcessBasicLook(IProcessorData <CommandModel> request, IPlayer player) { request.Handled = true; if (!string.IsNullOrEmpty(request.Data.SecondPart)) { await Game.Network.SendMessageToPlayerAsync(player, "Complex look not yet supported. Processing without arguments."); } var mapView = MudLikeOperationBuilder.Start() .AddWorldDate(Game.World.Time.WorldTime) .AddMap((GridMap)player.Map, includePlayers: true) .Build(); var itemsView = MudLikeOperationBuilder.Start("itemlist").AddItems(player.Map.Items) .Build(); var entitiesUpdate = MudLikeOperationBuilder.Start(MudContainers.EntityList.ToString()).AddEntities(player.Map.Entities) .Build(); await Game.Network.SendViewCommandsToPlayerAsync(player, MudLikeViewBuilder.Start().AddOperation(mapView).AddOperation(itemsView).AddOperation(entitiesUpdate).Build()); }
private Task ProcessListSpawnersAsync(IProcessorData <CommandModel> request, IPlayer player) { request.Handled = true; Parser.Default.ParseArguments <ListSpawnerParserOptions>(request.Data.StringFrom(2).Split(' ')) .WithParsed(async(parsed) => { var validSpawnTypes = new List <string>() { "item", "entity" }; var match = validSpawnTypes.FirstOrDefault(s => s == parsed.SpawnType); if (match != null) { validSpawnTypes.RemoveAll(s => s != match); } var viewbuilder = MudLikeViewBuilder.Start(); var partial = Game.Spawners.Cast <GridSpawner>().Where(spawner => spawner.Map == player.Map).ToList(); foreach (var spawnType in validSpawnTypes) { IViewOperation <IViewItem> operation = null; var opBuilder = MudLikeOperationBuilder.Start(); opBuilder .AddTextLine(spawnType, TextColor.Olive) .AddTextLine("------------------------------", TextColor.Olive); switch (spawnType) { case "entity": var entityMatches = partial.Where(spawner => spawner.SpawnType == Core.Game.SpawnType.Entity).Select(s => s.EntityId).ToList(); var entities = Game.Entities.Where(e => entityMatches.Contains(e.Id)).ToList(); foreach (GridEntity entity in entities) { opBuilder .AddText($"{entity.Id} ", TextColor.Aqua) .AddText($"{entity.Name} "); entity.Stats.ToList().ForEach(stat => { opBuilder .AddText($"{stat.Name} ", TextColor.Gray) .AddText($"{stat.Value} ") ; }); opBuilder.AddLineBreak(); } operation = opBuilder.Build(); break; case "item": var itemMatches = partial.Where(spawner => spawner.SpawnType == Core.Game.SpawnType.Item); var items = Game.Items.Where(e => itemMatches.Select(i => i.Id).Contains(e.Id)).ToList(); foreach (GridItem item in items) { opBuilder .AddText($"{item.Id} ", TextColor.Aqua) .AddText($"{item.Name} ") ; item.Stats.ToList().ForEach(stat => { opBuilder .AddText($"{stat.Name} ", TextColor.Gray) .AddText($"{stat.Value} ") ; }); opBuilder.AddLineBreak(); } operation = opBuilder.Build(); break; default: break; } if (operation != null) { viewbuilder.AddOperation(operation); } } await Game.Network.SendViewCommandsToPlayerAsync(player, viewbuilder.Build()); }) .WithNotParsed(async(issues) => { await Game.Network.SendMessageToPlayerAsync(player, "invalid command - for help type spawner help"); }); return(Task.CompletedTask); }
private async Task Encounter_Ended(IEncounter encounter, EncounterEndings ending) { encounter.ActionExecuted -= Encounter_ActionExecuted; encounter.Ended -= Encounter_Ended; if (ending == EncounterEndings.Expired) { return; } var gridEncounter = (GridEncounter)encounter; // allocate experience to winners var factionInfo = gridEncounter.Factions.Select(f => new { FactionName = f.Key, FactionEntities = f.Value, isWinner = f.Value.Count(e => !gridEncounter.Dead.Contains(e)) > 0, AverageLevel = f.Value.Average(e => e.Stats.FirstOrDefault(s => s.Name == "level")?.Value).GetValueOrDefault(0), MinLevel = f.Value.Min(e => e.Stats.FirstOrDefault(s => s.Name == "level")?.Value).GetValueOrDefault(0), MaxLevel = f.Value.Max(e => e.Stats.FirstOrDefault(s => s.Name == "level")?.Value).GetValueOrDefault(0) }).ToList(); // this would need updated to support more than 2 factions properly var winners = factionInfo.FirstOrDefault(f => f.isWinner); var losers = factionInfo.FirstOrDefault(f => !f.isWinner); var cancelExperience = false; if (winners.MinLevel < winners.MaxLevel - 5) { cancelExperience = true; } var experienceScaler = 1 + (losers.AverageLevel - winners.AverageLevel) * 0.2; var experience = (3 * losers.AverageLevel) * experienceScaler; if (!cancelExperience) { foreach (var winner in winners.FactionEntities) { // players and monsters both gain experience the same for now var experienceStat = (BasicStat)winner.Stats.FirstOrDefault(s => s.Name == "experience"); await experienceStat?.ApplyAsync(Convert.ToInt32(experience)); if (experienceStat != null) { // check if leveled if (experienceStat.Value == experienceStat.Base) { var levelStat = winner.Stats.FirstOrDefault(s => s.Name == "level"); await levelStat?.ApplyAsync(1); await experienceStat.RebaseAsync(Convert.ToInt32(experienceStat.Base * 1.5), 0); // fill stats var vitalStats = new List <string>() { "health", "mana", "stamina" }; foreach (BasicStat stat in winner.Stats.Where(s => vitalStats.Contains(s.Name)).ToList()) { await stat.Fill(); } } } } } foreach (var faction in factionInfo) { var players = faction.FactionEntities.Where(e => e.IsPlayer()).Select(e => e).Distinct(); if (!players.Any()) { continue; } var combatView = MudLikeOperationBuilder.Start($"enc_{encounter.Id}") .StartContainer($"enc_{encounter.Id}").AddLineBreak(); foreach (var entity in faction.FactionEntities) { var experienceStat = entity.Stats.FirstOrDefault(s => s.Name == "experience"); combatView .AddText(entity.Name, (entity.IsAlive && !encounter.Dead.Contains(entity) ? TextColor.Normal : TextColor.Red)); if (entity.IsAlive && !encounter.Dead.Contains(entity)) { combatView .AddText($" {entity.Stats.FirstOrDefault(s => s.Name == "health")?.Value}", TextColor.Green) .AddText($" {entity.Stats.FirstOrDefault(s => s.Name == "mana")?.Value}", TextColor.Blue) .AddText($" {entity.Stats.FirstOrDefault(s => s.Name == "stamina")?.Value}", TextColor.Yellow) .AddText($" Lv {experienceStat.Value}/{experienceStat.Base}", TextColor.Yellow) ; } else { combatView.AddText(" Dead", TextColor.Red, TextSize.Small); } combatView.AddLineBreak(); } if (faction.isWinner) { combatView.AddTextLine($"You earned {experience} experience"); } else { combatView.AddTextLine($"You lost the encounter."); } combatView.EndContainer($"enc_{encounter.Id}"); var view = MudLikeViewBuilder.Start().AddOperation(combatView.Build()).Build(); await Game.Network.SendViewCommandsToPlayersAsync(players.Cast <IPlayer>(), view); } }
private async Task Encounter_ActionExecuted(IEncounter encounter, ICombatAction action) { // this whole thing can be optimized to send way smaller replacement segments later var combatView = MudLikeOperationBuilder.Start($"enc_{encounter.Id}") .StartContainer($"enc_{encounter.Id}") .AddTextLine(""); var gridEncounter = (GridEncounter)encounter; var entityAction = (GridTargetAction)action; //var dmgDone = encounter.ActionLog.Select((a) => (ICombatAction<GridEntity>)a) // .GroupBy(a => new { a.SourceEntity }) // .Select(a => new { Attacker = a.Key.SourceEntity, Damage = a.Sum(s => s.DamageDone) }) // .ToList(); //var dmgTaken = encounter.ActionLog.Select((a) => (GridSingleTargetAction)a) // .GroupBy(a => new { a.TargetEntity }) // .Select(a => new { Attacked = a.Key.TargetEntity, Damage = a.Sum(s => s.DamageDone) }) // .ToList(); foreach (var factionName in gridEncounter.Factions.Keys) { var factionEntities = gridEncounter.Factions[factionName]; foreach (var entity in factionEntities) { combatView .AddText(entity.Name, (entity.IsAlive && !encounter.Dead.Contains(entity) ? TextColor.Normal : TextColor.Red)); if (entity.IsAlive && !encounter.Dead.Contains(entity)) { combatView .AddText($" {entity.Stats.FirstOrDefault(s => s.Name == "health")?.Value}", TextColor.Green) .AddText($" {entity.Stats.FirstOrDefault(s => s.Name == "mana")?.Value}", TextColor.Blue) .AddText($" {entity.Stats.FirstOrDefault(s => s.Name == "stamina")?.Value}", TextColor.Yellow) ; } else { combatView.AddText(" Dead", TextColor.Red, TextSize.Small); } //var entityDmgDone = dmgDone.FirstOrDefault(d => d.Attacker == entity); //if (entityDmgDone != null) //{ // combatView // .AddText($" Dmg {entityDmgDone.Damage}", TextColor.Teal); // ; //} //var entityDmgTaken = dmgTaken.FirstOrDefault(d => d.Attacked == entity); //if (entityDmgTaken != null) //{ // combatView // .AddText($" Taken {entityDmgTaken.Damage}", TextColor.Teal); // ; //} combatView.AddLineBreak(); } combatView.AddTextLine("---------------------------"); } // add last X actions var actions = encounter.ActionLog.OrderByDescending(a => a.ExecutedTime).Take(10).OrderBy(a => a.ExecutedTime).ToList(); actions.ForEach((a) => a.AppendToOperation(combatView)); combatView.EndContainer($"enc_{encounter.Id}"); var view = MudLikeViewBuilder.Start() .AddOperation(combatView.Build() ).Build(); if (entityAction.TargetEntities.Contains(entityAction.SourceEntity) || entityAction.TargetEntities.Count == 0) { await Game.Network.SendViewCommandsToMapAsync(entityAction.SourceEntity.Map, view); } else { var maps = new List <IMap>() { entityAction.SourceEntity.Map }; maps.AddRange(entityAction.TargetEntities.Where(t => t.Map != entityAction.SourceEntity.Map).Select(t => t.Map).Distinct()); maps.ForEach(async m => await Game.Network.SendViewCommandsToMapAsync(m, view)); } }
private Task ProcessEditAsync(IProcessorData <CommandModel> request, IPlayer player) { request.Handled = true; Parser.Default.ParseArguments <EditMapParserOptions>(request.Data.StringFrom(2).Split(' ')) .WithParsed(async(parsed) => { var mapId = parsed.Id.HasValue ? parsed.Id.Value : player.Map.Id; var map = Game.World.Maps.FirstOrDefault(m => m.Id == mapId); var hasUpdate = false; if (parsed.Name.Any()) { var completeName = string.Join(" ", parsed.Name); if (!string.IsNullOrWhiteSpace(completeName)) { map.Name = completeName; hasUpdate = true; } } if (parsed.Description.Any()) { var complete = string.Join(" ", parsed.Description); if (!string.IsNullOrWhiteSpace(complete)) { map.Description = complete; hasUpdate = true; } } parsed.AddExits.ToList().ForEach((exit) => { try { map.AddExit(Enum.Parse <Exits>(exit, ignoreCase: true)); } catch (Exception) { Game.Log(Microsoft.Extensions.Logging.LogLevel.Information, "invalid exit.."); } hasUpdate = true; }); parsed.RemoveExits.ToList().ForEach((exit) => { map.RemoveExit(Enum.Parse <Exits>(exit, ignoreCase: true)); hasUpdate = true; }); if (hasUpdate) { await Game.Store.UpdateMapsAsync(Game, new List <IMap>() { map }); var mapView = MudLikeOperationBuilder.Start("mapdata").AddMap(map).Build(); await Game.Network.SendViewCommandsToMapAsync(map, MudLikeViewBuilder.Start().AddOperation(mapView).Build()); } }) .WithNotParsed(async(issues) => { await Game.Network.SendMessageToPlayerAsync(player, "invalid command(edit) - for help type map help"); }); return(Task.CompletedTask); }
private async Task MapEntitiesChanged(IMap map, IReadOnlyList <IEntity> entities) { var entitiesUpdate = MudLikeOperationBuilder.Start(MudContainers.EntityList.ToString()).AddEntities(entities) .Build(); await Game.Network.SendViewCommandsToMapAsync(map, MudLikeViewBuilder.Start().AddOperation(entitiesUpdate).Build()); }
public static MudLikeOperationBuilder AddEntities(this MudLikeOperationBuilder builder, IEnumerable <IEntity> entities) { return(builder.StartContainer(MudContainers.EntityList.ToString()).AddText("entities: ") .AddText(string.Join(",", entities.Select(p => p.Name)), TextColor.Red) .EndContainer(MudContainers.EntityList.ToString())); }
public static MudLikeOperationBuilder AddItems(this MudLikeOperationBuilder builder, IEnumerable <IItem> items) { return(builder.StartContainer("itemlist").AddText("ground items: ") .AddText(string.Join(",", items.Select(p => p.Name)), TextColor.Olive) .EndContainer("itemlist")); }
public static MudLikeOperationBuilder AddPlayers(this MudLikeOperationBuilder builder, IEnumerable <IPlayer> players) { return(builder.StartContainer("playerlist").AddText("players: ") .AddText(string.Join(",", players.Select(p => p.Name)), TextColor.Gray) .EndContainer("playerlist")); }
private async Task MapPlayersChanged(IMap map, IReadOnlyList <IPlayer> arg) { var playersUpdate = MudLikeOperationBuilder.Start("playerlist").AddPlayers(map.Players) .Build(); await Game.Network.SendViewCommandsToMapAsync(map, MudLikeViewBuilder.Start().AddOperation(playersUpdate).Build()); }
private async Task MapItemsChanged(IMap map, IReadOnlyList <IItem> arg) { var itemsUpdate = MudLikeOperationBuilder.Start("itemlist").AddItems(map.Items) .Build(); await Game.Network.SendViewCommandsToMapAsync(map, MudLikeViewBuilder.Start().AddOperation(itemsUpdate).Build()); }