From 66fb58c5440f97be0561ceea7e7fedd667613174 Mon Sep 17 00:00:00 2001 From: ThePerkinrex Date: Tue, 12 Oct 2021 17:23:37 +0200 Subject: [PATCH] Add has_finished & custom info messages --- protobuf/game.proto | 7 + server/src/games/run.rs | 31 +-- server/src/games/run/engine.rs | 14 ++ server/src/server/game.rs | 15 +- server/src/server/protos/game.rs | 11 ++ unity/Assets/Scripts/grpc/Game.cs | 313 +++++++++++++++++++++++++++++- 6 files changed, 361 insertions(+), 30 deletions(-) diff --git a/protobuf/game.proto b/protobuf/game.proto index 96350f6..2ee2170 100644 --- a/protobuf/game.proto +++ b/protobuf/game.proto @@ -60,8 +60,15 @@ message GameStatus { map piles = 1; } + message CustomInfoMessage { + string title = 1; + string m = 2; + } + Piles commonPiles = 1; // {a: [""], b:[""]} repeated Piles playerPiles = 2; // [{...}, {...}] repeated common.Name names = 3; uint32 currentTurn = 4; + bool hasFinished = 5; + CustomInfoMessage info = 6; } \ No newline at end of file diff --git a/server/src/games/run.rs b/server/src/games/run.rs index 529aa15..9009f51 100644 --- a/server/src/games/run.rs +++ b/server/src/games/run.rs @@ -24,6 +24,7 @@ pub struct RunningGame { current_player: Player, data: HashMap, pub players: HashMap, + pub has_finished: bool, } // TODO add errors @@ -91,6 +92,7 @@ impl RunningGame { current_player: Player::new(0, current_players.len() as u32), data: other, players, + has_finished: false, } // Self {setup: Box::new(Func::<(Vec, Vec>), ()>::create_from_ast(engine, ast, "setup"))} } @@ -120,38 +122,39 @@ impl RunningGame { Ok(()) } - pub fn on_click(&mut self, card: CardId, player: u32) { + pub fn on_click(&mut self, card: CardId, player: u32) -> RhaiResult<()> { let action_author = Player::new(player, self.current_player.max); let data = self.data_as_dynamic().unwrap(); let arr = self .functions - .on_click(data, card, action_author, self.current_player) - .unwrap(); + .on_click(data, card, action_author, self.current_player)?; self.save_data(&arr[0]).unwrap(); let turn_end: bool = arr[1].clone().cast(); if turn_end { self.turn_end() + }else{ + Ok(()) } } - fn turn_end(&mut self) { - let data = self.data_as_dynamic().unwrap(); - let mut arr = self.functions.turn_end(data, self.current_player).unwrap(); - self.save_data(&arr[0]).unwrap(); + fn turn_end(&mut self) -> RhaiResult<()> { + let data = self.data_as_dynamic()?; + let mut arr = self.functions.turn_end(data, self.current_player)?; + self.save_data(&arr[0])?; self.current_player = arr.remove(1).cast(); - let has_finished: bool = arr.remove(1).cast(); - self.turn_start(); + self.has_finished = arr.remove(1).cast(); + self.turn_start() } - fn turn_start(&mut self) { - let data = self.data_as_dynamic().unwrap(); + fn turn_start(&mut self) -> RhaiResult<()> { + let data = self.data_as_dynamic()?; let data = self .functions .turn_start(data, self.current_player) - .transpose() - .unwrap(); + .transpose()?; if let Some(data) = data { - self.save_data(&data).unwrap(); + self.save_data(&data)?; } + Ok(()) } } diff --git a/server/src/games/run/engine.rs b/server/src/games/run/engine.rs index df90957..513505f 100644 --- a/server/src/games/run/engine.rs +++ b/server/src/games/run/engine.rs @@ -64,6 +64,20 @@ pub fn setup_engine(conf: &Config) -> Engine { .register_fn("+", |s: &str, p: CardId| format!("{}{}", s, p)) .register_fn("+", |p: CardId, s: &str| p.to_string().push_str(s)); + // engine.register_result_fn("new_card_idx", |card_idx: Dynamic| { + // if card_idx.is::() { + // match card_idx.cast::().to_lowercase().as_str() { + // "top" => Ok(CardIdx::Top), + // "bottom" => Ok(CardIdx::Bottom), + // _ => Err(Box::new(EvalAltResult::ErrorSystem("card_idx should be \"top\", \"bottom\" or a number".into(), Box::new(RhaiError)))) + // } + // }else if card_idx.is::() { + // Ok(CardIdx::Indexed(card_idx.cast::() as usize)) + // }else{ + // Err(Box::new(EvalAltResult::ErrorSystem("card_idx should be \"top\", \"bottom\" or a number".into(), Box::new(RhaiError)))) + // } + // }); + let available_cards = conf.available_cards.clone(); engine.register_result_fn("new_card", move |kind: &str| { let card = available_cards.get(kind).unwrap(); diff --git a/server/src/server/game.rs b/server/src/server/game.rs index 8eb1c01..35a2304 100644 --- a/server/src/server/game.rs +++ b/server/src/server/game.rs @@ -3,10 +3,7 @@ use super::{ socket_manager::SocketManager, ServiceData, }; -use crate::{ - games::{CardId, CardIdx, PileKind, RunningPile}, - server::protos::protocol::server_client_packet::Data, -}; +use crate::{games::{CardId, CardIdx, PileKind, RunningPile}, server::protos::{game::game_status::CustomInfoMessage, protocol::server_client_packet::Data}}; use anyhow::{anyhow, Result}; pub(super) async fn get_status(data: &mut ServiceData) -> Result { @@ -91,6 +88,8 @@ pub(super) async fn get_status(data: &mut ServiceData) -> Result { }) .collect(), names, + has_finished: game.has_finished, + info: None, }; log::info!("Created a new status for {}", uuid); Ok(status) @@ -150,6 +149,7 @@ pub(super) async fn on_click( card: super::protos::game::CardId, ) -> Result<()> { let uuid = data.user_id.get()?; + let mut message = None; { let lobby: u32 = match data.db.get_lobby_for_user(uuid).await { Some(l) => l, @@ -176,9 +176,12 @@ pub(super) async fn on_click( pile_kind, pile_name: card.pile_name, }; - game.on_click(card, game.get_player_for_uuid(&uuid).unwrap()); + if let Err(e) = game.on_click(card, game.get_player_for_uuid(&uuid).unwrap()) { + message = Some(CustomInfoMessage { title: "Error in game execution".to_string(), m: e.to_string() }); + } } // drop the connection so that the lock is released - let status = get_status(data).await?; + let mut status = get_status(data).await?; + status.info = message; socket_mgr .broadcast_to_lobby(&mut data.db, data.user_id.get()?, Data::GameStatus(status)) diff --git a/server/src/server/protos/game.rs b/server/src/server/protos/game.rs index f45fc1c..c86faa7 100644 --- a/server/src/server/protos/game.rs +++ b/server/src/server/protos/game.rs @@ -73,6 +73,10 @@ pub struct GameStatus { pub names: ::prost::alloc::vec::Vec, #[prost(uint32, tag="4")] pub current_turn: u32, + #[prost(bool, tag="5")] + pub has_finished: bool, + #[prost(message, optional, tag="6")] + pub info: ::core::option::Option, } /// Nested message and enum types in `GameStatus`. pub mod game_status { @@ -101,4 +105,11 @@ pub mod game_status { #[prost(map="string, message", tag="1")] pub piles: ::std::collections::HashMap<::prost::alloc::string::String, Pile>, } + #[derive(Clone, PartialEq, ::prost::Message)] + pub struct CustomInfoMessage { + #[prost(string, tag="1")] + pub title: ::prost::alloc::string::String, + #[prost(string, tag="2")] + pub m: ::prost::alloc::string::String, + } } diff --git a/unity/Assets/Scripts/grpc/Game.cs b/unity/Assets/Scripts/grpc/Game.cs index bcb97d9..5803ab6 100644 --- a/unity/Assets/Scripts/grpc/Game.cs +++ b/unity/Assets/Scripts/grpc/Game.cs @@ -33,17 +33,20 @@ namespace Game { "CgVvd25lZBgBIAEoDUgAEigKBmNvbW1vbhgCIAEoCzIWLmdvb2dsZS5wcm90", "b2J1Zi5FbXB0eUgAQgYKBGtpbmQiYAoGQ2FyZElkEiAKCHBpbGVLaW5kGAEg", "ASgLMg4uZ2FtZS5QaWxlS2luZBIQCghwaWxlTmFtZRgCIAEoCRIiCgljYXJk", - "SW5kZXgYAyABKAsyDy5nYW1lLkNhcmRJbmRleCK8AwoKR2FtZVN0YXR1cxIr", + "SW5kZXgYAyABKAsyDy5nYW1lLkNhcmRJbmRleCKyBAoKR2FtZVN0YXR1cxIr", "Cgtjb21tb25QaWxlcxgBIAEoCzIWLmdhbWUuR2FtZVN0YXR1cy5QaWxlcxIr", "CgtwbGF5ZXJQaWxlcxgCIAMoCzIWLmdhbWUuR2FtZVN0YXR1cy5QaWxlcxIb", "CgVuYW1lcxgDIAMoCzIMLmNvbW1vbi5OYW1lEhMKC2N1cnJlbnRUdXJuGAQg", - "ASgNGkMKBENhcmQSHAoEa2luZBgBIAEoCzIOLmdhbWUuQ2FyZEtpbmQSDwoH", - "dmlzaWJsZRgCIAEoCBIMCgR1dWlkGAMgASgJGl0KBFBpbGUSJAoFY2FyZHMY", - "ASADKAsyFS5nYW1lLkdhbWVTdGF0dXMuQ2FyZBIQCghmYWNlRG93bhgCIAEo", - "CBIPCgd2aXNpYmxlGAMgASgIEgwKBG5hbWUYBCABKAkafgoFUGlsZXMSMAoF", - "cGlsZXMYASADKAsyIS5nYW1lLkdhbWVTdGF0dXMuUGlsZXMuUGlsZXNFbnRy", - "eRpDCgpQaWxlc0VudHJ5EgsKA2tleRgBIAEoCRIkCgV2YWx1ZRgCIAEoCzIV", - "LmdhbWUuR2FtZVN0YXR1cy5QaWxlOgI4AWIGcHJvdG8z")); + "ASgNEhMKC2hhc0ZpbmlzaGVkGAUgASgIEjAKBGluZm8YBiABKAsyIi5nYW1l", + "LkdhbWVTdGF0dXMuQ3VzdG9tSW5mb01lc3NhZ2UaQwoEQ2FyZBIcCgRraW5k", + "GAEgASgLMg4uZ2FtZS5DYXJkS2luZBIPCgd2aXNpYmxlGAIgASgIEgwKBHV1", + "aWQYAyABKAkaXQoEUGlsZRIkCgVjYXJkcxgBIAMoCzIVLmdhbWUuR2FtZVN0", + "YXR1cy5DYXJkEhAKCGZhY2VEb3duGAIgASgIEg8KB3Zpc2libGUYAyABKAgS", + "DAoEbmFtZRgEIAEoCRp+CgVQaWxlcxIwCgVwaWxlcxgBIAMoCzIhLmdhbWUu", + "R2FtZVN0YXR1cy5QaWxlcy5QaWxlc0VudHJ5GkMKClBpbGVzRW50cnkSCwoD", + "a2V5GAEgASgJEiQKBXZhbHVlGAIgASgLMhUuZ2FtZS5HYW1lU3RhdHVzLlBp", + "bGU6AjgBGi0KEUN1c3RvbUluZm9NZXNzYWdlEg0KBXRpdGxlGAEgASgJEgkK", + "AW0YAiABKAliBnByb3RvMw==")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { global::Google.Protobuf.WellKnownTypes.EmptyReflection.Descriptor, global::Common.CommonReflection.Descriptor, }, new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] { @@ -52,9 +55,10 @@ namespace Game { new pbr::GeneratedClrTypeInfo(typeof(global::Game.CardIndex), global::Game.CardIndex.Parser, new[]{ "Index", "Top", "Bottom" }, new[]{ "Pos" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Game.PileKind), global::Game.PileKind.Parser, new[]{ "Owned", "Common" }, new[]{ "Kind" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Game.CardId), global::Game.CardId.Parser, new[]{ "PileKind", "PileName", "CardIndex" }, null, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Game.GameStatus), global::Game.GameStatus.Parser, new[]{ "CommonPiles", "PlayerPiles", "Names", "CurrentTurn" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Game.GameStatus.Types.Card), global::Game.GameStatus.Types.Card.Parser, new[]{ "Kind", "Visible", "Uuid" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Game.GameStatus), global::Game.GameStatus.Parser, new[]{ "CommonPiles", "PlayerPiles", "Names", "CurrentTurn", "HasFinished", "Info" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Game.GameStatus.Types.Card), global::Game.GameStatus.Types.Card.Parser, new[]{ "Kind", "Visible", "Uuid" }, null, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Game.GameStatus.Types.Pile), global::Game.GameStatus.Types.Pile.Parser, new[]{ "Cards", "FaceDown", "Visible", "Name" }, null, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::Game.GameStatus.Types.Piles), global::Game.GameStatus.Types.Piles.Parser, new[]{ "Piles_" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { null, })}) + new pbr::GeneratedClrTypeInfo(typeof(global::Game.GameStatus.Types.Piles), global::Game.GameStatus.Types.Piles.Parser, new[]{ "Piles_" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { null, }), + new pbr::GeneratedClrTypeInfo(typeof(global::Game.GameStatus.Types.CustomInfoMessage), global::Game.GameStatus.Types.CustomInfoMessage.Parser, new[]{ "Title", "M" }, null, null, null, null)}) })); } #endregion @@ -1328,6 +1332,8 @@ namespace Game { playerPiles_ = other.playerPiles_.Clone(); names_ = other.names_.Clone(); currentTurn_ = other.currentTurn_; + hasFinished_ = other.hasFinished_; + info_ = other.info_ != null ? other.info_.Clone() : null; _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } @@ -1384,6 +1390,28 @@ namespace Game { } } + /// Field number for the "hasFinished" field. + public const int HasFinishedFieldNumber = 5; + private bool hasFinished_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool HasFinished { + get { return hasFinished_; } + set { + hasFinished_ = value; + } + } + + /// Field number for the "info" field. + public const int InfoFieldNumber = 6; + private global::Game.GameStatus.Types.CustomInfoMessage info_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public global::Game.GameStatus.Types.CustomInfoMessage Info { + get { return info_; } + set { + info_ = value; + } + } + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) { return Equals(other as GameStatus); @@ -1401,6 +1429,8 @@ namespace Game { if(!playerPiles_.Equals(other.playerPiles_)) return false; if(!names_.Equals(other.names_)) return false; if (CurrentTurn != other.CurrentTurn) return false; + if (HasFinished != other.HasFinished) return false; + if (!object.Equals(Info, other.Info)) return false; return Equals(_unknownFields, other._unknownFields); } @@ -1411,6 +1441,8 @@ namespace Game { hash ^= playerPiles_.GetHashCode(); hash ^= names_.GetHashCode(); if (CurrentTurn != 0) hash ^= CurrentTurn.GetHashCode(); + if (HasFinished != false) hash ^= HasFinished.GetHashCode(); + if (info_ != null) hash ^= Info.GetHashCode(); if (_unknownFields != null) { hash ^= _unknownFields.GetHashCode(); } @@ -1437,6 +1469,14 @@ namespace Game { output.WriteRawTag(32); output.WriteUInt32(CurrentTurn); } + if (HasFinished != false) { + output.WriteRawTag(40); + output.WriteBool(HasFinished); + } + if (info_ != null) { + output.WriteRawTag(50); + output.WriteMessage(Info); + } if (_unknownFields != null) { _unknownFields.WriteTo(output); } @@ -1456,6 +1496,14 @@ namespace Game { output.WriteRawTag(32); output.WriteUInt32(CurrentTurn); } + if (HasFinished != false) { + output.WriteRawTag(40); + output.WriteBool(HasFinished); + } + if (info_ != null) { + output.WriteRawTag(50); + output.WriteMessage(Info); + } if (_unknownFields != null) { _unknownFields.WriteTo(ref output); } @@ -1473,6 +1521,12 @@ namespace Game { if (CurrentTurn != 0) { size += 1 + pb::CodedOutputStream.ComputeUInt32Size(CurrentTurn); } + if (HasFinished != false) { + size += 1 + 1; + } + if (info_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Info); + } if (_unknownFields != null) { size += _unknownFields.CalculateSize(); } @@ -1495,6 +1549,15 @@ namespace Game { if (other.CurrentTurn != 0) { CurrentTurn = other.CurrentTurn; } + if (other.HasFinished != false) { + HasFinished = other.HasFinished; + } + if (other.info_ != null) { + if (info_ == null) { + Info = new global::Game.GameStatus.Types.CustomInfoMessage(); + } + Info.MergeFrom(other.Info); + } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } @@ -1528,6 +1591,17 @@ namespace Game { CurrentTurn = input.ReadUInt32(); break; } + case 40: { + HasFinished = input.ReadBool(); + break; + } + case 50: { + if (info_ == null) { + Info = new global::Game.GameStatus.Types.CustomInfoMessage(); + } + input.ReadMessage(Info); + break; + } } } #endif @@ -1561,6 +1635,17 @@ namespace Game { CurrentTurn = input.ReadUInt32(); break; } + case 40: { + HasFinished = input.ReadBool(); + break; + } + case 50: { + if (info_ == null) { + Info = new global::Game.GameStatus.Types.CustomInfoMessage(); + } + input.ReadMessage(Info); + break; + } } } } @@ -2253,6 +2338,214 @@ namespace Game { } + public sealed partial class CustomInfoMessage : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new CustomInfoMessage()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public static pbr::MessageDescriptor Descriptor { + get { return global::Game.GameStatus.Descriptor.NestedTypes[3]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public CustomInfoMessage() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public CustomInfoMessage(CustomInfoMessage other) : this() { + title_ = other.title_; + m_ = other.m_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public CustomInfoMessage Clone() { + return new CustomInfoMessage(this); + } + + /// Field number for the "title" field. + public const int TitleFieldNumber = 1; + private string title_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string Title { + get { return title_; } + set { + title_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + /// Field number for the "m" field. + public const int MFieldNumber = 2; + private string m_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public string M { + get { return m_; } + set { + m_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override bool Equals(object other) { + return Equals(other as CustomInfoMessage); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public bool Equals(CustomInfoMessage other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Title != other.Title) return false; + if (M != other.M) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override int GetHashCode() { + int hash = 1; + if (Title.Length != 0) hash ^= Title.GetHashCode(); + if (M.Length != 0) hash ^= M.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Title.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Title); + } + if (M.Length != 0) { + output.WriteRawTag(18); + output.WriteString(M); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Title.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Title); + } + if (M.Length != 0) { + output.WriteRawTag(18); + output.WriteString(M); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public int CalculateSize() { + int size = 0; + if (Title.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Title); + } + if (M.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(M); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(CustomInfoMessage other) { + if (other == null) { + return; + } + if (other.Title.Length != 0) { + Title = other.Title; + } + if (other.M.Length != 0) { + M = other.M; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + Title = input.ReadString(); + break; + } + case 18: { + M = input.ReadString(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + Title = input.ReadString(); + break; + } + case 18: { + M = input.ReadString(); + break; + } + } + } + } + #endif + + } + } #endregion