diff --git a/RueI/Main.cs b/RueI/Main.cs index 0b0e086..e673dfc 100644 --- a/RueI/Main.cs +++ b/RueI/Main.cs @@ -1,6 +1,5 @@ namespace RueI; -using System.Reflection; using System.Runtime.CompilerServices; /*********\ diff --git a/RueI/RueI/Displays/AutoGiving/AutoGivers.cs b/RueI/RueI/Displays/AutoGiving/AutoGivers.cs index 31334e5..82ba14f 100644 --- a/RueI/RueI/Displays/AutoGiving/AutoGivers.cs +++ b/RueI/RueI/Displays/AutoGiving/AutoGivers.cs @@ -3,6 +3,7 @@ using PlayerRoles; using RueI.Displays; +using RueI.Displays.Scheduling; using RueI.Elements; /// @@ -27,12 +28,16 @@ public record ElemRefResolver(IElemReference elemRef, Func creator) /// public class AutoElement { + private record PeriodicUpdate(TimeSpan time, int priority, JobToken token); + private static readonly List AutoGivers = new(); private readonly Element? element; private readonly Func? creator; - private readonly IElemReference? reference; + private readonly IElemReference reference; + + private PeriodicUpdate? periodicUpdate; static AutoElement() { @@ -58,10 +63,12 @@ private AutoElement(Roles roles, IElemReference reference, Func class. /// /// The to use for the . + /// The to use. /// The element to automatically give. - private AutoElement(Roles roles, Element element) + private AutoElement(Roles roles, IElemReference reference, Element element) { this.element = element; + this.reference = reference; Roles = roles; AutoGivers.Add(this); @@ -82,7 +89,7 @@ private AutoElement(Roles roles, Element element) public static AutoElement Create(Roles roles, T element) where T : Element { - return new AutoElement(roles, element); + return new AutoElement(roles, DisplayCore.GetReference(), element); } /// @@ -90,13 +97,12 @@ public static AutoElement Create(Roles roles, T element) /// /// The type of the . /// The to use for the . - /// The to use. /// A that creates the elements. /// A new . - public static AutoElement Create(Roles roles, IElemReference reference, Func creator) + public static AutoElement Create(Roles roles, Func creator) where T : Element { - return new AutoElement(roles, reference, (core) => creator(core)); + return new AutoElement(roles, DisplayCore.GetReference(), (core) => creator(core)); } /// @@ -107,22 +113,37 @@ public virtual void Disable() AutoGivers.Remove(this); } + /// + /// Schedules an update for all players with one of the every . + /// + /// How often to schedule an update. + /// The priority of the update. + /// A reference to this . + public AutoElement UpdateEvery(TimeSpan span, int priority = 35) + { + periodicUpdate = new(span, priority, new()); + return this; + } + /// /// Gives this to a . /// /// The to give to. protected virtual void GiveTo(DisplayCore core) { + ServerConsole.AddLog("Hello"); if (element != null) { - if (!core.AnonymousDisplay.Elements.Contains(element)) - { - core.AnonymousDisplay.Elements.Add(element); - } + core.AddAsReference(reference, element); } else { - core.AddAsReference(reference!, creator!(core)); + core.AddAsReference(reference, creator!(core)); + } + + if (periodicUpdate != null) + { + ScheduleUpdate(core, periodicUpdate); } } @@ -132,13 +153,11 @@ protected virtual void GiveTo(DisplayCore core) /// The to give to. protected virtual void RemoveFrom(DisplayCore core) { - if (element != null) - { - core.AnonymousDisplay.Elements.Remove(element); - } - else + core.RemoveReference(reference); + + if (periodicUpdate != null) { - core.RemoveReference(reference!); + core.Scheduler.KillJob(periodicUpdate.token); } } @@ -156,9 +175,16 @@ private static void OnRoleChanged(ReferenceHub hub, PlayerRoleBase prevRole, Pla } else { - + autoElement.RemoveFrom(core); } } + + core.Update(35); } } + + private static void ScheduleUpdate(DisplayCore core, PeriodicUpdate update) + { + core.Scheduler.Schedule(update.time, () => ScheduleUpdate(core, update), update.token); + } } \ No newline at end of file diff --git a/RueI/RueI/Displays/AutoGiving/Roles.cs b/RueI/RueI/Displays/AutoGiving/Roles.cs index 03b0926..a09d0c2 100644 --- a/RueI/RueI/Displays/AutoGiving/Roles.cs +++ b/RueI/RueI/Displays/AutoGiving/Roles.cs @@ -5,6 +5,11 @@ /// /// Provides a means for describing multiple s. /// +/// +/// The purpose of the enum is to enable roles to be treated like a enum. Normally, +/// cannot be treated like bit flags, so this acts as a fast and convenient way to do so. +/// +/// [Flags] public enum Roles { diff --git a/RueI/RueI/Displays/Display.cs b/RueI/RueI/Displays/Display.cs index 51e34c2..2ebf58a 100644 --- a/RueI/RueI/Displays/Display.cs +++ b/RueI/RueI/Displays/Display.cs @@ -5,9 +5,9 @@ using RueI.Displays.Interfaces; /// -/// Represents a display attached to a . +/// Represents a basic display attached to a . /// -/// +/// public class Display : DisplayBase, IElementContainer { /// diff --git a/RueI/RueI/Displays/DisplayCore.cs b/RueI/RueI/Displays/DisplayCore.cs index 1bc8b49..73dd8c0 100644 --- a/RueI/RueI/Displays/DisplayCore.cs +++ b/RueI/RueI/Displays/DisplayCore.cs @@ -5,7 +5,7 @@ using RueI.Extensions; /// -/// Is responsible for managing all of the s for a . +/// Manages all of the s for a . /// public class DisplayCore { @@ -33,7 +33,6 @@ protected DisplayCore(ReferenceHub hub) } Scheduler = new(this); - AnonymousDisplay = new(this); } /// @@ -46,11 +45,6 @@ protected DisplayCore(ReferenceHub hub) /// internal static Dictionary DisplayCores { get; } = new(); - /// - /// Gets a display of anonymous s added to this display. - /// - internal Display AnonymousDisplay { get; } - /// /// Gets the that this display is for. /// @@ -96,6 +90,7 @@ public static IElemReference GetReference() /// The priority of the update - defaults to 100. public void Update(int priority = 100) { + ServerConsole.AddLog("updating"); if (IgnoreUpdate) { return; @@ -174,6 +169,7 @@ public void RemoveReference(IElemReference reference) internal void InternalUpdate() { string text = ElemCombiner.Combine(GetAllElements()); + ServerConsole.AddLog(text); UnityAlternative.Provider.ShowHint(Hub, text); Events.Events.OnDisplayUpdated(new(this)); } diff --git a/RueI/RueI/Displays/ElemCombiner.cs b/RueI/RueI/Displays/ElemCombiner.cs index 1f3faea..7b2bbf6 100644 --- a/RueI/RueI/Displays/ElemCombiner.cs +++ b/RueI/RueI/Displays/ElemCombiner.cs @@ -20,6 +20,7 @@ public static class ElemCombiner /// A with all of the combined s. public static string Combine(IEnumerable enumElems) { + ServerConsole.AddLog("hello world!!!"); List elements = ListPool.Shared.Rent(enumElems); if (!elements.Any()) @@ -32,18 +33,19 @@ public static string Combine(IEnumerable enumElems) float lastPosition = 0; float lastOffset = 0; - + ServerConsole.AddLog("im kind of a big deal"); elements.Sort(CompareElement); for (int i = 0; i < elements.Count; i++) { Element curElement = elements[i]; - + ServerConsole.AddLog(curElement.ZIndex.ToString()); ParsedData parsedData = curElement.GetParsedData(); + ServerConsole.AddLog(curElement.ZIndex.ToString()); float funcPos = curElement.GetFunctionalPosition(); if (curElement.Options.HasFlagFast(Elements.Enums.ElementOptions.PreserveSpacing)) { - funcPos -= parsedData.offset; + funcPos -= parsedData.Offset; } if (i != 0) @@ -57,16 +59,18 @@ public static string Combine(IEnumerable enumElems) totalOffset += funcPos; } - sb.Append(parsedData.content); + sb.Append(parsedData.Content); - totalOffset += parsedData.offset; + totalOffset += parsedData.Offset; lastPosition = funcPos; - lastOffset = parsedData.offset; + lastOffset = parsedData.Offset; + ServerConsole.AddLog("What the fuck"); } ListPool.Shared.Return(elements); sb.Insert(0, $"\n"); sb.Append(Constants.ZeroWidthSpace); + ServerConsole.AddLog(sb.ToString()); return StringBuilderPool.Shared.ToStringReturn(sb); } diff --git a/RueI/RueI/Displays/IDGenerator.cs b/RueI/RueI/Displays/IDGenerator.cs index e6e0ea5..9ccc9d3 100644 --- a/RueI/RueI/Displays/IDGenerator.cs +++ b/RueI/RueI/Displays/IDGenerator.cs @@ -3,13 +3,16 @@ /// /// Generates new, unique IDs. /// +/// +/// This class is not thread safe. +/// internal static class IDGenerator { private static int nextID = 0; /// - /// Gets a new ID. + /// Gets a new and unique ID. /// - /// A new ID. + /// A new, unique ID. internal static int GetID() => nextID++; } \ No newline at end of file diff --git a/RueI/RueI/Displays/Scheduling/JobToken.cs b/RueI/RueI/Displays/Scheduling/JobToken.cs index e6079b9..03d6a47 100644 --- a/RueI/RueI/Displays/Scheduling/JobToken.cs +++ b/RueI/RueI/Displays/Scheduling/JobToken.cs @@ -3,6 +3,10 @@ /// /// Represents a reference to any number of . /// +/// +/// A provides a unique identifier for a within any number of s. In other words, a can reference multiple (or no) , but only a single with the given can exist in a . +/// +/// public class JobToken { /// diff --git a/RueI/RueI/Displays/Scheduling/RateLimiter.cs b/RueI/RueI/Displays/Scheduling/RateLimiter.cs index 8023bda..4b05613 100644 --- a/RueI/RueI/Displays/Scheduling/RateLimiter.cs +++ b/RueI/RueI/Displays/Scheduling/RateLimiter.cs @@ -1,10 +1,9 @@ -using System.Diagnostics; - -namespace RueI.Displays.Scheduling; +namespace RueI.Displays.Scheduling; /// /// Provides a way to ratelimit actions or detect ratelimits. /// +/// public class RateLimiter { private DateTimeOffset lastConsumed = DateTime.UtcNow; diff --git a/RueI/RueI/Displays/Scheduling/Records/ScheduledJob.cs b/RueI/RueI/Displays/Scheduling/Records/ScheduledJob.cs index 09093e3..c8b3948 100644 --- a/RueI/RueI/Displays/Scheduling/Records/ScheduledJob.cs +++ b/RueI/RueI/Displays/Scheduling/Records/ScheduledJob.cs @@ -5,6 +5,8 @@ /// /// Defines a scheduled job for a . /// +/// +/// public class ScheduledJob : IComparable { /// diff --git a/RueI/RueI/Displays/Scheduling/Scheduler.cs b/RueI/RueI/Displays/Scheduling/Scheduler.cs index d6ae45e..09374f5 100644 --- a/RueI/RueI/Displays/Scheduling/Scheduler.cs +++ b/RueI/RueI/Displays/Scheduling/Scheduler.cs @@ -1,6 +1,5 @@ namespace RueI.Displays.Scheduling; -using NorthwoodLib.Pools; using Utils.NonAllocLINQ; using eMEC; @@ -10,9 +9,11 @@ /// /// Provides a means of doing batch operations. /// +/// +/// The is a powerful class that enables "batch operations". This means that multiple updates to a display can happen at once, helping to avoid the hint ratelimit. +/// public class Scheduler { - private static readonly TimeSpan MinimumBatch = TimeSpan.FromMilliseconds(625); private readonly Cooldown rateLimiter = new(); @@ -69,8 +70,11 @@ public static DateTimeOffset CalculateWeighted(IEnumerable jobs) /// The job to schedule. public void Schedule(ScheduledJob job) { - jobs.Add(job); - UpdateBatches(); + if (job.Token == null || !jobs.Any(x => x.Token == job.Token)) + { + jobs.Add(job); + UpdateBatches(); + } } /// @@ -157,7 +161,7 @@ private void UpdateBatches() jobs.Sort(); currentBatches.Clear(); - List currentBatch = ListPool.Shared.Rent(10); + List currentBatch = new(); DateTimeOffset currentBatchTime = jobs.First().FinishAt + MinimumBatch; foreach (ScheduledJob job in jobs) @@ -170,9 +174,10 @@ private void UpdateBatches() { BatchJob finishedBatch = new(currentBatch, CalculateWeighted(currentBatch)); currentBatches.Add(finishedBatch); - currentBatch = ListPool.Shared.Rent(10); - - currentBatch.Add(job); + currentBatch = new() + { + job, + }; } } @@ -184,7 +189,7 @@ private void UpdateBatches() } TimeSpan performAt = (currentBatches.First().PerformAt - Now).MaxIf(rateLimiter.Active, rateLimiter.TimeLeft); - + ServerConsole.AddLog("Starting"); performTask.Start(performAt, PerformFirstBatch); } @@ -202,7 +207,6 @@ private void PerformFirstBatch() } coordinator.IgnoreUpdate = false; - ListPool.Shared.Return(batchJob.Jobs); currentBatches.RemoveAt(0); rateLimiter.Start(Constants.HintRateLimit); diff --git a/RueI/RueI/Displays/Scheduling/TimeElemRef.cs b/RueI/RueI/Displays/Scheduling/TimedElemRef.cs similarity index 70% rename from RueI/RueI/Displays/Scheduling/TimeElemRef.cs rename to RueI/RueI/Displays/Scheduling/TimedElemRef.cs index 46986c5..93a948b 100644 --- a/RueI/RueI/Displays/Scheduling/TimeElemRef.cs +++ b/RueI/RueI/Displays/Scheduling/TimedElemRef.cs @@ -6,6 +6,7 @@ /// Represents a with an associated . /// /// The type of the element. +/// A is an that also provides a , allowing for both of these to be easily stored together. public class TimedElemRef : IElemReference where T : Element { diff --git a/RueI/RueI/EffectApplier.cs b/RueI/RueI/EffectApplier.cs deleted file mode 100644 index 2d22100..0000000 --- a/RueI/RueI/EffectApplier.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace RueI.Displays; - -/// -/// Provides a means of doing batch operations. -/// -public class EffectApplier -{ -} diff --git a/RueI/RueI/Elements/DynamicElement.cs b/RueI/RueI/Elements/DynamicElement.cs index 6d0da2f..5c3d1ec 100644 --- a/RueI/RueI/Elements/DynamicElement.cs +++ b/RueI/RueI/Elements/DynamicElement.cs @@ -29,5 +29,5 @@ public DynamicElement(GetContent contentGetter, float position) public GetContent ContentGetter { get; set; } /// - protected internal override ParsedData GetParsedData() => Parser.Parse(ContentGetter()); + protected internal override ParsedData GetParsedData() => Parser.Parse(ContentGetter(), Options); } \ No newline at end of file diff --git a/RueI/RueI/Elements/Element.cs b/RueI/RueI/Elements/Element.cs index 76f1610..c15c554 100644 --- a/RueI/RueI/Elements/Element.cs +++ b/RueI/RueI/Elements/Element.cs @@ -5,7 +5,7 @@ namespace RueI.Elements; using RueI.Parsing.Records; /// -/// Represents the base interface for all elements. +/// Represents the base class for all elements, which are individual 'hints' present within an arbitrary number of s. /// public abstract class Element { @@ -42,7 +42,7 @@ public Element(float position) /// /// Gets or sets the options for this element. /// - public ElementOptions Options { get; set; } = ElementOptions.Default; + public virtual ElementOptions Options { get; set; } = ElementOptions.Default; /// /// Gets the data used for parsing. diff --git a/RueI/RueI/Elements/Enums/ElementOptions.cs b/RueI/RueI/Elements/Enums/ElementOptions.cs index baea0a9..2aea36a 100644 --- a/RueI/RueI/Elements/Enums/ElementOptions.cs +++ b/RueI/RueI/Elements/Enums/ElementOptions.cs @@ -7,9 +7,9 @@ public enum ElementOptions { /// - /// Indicates whether or not noparse ignores escape sequences like \r, \u, and \n. + /// Indicates whether or not noparse parses escape sequences like \r, \u, and \n. /// - NoparseIgnoresEscape = 1 << 0, + NoparseParsesEscape = 1 << 0, /// /// Indicates whether or not the vertical spacing of an element affects the baseline. @@ -24,10 +24,10 @@ public enum ElementOptions /// /// Gets the default element settings. /// - Default = NoparseIgnoresEscape, + Default = 0, /// /// Gets the vanilla options for hints. /// - Vanilla = PreserveSpacing, + Vanilla = PreserveSpacing | UseFunctionalPosition | NoparseParsesEscape, } \ No newline at end of file diff --git a/RueI/RueI/Elements/Interfaces/ISettable.cs b/RueI/RueI/Elements/Interfaces/ISettable.cs index 805a10f..fdba420 100644 --- a/RueI/RueI/Elements/Interfaces/ISettable.cs +++ b/RueI/RueI/Elements/Interfaces/ISettable.cs @@ -1,13 +1,12 @@ namespace RueI.Elements.Interfaces; /// -/// Defines an element that can be set. +/// Defines an that can be set. /// public interface ISettable { /// - /// Sets the content of this element. + /// Gets or sets the content of this element. /// - /// The new element. - public void Set(string text); + public string Content { get; set; } } diff --git a/RueI/RueI/Elements/SetElement.cs b/RueI/RueI/Elements/SetElement.cs index 6ee6d4e..ff1d6c5 100644 --- a/RueI/RueI/Elements/SetElement.cs +++ b/RueI/RueI/Elements/SetElement.cs @@ -1,5 +1,6 @@ namespace RueI.Elements; +using RueI.Elements.Enums; using RueI.Elements.Interfaces; using RueI.Parsing; using RueI.Parsing.Records; @@ -9,8 +10,6 @@ namespace RueI.Elements; /// public class SetElement : Element, ISettable { - private ParsedData data; - /// /// Initializes a new instance of the class. /// @@ -20,18 +19,14 @@ public SetElement(float position, string content = "") : base(position) { Position = position; - data = Parser.Parse(content); + Content = content; } /// - /// Sets the content of this element. + /// Gets or sets the content of this element. /// - /// The text to set the content to (will be parsed). - public virtual void Set(string content) - { - data = Parser.Parse(content); - } + public virtual string Content { get; set; } /// - protected internal override ParsedData GetParsedData() => data; + protected internal override ParsedData GetParsedData() => Parser.Parse(Content, Options); } \ No newline at end of file diff --git a/RueI/RueI/Extensions/DisplayCoreExtensions.cs b/RueI/RueI/Extensions/DisplayCoreExtensions.cs index 458a2ad..82c6ffe 100644 --- a/RueI/RueI/Extensions/DisplayCoreExtensions.cs +++ b/RueI/RueI/Extensions/DisplayCoreExtensions.cs @@ -22,7 +22,7 @@ public static void SetElementOrNew(this DisplayCore core, IElemReference public static class HintBuilding { + /// + /// Represents all of the options for the alignment of a string of text. + /// + public enum AlignStyle + { + /// + /// Indicates that the text should be left-aligned. + /// + Left, + + /// + /// Indicates that the text should be center-aligned. + /// + Center, + + /// + /// Indicates that the text should be right-aligned. + /// + Right, + + /// + /// Indicates that every line should be stretched to fill the display area, excluding the last line. + /// + Justified, + + /// + /// Indicates that every line should be stretched to fill the display area. This includes the last line. + /// + Flush, + } + /// /// Converts a to a hex code string. /// @@ -33,6 +64,26 @@ public static string ConvertToHex(Color color) /// A reference to the original . public static StringBuilder AddLinebreak(this StringBuilder sb) => sb.Append('\n'); + /// + /// Adds an alignment tag to a . + /// + /// The to use. + /// The to use. + /// A reference to the original . + public static StringBuilder SetAlignment(this StringBuilder sb, AlignStyle align) + { + string alignment = align switch + { + AlignStyle.Left => "left", + AlignStyle.Right => "right", + AlignStyle.Justified => "justified", + AlignStyle.Flush => "flush", + _ => "center", + }; + + return sb.Append($""); + } + /// /// Adds a size tag to a . /// @@ -416,6 +467,13 @@ public static StringBuilder AddVOffset(this StringBuilder sb, float offset, Meas /// A reference to the original . public static StringBuilder CloseColor(this StringBuilder sb) => sb.Append(""); + /// + /// Adds a closing align tag to a . + /// + /// The to use. + /// A reference to the original . + public static StringBuilder CloseAlign(this StringBuilder sb) => sb.Append(""); + /// /// Adds a closing alpha tag to a . /// diff --git a/RueI/RueI/Parsing/Parser.cs b/RueI/RueI/Parsing/Parser.cs index b7149bb..f179040 100644 --- a/RueI/RueI/Parsing/Parser.cs +++ b/RueI/RueI/Parsing/Parser.cs @@ -5,16 +5,23 @@ using System.Text; using NorthwoodLib.Pools; - +using RueI.Elements.Enums; +using RueI.Extensions; using RueI.Parsing.Enums; using RueI.Parsing.Records; using RueI.Parsing.Tags.ConcreteTags; /// -/// Helps parse the content of elements. +/// Helps parse the content of elements. This class cannot be inherited. /// +/// +/// The is a sealed, immutable class that provides APIs for parsing (extracting the information of) hints so that +/// multiple can be displayed at once, along with the ability to add new s. In order to create new s, +/// you must use the class. +/// /// -public class Parser +/// +public sealed class Parser { /// /// Initializes a new instance of the class. @@ -51,7 +58,8 @@ internal Parser(IEnumerable tags, IEnumerable backups) /// /// The context of the parser. /// The character to add. - public static void AddCharacter(ParserContext context, char ch) + /// Whether or not the character should be appended to the 's . + public static void AddCharacter(ParserContext context, char ch, bool append = true) { float size = CalculateCharacterLength(context, ch); @@ -83,6 +91,11 @@ public static void AddCharacter(ParserContext context, char ch) context.BiggestCharSize = context.Size; } } + + if (append) + { + context.ResultBuilder.Append(ch); + } } /// @@ -210,9 +223,11 @@ public static bool GetTagAttributes(string content, out Dictionary /// The string to parse. + /// The options of the element. /// A containing information about the string. - public ParsedData Parse(string text) + public ParsedData Parse(string text, ElementOptions options = ElementOptions.Default) { + ServerConsole.AddLog("what"); ParserState currentState = ParserState.CollectingTags; StringBuilder tagBuffer = StringBuilderPool.Shared.Rent(Constants.MAXTAGNAMESIZE); @@ -235,17 +250,17 @@ void FailTagMatch() // not a tag, unload buffer AddCharacter(context, ch); } - foreach (char ch in paramBuffer.ToString()) - { - AddCharacter(context, ch); - } - if (delimiter != null) { AddCharacter(context, delimiter.Value); delimiter = null; } + foreach (char ch in paramBuffer.ToString()) + { + AddCharacter(context, ch); + } + tagBuffer.Clear(); paramBuffer.Clear(); @@ -257,6 +272,7 @@ void FailTagMatch() // not a tag, unload buffer char[] chars = text.ToCharArray(); for (int i = 0; i < chars.Length; i++) { + ServerConsole.AddLog(chars[i].ToString()); char ch = chars[i]; if (ch == '\\') @@ -274,27 +290,34 @@ void FailTagMatch() // not a tag, unload buffer // detect if an escape sequence is escaped by backslashes if ((i - original) % 3 == 0) { - switch (chars[i]) + if (context.ShouldParse || options.HasFlagFast(ElementOptions.NoparseParsesEscape)) { - case 'n': - CreateLineBreak(context); - i++; - break; - case 'r': - context.CurrentLineWidth = 0; - i++; - break; - case 'u': - context.ResultBuilder.Append('\\'); // TODO: add support for unicode literals - break; - default: - break; + switch (chars[i]) + { + case 'n': + CreateLineBreak(context); + i++; + break; + case 'r': + context.CurrentLineWidth = 0; + i++; + break; + case 'u': + context.ResultBuilder.Append('\\'); // TODO: add support for unicode literals + break; + default: + break; + } + } + else + { + context.ResultBuilder.Append('\\'); } } for (int newIndex = 0; newIndex < times; newIndex++) { - AddCharacter(context, chars[i + newIndex]); + AddCharacter(context, chars[i + newIndex], false); } } else if (ch == '<') // indicates start of tag @@ -337,6 +360,13 @@ void FailTagMatch() // not a tag, unload buffer if (context.ShouldParse || tag is CloseNoparseTag) { tag!.HandleTag(context, string.Empty); + + tagBuffer.Clear(); + paramBuffer.Clear(); + + currentTag = null; + currentState = ParserState.CollectingTags; + tagBufferSize = 0; continue; } else @@ -396,6 +426,8 @@ void FailTagMatch() // not a tag, unload buffer delimiter = null; currentState = ParserState.CollectingTags; tagBufferSize = 0; + + continue; } else { @@ -434,7 +466,7 @@ void FailTagMatch() // not a tag, unload buffer /// Avoids the client TMP matching a tag. /// /// The context of the parser. - private static void AvoidMatch(ParserContext context) => context.ResultBuilder.Append(""); + private static void AvoidMatch(ParserContext context) => context.ResultBuilder.Append(context.IsBold ? "" : ""); /// /// Tries to get a for the given name and . diff --git a/RueI/RueI/Parsing/ParserContext.cs b/RueI/RueI/Parsing/ParserContext.cs index 8da4b1b..440af21 100644 --- a/RueI/RueI/Parsing/ParserContext.cs +++ b/RueI/RueI/Parsing/ParserContext.cs @@ -39,7 +39,7 @@ public class ParserContext : TextInfo, IDisposable /// /// Gets the current functional width of the text. /// - public float FunctionalWidth => DisplayAreaWidth - this.LeftMargin - this.RightMargin; + public float FunctionalWidth => DisplayAreaWidth - LeftMargin - RightMargin; /// /// Gets a stack containing all of the nested sizes. @@ -141,6 +141,7 @@ public void AddEndingTag(bool allowDuplicates = false) public void RemoveEndingTag() where T : NoParamsTag, new() { + ServerConsole.AddLog("doing the thing lol"); endingTags.Remove(SharedTag.Singleton); } diff --git a/RueI/RueI/Parsing/Records/ParsedData.cs b/RueI/RueI/Parsing/Records/ParsedData.cs index cba6a83..900df6a 100644 --- a/RueI/RueI/Parsing/Records/ParsedData.cs +++ b/RueI/RueI/Parsing/Records/ParsedData.cs @@ -1,8 +1,39 @@ namespace RueI.Parsing.Records; /// -/// Defines a record that contains information used for displaying multiple elements. +/// Defines a class that contains parsed information about a single element, used for displaying multiple at a time. /// -/// The element's content. -/// The offset that should be applied. Equivalent to the total linebreaks within the element. -public record ParsedData(string content, float offset); +public class ParsedData +{ + /// + /// Initializes a new instance of the class. + /// + /// The element's content. + /// The offset that should be applied. Equivalent to the total linebreaks within the element. + internal ParsedData(string content, float offset) + { + Content = content; + Offset = offset; + } + + /// + /// Gets the content of the element. + /// + public string Content { get; } + + /// + /// Gets the offset that should be applied to the element. + /// + public float Offset { get; } + + /// + /// Deconstructs this . + /// + /// The returned new content of the element. + /// The returned offset of the element. + public void Deconstruct(out string content, out float offset) + { + content = Content; + offset = Offset; + } +} diff --git a/RueI/RueI/Parsing/Tags/ClosingTag{T}.cs b/RueI/RueI/Parsing/Tags/ClosingTag{T}.cs index 5ce3723..6e104cd 100644 --- a/RueI/RueI/Parsing/Tags/ClosingTag{T}.cs +++ b/RueI/RueI/Parsing/Tags/ClosingTag{T}.cs @@ -19,7 +19,6 @@ public abstract class ClosingTag : NoParamsTag public sealed override bool HandleTag(ParserContext context) { ApplyTo(context); - context.ResultBuilder.Append($"<{Name}>"); context.RemoveEndingTag(); return true; diff --git a/RueI/RueI/Parsing/Tags/ConcreteTags/AlignTag.cs b/RueI/RueI/Parsing/Tags/ConcreteTags/AlignTag.cs index a438910..c99ed45 100644 --- a/RueI/RueI/Parsing/Tags/ConcreteTags/AlignTag.cs +++ b/RueI/RueI/Parsing/Tags/ConcreteTags/AlignTag.cs @@ -9,7 +9,7 @@ public class AlignTag : RichTextTag { /// - public override string[] Names { get; } = { "scale" }; + public override string[] Names { get; } = { "align" }; /// public override TagStyle TagStyle { get; } = TagStyle.ValueParam; diff --git a/RueI/RueI/Parsing/Tags/NoParamsTag.cs b/RueI/RueI/Parsing/Tags/NoParamsTag.cs index 68f5eb0..46a6633 100644 --- a/RueI/RueI/Parsing/Tags/NoParamsTag.cs +++ b/RueI/RueI/Parsing/Tags/NoParamsTag.cs @@ -11,7 +11,7 @@ public abstract class NoParamsTag : RichTextTag public sealed override TagStyle TagStyle { get; } = TagStyle.NoParams; /// - public sealed override bool HandleTag(ParserContext context, string parameters) => HandleTag(context, string.Empty); + public sealed override bool HandleTag(ParserContext context, string parameters) => HandleTag(context); /// /// Applies this tag (without parameters) to a . diff --git a/RueI/RueI/Utility.cs b/RueI/RueI/Utility.cs index ab5f7f4..372b281 100644 --- a/RueI/RueI/Utility.cs +++ b/RueI/RueI/Utility.cs @@ -12,7 +12,7 @@ public static class Ruetility /// The cleaned string. public static string GetCleanText(string text) { - string cleanText = text.Replace("", ""); // zero width space is inserted + string cleanText = text.Replace("", "rse>"); return $"{cleanText}"; } diff --git a/RueI/UnityAlternative.cs b/RueI/UnityAlternative.cs index 6453cb0..50a6d3c 100644 --- a/RueI/UnityAlternative.cs +++ b/RueI/UnityAlternative.cs @@ -158,7 +158,21 @@ public class UnityProvider : UnityAlternative public override IAsyncOperation PerformAsync(TimeSpan span, Action action) => new MECAsyncOperation(span, action); /// - internal override void ShowHint(ReferenceHub hub, string message) => hub.connectionToClient.Send(new HintMessage(new TextHint(message, new HintParameter[] { new StringHintParameter(message) }, new HintEffect[] { HintEffectPresets.FadeIn(0, 0, 1) }, 99999))); + internal override void ShowHint(ReferenceHub hub, string message) + { + ServerConsole.AddLog("Showing"); + + string docPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); + + // Append text to an existing file named "WriteLines.txt". + using (StreamWriter outputFile = new(Path.Combine(docPath, "hello.txt"), true)) + { + outputFile.WriteLine(message); + } + + hub.connectionToClient.Send(new HintMessage(new TextHint(message, new HintParameter[] { new StringHintParameter(message) }, null, 99999))); + Log(message); + } // HintEffectPresets.FadeIn(0, 0, 1) /// /// Represents an async operation using a . diff --git a/RueI/docs.xml b/RueI/docs.xml index 4e0b326..cee5eff 100644 --- a/RueI/docs.xml +++ b/RueI/docs.xml @@ -13,22 +13,41 @@ - - - - This example demonstrates creating and using a . - - Display display = new(referenceHub); // Create a new display from a - - SetElement helloElem = new(300, zIndex: 10, "hello").AddTo(display); - SetElement worldElem = new(250, zIndex: 10, "world").AddTo(display); - display.Elements.Add(helloElem, worldElem); + + + + + This example shows how can be used to perform bitfield operations with s. + + // the | (pipe) is the bitwise OR operator + // it combines the bits of all of the provided fields + // 1010 | 1100 -> 1110 + Roles roles = Roles.CivilianRoles | Roles.FacilityGuard | Roles.ScpsNo0492; // all things that can spawn in at the start of the game - display.Update(); // Update the display - - - - + // using RueI.Extensions.HasFlagFast because it is much quicker + roles.HasFlagFast(Roles.ChaosRifleman); // -> false + roles.HasFlagFast(Roles.Scientist); // -> true + + + + + + + + This example demonstrates creating and using a . + + Display display = new(referenceHub); // Create a new display from a ReferenceHub + + SetElement helloElem = new(300, zIndex: 10, "hello").AddTo(display); + SetElement worldElem = new(250, zIndex: 10, "world").AddTo(display); + display.Elements.Add(helloElem, worldElem); + + display.Update(); // Update the display + + + + +