feat(bridge): protocol 12 — BetterChat titles and styles, popups (phase 17) #12
@@ -1372,8 +1372,10 @@ namespace Oxide.Plugins
|
||||
// The map's sets are seeded here for the same reason: a hotload hears no spawns.
|
||||
SeedMapSets();
|
||||
|
||||
// Hand BetterChat the title getter, if it is here. When it loads later, or reloads and
|
||||
// forgets us, OnPluginLoaded does this again (§33.1).
|
||||
// The titles this plugin last held, if they are this wipe's (D144), and then the getter
|
||||
// handed to BetterChat, if it is here. When it loads later, or reloads and forgets us,
|
||||
// OnPluginLoaded does this again (§33.1).
|
||||
LoadTitles();
|
||||
RegisterTitles("load");
|
||||
|
||||
// Started here rather than in Init: this hook fires both at the end of server startup
|
||||
@@ -8459,8 +8461,15 @@ namespace Oxide.Plugins
|
||||
/// <summary>
|
||||
/// The chat titles players have earned on this server, by Steam id, already in
|
||||
/// BetterChat's markup. The website composes them from the wipe's standings and pushes
|
||||
/// the whole set (<c>titles.set</c>); nothing here is persisted, because the site sends
|
||||
/// it again on every boot it has not sent to.
|
||||
/// the whole set (<c>titles.set</c>).
|
||||
///
|
||||
/// <para>
|
||||
/// <b>Kept on disk as well (D144).</b> The site re-sends on a new boot id or wipe id, and
|
||||
/// a hot reload of this plugin — an update, an <c>oxide.reload</c> — is neither: the boot
|
||||
/// id names the server process. Without the file a reload empties every title until the
|
||||
/// standings next move. A file from another wipe is not loaded, because titles rank the
|
||||
/// wipe they were earned on.
|
||||
/// </para>
|
||||
///
|
||||
/// <para>
|
||||
/// <b>Swapped, never edited.</b> BetterChat reads this through <see cref="TitleFor"/> on
|
||||
@@ -8598,6 +8607,7 @@ namespace Oxide.Plugins
|
||||
}
|
||||
|
||||
_titles = next;
|
||||
SaveTitles();
|
||||
|
||||
// A BetterChat that arrived without us hearing it load is picked up here, which also
|
||||
// makes a restart of either plugin heal on the site's next push.
|
||||
@@ -8622,6 +8632,65 @@ namespace Oxide.Plugins
|
||||
EmitFrame(reply);
|
||||
}
|
||||
|
||||
/// <summary>What <c>titles.json</c> holds: the set, and the wipe it was pushed on.</summary>
|
||||
private sealed class TitleFile
|
||||
{
|
||||
public string WipeId;
|
||||
public Dictionary<string, string> Titles = new Dictionary<string, string>();
|
||||
}
|
||||
|
||||
private string TitlesPath()
|
||||
{
|
||||
return Path.Combine(Interface.Oxide.DataDirectory, Name, "titles.json");
|
||||
}
|
||||
|
||||
/// <summary>Main thread. Written on every set the site pushes — a set arrives only when it changed.</summary>
|
||||
private void SaveTitles()
|
||||
{
|
||||
var file = new TitleFile { WipeId = _wipeId };
|
||||
|
||||
foreach (KeyValuePair<ulong, string> kv in _titles)
|
||||
file.Titles[kv.Key.ToString()] = kv.Value;
|
||||
|
||||
WriteDataFile(TitlesPath(), file, "titles");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Main thread, from <c>OnServerInitialized</c> — the first moment the wipe id is real.
|
||||
/// A file from another wipe, or with no wipe, is left unread: the site sends this wipe's.
|
||||
/// </summary>
|
||||
private void LoadTitles()
|
||||
{
|
||||
try
|
||||
{
|
||||
string path = TitlesPath();
|
||||
|
||||
if (!File.Exists(path))
|
||||
return;
|
||||
|
||||
var file = JsonConvert.DeserializeObject<TitleFile>(File.ReadAllText(path));
|
||||
|
||||
if (file == null || file.Titles == null || string.IsNullOrEmpty(_wipeId) || file.WipeId != _wipeId)
|
||||
return;
|
||||
|
||||
var loaded = new Dictionary<ulong, string>();
|
||||
|
||||
foreach (KeyValuePair<string, string> kv in file.Titles)
|
||||
{
|
||||
ulong id;
|
||||
if (ulong.TryParse(kv.Key, out id) && !string.IsNullOrEmpty(kv.Value))
|
||||
loaded[id] = kv.Value;
|
||||
}
|
||||
|
||||
_titles = loaded;
|
||||
_lastTitlesSummary = $"{loaded.Count} titles from disk, at={DateTime.UtcNow:HH:mm:ss}Z";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Puts($"could not read the titles: {Flatten(ex.Message)}");
|
||||
}
|
||||
}
|
||||
|
||||
private void EmitTitlesError(string reqId, string reason, string message)
|
||||
{
|
||||
Dictionary<string, object> frame = Frame("titles.error", "reply");
|
||||
|
||||
Reference in New Issue
Block a user