feat: Adds TextDefinition serialization support. (#1217)

This commit is contained in:
Kamron Batman 2022-10-30 01:42:48 -07:00 committed by GitHub
parent 39e6f62ec9
commit d791feb583
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
29 changed files with 301 additions and 267 deletions

View file

@ -3,7 +3,7 @@
"isRoot": true,
"tools": {
"modernuoschemagenerator": {
"version": "2.5.0",
"version": "2.5.1",
"commands": [
"ModernUOSchemaGenerator"
]

View file

@ -120,5 +120,16 @@ public interface IGenericReader
BitArray ReadBitArray();
TextDefinition ReadTextDefinition()
{
return ReadEncodedInt() switch
{
0 => new TextDefinition(),
1 => new TextDefinition(ReadEncodedInt()),
2 => new TextDefinition(ReadString()),
_ => null
};
}
long Seek(long offset, SeekOrigin origin);
}

View file

@ -164,5 +164,27 @@ public interface IGenericWriter
void Write(BitArray bitArray);
void Write(TextDefinition def)
{
if (def == null)
{
WriteEncodedInt(3);
}
else if (def.Number > 0)
{
WriteEncodedInt(1);
WriteEncodedInt(def.Number);
}
else if (def.String != null)
{
WriteEncodedInt(2);
Write(def.String);
}
else
{
WriteEncodedInt(0); // Empty
}
}
long Seek(long offset, SeekOrigin origin);
}

View file

@ -42,7 +42,7 @@
<PackageReference Include="Zlib.Bindings" Version="1.9.2" />
<PackageReference Include="ModernUO.Serialization.Annotations" Version="2.5.0" />
<PackageReference Include="ModernUO.Serialization.Generator" Version="2.5.0" />
<PackageReference Include="ModernUO.Serialization.Generator" Version="2.5.1" />
</ItemGroup>
<ItemGroup>
<AdditionalFiles Include="Migrations/*.v*.json" />

View file

@ -0,0 +1,65 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: TextDefinition.cs *
* *
* This program 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. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
*************************************************************************/
namespace Server;
[Parsable]
[PropertyObject]
public class TextDefinition
{
public TextDefinition(string text) : this(0, text)
{
}
public TextDefinition(int number = 0, string text = null)
{
Number = number;
String = text;
}
[CommandProperty(AccessLevel.GameMaster)]
public int Number { get; }
[CommandProperty(AccessLevel.GameMaster)]
public string String { get; }
public bool IsEmpty => Number <= 0 && String == null;
public override string ToString() => Number > 0 ? $"#{Number}" : String ?? "";
public string Format() =>
Number > 0 ? $"{Number} (0x{Number:X})" :
String != null ? $"\"{String}\"" : null;
public string GetValue() => Number > 0 ? Number.ToString() : String ?? "";
public static implicit operator TextDefinition(int v) => new(v);
public static implicit operator TextDefinition(string s) => new(s);
public static implicit operator int(TextDefinition m) => m?.Number ?? 0;
public static implicit operator string(TextDefinition m) => m?.String;
public static TextDefinition Parse(string value)
{
if (value == null)
{
return null;
}
return Utility.ToInt32(value, out var i) ? new TextDefinition(i) : new TextDefinition(value);
}
}

View file

@ -0,0 +1,159 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: TextDefinitionExtensions.cs *
* *
* This program 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. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
*************************************************************************/
using Server.Gumps;
using Server.Network;
namespace Server;
public static class TextDefinitionExtensions
{
public static void AddHtmlText(
this TextDefinition def,
Gump g,
int x,
int y,
int width,
int height,
bool back,
bool scroll,
int numberColor = -1,
int stringColor = -1
)
{
if (def == null)
{
return;
}
if (def.Number > 0)
{
if (numberColor >= 0) // 5 bits per RGB component (15 bit RGB)
{
g.AddHtmlLocalized(x, y, width, height, def.Number, numberColor, back, scroll);
}
else
{
g.AddHtmlLocalized(x, y, width, height, def.Number, back, scroll);
}
}
else if (def.String != null)
{
if (stringColor >= 0) // 8 bits per RGB component (24 bit RGB)
{
g.AddHtml(
x,
y,
width,
height,
$"<BASEFONT COLOR=#{stringColor:X6}>{def.String}</BASEFONT>",
back,
scroll
);
}
else
{
g.AddHtml(x, y, width, height, def.String, back, scroll);
}
}
}
public static void AddTo(this TextDefinition def, IPropertyList list)
{
if (def == null)
{
return;
}
if (def.Number > 0)
{
list.Add(def.Number);
}
else if (def.String != null)
{
list.Add(def.String);
}
}
public static void AddTo(this TextDefinition def, IPropertyList list, int number)
{
if (def == null)
{
return;
}
if (def.Number > 0)
{
list.Add(number, $"{def.Number:#}");
}
else if (def.String != null)
{
list.Add(number, $"{def.String}");
}
}
public static void SendMessageTo(this TextDefinition def, Mobile m)
{
if (def == null)
{
return;
}
if (def.Number > 0)
{
m.SendLocalizedMessage(def.Number);
}
else if (def.String != null)
{
m.SendMessage(def.String);
}
}
public static void SendMessageTo(this TextDefinition def, Mobile m, int hue)
{
if (def == null)
{
return;
}
if (def.Number > 0)
{
m.SendLocalizedMessage(def.Number, "", hue);
}
else if (def.String != null)
{
m.SendMessage(hue, def.String);
}
}
public static void PublicOverheadMessage(this TextDefinition def, Mobile m, MessageType messageType, int hue)
{
if (def == null)
{
return;
}
if (def.Number > 0)
{
m.PublicOverheadMessage(messageType, hue, def.Number);
}
else if (def.String != null)
{
m.PublicOverheadMessage(messageType, hue, false, def.String);
}
}
public static bool IsNullOrEmpty(this TextDefinition def) => def?.IsEmpty != false;
}

View file

@ -319,7 +319,7 @@ namespace Server.Commands
}
else if (IsText(type))
{
toString = ((TextDefinition)value).Format(false);
toString = ((TextDefinition)value).Format() ?? "empty";
}
else
{

View file

@ -112,13 +112,12 @@ namespace Server.Engines.Craft
if (craftItem.RequiredExpansion != Expansion.None)
{
var supportsEx = from.NetState?.SupportsExpansion(craftItem.RequiredExpansion) == true;
TextDefinition.AddHtmlText(
RequiredExpansionMessage(craftItem.RequiredExpansion).AddHtmlText(
this,
170,
302 + m_OtherCount++ * 20,
310,
18,
RequiredExpansionMessage(craftItem.RequiredExpansion),
false,
false,
supportsEx ? LabelColor : RedLabelColor,

View file

@ -134,7 +134,7 @@ namespace Server.Factions
if (IsCorrupted)
{
TextDefinition.AddTo(list, m_Corrupted.Definition.SigilControl);
m_Corrupted.Definition.SigilControl.AddTo(list);
}
else
{

View file

@ -23,7 +23,7 @@ namespace Server.Engines.Harvest
public void SendSuccessTo(Mobile m)
{
TextDefinition.SendMessageTo(m, SuccessMessage);
SuccessMessage.SendMessageTo(m);
}
}
}

View file

@ -149,7 +149,7 @@ namespace Server.Engines.MLQuests.Gumps
0x2710
);
TextDefinition.AddHtmlText(this, 98, 156, 312, 240, quest.Description, false, true, 0x15F90, 0xBDE784);
quest.Description.AddHtmlText(this, 98, 156, 312, 240, false, true, 0x15F90, 0xBDE784);
}
public void AddObjectives(MLQuest quest)
@ -250,7 +250,7 @@ namespace Server.Engines.MLQuests.Gumps
public void AddConversation(TextDefinition text)
{
TextDefinition.AddHtmlText(this, 98, 140, 312, 180, text, false, true, 0x15F90, 0xBDE784);
text.AddHtmlText(this, 98, 140, 312, 180, false, true, 0x15F90, 0xBDE784);
}
/* OSI gump IDs:

View file

@ -10,8 +10,8 @@ namespace Server.Engines.MLQuests.Gumps
SetPageCount(1);
BuildPage();
TextDefinition.AddHtmlText(this, 160, 108, 250, 16, title, false, false, 0x2710, 0x4AC684);
TextDefinition.AddHtmlText(this, 98, 156, 312, 180, message, false, true, 0x15F90, 0xBDE784);
title.AddHtmlText(this, 160, 108, 250, 16, false, false, 0x2710, 0x4AC684);
message.AddHtmlText(this, 98, 156, 312, 180, false, true, 0x15F90, 0xBDE784);
}
}
}

View file

@ -47,13 +47,12 @@ namespace Server.Engines.MLQuests.Gumps
numberColor = stringColor = 0xFFFFFF;
}
TextDefinition.AddHtmlText(
instances[i].Quest.Title.AddHtmlText(
this,
98,
140 + 21 * i,
270,
21,
instances[i].Quest.Title,
false,
false,
numberColor,

View file

@ -67,7 +67,7 @@ namespace Server.Engines.MLQuests.Items
return true;
}
TextDefinition.SendMessageTo(m, Message);
Message.SendMessageTo(m);
return false;
}
@ -88,7 +88,7 @@ namespace Server.Engines.MLQuests.Items
writer.Write(0); // version
writer.Write(m_QuestType?.FullName);
TextDefinition.Serialize(writer, Message);
writer.Write(Message);
}
public override void Deserialize(IGenericReader reader)
@ -104,7 +104,7 @@ namespace Server.Engines.MLQuests.Items
m_QuestType = AssemblyHandler.FindTypeByFullName(typeName);
}
Message = TextDefinition.Deserialize(reader);
Message = reader.ReadTextDefinition();
}
}
@ -170,7 +170,7 @@ namespace Server.Engines.MLQuests.Items
if (ticket == null)
{
TextDefinition.SendMessageTo(m, Message);
Message.SendMessageTo(m);
return false;
}
@ -196,7 +196,7 @@ namespace Server.Engines.MLQuests.Items
writer.Write(0); // version
writer.Write( m_TicketType?.FullName);
TextDefinition.Serialize(writer, Message);
writer.Write(Message);
}
public override void Deserialize(IGenericReader reader)
@ -212,7 +212,7 @@ namespace Server.Engines.MLQuests.Items
m_TicketType = AssemblyHandler.FindTypeByFullName(typeName);
}
Message = TextDefinition.Deserialize(reader);
Message = reader.ReadTextDefinition();
}
}
}

View file

@ -96,7 +96,7 @@ namespace Server.Engines.MLQuests
public BaseObjectiveInstance[] Objectives { get; set; }
public bool SkipReportBack => TextDefinition.IsNullOrEmpty(Quest.CompletionMessage);
public bool SkipReportBack => Quest.CompletionMessage.IsNullOrEmpty();
private void Register()
{
@ -166,7 +166,7 @@ namespace Server.Engines.MLQuests
obj.OnQuestCompleted();
}
TextDefinition.SendMessageTo(Player, Quest.CompletionNotice, 0x23);
Quest.CompletionNotice.SendMessageTo(Player, 0x23);
/*
* Advance to the ClaimReward=true stage if this quest has no
@ -176,8 +176,8 @@ namespace Server.Engines.MLQuests
* For quests that require collections, this is done later when
* the player double clicks the quester.
*/
if (!Removed && SkipReportBack && !Quest.RequiresCollection
) // An OnQuestCompleted can potentially have removed this instance already
// An OnQuestCompleted can potentially have removed this instance already
if (!Removed && SkipReportBack && !Quest.RequiresCollection)
{
ContinueReportBack(false);
}

View file

@ -243,7 +243,7 @@ namespace Server.Engines.MLQuests.Mobiles
}
}
TextDefinition.PublicOverheadMessage(m_Owner, MessageType.Regular, 0x3B2, m_Conversation[m_Index++]);
m_Conversation[m_Index++].PublicOverheadMessage(m_Owner, MessageType.Regular, 0x3B2);
Interval = GetDelay();
}
}
@ -257,9 +257,9 @@ namespace Server.Engines.MLQuests.Mobiles
1073998, // Blessings of Sosaria to you and merry met, friend.
1073999, // I am glad for your company and wonder if you seek the heritage of your people? I sense within you an elven bloodline -- the purity of which was lost when our brothers and sisters were exiled here in the Rupture.
1074000, // If it is your desire to reclaim your place amongst the people, you must demonstrate that you understand and embrace the responsibilities expected of you as an elf.
1074001, // The most basic lessons of our Sosaria are taught by her humblest children. Seek Maul, the great bear, who understands instictively the seasons.
1074001, // The most basic lessons of our Sosaria are taught by her humblest children. Seek Maul, the great bear, who understands instinctively the seasons.
1074398, // Seek Strongroot, the great treefellow, whose very roots reach to the heart of the world. Seek Enigma, whose wisdom can only be conveyed in riddles and rhymes. Seek Bravehorn, the great hart, who exemplifies the fierce dedication of a protector of his people.
1074399, // Seek the Huntsman, the centuar tasked with maintaining the balance. And lastly seek Arielle, the pixie, who has perhaps the most important lesson -- not to take yourself too seriously.
1074399, // Seek the Huntsman, the centaur tasked with maintaining the balance. And lastly seek Arielle, the pixie, who has perhaps the most important lesson -- not to take yourself too seriously.
1074400 // Or do none of these things. You must choose your own path in the world, and what use you'll make of your existence.
};

