Skip to content

Commit

Permalink
Introducing support for showing images through primitive objects & hi…
Browse files Browse the repository at this point in the history
…nts.
  • Loading branch information
marchellc committed Feb 5, 2025
1 parent 864a2c9 commit e015990
Show file tree
Hide file tree
Showing 36 changed files with 1,144 additions and 777 deletions.
10 changes: 8 additions & 2 deletions LabExtended/API/CustomCommands/Hints/HintsCommand.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
using CommandSystem;

using LabExtended.API.CustomCommands.Hints.Image;
using LabExtended.API.CustomCommands.Hints.Refresh;
using LabExtended.API.CustomCommands.Hints.Image;
using LabExtended.API.CustomCommands.Hints.Loop;
using LabExtended.API.CustomCommands.Hints.Pause;
using LabExtended.API.CustomCommands.Hints.Show;
using LabExtended.API.CustomCommands.Hints.Stop;

using LabExtended.Commands;

Expand All @@ -19,8 +22,11 @@ public override void LoadGeneratedCommands()
{
base.LoadGeneratedCommands();

RegisterCommand(new ShowCommand());
RegisterCommand(new ImageCommand());
RegisterCommand(new LoopCommand());
RegisterCommand(new PauseCommand());
RegisterCommand(new RefreshCommand());
RegisterCommand(new ShowCommand());
RegisterCommand(new StopCommand());
}
}
50 changes: 11 additions & 39 deletions LabExtended/API/CustomCommands/Hints/Image/ImageCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
using LabApi.Loader.Features.Paths;

using LabExtended.API.Hints;
using LabExtended.API.Hints.Elements;
using LabExtended.API.Hints.Elements.Personal;

using LabExtended.Commands;
using LabExtended.Commands.Arguments;
Expand All @@ -30,12 +30,12 @@ public override ArgumentDefinition[] BuildArgs()
x.WithArg<PlayerListData>("Players", "The players to show the image.");

x.WithArg<string>("Link", "Link to the image.");


x.WithArg<int>("Size", "Size of pixels (33 default).");
x.WithArg<int>("Line Height", "Height of each line (75 default).");
x.WithArg<int>("Height", "The height of the image.");
x.WithArg<int>("Width", "The width of the image.");
x.WithArg<int>("Fps", "Frames per second");

x.WithOptional<int>("Duration", "The duration of the image.", -1);
});
}

