Add EventDef notices, morning and lesson bells, and info toasts.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -15,6 +15,7 @@ public enum MessageType : byte
|
||||
ClientSetRunning = 0x05,
|
||||
ClientSetSpeed = 0x06,
|
||||
ClientSkipEmpty = 0x07,
|
||||
ClientDismissNotice = 0x08,
|
||||
|
||||
ServerWelcome = 0x81,
|
||||
ServerPong = 0x82,
|
||||
@@ -22,4 +23,5 @@ public enum MessageType : byte
|
||||
ServerSchoolGone = 0x84,
|
||||
ServerMapSnapshot = 0x85,
|
||||
ServerPresence = 0x86,
|
||||
ServerNotice = 0x87,
|
||||
}
|
||||
|
||||
@@ -84,6 +84,29 @@ public sealed record ServerMapSnapshotMessage(int SchoolId, IReadOnlyList<MapSna
|
||||
/// <summary>Jump empty nights, weekends and holidays. The server re-checks the conditions.</summary>
|
||||
public readonly record struct ClientSkipEmptyMessage;
|
||||
|
||||
/// <summary>Closes one notice by id. Info is not stored; pausing dismiss is phase 65.</summary>
|
||||
public readonly record struct ClientDismissNoticeMessage(uint Id);
|
||||
|
||||
/// <summary>Wire values for <see cref="ServerNoticeMessage.Severity"/>.</summary>
|
||||
public static class NoticeSeverity
|
||||
{
|
||||
public const byte Info = 0;
|
||||
public const byte Warning = 1;
|
||||
public const byte Error = 2;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// One school event for open clients. <paramref name="PersonId"/> is 0 when nobody is in frame.
|
||||
/// Info toasts are not replayed on OpenSchool.
|
||||
/// </summary>
|
||||
public readonly record struct ServerNoticeMessage(
|
||||
uint Id,
|
||||
string DefName,
|
||||
byte Severity,
|
||||
bool Pause,
|
||||
uint TtlMs,
|
||||
uint PersonId = 0);
|
||||
|
||||
/// <summary>Where people are: 1 in a node, 2 walking through it. Off campus is omitted.</summary>
|
||||
public static class PresenceState
|
||||
{
|
||||
|
||||
@@ -70,6 +70,14 @@ public static class ProtocolCodec
|
||||
return writer.Position;
|
||||
}
|
||||
|
||||
public static int WriteDismissNotice(Span<byte> destination, in ClientDismissNoticeMessage message)
|
||||
{
|
||||
var writer = new PacketWriter(destination);
|
||||
writer.WriteMessageType(MessageType.ClientDismissNotice);
|
||||
writer.WriteUInt32(message.Id);
|
||||
return writer.Position;
|
||||
}
|
||||
|
||||
public static int WriteWelcome(Span<byte> destination, in ServerWelcomeMessage message)
|
||||
{
|
||||
var writer = new PacketWriter(destination);
|
||||
@@ -271,6 +279,22 @@ public static class ProtocolCodec
|
||||
return writer.Position;
|
||||
}
|
||||
|
||||
public static int NoticeSize(in ServerNoticeMessage message) =>
|
||||
sizeof(byte) + sizeof(uint) + StringSize(message.DefName) + sizeof(byte) + sizeof(byte) + sizeof(uint) + sizeof(uint);
|
||||
|
||||
public static int WriteNotice(Span<byte> destination, in ServerNoticeMessage message)
|
||||
{
|
||||
var writer = new PacketWriter(destination);
|
||||
writer.WriteMessageType(MessageType.ServerNotice);
|
||||
writer.WriteUInt32(message.Id);
|
||||
writer.WriteString(message.DefName);
|
||||
writer.WriteByte(message.Severity);
|
||||
writer.WriteByte(message.Pause ? (byte)1 : (byte)0);
|
||||
writer.WriteUInt32(message.TtlMs);
|
||||
writer.WriteUInt32(message.PersonId);
|
||||
return writer.Position;
|
||||
}
|
||||
|
||||
public static MessageType PeekMessageType(ReadOnlySpan<byte> source) =>
|
||||
source.IsEmpty ? MessageType.None : (MessageType)source[0];
|
||||
|
||||
@@ -441,6 +465,26 @@ public static class ProtocolCodec
|
||||
return new ServerPresenceMessage(schoolId, nodes, people);
|
||||
}
|
||||
|
||||
public static ClientDismissNoticeMessage ReadDismissNotice(ReadOnlySpan<byte> source)
|
||||
{
|
||||
var reader = new PacketReader(source);
|
||||
Expect(ref reader, MessageType.ClientDismissNotice);
|
||||
return new ClientDismissNoticeMessage(reader.ReadUInt32());
|
||||
}
|
||||
|
||||
public static ServerNoticeMessage ReadNotice(ReadOnlySpan<byte> source)
|
||||
{
|
||||
var reader = new PacketReader(source);
|
||||
Expect(ref reader, MessageType.ServerNotice);
|
||||
var id = reader.ReadUInt32();
|
||||
var defName = reader.ReadString();
|
||||
var severity = reader.ReadByte();
|
||||
var pause = reader.ReadByte() != 0;
|
||||
var ttlMs = reader.ReadUInt32();
|
||||
var personId = reader.ReadUInt32();
|
||||
return new ServerNoticeMessage(id, defName, severity, pause, ttlMs, personId);
|
||||
}
|
||||
|
||||
private static bool HasPresenceActivity(PresenceNode node) =>
|
||||
node.ActivitySubject.Length > 0 || node.ActivityClass.Length > 0;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ namespace HSchool.Protocol;
|
||||
public static class ProtocolConstants
|
||||
{
|
||||
/// <summary>Bumped on every breaking change to the binary layout.</summary>
|
||||
public const byte Version = 9;
|
||||
public const byte Version = 10;
|
||||
|
||||
/// <summary>Upper bound for a single WebSocket frame accepted by the server.</summary>
|
||||
public const int MaxMessageSize = 8 * 1024;
|
||||
|
||||
Reference in New Issue
Block a user