/// <inheritdoc /> protected override async Task <ShiftBodypartResult> ShiftBodypartAsync(Bodypart bodypart, Chirality chirality) { if (_species is null) { throw new InvalidOperationException ( "The shifter must be constructed with a target species when shifting parts." ); } var getTFResult = await _transformations.GetTransformationsByPartAndSpeciesAsync(bodypart, _species); if (!getTFResult.IsSuccess) { return(ShiftBodypartResult.FromError(getTFResult)); } var transformation = getTFResult.Entity.First(); if (this.Appearance.TryGetAppearanceComponent(bodypart, chirality, out var existingComponent)) { if (existingComponent.Transformation.Species.Name.Equals(transformation.Species.Name)) { var message = await GetNoChangeMessageAsync(bodypart); return(ShiftBodypartResult.FromError ( message )); } } string shiftMessage; if (!this.Appearance.TryGetAppearanceComponent(bodypart, chirality, out var currentComponent)) { currentComponent = AppearanceComponent.CreateFrom(transformation, chirality); this.Appearance.Components.Add(currentComponent); shiftMessage = await GetAddMessageAsync(bodypart, chirality); return(ShiftBodypartResult.FromSuccess(shiftMessage, ShiftBodypartAction.Add)); } if (currentComponent.Transformation.Species.Name == "template") { // Apply default settings currentComponent.BaseColour = transformation.DefaultBaseColour.Clone(); currentComponent.Pattern = transformation.DefaultPattern; currentComponent.PatternColour = transformation.DefaultPatternColour?.Clone(); } currentComponent.Transformation = transformation; shiftMessage = await GetShiftMessageAsync(bodypart, chirality); return(ShiftBodypartResult.FromSuccess(shiftMessage, ShiftBodypartAction.Shift)); }
/// <inheritdoc /> protected override async Task <ShiftBodypartResult> ShiftBodypartAsync(Bodypart bodypart, Chirality chirality) { var character = this.Appearance.Character; var getAppearanceResult = await _transformations.GetOrCreateCurrentAppearanceAsync(character); if (!getAppearanceResult.IsSuccess) { return(ShiftBodypartResult.FromError(getAppearanceResult)); } var appearance = getAppearanceResult.Entity; if (!appearance.TryGetAppearanceComponent(bodypart, chirality, out var currentComponent)) { return(ShiftBodypartResult.FromError("The character doesn't have that bodypart.")); } if (currentComponent.BaseColour.IsSameColourAs(_colour)) { return(ShiftBodypartResult.FromError("The bodypart is already that colour.")); } currentComponent.BaseColour = _colour.Clone(); var shiftMessage = await GetShiftMessageAsync(bodypart, chirality); return(ShiftBodypartResult.FromSuccess(shiftMessage, ShiftBodypartAction.Shift)); }
/// <inheritdoc /> protected override async Task <ShiftBodypartResult> ShiftBodypartAsync(Bodypart bodypart, Chirality chirality) { if (!this.Appearance.TryGetAppearanceComponent(bodypart, chirality, out var currentComponent)) { return(ShiftBodypartResult.FromError("The character doesn't have that bodypart.")); } if (currentComponent.Pattern == _pattern) { return(ShiftBodypartResult.FromError("The character already has that pattern.")); } var shiftAction = ShiftBodypartAction.Shift; if (currentComponent.Pattern is null) { shiftAction = ShiftBodypartAction.Add; } currentComponent.Pattern = _pattern; currentComponent.PatternColour = _patternColour.Clone(); var shiftMessage = await GetShiftMessageAsync(bodypart, chirality); return(ShiftBodypartResult.FromSuccess(shiftMessage, shiftAction)); }
/// <inheritdoc /> protected override async Task <ShiftBodypartResult> RemoveBodypartAsync(Bodypart bodypart, Chirality chirality) { var character = this.Appearance.Character; var getAppearanceResult = await _transformations.GetOrCreateCurrentAppearanceAsync(character); if (!getAppearanceResult.IsSuccess) { return(ShiftBodypartResult.FromError(getAppearanceResult)); } var appearance = getAppearanceResult.Entity; if (!appearance.TryGetAppearanceComponent(bodypart, chirality, out var currentComponent)) { return(ShiftBodypartResult.FromError("The character doesn't have that bodypart.")); } if (currentComponent.Pattern is null) { return(ShiftBodypartResult.FromError("The character doesn't have a pattern on that part.")); } currentComponent.Pattern = null; currentComponent.PatternColour = null; var shiftMessage = await GetRemoveMessageAsync(bodypart, chirality); return(ShiftBodypartResult.FromSuccess(shiftMessage, ShiftBodypartAction.Remove)); }
/// <inheritdoc /> protected override async Task <ShiftBodypartResult> ShiftBodypartAsync(Bodypart bodypart, Chirality chirality) { if (!this.Appearance.TryGetAppearanceComponent(bodypart, chirality, out var currentComponent)) { return(ShiftBodypartResult.FromError("The character doesn't have that bodypart.")); } if (currentComponent.Pattern is null) { return(ShiftBodypartResult.FromError("That bodypart doesn't have a pattern.")); } // ReSharper disable once PossibleNullReferenceException // Having a pattern implies having a pattern colour if (currentComponent.PatternColour.IsSameColourAs(_colour)) { return(ShiftBodypartResult.FromError("The pattern is already that colour.")); } currentComponent.PatternColour = _colour.Clone(); var shiftMessage = await GetShiftMessageAsync(bodypart, chirality); return(ShiftBodypartResult.FromSuccess(shiftMessage, ShiftBodypartAction.Shift)); }
private Task <string> BuildMessageFromResultAsync ( ShiftBodypartResult result, Bodypart bodypart, Chirality chirality ) { switch (result.Action) { case ShiftBodypartAction.Remove: { return(GetRemoveMessageAsync(bodypart, chirality)); } case ShiftBodypartAction.Nothing: { throw new InvalidOperationException("Can't build a message for something that didn't happen."); } default: { throw new ArgumentOutOfRangeException(); } } }
/// <inheritdoc /> protected override Task <ShiftBodypartResult> RemoveBodypartAsync(Bodypart bodypart, Chirality chirality) { if (!this.Appearance.TryGetAppearanceComponent(bodypart, chirality, out var component)) { return(Task.FromResult(ShiftBodypartResult.FromError("The character doesn't have that bodypart."))); } this.Appearance.Components.Remove(component); var removeMessage = _descriptionBuilder.BuildRemoveMessage(this.Appearance, bodypart); return(Task.FromResult(ShiftBodypartResult.FromSuccess(removeMessage, ShiftBodypartAction.Remove))); }
/// <inheritdoc /> public async Task <ShiftBodypartResult> RemoveAsync(Bodypart bodypart, Chirality chirality) { if (bodypart.IsChiral() && chirality == Chirality.Center) { return(ShiftBodypartResult.FromError("Please specify left or right when removing one-sided bodyparts.")); } if (bodypart.IsComposite()) { return(await RemoveCompositeBodypartAsync(bodypart)); } return(await RemoveBodypartAsync(bodypart, chirality)); }
private Task <string> BuildMessageFromResultAsync ( ShiftBodypartResult result, Bodypart bodypart, Chirality chirality ) { return(result.Action switch { ShiftBodypartAction.Remove => GetRemoveMessageAsync(bodypart, chirality), ShiftBodypartAction.Nothing => throw new InvalidOperationException ( "Can't build a message for something that didn't happen." ), _ => throw new ArgumentOutOfRangeException(nameof(result.Action)) });
/// <summary> /// Shifts the given character's bodypart to the given species. /// </summary> /// <param name="context">The context of the command.</param> /// <param name="character">The character to shift.</param> /// <param name="bodyPart">The bodypart to shift.</param> /// <param name="speciesName">The species to shift the bodypart into.</param> /// <param name="chirality">The chirality of the bodypart.</param> /// <returns>A shifting result which may or may not have succeeded.</returns> public async Task <ShiftBodypartResult> ShiftBodypartAsync ( ICommandContext context, Character character, Bodypart bodyPart, string speciesName, Chirality chirality = Chirality.Center ) { var discordUser = await context.Guild.GetUserAsync((ulong)character.Owner.DiscordID); var canTransformResult = await CanUserTransformUserAsync(context.Guild, context.User, discordUser); if (!canTransformResult.IsSuccess) { return(ShiftBodypartResult.FromError(canTransformResult)); } var getSpeciesResult = await GetSpeciesByNameAsync(speciesName); if (!getSpeciesResult.IsSuccess) { return(ShiftBodypartResult.FromError(getSpeciesResult)); } var species = getSpeciesResult.Entity; var getCurrentAppearance = await GetOrCreateCurrentAppearanceAsync(character); if (!getCurrentAppearance.IsSuccess) { return(ShiftBodypartResult.FromError(getCurrentAppearance)); } var appearance = getCurrentAppearance.Entity; var speciesShifter = new SpeciesShifter(appearance, species, this, _descriptionBuilder); var shiftResult = await speciesShifter.ShiftAsync(bodyPart, chirality); if (shiftResult.IsSuccess) { await _database.SaveChangesAsync(); } return(shiftResult); }
/// <summary> /// Shifts the colour of the given bodypart on the given character to the given colour. /// </summary> /// <param name="context">The command context.</param> /// <param name="character">The character to shift.</param> /// <param name="bodyPart">The bodypart to shift.</param> /// <param name="colour">The colour to shift it into.</param> /// <param name="chirality">The chirality of the bodypart.</param> /// <returns>A shifting result which may or may not have succeeded.</returns> public async Task <ShiftBodypartResult> ShiftBodypartColourAsync ( ICommandContext context, Character character, Bodypart bodyPart, Colour colour, Chirality chirality = Chirality.Center ) { var discordUser = await context.Guild.GetUserAsync((ulong)character.Owner.DiscordID); var canTransformResult = await CanUserTransformUserAsync(context.Guild, context.User, discordUser); if (!canTransformResult.IsSuccess) { return(ShiftBodypartResult.FromError(canTransformResult)); } if (bodyPart.IsChiral() && chirality == Chirality.Center) { return(ShiftBodypartResult.FromError ( $"Please specify if it's the left or right {bodyPart.Humanize().ToLower()}." )); } var getCurrentAppearance = await GetOrCreateCurrentAppearanceAsync(character); if (!getCurrentAppearance.IsSuccess) { return(ShiftBodypartResult.FromError(getCurrentAppearance)); } var appearance = getCurrentAppearance.Entity; var colourShifter = new ColourShifter(appearance, colour, _descriptionBuilder); var shiftResult = await colourShifter.ShiftAsync(bodyPart, chirality); if (shiftResult.IsSuccess) { await _database.SaveChangesAsync(); } return(shiftResult); }
/// <inheritdoc /> protected override async Task <ShiftBodypartResult> ShiftBodypartAsync(Bodypart bodypart, Chirality chirality) { if (!this.Appearance.TryGetAppearanceComponent(bodypart, chirality, out var currentComponent)) { return(ShiftBodypartResult.FromError("The character doesn't have that bodypart.")); } if (currentComponent.BaseColour.IsSameColourAs(_colour)) { return(ShiftBodypartResult.FromError("The bodypart is already that colour.")); } currentComponent.BaseColour = _colour.Clone(); var shiftMessage = await GetShiftMessageAsync(bodypart, chirality); return(ShiftBodypartResult.FromSuccess(shiftMessage, ShiftBodypartAction.Shift)); }
/// <inheritdoc /> protected override async Task <ShiftBodypartResult> RemoveBodypartAsync(Bodypart bodypart, Chirality chirality) { if (!this.Appearance.TryGetAppearanceComponent(bodypart, chirality, out var currentComponent)) { return(ShiftBodypartResult.FromError("The character doesn't have that bodypart.")); } if (currentComponent.Pattern is null) { return(ShiftBodypartResult.FromError("The character doesn't have a pattern on that part.")); } currentComponent.Pattern = null; currentComponent.PatternColour = null; var shiftMessage = await GetRemoveMessageAsync(bodypart, chirality); return(ShiftBodypartResult.FromSuccess(shiftMessage, ShiftBodypartAction.Remove)); }
/// <summary> /// Shifts the pattern of the given bodypart on the given character to the given pattern with the given colour. /// </summary> /// <param name="context">The command context.</param> /// <param name="character">The character to shift.</param> /// <param name="bodyPart">The bodypart to shift.</param> /// <param name="pattern">The pattern to shift the bodypart into.</param> /// <param name="patternColour">The colour to shift it into.</param> /// <param name="chirality">The chirality of the bodypart.</param> /// <returns>A shifting result which may or may not have succeeded.</returns> public async Task <ShiftBodypartResult> ShiftBodypartPatternAsync ( ICommandContext context, Character character, Bodypart bodyPart, Pattern pattern, Colour patternColour, Chirality chirality = Chirality.Center ) { var discordUser = await context.Guild.GetUserAsync((ulong)character.Owner.DiscordID); var canTransformResult = await CanUserTransformUserAsync(context.Guild, context.User, discordUser); if (!canTransformResult.IsSuccess) { return(ShiftBodypartResult.FromError(canTransformResult)); } var getAppearanceResult = await GetOrCreateCurrentAppearanceAsync(character); if (!getAppearanceResult.IsSuccess) { return(ShiftBodypartResult.FromError(getAppearanceResult)); } var appearance = getAppearanceResult.Entity; var patternShifter = new PatternShifter(appearance, pattern, patternColour, _descriptionBuilder); var shiftResult = await patternShifter.ShiftAsync(bodyPart, chirality); if (shiftResult.IsSuccess) { await _database.SaveChangesAsync(); } return(shiftResult); }
/// <inheritdoc /> protected override async Task <ShiftBodypartResult> ShiftBodypartAsync(Bodypart bodypart, Chirality chirality) { var character = this.Appearance.Character; var getAppearanceResult = await _transformations.GetOrCreateCurrentAppearanceAsync(character); if (!getAppearanceResult.IsSuccess) { return(ShiftBodypartResult.FromError(getAppearanceResult)); } var appearance = getAppearanceResult.Entity; if (!appearance.TryGetAppearanceComponent(bodypart, chirality, out var currentComponent)) { return(ShiftBodypartResult.FromError("The character doesn't have that bodypart.")); } if (currentComponent.Pattern == _pattern) { return(ShiftBodypartResult.FromError("The character already has that pattern.")); } var shiftAction = ShiftBodypartAction.Shift; if (currentComponent.Pattern is null) { shiftAction = ShiftBodypartAction.Add; } currentComponent.Pattern = _pattern; currentComponent.PatternColour = _patternColour.Clone(); var shiftMessage = await GetShiftMessageAsync(bodypart, chirality); return(ShiftBodypartResult.FromSuccess(shiftMessage, shiftAction)); }
/// <inheritdoc /> protected override async Task <ShiftBodypartResult> RemoveBodypartAsync(Bodypart bodypart, Chirality chirality) { var character = this.Appearance.Character; var getAppearanceResult = await _transformations.GetOrCreateCurrentAppearanceAsync(character); if (!getAppearanceResult.IsSuccess) { return(ShiftBodypartResult.FromError(getAppearanceResult)); } var appearance = getAppearanceResult.Entity; if (!appearance.TryGetAppearanceComponent(bodypart, chirality, out var component)) { return(ShiftBodypartResult.FromError("The character doesn't have that bodypart.")); } appearance.Components.Remove(component); var removeMessage = _descriptionBuilder.BuildRemoveMessage(appearance, bodypart); return(ShiftBodypartResult.FromSuccess(removeMessage, ShiftBodypartAction.Remove)); }
/// <summary> /// Decomposes and removes the given composite bodypart. /// </summary> /// <param name="bodypart">The bodypart.</param> /// <returns>A shifting result which may or may not have succeeded.</returns> private async Task <ShiftBodypartResult> RemoveCompositeBodypartAsync(Bodypart bodypart) { var composingParts = bodypart.GetComposingParts(); var currentParagraphLength = 0; var messageBuilder = new StringBuilder(); void InsertRemovalMessage(string message) { messageBuilder !.Append(message); if (!message.EndsWith(" ")) { messageBuilder.Append(" "); } if (currentParagraphLength > 240) { messageBuilder.AppendLine(); messageBuilder.AppendLine(); currentParagraphLength = 0; } currentParagraphLength += message.Length; } foreach (var composingPart in composingParts) { if (composingPart.IsComposite()) { var shiftResult = await RemoveCompositeBodypartAsync(composingPart); if (!shiftResult.IsSuccess || shiftResult.Action == ShiftBodypartAction.Nothing) { continue; } InsertRemovalMessage(shiftResult.ShiftMessage !); continue; } if (composingPart.IsChiral()) { var leftShift = await RemoveBodypartAsync(composingPart, Chirality.Left); var rightShift = await RemoveBodypartAsync(composingPart, Chirality.Right); // There's a couple of cases here for us to deal with. // 1: both parts were removed // 2: one part was removed // 3: no changes were made if (leftShift.Action == ShiftBodypartAction.Nothing && rightShift.Action == ShiftBodypartAction.Nothing) { // No change, keep moving continue; } if (leftShift.Action == ShiftBodypartAction.Remove && rightShift.Action == ShiftBodypartAction.Remove) { var uniformShiftMessage = await GetUniformRemoveMessageAsync(composingPart); InsertRemovalMessage(uniformShiftMessage); continue; } if (leftShift.Action != ShiftBodypartAction.Nothing) { InsertRemovalMessage ( await BuildMessageFromResultAsync(leftShift, composingPart, Chirality.Left) ); } if (rightShift.Action != ShiftBodypartAction.Nothing) { InsertRemovalMessage ( await BuildMessageFromResultAsync(rightShift, composingPart, Chirality.Right) ); } } else { var simpleShiftResult = await RemoveBodypartAsync ( composingPart, Chirality.Center ); if (simpleShiftResult.Action != ShiftBodypartAction.Nothing) { InsertRemovalMessage ( await BuildMessageFromResultAsync(simpleShiftResult, composingPart, Chirality.Center) ); } } } if (messageBuilder.Length == 0) { return(ShiftBodypartResult.FromSuccess ( await GetNoChangeMessageAsync(bodypart), ShiftBodypartAction.Nothing )); } return(ShiftBodypartResult.FromSuccess(messageBuilder.ToString(), ShiftBodypartAction.Shift)); }