-
-
Notifications
You must be signed in to change notification settings - Fork 406
Expand file tree
/
Copy pathConsoleCommandSender.cs
More file actions
107 lines (92 loc) · 3.97 KB
/
ConsoleCommandSender.cs
File metadata and controls
107 lines (92 loc) · 3.97 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
// Copyright (c) 2019 Pryaxis & TShock Contributors
//
// This file is part of TShock.
//
// TShock is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// TShock is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with TShock. If not, see <https://www.gnu.org/licenses/>.
using System;
using System.Globalization;
using System.Text;
using Destructurama;
using JetBrains.Annotations;
using Microsoft.Xna.Framework;
using Orion.Players;
using Serilog;
using Serilog.Events;
using Serilog.Sinks.SystemConsole.Themes;
namespace TShock.Commands {
/// <summary>
/// Represents a console-based command sender.
/// </summary>
public sealed class ConsoleCommandSender : ICommandSender {
#if DEBUG
private const LogEventLevel LogLevel = LogEventLevel.Verbose;
#else
private const LogEventLevel LogLevel = LogEventLevel.Error;
#endif
/// <summary>
/// Gets the console-based command sender.
/// </summary>
/// <value>The console-based command sender.</value>
public static ConsoleCommandSender Instance { get; } = new ConsoleCommandSender();
/// <inheritdoc/>
public string Name => "Console";
/// <inheritdoc/>
public ILogger Log { get; }
/// <inheritdoc/>
public IPlayer? Player => null;
[Pure]
private static string GetColorString(Color color) => $"\x1b[38;2;{color.R};{color.G};{color.B}m";
private ConsoleCommandSender() {
Log = new LoggerConfiguration()
.Destructure.UsingAttributes()
.WriteTo.Console(
outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:l}{NewLine}{Exception}",
theme: AnsiConsoleTheme.Code)
.MinimumLevel.Is(LogLevel)
.CreateLogger();
}
/// <inheritdoc/>
public void SendMessage(string message) => SendMessageImpl(message, string.Empty);
/// <inheritdoc/>
public void SendMessage(string message, Color color) => SendMessageImpl(message, GetColorString(color));
private static void SendMessageImpl(ReadOnlySpan<char> message, string colorString) {
var output = new StringBuilder(message.Length);
while (true) {
output.Append(colorString);
var leftBracket = message.IndexOf('[');
var rightBracket = leftBracket + 1 + message[(leftBracket + 1)..].IndexOf(']');
if (leftBracket < 0 || rightBracket < 0) {
break;
}
output.Append(message[..leftBracket]);
var inside = message[(leftBracket + 1)..rightBracket];
message = message[(rightBracket + 1)..];
var colon = inside.IndexOf(':');
var isValidColorTag = inside.StartsWith("c/", StringComparison.OrdinalIgnoreCase) && colon > 2;
if (!isValidColorTag) {
output.Append('[').Append(inside).Append(']');
continue;
}
if (int.TryParse(inside[2..colon], NumberStyles.AllowHexSpecifier,
CultureInfo.InvariantCulture, out var numberColor)) {
var tagColor = new Color((numberColor >> 16) & 255, (numberColor >> 8) & 255, numberColor & 255);
output.Append(GetColorString(tagColor));
}
output.Append(inside[(colon + 1)..]);
}
output.Append(message).Append("\x1b[0m");
Console.WriteLine(output);
}
}
}