Expand All @@ -45,42 +45,31 @@ public override void OnCommand(ExPlayer sender, ICommandContext ctx, ArgumentCol

var players = args.Get<PlayerListData>("Players");
var link = args.Get<string>("Link");
var size = args.Get<int>("Size");
var lineHeight = args.Get<int>("Line Height");
var height = args.Get<int>("Height");
var width = args.Get<int>("Width");
var fps = args.Get<int>("Fps");
var duration = args.Get<int>("Duration");

ctx.RespondOk($"Downloading image from {link}...");

Task.Run(async () =>
{
ApiLog.Debug("ImageCommand", $"Downloading image from {link}...");

try
{
var client = new WebClient();

ApiLog.Debug("ImageCommand", $"Sending GET");

var path = Path.GetTempFileName();

await client.DownloadFileTaskAsync(link, path);

ApiLog.Debug("ImageCommand", "Successfully downloaded image.");

var image = System.Drawing.Image.FromFile(path);

ApiLog.Debug("ImageCommand", $"Image: {image.Height}x{image.Width} ({image.HorizontalResolution}h x {image.VerticalResolution}v) Raw={image.RawFormat} Pixel={image.PixelFormat} Dimensions={image.FrameDimensionsList.Length}");

var frames = image.ExtractFrames(width, height);

ApiLog.Debug("ImageCommand", $"Extracted {frames.Length} frame(s)");
return ImageUtils.ToHintFrames(frames);

return ImageUtils.ToHintFrames(frames, size <= 0 ? 33 : size, lineHeight <= 0 ? 75 : height);
}
catch (Exception ex)
{
ApiLog.Error("ImageCommand", ex);

throw ex;
}
}).ContinueWithOnMain(task =>
Expand All @@ -95,35 +84,18 @@ public override void OnCommand(ExPlayer sender, ICommandContext ctx, ArgumentCol
{
ctx.Message($"Extracted {task.Result.Length} frame(s)");

var directory = Path.Combine(PathManager.LabApi.FullName, "Downloaded Images");

if (!Directory.Exists(directory))
Directory.CreateDirectory(directory);

var index = 0;

foreach (var frame in task.Result)
File.WriteAllText(Path.Combine(directory, $"Frame {index++}.txt"), frame);

foreach (var player in players)
{
if (!player)
continue;

if (!HintController.TryGet<PersonalImageElement>(player, out var personalImageElement))
if (!player.TryGetHintElement<PersonalImageElement>(out var personalImageElement))
{
ApiLog.Debug("ImageCommand", $"Player {player.Name} has no image element");
continue;
player.AddHintElement(new PersonalImageElement());
personalImageElement = player.GetHintElement<PersonalImageElement>();
}

ApiLog.Debug("ImageCommand", personalImageElement);

if (duration != -1)
personalImageElement.CustomFrameDelay = duration;

personalImageElement.Play(task.Result, fps);

ApiLog.Debug("ImageCommand", personalImageElement);
}

ctx.Message($"Image shown to {players.Count} player(s).");
Expand Down
32 changes: 32 additions & 0 deletions LabExtended/API/CustomCommands/Hints/Loop/LoopCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using LabExtended.API.Hints;
using LabExtended.API.Hints.Elements.Personal;

using LabExtended.Commands;
using LabExtended.Commands.Arguments;
using LabExtended.Commands.Interfaces;

namespace LabExtended.API.CustomCommands.Hints.Loop;

public class LoopCommand : CustomCommand
{
public override string Command { get; } = "loop";
public override string Description { get; } = "Toggles looping.";

public override void OnCommand(ExPlayer sender, ICommandContext ctx, ArgumentCollection args)
{
base.OnCommand(sender, ctx, args);

if (!sender.TryGetHintElement<PersonalImageElement>(out var personalImageElement))
{
ctx.RespondFail($"No personal image element found.");
return;
}

personalImageElement.IsLooping = !personalImageElement.IsLooping;

if (personalImageElement.IsLooping)
ctx.RespondOk($"Enabled looping.");
else
ctx.RespondOk($"Disabled looping.");
}
}
32 changes: 32 additions & 0 deletions LabExtended/API/CustomCommands/Hints/Pause/PauseCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using LabExtended.API.Hints;
using LabExtended.API.Hints.Elements.Personal;

using LabExtended.Commands;
using LabExtended.Commands.Arguments;
using LabExtended.Commands.Interfaces;

namespace LabExtended.API.CustomCommands.Hints.Pause;

public class PauseCommand : CustomCommand
{
public override string Command { get; } = "pause";
public override string Description { get; } = "Toggles image pause.";

public override void OnCommand(ExPlayer sender, ICommandContext ctx, ArgumentCollection args)
{
base.OnCommand(sender, ctx, args);

if (!sender.TryGetHintElement<PersonalImageElement>(out var personalImageElement))
{
ctx.RespondFail($"No personal image element found.");
return;
}

personalImageElement.IsPaused = !personalImageElement.IsPaused;

if (personalImageElement.IsPaused)
ctx.RespondOk($"Paused image.");
else
ctx.RespondOk($"Unpaused image.");
}
}
29 changes: 29 additions & 0 deletions LabExtended/API/CustomCommands/Hints/Stop/StopCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using LabExtended.API.Hints;
using LabExtended.API.Hints.Elements.Personal;

using LabExtended.Commands;
using LabExtended.Commands.Arguments;
using LabExtended.Commands.Interfaces;

namespace LabExtended.API.CustomCommands.Hints.Stop;

public class StopCommand : CustomCommand
{
public override string Command { get; } = "stop";
public override string Description { get; } = "Stops image playback.";

public override void OnCommand(ExPlayer sender, ICommandContext ctx, ArgumentCollection args)
{
base.OnCommand(sender, ctx, args);

if (!sender.TryGetHintElement<PersonalImageElement>(out var personalImageElement))
{
ctx.RespondFail($"No personal image element found.");
return;
}

personalImageElement.Reset();

ctx.RespondOk($"Playback stopped.");
}
}
34 changes: 34 additions & 0 deletions LabExtended/API/CustomCommands/Image/Destroy/DestroyCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using LabExtended.Commands;
using LabExtended.Commands.Arguments;
using LabExtended.Commands.Interfaces;

namespace LabExtended.API.CustomCommands.Image.Destroy;

public class DestroyCommand : CustomCommand
{
public override string Command { get; } = "destroy";
public override string Description { get; } = "Destroys an active primitive image.";

public override ArgumentDefinition[] BuildArgs()
{
return GetArg<int>("ID", "ID of the image.");
}

public override void OnCommand(ExPlayer sender, ICommandContext ctx, ArgumentCollection args)
{
base.OnCommand(sender, ctx, args);

var id = args.Get<int>("ID");

if (!ImageCommand.SpawnedImages.TryGetValue(id, out var image))
{
ctx.RespondFail($"No image with ID {id}");
return;
}

image.Dispose();
ImageCommand.SpawnedImages.Remove(id);

ctx.RespondOk($"Image with ID {id} has been destroyed.");
}
}
61 changes: 61 additions & 0 deletions LabExtended/API/CustomCommands/Image/ImageCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
using CommandSystem;

using LabExtended.API.CustomCommands.Image.Destroy;
using LabExtended.API.CustomCommands.Image.Loop;
using LabExtended.API.CustomCommands.Image.Pause;
using LabExtended.API.CustomCommands.Image.Play;
using LabExtended.API.CustomCommands.Image.Spawn;
using LabExtended.API.CustomCommands.Image.Stop;

using LabExtended.API.Toys.Primitives;

using LabExtended.Attributes;
using LabExtended.Commands;
using LabExtended.Events;

using Utils.NonAllocLINQ;

namespace LabExtended.API.CustomCommands.Image;

[CommandHandler(typeof(RemoteAdminCommandHandler))]
[CommandHandler(typeof(GameConsoleCommandHandler))]
public class ImageCommand : VanillaParentCommandBase
{
#region Static Methods
private static int idClock = 0;

public static int NewId => idClock++;

public static Dictionary<int, PrimitiveDynamicImage> SpawnedImages { get; } =
new Dictionary<int, PrimitiveDynamicImage>();

private static void OnRoundRestart()
{
SpawnedImages.ForEachValue(x => x.Dispose());
SpawnedImages.Clear();

idClock = 0;
}

[LoaderInitialize(1)]
private static void OnInit()
=> RoundEvents.OnRoundRestarted += OnRoundRestart;
#endregion

public override string Command { get; } = "image";
public override string Description { get; } = "Commands for spawning images via primitive objects.";

public override void LoadGeneratedCommands()
{
base.LoadGeneratedCommands();

RegisterCommand(new DestroyCommand());
RegisterCommand(new LoopCommand());
RegisterCommand(new PauseCommand());
RegisterCommand(new PlayCommand());
RegisterCommand(new SpawnCommand());
RegisterCommand(new StopCommand());

RegisterCommand(new Parent.ParentCommand());
}
}
36 changes: 36 additions & 0 deletions LabExtended/API/CustomCommands/Image/Loop/LoopCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using LabExtended.Commands;
using LabExtended.Commands.Arguments;
using LabExtended.Commands.Interfaces;

namespace LabExtended.API.CustomCommands.Image.Loop;

public class LoopCommand : CustomCommand
{
public override string Command { get; } = "loop";
public override string Description { get; } = "Toggles image looping.";

public override ArgumentDefinition[] BuildArgs()
{
return GetArg<int>("ID", "ID of the image to loop");
}

public override void OnCommand(ExPlayer sender, ICommandContext ctx, ArgumentCollection args)
{
base.OnCommand(sender, ctx, args);

var id = args.Get<int>("ID");

if (!ImageCommand.SpawnedImages.TryGetValue(id, out var image))
{
ctx.RespondFail($"No image with ID {id}");
return;
}

image.IsLooping = !image.IsLooping;

if (image.IsLooping)
ctx.RespondOk($"Looping enabled.");
else
ctx.RespondOk($"Looping disabled.");
}
}
Loading

0 comments on commit e015990

Please sign in to comment.