feat(proto): a dead-end claim, a word report, quick-match and a scored breakdown

Four client messages and two server ones, all additive. ClaimDeadEnd lets
the player to act say the syllable has no answer instead of waiting out
the clock; the server verifies. ReportWord files a refused word for the
maintainers and is acknowledged with WordReported. QuickMatch and
CancelQuickMatch join and leave a pairing queue, answered by
QuickMatchStatus. PlayedWord gains parts, the named terms that sum to
its points, and MoveRejected a suggestion for a word that differs from a
real one by diacritics alone. Generated code and cross-language fixtures
regenerated.
This commit is contained in:
tiennm99 committed 2026-09-21 01:20:22 +07:00
1 parent 8223f40b16
commit 865222d2cd
13 files changed
+1129 -160

No files matched your search

+76
View File
@@ -52,6 +52,24 @@ enum GameEndReason {
GAME_END_REASON_RESIGNED = 4;
}
// PointKind names one term of a word's score. The engine adds several and
// the client cannot re-derive any of them — it has no wordlist by design — so
// each term travels named, and a new term is a new value rather than a wire
// break.
enum PointKind {
POINT_KIND_UNSPECIFIED = 0;
// Every accepted word.
POINT_KIND_BASE = 1;
// For the length of the chain the word extends.
POINT_KIND_CHAIN = 2;
// For each syllable past the minimum.
POINT_KIND_SYLLABLES = 3;
// For the share of the turn left on the clock.
POINT_KIND_SPEED = 4;
// For how few words the dictionary has on the syllable it answered.
POINT_KIND_RARITY = 5;
}
// ---------------------------------------------------------------------------
// Client -> server
// ---------------------------------------------------------------------------
@@ -123,6 +141,30 @@ message Ping {
int64 client_time_ms = 1;
}
// ClaimDeadEnd is the player to act saying the syllable has no answer left.
// The server checks. A true claim takes them out at once with
// GAME_END_REASON_NO_LEGAL_MOVE, exactly as the clock would have, so the
// rule is unchanged and only the waiting is gone. A false one is refused with
// the error not_a_dead_end and the clock keeps running: the server has just
// confirmed a word exists, which is hint enough to be the whole cost.
message ClaimDeadEnd {}
// ReportWord is a player saying a word the dictionary refused is real. The
// server records it for the maintainers and acknowledges with WordReported;
// nothing about the current game changes. Only words of at least two
// syllables are recorded, and a session is bounded in how many it may file.
message ReportWord {
string word = 1;
}
// QuickMatch asks to be paired with the next stranger who asks the same. The
// two are seated in an ordinary room whose first game starts by itself; from
// then on it is a room like any other. CancelQuickMatch leaves the queue.
// Both are answered with QuickMatchStatus.
message QuickMatch {}
message CancelQuickMatch {}
message ClientMessage {
// 8 was RequestRematch, retired with the rematch handshake: the lobby is
// where a next game is agreed now. Reserved at message level because a
@@ -142,6 +184,10 @@ message ClientMessage {
KickPlayer kick_player = 11;
LeaveRoom leave_room = 12;
SendChat send_chat = 13;
ClaimDeadEnd claim_dead_end = 14;
ReportWord report_word = 15;
QuickMatch quick_match = 16;
CancelQuickMatch cancel_quick_match = 17;
}
}
@@ -175,6 +221,16 @@ message PlayedWord {
// no definition for the word; the client then says so rather than hiding
// the row's panel, so every word in the chain behaves the same.
repeated Sense meanings = 7;
// How points was arrived at, one entry per non-zero term, summing exactly
// to points. The client shows why a word scored what it did rather than
// only that it did.
repeated PointPart parts = 8;
}
// PointPart is one named term of a word's score.
message PointPart {
PointKind kind = 1;
uint32 value = 2;
}
// Sense is one definition of a word as Wiktionary gives it: the part of
@@ -282,6 +338,24 @@ message MoveRejected {
RejectReason reason = 1;
string word = 2;
uint32 turn_seq = 3;
// For REJECT_REASON_NOT_IN_DICTIONARY only: the one real word that differs
// from what was typed by diacritics alone, when exactly one does. It
// corrects typing, never vocabulary — a word the player did not know is
// never offered — and the move is still refused; the player retypes it.
string suggestion = 4;
}
// WordReported acknowledges a ReportWord, echoing the word as the server
// recorded it so the player sees that it was heard.
message WordReported {
string word = 1;
}
// QuickMatchStatus is where the sender stands with the queue: queued after a
// QuickMatch, not queued after a CancelQuickMatch or once a room has seated
// them — the RoomState that follows is the match itself.
message QuickMatchStatus {
bool queued = 1;
}
// GameOver is rendered per recipient: i_won is true for exactly one player,
@@ -415,5 +489,7 @@ message ServerMessage {
ChatMessage chat_message = 13;
ChatHistory chat_history = 14;
PlayerEliminated player_eliminated = 15;
WordReported word_reported = 16;
QuickMatchStatus quick_match_status = 17;
}
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
+3
View File
@@ -0,0 +1,3 @@
z
bình tâm
+2
View File
@@ -0,0 +1,2 @@
2binh yen"
bình yên
+1
View File
@@ -0,0 +1 @@
�
+3 -3
View File
@@ -1,9 +1,9 @@
*É
h
*Õ
t
bình yên * binh yên2p2:6
tính từ(Yên lành, không có gì xáo động.: Xem bình an.yên Àóù©‘3(@J
tính từ(Yên lành, không có gì xáo động.: Xem bình an.BByên Àóù©‘3(@J
p1Người chơi 0J
p2 Khách mời *(0J
p3Khách 2 Rp3
+3
View File
@@ -0,0 +1,3 @@
‚
bình tâm
+692 -139
View File
File diff suppressed because it is too large. Load diff
+24
View File
@@ -58,6 +58,12 @@ func clientVariants() map[string]*noituv1.ClientMessage {
"client_send_chat": {Payload: &noituv1.ClientMessage_SendChat{SendChat: &noituv1.SendChat{
Text: "Chào bạn, ván này khó thật!",
}}},
"client_claim_dead_end": {Payload: &noituv1.ClientMessage_ClaimDeadEnd{ClaimDeadEnd: &noituv1.ClaimDeadEnd{}}},
"client_report_word": {Payload: &noituv1.ClientMessage_ReportWord{ReportWord: &noituv1.ReportWord{
Word: "bình tâm",
}}},
"client_quick_match": {Payload: &noituv1.ClientMessage_QuickMatch{QuickMatch: &noituv1.QuickMatch{}}},
"client_cancel_quick_match": {Payload: &noituv1.ClientMessage_CancelQuickMatch{CancelQuickMatch: &noituv1.CancelQuickMatch{}}},
}
}
@@ -93,6 +99,12 @@ func serverVariants() map[string]*noituv1.ServerMessage {
{Pos: "tính từ", Gloss: "Yên lành, không có gì xáo động."},
{Pos: "", Gloss: "Xem bình an."},
},
// The parts sum to points, which the client relies on when it
// draws them beside the total.
Parts: []*noituv1.PointPart{
{Kind: noituv1.PointKind_POINT_KIND_BASE, Value: 1},
{Kind: noituv1.PointKind_POINT_KIND_SPEED, Value: 1},
},
},
CurrentSyllable: "yên",
MyTurn: true,
@@ -107,6 +119,18 @@ func serverVariants() map[string]*noituv1.ServerMessage {
Word: "cà phê",
TurnSeq: 2,
}}},
"server_move_rejected_near_miss": {Payload: &noituv1.ServerMessage_MoveRejected{MoveRejected: &noituv1.MoveRejected{
Reason: noituv1.RejectReason_REJECT_REASON_NOT_IN_DICTIONARY,
Word: "binh yen",
TurnSeq: 2,
Suggestion: "bình yên",
}}},
"server_word_reported": {Payload: &noituv1.ServerMessage_WordReported{WordReported: &noituv1.WordReported{
Word: "bình tâm",
}}},
"server_quick_match_status": {Payload: &noituv1.ServerMessage_QuickMatchStatus{QuickMatchStatus: &noituv1.QuickMatchStatus{
Queued: true,
}}},
"server_game_over": {Payload: &noituv1.ServerMessage_GameOver{GameOver: &noituv1.GameOver{
IWon: false,
Reason: noituv1.GameEndReason_GAME_END_REASON_NO_LEGAL_MOVE,
+241
View File
@@ -248,6 +248,75 @@ export declare type Ping = Message<"noitu.v1.Ping"> & {
*/
export declare const PingSchema: GenMessage<Ping>;
/**
* ClaimDeadEnd is the player to act saying the syllable has no answer left.
* The server checks. A true claim takes them out at once with
* GAME_END_REASON_NO_LEGAL_MOVE, exactly as the clock would have, so the
* rule is unchanged and only the waiting is gone. A false one is refused with
* the error not_a_dead_end and the clock keeps running: the server has just
* confirmed a word exists, which is hint enough to be the whole cost.
*
* @generated from message noitu.v1.ClaimDeadEnd
*/
export declare type ClaimDeadEnd = Message<"noitu.v1.ClaimDeadEnd"> & {
};
/**
* Describes the message noitu.v1.ClaimDeadEnd.
* Use `create(ClaimDeadEndSchema)` to create a new message.
*/
export declare const ClaimDeadEndSchema: GenMessage<ClaimDeadEnd>;
/**
* ReportWord is a player saying a word the dictionary refused is real. The
* server records it for the maintainers and acknowledges with WordReported;
* nothing about the current game changes. Only words of at least two
* syllables are recorded, and a session is bounded in how many it may file.
*
* @generated from message noitu.v1.ReportWord
*/
export declare type ReportWord = Message<"noitu.v1.ReportWord"> & {
/**
* @generated from field: string word = 1;
*/
word: string;
};
/**
* Describes the message noitu.v1.ReportWord.
* Use `create(ReportWordSchema)` to create a new message.
*/
export declare const ReportWordSchema: GenMessage<ReportWord>;
/**
* QuickMatch asks to be paired with the next stranger who asks the same. The
* two are seated in an ordinary room whose first game starts by itself; from
* then on it is a room like any other. CancelQuickMatch leaves the queue.
* Both are answered with QuickMatchStatus.
*
* @generated from message noitu.v1.QuickMatch
*/
export declare type QuickMatch = Message<"noitu.v1.QuickMatch"> & {
};
/**
* Describes the message noitu.v1.QuickMatch.
* Use `create(QuickMatchSchema)` to create a new message.
*/
export declare const QuickMatchSchema: GenMessage<QuickMatch>;
/**
* @generated from message noitu.v1.CancelQuickMatch
*/
export declare type CancelQuickMatch = Message<"noitu.v1.CancelQuickMatch"> & {
};
/**
* Describes the message noitu.v1.CancelQuickMatch.
* Use `create(CancelQuickMatchSchema)` to create a new message.
*/
export declare const CancelQuickMatchSchema: GenMessage<CancelQuickMatch>;
/**
* @generated from message noitu.v1.ClientMessage
*/
@@ -327,6 +396,30 @@ export declare type ClientMessage = Message<"noitu.v1.ClientMessage"> & {
*/
value: SendChat;
case: "sendChat";
} | {
/**
* @generated from field: noitu.v1.ClaimDeadEnd claim_dead_end = 14;
*/
value: ClaimDeadEnd;
case: "claimDeadEnd";
} | {
/**
* @generated from field: noitu.v1.ReportWord report_word = 15;
*/
value: ReportWord;
case: "reportWord";
} | {
/**
* @generated from field: noitu.v1.QuickMatch quick_match = 16;
*/
value: QuickMatch;
case: "quickMatch";
} | {
/**
* @generated from field: noitu.v1.CancelQuickMatch cancel_quick_match = 17;
*/
value: CancelQuickMatch;
case: "cancelQuickMatch";
} | { case: undefined; value?: undefined };
};
@@ -420,6 +513,15 @@ export declare type PlayedWord = Message<"noitu.v1.PlayedWord"> & {
* @generated from field: repeated noitu.v1.Sense meanings = 7;
*/
meanings: Sense[];
/**
* How points was arrived at, one entry per non-zero term, summing exactly
* to points. The client shows why a word scored what it did rather than
* only that it did.
*
* @generated from field: repeated noitu.v1.PointPart parts = 8;
*/
parts: PointPart[];
};
/**
@@ -428,6 +530,29 @@ export declare type PlayedWord = Message<"noitu.v1.PlayedWord"> & {
*/
export declare const PlayedWordSchema: GenMessage<PlayedWord>;
/**
* PointPart is one named term of a word's score.
*
* @generated from message noitu.v1.PointPart
*/
export declare type PointPart = Message<"noitu.v1.PointPart"> & {
/**
* @generated from field: noitu.v1.PointKind kind = 1;
*/
kind: PointKind;
/**
* @generated from field: uint32 value = 2;
*/
value: number;
};
/**
* Describes the message noitu.v1.PointPart.
* Use `create(PointPartSchema)` to create a new message.
*/
export declare const PointPartSchema: GenMessage<PointPart>;
/**
* Sense is one definition of a word as Wiktionary gives it: the part of
* speech it sits under, in Vietnamese ("danh từ"), empty when the heading was
@@ -732,6 +857,16 @@ export declare type MoveRejected = Message<"noitu.v1.MoveRejected"> & {
* @generated from field: uint32 turn_seq = 3;
*/
turnSeq: number;
/**
* For REJECT_REASON_NOT_IN_DICTIONARY only: the one real word that differs
* from what was typed by diacritics alone, when exactly one does. It
* corrects typing, never vocabulary — a word the player did not know is
* never offered — and the move is still refused; the player retypes it.
*
* @generated from field: string suggestion = 4;
*/
suggestion: string;
};
/**
@@ -740,6 +875,45 @@ export declare type MoveRejected = Message<"noitu.v1.MoveRejected"> & {
*/
export declare const MoveRejectedSchema: GenMessage<MoveRejected>;
/**
* WordReported acknowledges a ReportWord, echoing the word as the server
* recorded it so the player sees that it was heard.
*
* @generated from message noitu.v1.WordReported
*/
export declare type WordReported = Message<"noitu.v1.WordReported"> & {
/**
* @generated from field: string word = 1;
*/
word: string;
};
/**
* Describes the message noitu.v1.WordReported.
* Use `create(WordReportedSchema)` to create a new message.
*/
export declare const WordReportedSchema: GenMessage<WordReported>;
/**
* QuickMatchStatus is where the sender stands with the queue: queued after a
* QuickMatch, not queued after a CancelQuickMatch or once a room has seated
* them — the RoomState that follows is the match itself.
*
* @generated from message noitu.v1.QuickMatchStatus
*/
export declare type QuickMatchStatus = Message<"noitu.v1.QuickMatchStatus"> & {
/**
* @generated from field: bool queued = 1;
*/
queued: boolean;
};
/**
* Describes the message noitu.v1.QuickMatchStatus.
* Use `create(QuickMatchStatusSchema)` to create a new message.
*/
export declare const QuickMatchStatusSchema: GenMessage<QuickMatchStatus>;
/**
* GameOver is rendered per recipient: i_won is true for exactly one player,
* the one still standing when everybody else had been eliminated.
@@ -1082,6 +1256,18 @@ export declare type ServerMessage = Message<"noitu.v1.ServerMessage"> & {
*/
value: PlayerEliminated;
case: "playerEliminated";
} | {
/**
* @generated from field: noitu.v1.WordReported word_reported = 16;
*/
value: WordReported;
case: "wordReported";
} | {
/**
* @generated from field: noitu.v1.QuickMatchStatus quick_match_status = 17;
*/
value: QuickMatchStatus;
case: "quickMatchStatus";
} | { case: undefined; value?: undefined };
};
@@ -1223,3 +1409,58 @@ export enum GameEndReason {
*/
export declare const GameEndReasonSchema: GenEnum<GameEndReason>;
/**
* PointKind names one term of a word's score. The engine adds several and
* the client cannot re-derive any of them — it has no wordlist by design — so
* each term travels named, and a new term is a new value rather than a wire
* break.
*
* @generated from enum noitu.v1.PointKind
*/
export enum PointKind {
/**
* @generated from enum value: POINT_KIND_UNSPECIFIED = 0;
*/
UNSPECIFIED = 0,
/**
* Every accepted word.
*
* @generated from enum value: POINT_KIND_BASE = 1;
*/
BASE = 1,
/**
* For the length of the chain the word extends.
*
* @generated from enum value: POINT_KIND_CHAIN = 2;
*/
CHAIN = 2,
/**
* For each syllable past the minimum.
*
* @generated from enum value: POINT_KIND_SYLLABLES = 3;
*/
SYLLABLES = 3,
/**
* For the share of the turn left on the clock.
*
* @generated from enum value: POINT_KIND_SPEED = 4;
*/
SPEED = 4,
/**
* For how few words the dictionary has on the syllable it answered.
*
* @generated from enum value: POINT_KIND_RARITY = 5;
*/
RARITY = 5,
}
/**
* Describes the enum noitu.v1.PointKind.
*/
export declare const PointKindSchema: GenEnum<PointKind>;
+84 -18
View File
@@ -21,7 +21,7 @@ import { enumDesc, fileDesc, messageDesc, tsEnum } from "@bufbuild/protobuf/code
* Describes the file noitu/v1/game.proto.
*/
export const file_noitu_v1_game = /*@__PURE__*/
fileDesc("ChNub2l0dS92MS9nYW1lLnByb3RvEghub2l0dS52MSJJCgVIZWxsbxIYChBwcm90b2NvbF92ZXJzaW9uGAEgASgNEhQKDHJlc3VtZV90b2tlbhgCIAEoCRIQCghuaWNrbmFtZRgDIAEoCSI4CgxTdGFydEJvdEdhbWUSKAoKZGlmZmljdWx0eRgBIAEoDjIULm5vaXR1LnYxLkRpZmZpY3VsdHkiDAoKQ3JlYXRlUm9vbSIdCghKb2luUm9vbRIRCglyb29tX2NvZGUYASABKAkiLAoKU3VibWl0V29yZBIMCgR3b3JkGAEgASgJEhAKCHR1cm5fc2VxGAIgASgNIggKBlJlc2lnbiIZCghTZXRSZWFkeRINCgVyZWFkeRgBIAEoCCILCglTdGFydEdhbWUiHwoKS2lja1BsYXllchIRCglwbGF5ZXJfaWQYASABKAkiCwoJTGVhdmVSb29tIhgKCFNlbmRDaGF0EgwKBHRleHQYASABKAkiHgoEUGluZxIWCg5jbGllbnRfdGltZV9tcxgBIAEoAyKQBAoNQ2xpZW50TWVzc2FnZRIgCgVoZWxsbxgBIAEoCzIPLm5vaXR1LnYxLkhlbGxvSAASMAoOc3RhcnRfYm90X2dhbWUYAiABKAsyFi5ub2l0dS52MS5TdGFydEJvdEdhbWVIABIrCgtjcmVhdGVfcm9vbRgDIAEoCzIULm5vaXR1LnYxLkNyZWF0ZVJvb21IABInCglqb2luX3Jvb20YBCABKAsyEi5ub2l0dS52MS5Kb2luUm9vbUgAEisKC3N1Ym1pdF93b3JkGAUgASgLMhQubm9pdHUudjEuU3VibWl0V29yZEgAEiIKBnJlc2lnbhgGIAEoCzIQLm5vaXR1LnYxLlJlc2lnbkgAEh4KBHBpbmcYByABKAsyDi5ub2l0dS52MS5QaW5nSAASJwoJc2V0X3JlYWR5GAkgASgLMhIubm9pdHUudjEuU2V0UmVhZHlIABIpCgpzdGFydF9nYW1lGAogASgLMhMubm9pdHUudjEuU3RhcnRHYW1lSAASKwoLa2lja19wbGF5ZXIYCyABKAsyFC5ub2l0dS52MS5LaWNrUGxheWVySAASKQoKbGVhdmVfcm9vbRgMIAEoCzITLm5vaXR1LnYxLkxlYXZlUm9vbUgAEicKCXNlbmRfY2hhdBgNIAEoCzISLm5vaXR1LnYxLlNlbmRDaGF0SABCCQoHcGF5bG9hZEoECAgQCSJoCgdXZWxjb21lEhIKCnNlc3Npb25faWQYASABKAkSFAoMcmVzdW1lX3Rva2VuGAIgASgJEhgKEHByb3RvY29sX3ZlcnNpb24YAyABKA0SGQoRYWNjZXB0ZWRfbmlja25hbWUYBCABKAkikQEKClBsYXllZFdvcmQSDAoEd29yZBgBIAEoCRINCgVieV9tZRgCIAEoCBIOCgZwb2ludHMYAyABKA0SEQoJc3lsbGFibGVzGAQgASgNEg0KBXR5cGVkGAUgASgJEhEKCXBsYXllcl9pZBgGIAEoCRIhCghtZWFuaW5ncxgHIAMoCzIPLm5vaXR1LnYxLlNlbnNlIiMKBVNlbnNlEgsKA3BvcxgBIAEoCRINCgVnbG9zcxgCIAEoCSJ+CgpQbGF5ZXJTbG90EhEKCXBsYXllcl9pZBgBIAEoCRIMCgRuYW1lGAIgASgJEg0KBWlzX21lGAMgASgIEhAKCGlzX293bmVyGAQgASgIEg0KBXJlYWR5GAUgASgIEhEKCWNvbm5lY3RlZBgGIAEoCBIMCgR3aW5zGAcgASgNIoEBCgtQbGF5ZXJTY29yZRIRCglwbGF5ZXJfaWQYASABKAkSDAoEbmFtZRgCIAEoCRINCgVpc19tZRgDIAEoCBINCgVzY29yZRgEIAEoDRISCgplbGltaW5hdGVkGAUgASgIEhEKCWNvbm5lY3RlZBgGIAEoCBIMCgRyYW5rGAcgASgNIvwBCgtHYW1lU3RhcnRlZBIUCgxvcGVuaW5nX3dvcmQYASABKAkSGAoQY3VycmVudF9zeWxsYWJsZRgCIAEoCRIPCgdteV90dXJuGAMgASgIEhgKEGRlYWRsaW5lX3VuaXhfbXMYBCABKAMSEAoIdHVybl9zZXEYBSABKA0SFQoNdHVybl9saW1pdF9tcxgGIAEoDRImCgdwbGF5ZXJzGAcgAygLMhUubm9pdHUudjEuUGxheWVyU2NvcmUSFgoOdHVybl9wbGF5ZXJfaWQYCCABKAkSKQoQb3BlbmluZ19tZWFuaW5ncxgJIAMoCzIPLm5vaXR1LnYxLlNlbnNlIusBCgpUdXJuVXBkYXRlEiQKBnBsYXllZBgBIAEoCzIULm5vaXR1LnYxLlBsYXllZFdvcmQSGAoQY3VycmVudF9zeWxsYWJsZRgCIAEoCRIPCgdteV90dXJuGAMgASgIEhgKEGRlYWRsaW5lX3VuaXhfbXMYBCABKAMSEAoIdHVybl9zZXEYBSABKA0SFAoMY2hhaW5fbGVuZ3RoGAggASgNEiYKB3BsYXllcnMYCSADKAsyFS5ub2l0dS52MS5QbGF5ZXJTY29yZRIWCg50dXJuX3BsYXllcl9pZBgKIAEoCUoECAYQB0oECAcQCCJWCgxNb3ZlUmVqZWN0ZWQSJgoGcmVhc29uGAEgASgOMhYubm9pdHUudjEuUmVqZWN0UmVhc29uEgwKBHdvcmQYAiABKAkSEAoIdHVybl9zZXEYAyABKA0ijgEKCEdhbWVPdmVyEg0KBWlfd29uGAEgASgIEicKBnJlYXNvbhgCIAEoDjIXLm5vaXR1LnYxLkdhbWVFbmRSZWFzb24SFAoMY2hhaW5fbGVuZ3RoGAQgASgNEigKCXN0YW5kaW5ncxgGIAMoCzIVLm5vaXR1LnYxLlBsYXllclNjb3JlSgQIAxAESgQIBRAGIoABChBQbGF5ZXJFbGltaW5hdGVkEhEKCXBsYXllcl9pZBgBIAEoCRIMCgRuYW1lGAIgASgJEg0KBWlzX21lGAMgASgIEicKBnJlYXNvbhgEIAEoDjIXLm5vaXR1LnYxLkdhbWVFbmRSZWFzb24SEwoLc3VnZ2VzdGlvbnMYBSADKAkiLAoLU2VydmVyRXJyb3ISDAoEY29kZRgBIAEoCRIPCgdtZXNzYWdlGAIgASgJIjYKBFBvbmcSFgoOY2xpZW50X3RpbWVfbXMYASABKAMSFgoOc2VydmVyX3RpbWVfbXMYAiABKAMiuAEKCVJvb21TdGF0ZRIRCglyb29tX2NvZGUYASABKAkSEQoJY2FuX3N0YXJ0GAMgASgIEiUKB3BsYXllcnMYCSADKAsyFC5ub2l0dS52MS5QbGF5ZXJTbG90EhMKC21heF9wbGF5ZXJzGAogASgNEhMKC21pbl9wbGF5ZXJzGAsgASgNEhAKCGdyYWNlX21zGAwgASgNSgQIAhADSgQIBBAFSgQIBRAGSgQIBhAHSgQIBxAISgQICBAJImUKC0NoYXRNZXNzYWdlEg8KB2Zyb21fbWUYASABKAgSDgoGYXV0aG9yGAIgASgJEgwKBHRleHQYAyABKAkSFAoMc2VudF91bml4X21zGAQgASgDEhEKCXBsYXllcl9pZBgFIAEoCSI2CgtDaGF0SGlzdG9yeRInCghtZXNzYWdlcxgBIAMoCzIVLm5vaXR1LnYxLkNoYXRNZXNzYWdlIpgECg1TZXJ2ZXJNZXNzYWdlEiQKB3dlbGNvbWUYASABKAsyES5ub2l0dS52MS5XZWxjb21lSAASLQoMZ2FtZV9zdGFydGVkGAQgASgLMhUubm9pdHUudjEuR2FtZVN0YXJ0ZWRIABIrCgt0dXJuX3VwZGF0ZRgFIAEoCzIULm5vaXR1LnYxLlR1cm5VcGRhdGVIABIvCg1tb3ZlX3JlamVjdGVkGAYgASgLMhYubm9pdHUudjEuTW92ZVJlamVjdGVkSAASJwoJZ2FtZV9vdmVyGAcgASgLMhIubm9pdHUudjEuR2FtZU92ZXJIABImCgVlcnJvchgJIAEoCzIVLm5vaXR1LnYxLlNlcnZlckVycm9ySAASHgoEcG9uZxgKIAEoCzIOLm5vaXR1LnYxLlBvbmdIABIpCgpyb29tX3N0YXRlGAwgASgLMhMubm9pdHUudjEuUm9vbVN0YXRlSAASLQoMY2hhdF9tZXNzYWdlGA0gASgLMhUubm9pdHUudjEuQ2hhdE1lc3NhZ2VIABItCgxjaGF0X2hpc3RvcnkYDiABKAsyFS5ub2l0dS52MS5DaGF0SGlzdG9yeUgAEjcKEXBsYXllcl9lbGltaW5hdGVkGA8gASgLMhoubm9pdHUudjEuUGxheWVyRWxpbWluYXRlZEgAQgkKB3BheWxvYWRKBAgCEANKBAgDEARKBAgIEAlKBAgLEAwqaQoKRGlmZmljdWx0eRIaChZESUZGSUNVTFRZX1VOU1BFQ0lGSUVEEAASEwoPRElGRklDVUxUWV9FQVNZEAESFQoRRElGRklDVUxUWV9NRURJVU0QAhITCg9ESUZGSUNVTFRZX0hBUkQQAyqOAgoMUmVqZWN0UmVhc29uEh0KGVJFSkVDVF9SRUFTT05fVU5TUEVDSUZJRUQQABIjCh9SRUpFQ1RfUkVBU09OX1RPT19GRVdfU1lMTEFCTEVTEAESHAoYUkVKRUNUX1JFQVNPTl9XUk9OR19MSU5LEAISIwofUkVKRUNUX1JFQVNPTl9OT1RfSU5fRElDVElPTkFSWRADEh4KGlJFSkVDVF9SRUFTT05fQUxSRUFEWV9VU0VEEAQSHwobUkVKRUNUX1JFQVNPTl9OT1RfWU9VUl9UVVJOEAUSGQoVUkVKRUNUX1JFQVNPTl9USU1FT1VUEAYSGwoXUkVKRUNUX1JFQVNPTl9HQU1FX09WRVIQByqxAQoNR2FtZUVuZFJlYXNvbhIfChtHQU1Line truncated
fileDesc("ChNub2l0dS92MS9nYW1lLnByb3RvEghub2l0dS52MSJJCgVIZWxsbxIYChBwcm90b2NvbF92ZXJzaW9uGAEgASgNEhQKDHJlc3VtZV90b2tlbhgCIAEoCRIQCghuaWNrbmFtZRgDIAEoCSI4CgxTdGFydEJvdEdhbWUSKAoKZGlmZmljdWx0eRgBIAEoDjIULm5vaXR1LnYxLkRpZmZpY3VsdHkiDAoKQ3JlYXRlUm9vbSIdCghKb2luUm9vbRIRCglyb29tX2NvZGUYASABKAkiLAoKU3VibWl0V29yZBIMCgR3b3JkGAEgASgJEhAKCHR1cm5fc2VxGAIgASgNIggKBlJlc2lnbiIZCghTZXRSZWFkeRINCgVyZWFkeRgBIAEoCCILCglTdGFydEdhbWUiHwoKS2lja1BsYXllchIRCglwbGF5ZXJfaWQYASABKAkiCwoJTGVhdmVSb29tIhgKCFNlbmRDaGF0EgwKBHRleHQYASABKAkiHgoEUGluZxIWCg5jbGllbnRfdGltZV9tcxgBIAEoAyIOCgxDbGFpbURlYWRFbmQiGgoKUmVwb3J0V29yZBIMCgR3b3JkGAEgASgJIgwKClF1aWNrTWF0Y2giEgoQQ2FuY2VsUXVpY2tNYXRjaCLWBQoNQ2xpZW50TWVzc2FnZRIgCgVoZWxsbxgBIAEoCzIPLm5vaXR1LnYxLkhlbGxvSAASMAoOc3RhcnRfYm90X2dhbWUYAiABKAsyFi5ub2l0dS52MS5TdGFydEJvdEdhbWVIABIrCgtjcmVhdGVfcm9vbRgDIAEoCzIULm5vaXR1LnYxLkNyZWF0ZVJvb21IABInCglqb2luX3Jvb20YBCABKAsyEi5ub2l0dS52MS5Kb2luUm9vbUgAEisKC3N1Ym1pdF93b3JkGAUgASgLMhQubm9pdHUudjEuU3VibWl0V29yZEgAEiIKBnJlc2lnbhgGIAEoCzIQLm5vaXR1LnYxLlJlc2lnbkgAEh4KBHBpbmcYByABKAsyDi5ub2l0dS52MS5QaW5nSAASJwoJc2V0X3JlYWR5GAkgASgLMhIubm9pdHUudjEuU2V0UmVhZHlIABIpCgpzdGFydF9nYW1lGAogASgLMhMubm9pdHUudjEuU3RhcnRHYW1lSAASKwoLa2lja19wbGF5ZXIYCyABKAsyFC5ub2l0dS52MS5LaWNrUGxheWVySAASKQoKbGVhdmVfcm9vbRgMIAEoCzITLm5vaXR1LnYxLkxlYXZlUm9vbUgAEicKCXNlbmRfY2hhdBgNIAEoCzISLm5vaXR1LnYxLlNlbmRDaGF0SAASMAoOY2xhaW1fZGVhZF9lbmQYDiABKAsyFi5ub2l0dS52MS5DbGFpbURlYWRFbmRIABIrCgtyZXBvcnRfd29yZBgPIAEoCzIULm5vaXR1LnYxLlJlcG9ydFdvcmRIABIrCgtxdWlja19tYXRjaBgQIAEoCzIULm5vaXR1LnYxLlF1aWNrTWF0Y2hIABI4ChJjYW5jZWxfcXVpY2tfbWF0Y2gYESABKAsyGi5ub2l0dS52MS5DYW5jZWxRdWlja01hdGNoSABCCQoHcGF5bG9hZEoECAgQCSJoCgdXZWxjb21lEhIKCnNlc3Npb25faWQYASABKAkSFAoMcmVzdW1lX3Rva2VuGAIgASgJEhgKEHByb3RvY29sX3ZlcnNpb24YAyABKA0SGQoRYWNjZXB0ZWRfbmlja25hbWUYBCABKAkitQEKClBsYXllZFdvcmQSDAoEd29yZBgBIAEoCRINCgVieV9tZRgCIAEoCBIOCgZwb2ludHMYAyABKA0SEQoJc3lsbGFibGVzGAQgASgNEg0KBXR5cGVkGAUgASgJEhEKCXBsYXllcl9pZBgGIAEoCRIhCghtZWFuaW5ncxgHIAMoCzIPLm5vaXR1LnYxLlNlbnNlEiIKBXBhcnRzGAggAygLMhMubm9pdHUudjEuUG9pbnRQYXJ0Ij0KCVBvaW50UGFydBIhCgRraW5kGAEgASgOMhMubm9pdHUudjEuUG9pbnRLaW5kEg0KBXZhbHVlGAIgASgNIiMKBVNlbnNlEgsKA3BvcxgBIAEoCRINCgVnbG9zcxgCIAEoCSJ+CgpQbGF5ZXJTbG90EhEKCXBsYXllcl9pZBgBIAEoCRIMCgRuYW1lGAIgASgJEg0KBWlzX21lGAMgASgIEhAKCGlzX293bmVyGAQgASgIEg0KBXJlYWR5GAUgASgIEhEKCWNvbm5lY3RlZBgGIAEoCBIMCgR3aW5zGAcgASgNIoEBCgtQbGF5ZXJTY29yZRIRCglwbGF5ZXJfaWQYASABKAkSDAoEbmFtZRgCIAEoCRINCgVpc19tZRgDIAEoCBINCgVzY29yZRgEIAEoDRISCgplbGltaW5hdGVkGAUgASgIEhEKCWNvbm5lY3RlZBgGIAEoCBIMCgRyYW5rGAcgASgNIvwBCgtHYW1lU3RhcnRlZBIUCgxvcGVuaW5nX3dvcmQYASABKAkSGAoQY3VycmVudF9zeWxsYWJsZRgCIAEoCRIPCgdteV90dXJuGAMgASgIEhgKEGRlYWRsaW5lX3VuaXhfbXMYBCABKAMSEAoIdHVybl9zZXEYBSABKA0SFQoNdHVybl9saW1pdF9tcxgGIAEoDRImCgdwbGF5ZXJzGAcgAygLMhUubm9pdHUudjEuUGxheWVyU2NvcmUSFgoOdHVybl9wbGF5ZXJfaWQYCCABKAkSKQoQb3BlbmluZ19tZWFuaW5ncxgJIAMoCzIPLm5vaXR1LnYxLlNlbnNlIusBCgpUdXJuVXBkYXRlEiQKBnBsYXllZBgBIAEoCzIULm5vaXR1LnYxLlBsYXllZFdvcmQSGAoQY3VycmVudF9zeWxsYWJsZRgCIAEoCRIPCgdteV90dXJuGAMgASgIEhgKEGRlYWRsaW5lX3VuaXhfbXMYBCABKAMSEAoIdHVybl9zZXEYBSABKA0SFAoMY2hhaW5fbGVuZ3RoGAggASgNEiYKB3BsYXllcnMYCSADKAsyFS5ub2l0dS52MS5QbGF5ZXJTY29yZRIWCg50dXJuX3BsYXllcl9pZBgKIAEoCUoECAYQB0oECAcQCCJqCgxNb3ZlUmVqZWN0ZWQSJgoGcmVhc29uGAEgASgOMhYubm9pdHUudjEuUmVqZWN0UmVhc29uEgwKBHdvcmQYAiABKAkSEAoIdHVybl9zZXEYAyABKA0SEgoKc3VnZ2VzdGlvbhgEIAEoCSIcCgxXb3JkUmVwb3J0ZWQSDAoEd29yZBgBIAEoCSIiChBRdWlja01hdGNoU3RhdHVzEg4KBnF1ZXVlZBgBIAEoCCKOAQoIR2FtZU92ZXISDQoFaV93b24YASABKAgSJwoGcmVhc29uGAIgASgOMhcubm9pdHUudjEuR2FtZUVuZFJlYXNvbhIUCgxjaGFpbl9sZW5ndGgYBCABKA0SKAoJc3RhbmRpbmdzGAYgAygLMhUubm9pdHUudjEuUGxheWVyU2NvcmVKBAgDEARKBAgFEAYigAEKEFBsYXllckVsaW1pbmF0ZWQSEQoJcGxheWVyX2lkGAEgASgJEgwKBG5hbWUYAiABKAkSDQoFaXNfbWUYAyABKAgSJwoGcmVhc29uGAQgASgOMhcubm9pdHUudjEuR2FtZUVuZFJlYXNvbhITCgtzdWdnZXN0aW9ucxgFIAMoCSIsCgtTZXJ2ZXJFcnJvchIMCgRjb2RlGAEgASgJEg8KB21lc3NhZ2UYAiABKAkiNgoEUG9uZxIWCg5jbGllbnRfdGltZV9tcxgBIAEoAxIWCg5zZXJ2ZXJfdGltZV9tcxgCIAEoAyK4AQoJUm9vbVN0YXRlEhEKCXJvb21fY29kZRgBIAEoCRIRCgljYW5fc3RhcnQYAyABKAgSJQoHcGxheWVycxgJIAMoCzIULm5vaXR1LnYxLlBsYXllclNsb3QSEwoLbWF4X3BsYXllcnMYCiABKA0SEwoLbWluX3BsYXllcnMYCyABKA0SEAoIZ3JhY2VfbXMYDCABKA1KBAgCEANKBAgEEAVKBAgFEAZKBAgGEAdKBAgHEAhKBAgIEAkiZQoLQ2hhdE1lc3NhZ2USDwoHZnJvbV9tZRgBIAEoCBIOCgZhdXRob3IYAiABKAkSDAoEdGV4dBgDIAEoCRIUCgxzZW50X3VuaXhfbXMYBCABKAMSEQoJcGxheWVyX2lkGAUgASgJIjYKC0NoYXRIaXN0b3J5EicKCG1lc3NhZ2VzGAEgAygLMhUubm9pdHUudjEuQ2hhdE1lc3NhZ2UigwUKDVNlcnZlck1lc3NhZ2USJAoHd2VsY29tZRgBIAEoCzIRLm5vaXR1LnYxLldlbGNvbWVIABItCgxnYW1lX3N0YXJ0ZWQYBCABKAsyFS5ub2l0dS52MS5HYW1lU3RhcnRlZEgAEisKC3R1cm5fdXBkYXRlGAUgASgLMhQubm9pdHUudjEuVHVyblVwZGF0ZUgAEi8KDW1vdmVfcmVqZWN0ZWQYBiABKAsyFi5ub2l0dS52MS5Nb3ZlUmVqZWN0ZWRIABInCglnYW1lX292ZXIYByABKAsyEi5ub2l0dS52MS5HYW1lT3ZlckgAEiYKBWVycm9yGAkgASgLMhUubm9pdHUudjEuU2VydmVyRXJyb3JIABIeCgRwb25nGAogASgLMg4ubm9pdHUudjEuUG9uZ0gAEikKCnJvb21fc3RhdGUYDCABKAsyEy5ub2l0dS52MS5Sb29tU3RhdGVIABItCgxjaGF0X21lc3NhZ2UYDSABKAsyFS5ub2l0dS52MS5DaGF0TWVzc2FnZUgAEi0KDGNoYXRfaGlzdG9yeRgOIAEoCzIVLm5vaXR1LnYxLkNoYXRIaXN0b3J5SAASNwoRcGxheWVyX2VsaW1pbmF0ZWQYDyABKAsyGi5ub2l0dS5Line truncated
/**
* Describes the message noitu.v1.Hello.
@@ -107,124 +107,173 @@ export const SendChatSchema = /*@__PURE__*/
export const PingSchema = /*@__PURE__*/
messageDesc(file_noitu_v1_game, 11);
/**
* Describes the message noitu.v1.ClaimDeadEnd.
* Use `create(ClaimDeadEndSchema)` to create a new message.
*/
export const ClaimDeadEndSchema = /*@__PURE__*/
messageDesc(file_noitu_v1_game, 12);
/**
* Describes the message noitu.v1.ReportWord.
* Use `create(ReportWordSchema)` to create a new message.
*/
export const ReportWordSchema = /*@__PURE__*/
messageDesc(file_noitu_v1_game, 13);
/**
* Describes the message noitu.v1.QuickMatch.
* Use `create(QuickMatchSchema)` to create a new message.
*/
export const QuickMatchSchema = /*@__PURE__*/
messageDesc(file_noitu_v1_game, 14);
/**
* Describes the message noitu.v1.CancelQuickMatch.
* Use `create(CancelQuickMatchSchema)` to create a new message.
*/
export const CancelQuickMatchSchema = /*@__PURE__*/
messageDesc(file_noitu_v1_game, 15);
/**
* Describes the message noitu.v1.ClientMessage.
* Use `create(ClientMessageSchema)` to create a new message.
*/
export const ClientMessageSchema = /*@__PURE__*/
messageDesc(file_noitu_v1_game, 12);
messageDesc(file_noitu_v1_game, 16);
/**
* Describes the message noitu.v1.Welcome.
* Use `create(WelcomeSchema)` to create a new message.
*/
export const WelcomeSchema = /*@__PURE__*/
messageDesc(file_noitu_v1_game, 13);
messageDesc(file_noitu_v1_game, 17);
/**
* Describes the message noitu.v1.PlayedWord.
* Use `create(PlayedWordSchema)` to create a new message.
*/
export const PlayedWordSchema = /*@__PURE__*/
messageDesc(file_noitu_v1_game, 14);
messageDesc(file_noitu_v1_game, 18);
/**
* Describes the message noitu.v1.PointPart.
* Use `create(PointPartSchema)` to create a new message.
*/
export const PointPartSchema = /*@__PURE__*/
messageDesc(file_noitu_v1_game, 19);
/**
* Describes the message noitu.v1.Sense.
* Use `create(SenseSchema)` to create a new message.
*/
export const SenseSchema = /*@__PURE__*/
messageDesc(file_noitu_v1_game, 15);
messageDesc(file_noitu_v1_game, 20);
/**
* Describes the message noitu.v1.PlayerSlot.
* Use `create(PlayerSlotSchema)` to create a new message.
*/
export const PlayerSlotSchema = /*@__PURE__*/
messageDesc(file_noitu_v1_game, 16);
messageDesc(file_noitu_v1_game, 21);
/**
* Describes the message noitu.v1.PlayerScore.
* Use `create(PlayerScoreSchema)` to create a new message.
*/
export const PlayerScoreSchema = /*@__PURE__*/
messageDesc(file_noitu_v1_game, 17);
messageDesc(file_noitu_v1_game, 22);
/**
* Describes the message noitu.v1.GameStarted.
* Use `create(GameStartedSchema)` to create a new message.
*/
export const GameStartedSchema = /*@__PURE__*/
messageDesc(file_noitu_v1_game, 18);
messageDesc(file_noitu_v1_game, 23);
/**
* Describes the message noitu.v1.TurnUpdate.
* Use `create(TurnUpdateSchema)` to create a new message.
*/
export const TurnUpdateSchema = /*@__PURE__*/
messageDesc(file_noitu_v1_game, 19);
messageDesc(file_noitu_v1_game, 24);
/**
* Describes the message noitu.v1.MoveRejected.
* Use `create(MoveRejectedSchema)` to create a new message.
*/
export const MoveRejectedSchema = /*@__PURE__*/
messageDesc(file_noitu_v1_game, 20);
messageDesc(file_noitu_v1_game, 25);
/**
* Describes the message noitu.v1.WordReported.
* Use `create(WordReportedSchema)` to create a new message.
*/
export const WordReportedSchema = /*@__PURE__*/
messageDesc(file_noitu_v1_game, 26);
/**
* Describes the message noitu.v1.QuickMatchStatus.
* Use `create(QuickMatchStatusSchema)` to create a new message.
*/
export const QuickMatchStatusSchema = /*@__PURE__*/
messageDesc(file_noitu_v1_game, 27);
/**
* Describes the message noitu.v1.GameOver.
* Use `create(GameOverSchema)` to create a new message.
*/
export const GameOverSchema = /*@__PURE__*/
messageDesc(file_noitu_v1_game, 21);
messageDesc(file_noitu_v1_game, 28);
/**
* Describes the message noitu.v1.PlayerEliminated.
* Use `create(PlayerEliminatedSchema)` to create a new message.
*/
export const PlayerEliminatedSchema = /*@__PURE__*/
messageDesc(file_noitu_v1_game, 22);
messageDesc(file_noitu_v1_game, 29);
/**
* Describes the message noitu.v1.ServerError.
* Use `create(ServerErrorSchema)` to create a new message.
*/
export const ServerErrorSchema = /*@__PURE__*/
messageDesc(file_noitu_v1_game, 23);
messageDesc(file_noitu_v1_game, 30);
/**
* Describes the message noitu.v1.Pong.
* Use `create(PongSchema)` to create a new message.
*/
export const PongSchema = /*@__PURE__*/
messageDesc(file_noitu_v1_game, 24);
messageDesc(file_noitu_v1_game, 31);
/**
* Describes the message noitu.v1.RoomState.
* Use `create(RoomStateSchema)` to create a new message.
*/
export const RoomStateSchema = /*@__PURE__*/
messageDesc(file_noitu_v1_game, 25);
messageDesc(file_noitu_v1_game, 32);
/**
* Describes the message noitu.v1.ChatMessage.
* Use `create(ChatMessageSchema)` to create a new message.
*/
export const ChatMessageSchema = /*@__PURE__*/
messageDesc(file_noitu_v1_game, 26);
messageDesc(file_noitu_v1_game, 33);
/**
* Describes the message noitu.v1.ChatHistory.
* Use `create(ChatHistorySchema)` to create a new message.
*/
export const ChatHistorySchema = /*@__PURE__*/
messageDesc(file_noitu_v1_game, 27);
messageDesc(file_noitu_v1_game, 34);
/**
* Describes the message noitu.v1.ServerMessage.
* Use `create(ServerMessageSchema)` to create a new message.
*/
export const ServerMessageSchema = /*@__PURE__*/
messageDesc(file_noitu_v1_game, 28);
messageDesc(file_noitu_v1_game, 35);
/**
* Describes the enum noitu.v1.Difficulty.
@@ -271,3 +320,20 @@ export const GameEndReasonSchema = /*@__PURE__*/
export const GameEndReason = /*@__PURE__*/
tsEnum(GameEndReasonSchema);
/**
* Describes the enum noitu.v1.PointKind.
*/
export const PointKindSchema = /*@__PURE__*/
enumDesc(file_noitu_v1_game, 3);
/**
* PointKind names one term of a word's score. The engine adds several and
* the client cannot re-derive any of them — it has no wordlist by design — so
* each term travels named, and a new term is a new value rather than a wire
* break.
*
* @generated from enum noitu.v1.PointKind
*/
export const PointKind = /*@__PURE__*/
tsEnum(PointKindSchema);