View file

@ -14,7 +14,7 @@ namespace Server.Engines.MLQuests.Rewards
public void WriteToGump(Gump g, int x, ref int y)
{
TextDefinition.AddHtmlText(g, x, y, 280, LabelHeight, Name, false, false, 0x15F90, 0xBDE784);
Name.AddHtmlText(g, x, y, 280, LabelHeight, false, false, 0x15F90, 0xBDE784);
}
public abstract void AddRewardItems(PlayerMobile pm, List<Item> rewards);

View file

@ -145,7 +145,7 @@ namespace Server.Engines.Spawners
if (IsEmpty && End <= Core.Now && m.InRange(GetWorldLocation(), TriggerRange) &&
m.Location != oldLocation && ValidTrigger(m))
{
TextDefinition.SendMessageTo(m, SpawnMessage);
SpawnMessage.SendMessageTo(m);
DoTimer();
Spawn();
@ -170,7 +170,7 @@ namespace Server.Engines.Spawners
writer.WriteEncodedInt(0); // version
writer.Write(TriggerRange);
TextDefinition.Serialize(writer, SpawnMessage);
writer.Write(SpawnMessage);
writer.Write(InstantFlag);
}
@ -181,7 +181,7 @@ namespace Server.Engines.Spawners
var version = reader.ReadEncodedInt();
TriggerRange = reader.ReadInt();
SpawnMessage = TextDefinition.Deserialize(reader);
SpawnMessage = reader.ReadTextDefinition();
InstantFlag = reader.ReadBool();
}
}

