/// <summary> /// Creates a local 'ServerString' instance for given text and /// style settings. /// </summary> /// <param name="Text"></param> /// <param name="IsBold"></param> /// <param name="IsCursive"></param> /// <param name="IsUnderline"></param> /// <param name="Color"></param> /// <returns></returns> public static ServerString GetServerStringForString( string Text, bool IsBold = false, bool IsCursive = false, bool IsUnderline = false, ChatColor Color = ChatColor.Red) { ChatStyle style = new ChatStyle( 0, Text.Length, IsBold, IsCursive, IsUnderline, Color); ServerString message = new ServerString(); message.FullString = Text; message.Styles.Add(style); return(message); }
/// <summary> /// Creates a local ChatMessage instance for given text and /// style settings. /// </summary> /// <param name="Text"></param> /// <param name="IsBold"></param> /// <param name="IsCursive"></param> /// <param name="IsUnderline"></param> /// <param name="Color"></param> /// <returns></returns> public static ChatMessage GetChatMessageForString( string Text, bool IsBold = false, bool IsCursive = false, bool IsUnderline = false, ChatColor Color = ChatColor.Red) { ChatStyle style = new ChatStyle( 0, Text.Length, IsBold, IsCursive, IsUnderline, Color); ChatMessage message = new ChatMessage(); message.FullString = Text; message.Styles.Add(style); return message; }
/// <summary> /// Builds the 'FullString' property based on /// the available parameters in 'Variables', /// the root resource id and the user-language dependent strings. /// </summary> /// <param name="RaiseChangedEvent"></param> public void BuildString(bool RaiseChangedEvent = false) { int index, varindex; int position = 0; int removed = 0; InlineVariable var; string strval; int intval; uint uintval; List <int> q_indices = new List <int>(); List <string> q_strings = new List <string>(); if (stringResources == null) { return; } // In this iteration we will use the parsed 'Variables' to actually build // the string in the user-lanuage, honoring the $ordering. // resolve root resource string in user-language if (!stringResources.TryGetValue(resourceID, out resourceName) || resourceName == null) { resourceName = String.Empty; } // will store fully constructed string fullString = String.Copy(resourceName); // specifies the index of next variable to use varindex = 0; // build string index = HasVariable(fullString); while (index > -1) { while (index > -1) { // which type of inline var switch (fullString[index + 1]) { // %% in string is literal %, remove one. case VARIABLEFLAG: fullString = fullString.Remove(index, 1); // adjust stringliteral indices right to this index for (int i = 0; i < q_indices.Count; i++) { if (q_indices[i] > index) { q_indices[i] = q_indices[i] - 1; } } break; // %i or %d are 4 byte integers. Their value should be inserted as a string. case INTEGERFLAG: case INTEGERFLAG2: #if !VANILLA if (ExtractPosition(fullString, index + 2, out fullString, out position, out removed) && position >= 0) { var = Variables[position]; } else { var = Variables[varindex]; } #else var = Variables[varindex]; #endif intval = (int)var.Data; // todo check type varindex++; string intstr = (position != -1) ? intval.ToString() : String.Empty; // remove the %i, %d and insert the integer directly fullString = fullString.Remove(index, 2); fullString = fullString.Insert(index, intstr); // adjust stringliteral indices right to this index for (int i = 0; i < q_indices.Count; i++) { if (q_indices[i] > index) { q_indices[i] = q_indices[i] + intstr.Length - 2 - removed; } } break; // %q is a server-sent string which is directly attached to the message and not looked up from rsb // if it contains any %vars itself, these MUST NOT be resolved further (won't be available in params) case EMBEDDEDSTRINGLITERALFLAG: #if !VANILLA if (ExtractPosition(fullString, index + 2, out fullString, out position, out removed) && position >= 0) { var = Variables[position]; } else { var = Variables[varindex]; } #else var = Variables[varindex]; #endif strval = (position != -1) ? (string)var.Data : String.Empty; varindex++; // remove the %q, save string and position for insert later fullString = fullString.Remove(index, 2); q_strings.Add(strval); q_indices.Add(index); // adjust stringliteral indices right to this index for (int i = 0; i < q_indices.Count; i++) { if (q_indices[i] > index) { q_indices[i] = q_indices[i] - 2 - removed; } } break; // %s is a server-sent string resource id. It must be resolved from .rsb // If it contains any %vars itself, these sub-vars must be resolved AFTER any next-vars. case STRINGRESOURCELITERALFLAG: #if !VANILLA // try to extract a $pos and possibly use it instead of the current index if (ExtractPosition(fullString, index + 2, out fullString, out position, out removed) && position >= 0) { var = Variables[position]; } else { var = Variables[varindex]; } #else var = Variables[varindex]; #endif uintval = (uint)var.Data; varindex++; // use empty string for $0 or in case not found if (position == -1 || !stringResources.TryGetValue(uintval, out strval) || strval == null) { strval = String.Empty; } // remove the %s, and insert the string, // but skip its content in this inner while() fullString = fullString.Remove(index, 2); fullString = fullString.Insert(index, strval); // adjust stringliteral indices right to this index for (int i = 0; i < q_indices.Count; i++) { if (q_indices[i] > index) { q_indices[i] = q_indices[i] + strval.Length - 2 - removed; } } // skip index += strval.Length; break; #if !VANILLA // %r is a server-sent string resource id. It must be resolved from .rsb // If it contains any %vars itself, these sub-vars must be resolved BEFORE any next-vars. case STRINGRESOURCERECURSIVEFLAG: // try to extract a $pos and possibly use it instead of the current index if (ExtractPosition(fullString, index + 2, out fullString, out position, out removed) && position >= 0) { var = Variables[position]; } else { var = Variables[varindex]; } uintval = (uint)var.Data; varindex++; // use empty string for $0 or in case not found if (position == -1 || !stringResources.TryGetValue(uintval, out strval)) { strval = String.Empty; } // remove the %r, insert the content (so we process it next) fullString = fullString.Remove(index, 2); fullString = fullString.Insert(index, strval); // adjust stringliteral indices right to this index for (int i = 0; i < q_indices.Count; i++) { if (q_indices[i] > index) { q_indices[i] = q_indices[i] + strval.Length - 2 - removed; } } break; #endif default: break; } // see if there is more inline vars to the right of current index // this makes sure we don't yet process nested and already inserted %s index = HasVariable(fullString, index); } // start from the beginning again, this will process nested %s index = HasVariable(fullString); } // Now finally add the %q stringliterals: // MUST iterate backwards (right to left in string) // so these inserts don't invalidate the other indices for (int i = q_indices.Count - 1; i >= 0; i--) { fullString = fullString.Insert(q_indices[i], q_strings[i]); } // extract and remove the inline styles (~B ...) Styles = ChatStyle.GetStyles(fullString, chatMessageType); fullString = ChatStyle.RemoveInlineStyles(fullString); // possibly raise changed event if (RaiseChangedEvent) { RaisePropertyChanged(new PropertyChangedEventArgs(PROPNAME_RESOURCENAME)); RaisePropertyChanged(new PropertyChangedEventArgs(PROPNAME_FULLSTRING)); } }
/// <summary> /// Builds the 'FullString' property based on /// the available parameters in 'Variables', /// the root resource id and the user-language dependent strings. /// </summary> protected void BuildString() { int index, varindex; InlineVariable var; string strval; int intval; uint uintval; List <int> q_indices = new List <int>(); List <string> q_strings = new List <string>(); // In this iteration we will use the parsed 'Variables' to actually build // the string in the user-lanuage, honoring the $ordering. // resolve root resource string in user-language if (!stringResources.TryGetValue(resourceID, out resourceName)) { resourceName = String.Empty; } // will store fully constructed string fullString = String.Copy(resourceName); // specifies the index of next variable to use varindex = 0; // build string index = HasVariable(fullString); while (index > -1) { while (index > -1) { // which type of inline var switch (fullString[index + 1]) { // %i or %d are 4 byte integers. Their value should be inserted as a string. case INTEGERFLAG: case INTEGERFLAG2: var = Variables[varindex]; intval = (int)var.Data; // todo check type varindex++; string intstr = intval.ToString(); // remove the %i, %d and insert the integer directly fullString = fullString.Remove(index, 2); fullString = fullString.Insert(index, intstr); // adjust stringliteral indices right to this index for (int i = 0; i < q_indices.Count; i++) { if (q_indices[i] > index) { q_indices[i] = q_indices[i] + intstr.Length - 2; } } break; // %q is a server-sent string which is directly attached to the message and not looked up from rsb // if it contains any %vars itself, these MUST NOT be resolved further (won't be available in params) case EMBEDDEDSTRINGLITERALFLAG: var = Variables[varindex]; strval = (string)var.Data; varindex++; // remove the %q, save string and position for insert later fullString = fullString.Remove(index, 2); q_strings.Add(strval); q_indices.Add(index); // adjust stringliteral indices right to this index for (int i = 0; i < q_indices.Count; i++) { if (q_indices[i] > index) { q_indices[i] = q_indices[i] - 2; } } break; // %s is a server-sent string resource id. It must be resolved from .rsb // If it contains any %vars itself, these sub-vars must be resolved AFTER any next-vars. case STRINGRESOURCELITERALFLAG: var = Variables[varindex]; uintval = (uint)var.Data; varindex++; if (!stringResources.TryGetValue(uintval, out strval)) { strval = String.Empty; } // remove the %s, and insert the string, // but skip its content in this inner while() fullString = fullString.Remove(index, 2); fullString = fullString.Insert(index, strval); // adjust stringliteral indices right to this index for (int i = 0; i < q_indices.Count; i++) { if (q_indices[i] > index) { q_indices[i] = q_indices[i] + strval.Length - 2; } } // skip index += strval.Length; break; #if !VANILLA // %r is a server-sent string resource id. It must be resolved from .rsb // If it contains any %vars itself, these sub-vars must be resolved BEFORE any next-vars. case STRINGRESOURCERECURSIVEFLAG: var = Variables[varindex]; uintval = (uint)var.Data; varindex++; if (!stringResources.TryGetValue(uintval, out strval)) { strval = String.Empty; } // remove the %r, insert the content (so we process it next) fullString = fullString.Remove(index, 2); fullString = fullString.Insert(index, strval); // adjust stringliteral indices right to this index for (int i = 0; i < q_indices.Count; i++) { if (q_indices[i] > index) { q_indices[i] = q_indices[i] + strval.Length - 2; } } break; #endif default: break; } // see if there is more inline vars to the right of current index // this makes sure we don't yet process nested and already inserted %s index = HasVariable(fullString, index); } // start from the beginning again, this will process nested %s index = HasVariable(fullString); } // Now finally add the %q stringliterals: // MUST iterate backwards (right to left in string) // so these inserts don't invalidate the other indices for (int i = q_indices.Count - 1; i >= 0; i--) { fullString = fullString.Insert(q_indices[i], q_strings[i]); } // extract and remove the inline styles (~B ...) Styles = ChatStyle.GetStyles(fullString, chatMessageType); fullString = ChatStyle.RemoveInlineStyles(fullString); }
/// <summary> /// Returns a list of TextStyles for a given Text /// </summary> /// <param name="Text"></param> /// <param name="MessageType"></param> /// <returns></returns> public static List<ChatStyle> GetStyles(string Text, ChatMessageType MessageType) { // styles we will parse List<ChatStyle> list = new List<ChatStyle>(); // the startcolor depends on messagetype ChatColor startColor; switch (MessageType) { case ChatMessageType.ServerChatMessage: #if !VANILLA startColor = ChatColor.Violet; #else startColor = ChatColor.Purple; #endif break; case ChatMessageType.SystemMessage: startColor = ChatColor.Blue; break; case ChatMessageType.ObjectChatMessage: default: startColor = ChatColor.White; break; } // first/default style ChatStyle style = new ChatStyle(0, 0, false, false, false, startColor); list.Add(style); // walk the characters up to the lastone-1 for (int i = 0; i < Text.Length - 1; i++) { // check if this is an inline style if (IsInlineStyle(Text, i)) { // get the index of this new style in a string without inline styles int index = GetIndexWithoutInlineStyle(Text, i); // if this index is bigger than our last one // we have a new style to create if (index > style.StartIndex) { // set length in last style style.Length = index - style.StartIndex; // create a new style definition // use the existing one to start from style = new ChatStyle(index, 0, style.IsBold, style.IsCursive, style.IsUnderline, style.Color); // process this stylechar style.ProcessStyleCharacter(Text[i + 1], MessageType); list.Add(style); } else { // process this inline style in existing style style.ProcessStyleCharacter(Text[i + 1], MessageType); } // skip the next character, we already processed it i++; } } // set length in last style style.Length = GetIndexWithoutInlineStyle(Text, Text.Length) - style.StartIndex; return list; }
public unsafe virtual void ReadFrom(ref byte *Buffer) { resourceID = *((uint *)Buffer); Buffer += TypeSizes.INT; string resourceName; stringResources.TryGetValue(resourceID, out resourceName); this.resourceName = resourceName; // start filling up variables (example: %s) with values // their values are attached to the packet/buffer and make it a variable length // also there might be more than one iteration necessary as varibles may be nested into variable-strings fullString = String.Copy(resourceName); int index = HasVariable(fullString); while (index > -1) { // which type of inline var switch (fullString[index + 1]) { case INTEGERFLAG: case INTEGERFLAG2: InlineVariable var1 = new InlineVariable(InlineVariableType.Integer, ref Buffer); Variables.Add(var1); int j = (int)var1.Data; // remove the %i and insert the integer fullString = fullString.Remove(index, 2); fullString = fullString.Insert(index, j.ToString()); break; case EMBEDDEDSTRINGFLAG: InlineVariable var2 = new InlineVariable(InlineVariableType.String, ref Buffer); Variables.Add(var2); string s = (string)var2.Data; // remove the %q and insert the string fullString = fullString.Remove(index, 2); fullString = fullString.Insert(index, s); break; case STRINGRESOURCEFLAG: InlineVariable var3 = new InlineVariable(InlineVariableType.Resource, ref Buffer); Variables.Add(var3); uint resourceid = (uint)var3.Data; // try to get it from strings string resourcestr; stringResources.TryGetValue(resourceid, out resourcestr); // still null? use dummy if (resourcestr == null) { resourcestr = String.Empty; } // remove the %s and insert the resourcestr fullString = fullString.Remove(index, 2); fullString = fullString.Insert(index, resourcestr); break; default: break; } // check if there is more inline vars (may start loop again) index = HasVariable(fullString); } // extract and remove the inline styles (~B ...) Styles = ChatStyle.GetStyles(fullString, chatMessageType); fullString = ChatStyle.RemoveInlineStyles(fullString); }