View file

@ -117,11 +117,7 @@ namespace Server.Items
{
base.GetProperties(list);
if (m_Label > 0)
{
TextDefinition.AddTo(list, m_Label);
}
m_Label.AddTo(list);
list.Add(1060584, m_UsesRemaining); // uses remaining: ~1_val~
}

View file

@ -70,7 +70,7 @@ namespace Server.Gumps
AddButton(10, y + 54, 0xFB1, 0xFB2, 0); // Cancel Button
AddHtmlLocalized(45, y + 56, x - 50, 20, 1060051, 0x7FFF); // CANCEL
TextDefinition.AddHtmlText(this, 14, 12, x, 20, header, false, false, 0x7FFF, 0xFFFFFF);
header.AddHtmlText(this, 14, 12, x, 20, false, false, 0x7FFF, 0xFFFFFF);
AddPage(1);
@ -112,7 +112,7 @@ namespace Server.Gumps
10
);
AddTooltip(b.LocalizedTooltip);
TextDefinition.AddHtmlText(this, innerX + 84, innerY, 250, 60, b.Label, false, false, 0x7FFF, 0xFFFFFF);
b.Label.AddHtmlText(this, innerX + 84, innerY, 250, 60, false, false, 0x7FFF, 0xFFFFFF);
}
}

View file

@ -545,7 +545,7 @@ namespace Server.Gumps
if (o is TextDefinition definition)
{
return definition.Format(true);
return definition.Format() ?? "-empty-";
}
return o.ToString();

View file

@ -78,16 +78,9 @@ public abstract partial class PromotionalToken : Item
AddPage(0);
AddBackground(0, 0, 240, 135, 0x2422);
AddHtmlLocalized(
15,
15,
210,
75,
1070972,
0x0,
true
); // Click "OKAY" to redeem the following promotional item:
TextDefinition.AddHtmlText(this, 15, 60, 210, 75, m_Token.ItemGumpName, false, false);
// Click "OKAY" to redeem the following promotional item:
AddHtmlLocalized(15, 15, 210, 75, 1070972, 0x0, true);
m_Token.ItemGumpName.AddHtmlText(this, 15, 60, 210, 75, false, false);
AddButton(160, 95, 0xF7, 0xF8, 1); // Okay
AddButton(90, 95, 0xF2, 0xF1, 0); // Cancel
@ -113,7 +106,7 @@ public abstract partial class PromotionalToken : Item
if (i != null)
{
from.BankBox.AddItem(i);
TextDefinition.SendMessageTo(from, m_Token.ItemReceiveMessage);
m_Token.ItemReceiveMessage.SendMessageTo(from);
m_Token.Delete();
}
}

View file

@ -313,7 +313,7 @@ namespace Server.Items
writer.Write(1); // version
TextDefinition.Serialize(writer, Message);
writer.Write(Message);
writer.WriteEncodedInt(GumpWidth);
writer.WriteEncodedInt(GumpHeight);
@ -334,7 +334,7 @@ namespace Server.Items
{
case 1:
{
Message = TextDefinition.Deserialize(reader);
Message = reader.ReadTextDefinition();
goto case 0;
}
case 0:

View file

@ -182,7 +182,7 @@ namespace Server.Items
}
else if (!VerifyRegion(from))
{
TextDefinition.SendMessageTo(from, RepairSkillInfo.GetInfo(m_Skill).NotNearbyMessage);
RepairSkillInfo.GetInfo(m_Skill).NotNearbyMessage.SendMessageTo(from);
}
else
{

View file

@ -39,7 +39,7 @@ namespace Server.Items
if (GetSaveFlag(flags, SaveFlag.Name))
{
Name = TextDefinition.Deserialize(reader);
Name = reader.ReadTextDefinition();
}
if (GetSaveFlag(flags, SaveFlag.Amount))
@ -94,7 +94,7 @@ namespace Server.Items
if (GetSaveFlag(flags, SaveFlag.Name))
{
TextDefinition.Serialize(writer, Name);
writer.Write(Name);
}
if (GetSaveFlag(flags, SaveFlag.Amount))

View file

@ -1,207 +0,0 @@
using Server.Gumps;
using Server.Network;
namespace Server
{
[Parsable]
public class TextDefinition
{
public TextDefinition(string text) : this(0, text)
{
}
public TextDefinition(int number = 0, string text = null)
{
Number = number;
String = text;
}
public int Number { get; }
public string String { get; }
public bool IsEmpty => Number <= 0 && String == null;
public override string ToString() => Number > 0 ? $"#{Number}" : String ?? "";
public string Format(bool propsGump) =>
Number > 0 ? $"{Number} (0x{Number:X})" :
String != null ? $"\"{String}\"" :
propsGump ? "-empty-" : "empty";
public string GetValue() => Number > 0 ? Number.ToString() : String ?? "";
public static void Serialize(IGenericWriter writer, TextDefinition def)
{
if (def == null)
{
writer.WriteEncodedInt(3);
}
else if (def.Number > 0)
{
writer.WriteEncodedInt(1);
writer.WriteEncodedInt(def.Number);
}
else if (def.String != null)
{
writer.WriteEncodedInt(2);
writer.Write(def.String);
}
else
{
writer.WriteEncodedInt(0);
}
}
public static TextDefinition Deserialize(IGenericReader reader)
{
var type = reader.ReadEncodedInt();
return type switch
{
0 => new TextDefinition(),
1 => new TextDefinition(reader.ReadEncodedInt()),
2 => new TextDefinition(reader.ReadString()),
_ => null
};
}
public static void AddTo(IPropertyList list, TextDefinition def)
{
if (def == null)
{
return;
}
if (def.Number > 0)
{
list.Add(def.Number);
}
else if (def.String != null)
{
list.Add(def.String);
}
}
public static implicit operator TextDefinition(int v) => new(v);
public static implicit operator TextDefinition(string s) => new(s);
public static implicit operator int(TextDefinition m) => m?.Number ?? 0;
public static implicit operator string(TextDefinition m) => m?.String;
public static void AddHtmlText(
Gump g, int x, int y, int width, int height, TextDefinition def, bool back,
bool scroll, int numberColor, int stringColor
)
{
if (def == null)
{
return;
}
if (def.Number > 0)
{
if (numberColor >= 0) // 5 bits per RGB component (15 bit RGB)
{
g.AddHtmlLocalized(x, y, width, height, def.Number, numberColor, back, scroll);
}
else
{
g.AddHtmlLocalized(x, y, width, height, def.Number, back, scroll);
}
}
else if (def.String != null)
{
if (stringColor >= 0) // 8 bits per RGB component (24 bit RGB)
{
g.AddHtml(
x,
y,
width,
height,
$"<BASEFONT COLOR=#{stringColor:X6}>{def.String}</BASEFONT>",
back,
scroll
);
}
else
{
g.AddHtml(x, y, width, height, def.String, back, scroll);
}
}
}
public static void AddHtmlText(
Gump g, int x, int y, int width, int height, TextDefinition def, bool back,
bool scroll
)
{
AddHtmlText(g, x, y, width, height, def, back, scroll, -1, -1);
}
public static void SendMessageTo(Mobile m, TextDefinition def)
{
if (def == null)
{
return;
}
if (def.Number > 0)
{
m.SendLocalizedMessage(def.Number);
}
else if (def.String != null)
{
m.SendMessage(def.String);
}
}
public static void SendMessageTo(Mobile m, TextDefinition def, int hue)
{
if (def == null)
{
return;
}
if (def.Number > 0)
{
m.SendLocalizedMessage(def.Number, "", hue);
}
else if (def.String != null)
{
m.SendMessage(hue, def.String);
}
}
public static void PublicOverheadMessage(Mobile m, MessageType messageType, int hue, TextDefinition def)
{
if (def == null)
{
return;
}
if (def.Number > 0)
{
m.PublicOverheadMessage(messageType, hue, def.Number);
}
else if (def.String != null)
{
m.PublicOverheadMessage(messageType, hue, false, def.String);
}
}
public static TextDefinition Parse(string value)
{
if (value == null)
{
return null;
}
return Utility.ToInt32(value, out var i) ? new TextDefinition(i) : new TextDefinition(value);
}
public static bool IsNullOrEmpty(TextDefinition def) => def?.IsEmpty != false;
}
}

View file

@ -252,7 +252,7 @@ namespace Server.Spells
m.NetState.SendToggleSpecialAbility(moveID + 1, true);
}
TextDefinition.SendMessageTo(m, move.AbilityMessage);
move.AbilityMessage.SendMessageTo(m);
}
return true;

View file

@ -33,10 +33,7 @@ namespace Server.Items
public override void HandleInvalidTransfer(Mobile from)
{
if (InvalidTransferMessage != null)
{
TextDefinition.SendMessageTo(from, InvalidTransferMessage);
}
InvalidTransferMessage.SendMessageTo(from);
Delete();
}

View file

@ -48,7 +48,7 @@
<PackageReference Include="Zstd.Binaries" Version="1.4.0" />
<PackageReference Include="ModernUO.Serialization.Annotations" Version="2.5.0" />
<PackageReference Include="ModernUO.Serialization.Generator" Version="2.5.0" />
<PackageReference Include="ModernUO.Serialization.Generator" Version="2.5.1" />
</ItemGroup>
<ItemGroup>
<AdditionalFiles Include="Migrations/*.v*.json" />