diff --git a/.gitignore b/.gitignore index bcbe477..d4a28fa 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ -*.pb.go *.swp # Binaries for programs and plugins *.exe diff --git a/README.md b/README.md index 0257912..d848eed 100644 --- a/README.md +++ b/README.md @@ -34,3 +34,4 @@ wisdom. I like the idea of mapping these mental spaces into a computer. I haven't moved over any design docs or notes or anything like that. Refer to the tildemush repo for that kind of stuff. +to regenerate the API code: `protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative proto/hermeticum.proto` diff --git a/client/cmd/main.go b/client/cmd/main.go index 14d8f44..f82b011 100644 --- a/client/cmd/main.go +++ b/client/cmd/main.go @@ -7,8 +7,10 @@ import ( "fmt" "io" "log" + "strings" "time" + "github.com/gdamore/tcell/v2" "github.com/rivo/tview" "github.com/vilmibm/hermeticum/proto" "google.golang.org/grpc" @@ -51,6 +53,37 @@ type ClientState struct { MaxMessages int messagesView *tview.TextView messages []*proto.ClientMessage + cmdStream proto.GameWorld_CommandsClient +} + +func (cs *ClientState) HandleInput(input string) error { + var verb string + rest := input + if strings.HasPrefix(input, "/") { + input = input[1:] + parts := strings.SplitN(input, " ", 1) + verb = parts[0] + rest = parts[1] + } else { + verb = "say" + } + cmd := &proto.Command{ + SessionInfo: cs.SessionInfo, + Verb: verb, + Rest: rest, + } + // TODO I'm punting on handling CommandAcks for now but it will be a nice UX thing later for showing connectivity problems + return cs.cmdStream.Send(cmd) +} + +func (cs *ClientState) InitCommandStream() error { + ctx := context.Background() + stream, err := cs.Client.Commands(ctx) + if err != nil { + return err + } + cs.cmdStream = stream + return nil } func (cs *ClientState) AddMessage(msg *proto.ClientMessage) { @@ -107,6 +140,11 @@ func _main() error { messages: []*proto.ClientMessage{}, } + err = cs.InitCommandStream() + if err != nil { + return fmt.Errorf("could not create command stream: %w", err) + } + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() @@ -129,6 +167,15 @@ func _main() error { true, true) + commandInput := tview.NewInputField().SetLabel("> ") + handleInput := func(_ tcell.Key) { + input := commandInput.GetText() + // TODO do i need to clear the input's text? + go cs.HandleInput(input) + } + + commandInput.SetDoneFunc(handleInput) + mainPage := tview.NewList(). AddItem("jack in", "connect using an existing account", '1', func() { pages.SwitchToPage("login") @@ -165,6 +212,7 @@ func _main() error { cs.SessionInfo = si pages.SwitchToPage("game") + app.SetFocus(commandInput) } // TODO login and register pages should refuse blank entries @@ -222,10 +270,10 @@ func _main() error { msgView, 1, 0, 1, 1, 10, 20, false). AddItem( - tview.NewTextView().SetText("TODO detail window"), + tview.NewTextView().SetText("TODO details"), 1, 1, 1, 1, 10, 10, false). AddItem( - tview.NewTextView().SetText("TODO input"), + commandInput, 2, 0, 1, 2, 1, 30, false) pages.AddPage("game", gamePage, true, false) diff --git a/proto/hermeticum.pb.go b/proto/hermeticum.pb.go new file mode 100644 index 0000000..a49b039 --- /dev/null +++ b/proto/hermeticum.pb.go @@ -0,0 +1,734 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.28.0 +// protoc v3.19.4 +// source: proto/hermeticum.proto + +package proto + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type ClientMessage_ClientMessageType int32 + +const ( + ClientMessage_WHISPER ClientMessage_ClientMessageType = 0 // someone or something sent a private message to user + ClientMessage_OVERHEARD ClientMessage_ClientMessageType = 1 // someone or something in the same room said something out loud + ClientMessage_EMOTE ClientMessage_ClientMessageType = 2 // someone or something in the same room performed an action + ClientMessage_GENERIC ClientMessage_ClientMessageType = 3 // just a string that should be printed (ie, "you hear noises in a nearby room") + ClientMessage_GLOBAL ClientMessage_ClientMessageType = 4 // the system sent out a PSA +) + +// Enum value maps for ClientMessage_ClientMessageType. +var ( + ClientMessage_ClientMessageType_name = map[int32]string{ + 0: "WHISPER", + 1: "OVERHEARD", + 2: "EMOTE", + 3: "GENERIC", + 4: "GLOBAL", + } + ClientMessage_ClientMessageType_value = map[string]int32{ + "WHISPER": 0, + "OVERHEARD": 1, + "EMOTE": 2, + "GENERIC": 3, + "GLOBAL": 4, + } +) + +func (x ClientMessage_ClientMessageType) Enum() *ClientMessage_ClientMessageType { + p := new(ClientMessage_ClientMessageType) + *p = x + return p +} + +func (x ClientMessage_ClientMessageType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (ClientMessage_ClientMessageType) Descriptor() protoreflect.EnumDescriptor { + return file_proto_hermeticum_proto_enumTypes[0].Descriptor() +} + +func (ClientMessage_ClientMessageType) Type() protoreflect.EnumType { + return &file_proto_hermeticum_proto_enumTypes[0] +} + +func (x ClientMessage_ClientMessageType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use ClientMessage_ClientMessageType.Descriptor instead. +func (ClientMessage_ClientMessageType) EnumDescriptor() ([]byte, []int) { + return file_proto_hermeticum_proto_rawDescGZIP(), []int{5, 0} +} + +type AuthInfo struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Username string `protobuf:"bytes,1,opt,name=username,proto3" json:"username,omitempty"` + Password string `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"` +} + +func (x *AuthInfo) Reset() { + *x = AuthInfo{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_hermeticum_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AuthInfo) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AuthInfo) ProtoMessage() {} + +func (x *AuthInfo) ProtoReflect() protoreflect.Message { + mi := &file_proto_hermeticum_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AuthInfo.ProtoReflect.Descriptor instead. +func (*AuthInfo) Descriptor() ([]byte, []int) { + return file_proto_hermeticum_proto_rawDescGZIP(), []int{0} +} + +func (x *AuthInfo) GetUsername() string { + if x != nil { + return x.Username + } + return "" +} + +func (x *AuthInfo) GetPassword() string { + if x != nil { + return x.Password + } + return "" +} + +type SessionInfo struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + SessionID string `protobuf:"bytes,1,opt,name=sessionID,proto3" json:"sessionID,omitempty"` +} + +func (x *SessionInfo) Reset() { + *x = SessionInfo{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_hermeticum_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SessionInfo) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SessionInfo) ProtoMessage() {} + +func (x *SessionInfo) ProtoReflect() protoreflect.Message { + mi := &file_proto_hermeticum_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SessionInfo.ProtoReflect.Descriptor instead. +func (*SessionInfo) Descriptor() ([]byte, []int) { + return file_proto_hermeticum_proto_rawDescGZIP(), []int{1} +} + +func (x *SessionInfo) GetSessionID() string { + if x != nil { + return x.SessionID + } + return "" +} + +type StateUpdate struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *StateUpdate) Reset() { + *x = StateUpdate{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_hermeticum_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *StateUpdate) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StateUpdate) ProtoMessage() {} + +func (x *StateUpdate) ProtoReflect() protoreflect.Message { + mi := &file_proto_hermeticum_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use StateUpdate.ProtoReflect.Descriptor instead. +func (*StateUpdate) Descriptor() ([]byte, []int) { + return file_proto_hermeticum_proto_rawDescGZIP(), []int{2} +} + +type Command struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + SessionInfo *SessionInfo `protobuf:"bytes,1,opt,name=sessionInfo,proto3" json:"sessionInfo,omitempty"` + Verb string `protobuf:"bytes,2,opt,name=verb,proto3" json:"verb,omitempty"` + Rest string `protobuf:"bytes,3,opt,name=rest,proto3" json:"rest,omitempty"` +} + +func (x *Command) Reset() { + *x = Command{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_hermeticum_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Command) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Command) ProtoMessage() {} + +func (x *Command) ProtoReflect() protoreflect.Message { + mi := &file_proto_hermeticum_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Command.ProtoReflect.Descriptor instead. +func (*Command) Descriptor() ([]byte, []int) { + return file_proto_hermeticum_proto_rawDescGZIP(), []int{3} +} + +func (x *Command) GetSessionInfo() *SessionInfo { + if x != nil { + return x.SessionInfo + } + return nil +} + +func (x *Command) GetVerb() string { + if x != nil { + return x.Verb + } + return "" +} + +func (x *Command) GetRest() string { + if x != nil { + return x.Rest + } + return "" +} + +type CommandAck struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Acked bool `protobuf:"varint,1,opt,name=acked,proto3" json:"acked,omitempty"` + ErrorMsg string `protobuf:"bytes,2,opt,name=errorMsg,proto3" json:"errorMsg,omitempty"` +} + +func (x *CommandAck) Reset() { + *x = CommandAck{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_hermeticum_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CommandAck) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CommandAck) ProtoMessage() {} + +func (x *CommandAck) ProtoReflect() protoreflect.Message { + mi := &file_proto_hermeticum_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CommandAck.ProtoReflect.Descriptor instead. +func (*CommandAck) Descriptor() ([]byte, []int) { + return file_proto_hermeticum_proto_rawDescGZIP(), []int{4} +} + +func (x *CommandAck) GetAcked() bool { + if x != nil { + return x.Acked + } + return false +} + +func (x *CommandAck) GetErrorMsg() string { + if x != nil { + return x.ErrorMsg + } + return "" +} + +type ClientMessage struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Type ClientMessage_ClientMessageType `protobuf:"varint,1,opt,name=type,proto3,enum=proto.ClientMessage_ClientMessageType" json:"type,omitempty"` + Speaker *string `protobuf:"bytes,2,opt,name=speaker,proto3,oneof" json:"speaker,omitempty"` + Text string `protobuf:"bytes,3,opt,name=text,proto3" json:"text,omitempty"` +} + +func (x *ClientMessage) Reset() { + *x = ClientMessage{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_hermeticum_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ClientMessage) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ClientMessage) ProtoMessage() {} + +func (x *ClientMessage) ProtoReflect() protoreflect.Message { + mi := &file_proto_hermeticum_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ClientMessage.ProtoReflect.Descriptor instead. +func (*ClientMessage) Descriptor() ([]byte, []int) { + return file_proto_hermeticum_proto_rawDescGZIP(), []int{5} +} + +func (x *ClientMessage) GetType() ClientMessage_ClientMessageType { + if x != nil { + return x.Type + } + return ClientMessage_WHISPER +} + +func (x *ClientMessage) GetSpeaker() string { + if x != nil && x.Speaker != nil { + return *x.Speaker + } + return "" +} + +func (x *ClientMessage) GetText() string { + if x != nil { + return x.Text + } + return "" +} + +type MapData struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + MapData string `protobuf:"bytes,1,opt,name=mapData,proto3" json:"mapData,omitempty"` +} + +func (x *MapData) Reset() { + *x = MapData{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_hermeticum_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MapData) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MapData) ProtoMessage() {} + +func (x *MapData) ProtoReflect() protoreflect.Message { + mi := &file_proto_hermeticum_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MapData.ProtoReflect.Descriptor instead. +func (*MapData) Descriptor() ([]byte, []int) { + return file_proto_hermeticum_proto_rawDescGZIP(), []int{6} +} + +func (x *MapData) GetMapData() string { + if x != nil { + return x.MapData + } + return "" +} + +type Pong struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + When string `protobuf:"bytes,1,opt,name=when,proto3" json:"when,omitempty"` // timestamp of pong creation +} + +func (x *Pong) Reset() { + *x = Pong{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_hermeticum_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Pong) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Pong) ProtoMessage() {} + +func (x *Pong) ProtoReflect() protoreflect.Message { + mi := &file_proto_hermeticum_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Pong.ProtoReflect.Descriptor instead. +func (*Pong) Descriptor() ([]byte, []int) { + return file_proto_hermeticum_proto_rawDescGZIP(), []int{7} +} + +func (x *Pong) GetWhen() string { + if x != nil { + return x.When + } + return "" +} + +var File_proto_hermeticum_proto protoreflect.FileDescriptor + +var file_proto_hermeticum_proto_rawDesc = []byte{ + 0x0a, 0x16, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x68, 0x65, 0x72, 0x6d, 0x65, 0x74, 0x69, 0x63, + 0x75, 0x6d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, + 0x42, 0x0a, 0x08, 0x41, 0x75, 0x74, 0x68, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1a, 0x0a, 0x08, 0x75, + 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, + 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, + 0x6f, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, + 0x6f, 0x72, 0x64, 0x22, 0x2b, 0x0a, 0x0b, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x6e, + 0x66, 0x6f, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x44, + 0x22, 0x0d, 0x0a, 0x0b, 0x53, 0x74, 0x61, 0x74, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x22, + 0x67, 0x0a, 0x07, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x34, 0x0a, 0x0b, 0x73, 0x65, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, + 0x6e, 0x66, 0x6f, 0x52, 0x0b, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, + 0x12, 0x12, 0x0a, 0x04, 0x76, 0x65, 0x72, 0x62, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x76, 0x65, 0x72, 0x62, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x65, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x72, 0x65, 0x73, 0x74, 0x22, 0x3e, 0x0a, 0x0a, 0x43, 0x6f, 0x6d, 0x6d, + 0x61, 0x6e, 0x64, 0x41, 0x63, 0x6b, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x12, 0x1a, 0x0a, 0x08, + 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x73, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x73, 0x67, 0x22, 0xdf, 0x01, 0x0a, 0x0d, 0x43, 0x6c, 0x69, + 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x3a, 0x0a, 0x04, 0x74, 0x79, + 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x43, + 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, + 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1d, 0x0a, 0x07, 0x73, 0x70, 0x65, 0x61, 0x6b, 0x65, + 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x07, 0x73, 0x70, 0x65, 0x61, 0x6b, + 0x65, 0x72, 0x88, 0x01, 0x01, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x65, 0x78, 0x74, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x78, 0x74, 0x22, 0x53, 0x0a, 0x11, 0x43, 0x6c, 0x69, + 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, + 0x0a, 0x07, 0x57, 0x48, 0x49, 0x53, 0x50, 0x45, 0x52, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x4f, + 0x56, 0x45, 0x52, 0x48, 0x45, 0x41, 0x52, 0x44, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x4d, + 0x4f, 0x54, 0x45, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x47, 0x45, 0x4e, 0x45, 0x52, 0x49, 0x43, + 0x10, 0x03, 0x12, 0x0a, 0x0a, 0x06, 0x47, 0x4c, 0x4f, 0x42, 0x41, 0x4c, 0x10, 0x04, 0x42, 0x0a, + 0x0a, 0x08, 0x5f, 0x73, 0x70, 0x65, 0x61, 0x6b, 0x65, 0x72, 0x22, 0x23, 0x0a, 0x07, 0x4d, 0x61, + 0x70, 0x44, 0x61, 0x74, 0x61, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x61, 0x70, 0x44, 0x61, 0x74, 0x61, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x61, 0x70, 0x44, 0x61, 0x74, 0x61, 0x22, + 0x1a, 0x0a, 0x04, 0x50, 0x6f, 0x6e, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x77, 0x68, 0x65, 0x6e, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x77, 0x68, 0x65, 0x6e, 0x32, 0xdc, 0x02, 0x0a, 0x09, + 0x47, 0x61, 0x6d, 0x65, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x12, 0x2f, 0x0a, 0x08, 0x52, 0x65, 0x67, + 0x69, 0x73, 0x74, 0x65, 0x72, 0x12, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x75, + 0x74, 0x68, 0x49, 0x6e, 0x66, 0x6f, 0x1a, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, + 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2c, 0x0a, 0x05, 0x4c, 0x6f, + 0x67, 0x69, 0x6e, 0x12, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x75, 0x74, 0x68, + 0x49, 0x6e, 0x66, 0x6f, 0x1a, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x31, 0x0a, 0x08, 0x43, 0x6f, 0x6d, 0x6d, + 0x61, 0x6e, 0x64, 0x73, 0x12, 0x0e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, + 0x6d, 0x61, 0x6e, 0x64, 0x1a, 0x11, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6d, + 0x6d, 0x61, 0x6e, 0x64, 0x41, 0x63, 0x6b, 0x28, 0x01, 0x30, 0x01, 0x12, 0x31, 0x0a, 0x05, 0x53, + 0x74, 0x61, 0x74, 0x65, 0x12, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x1a, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x30, 0x01, 0x12, 0x36, + 0x0a, 0x08, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x12, 0x12, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x1a, 0x14, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x30, 0x01, 0x12, 0x29, 0x0a, 0x03, 0x4d, 0x61, 0x70, 0x12, 0x12, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, + 0x6f, 0x1a, 0x0e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4d, 0x61, 0x70, 0x44, 0x61, 0x74, + 0x61, 0x12, 0x27, 0x0a, 0x04, 0x50, 0x69, 0x6e, 0x67, 0x12, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x1a, 0x0b, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x6f, 0x6e, 0x67, 0x42, 0x25, 0x5a, 0x23, 0x67, 0x69, + 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x69, 0x6c, 0x6d, 0x69, 0x62, 0x6d, + 0x2f, 0x68, 0x65, 0x72, 0x6d, 0x65, 0x74, 0x69, 0x63, 0x75, 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_proto_hermeticum_proto_rawDescOnce sync.Once + file_proto_hermeticum_proto_rawDescData = file_proto_hermeticum_proto_rawDesc +) + +func file_proto_hermeticum_proto_rawDescGZIP() []byte { + file_proto_hermeticum_proto_rawDescOnce.Do(func() { + file_proto_hermeticum_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_hermeticum_proto_rawDescData) + }) + return file_proto_hermeticum_proto_rawDescData +} + +var file_proto_hermeticum_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_proto_hermeticum_proto_msgTypes = make([]protoimpl.MessageInfo, 8) +var file_proto_hermeticum_proto_goTypes = []interface{}{ + (ClientMessage_ClientMessageType)(0), // 0: proto.ClientMessage.ClientMessageType + (*AuthInfo)(nil), // 1: proto.AuthInfo + (*SessionInfo)(nil), // 2: proto.SessionInfo + (*StateUpdate)(nil), // 3: proto.StateUpdate + (*Command)(nil), // 4: proto.Command + (*CommandAck)(nil), // 5: proto.CommandAck + (*ClientMessage)(nil), // 6: proto.ClientMessage + (*MapData)(nil), // 7: proto.MapData + (*Pong)(nil), // 8: proto.Pong +} +var file_proto_hermeticum_proto_depIdxs = []int32{ + 2, // 0: proto.Command.sessionInfo:type_name -> proto.SessionInfo + 0, // 1: proto.ClientMessage.type:type_name -> proto.ClientMessage.ClientMessageType + 1, // 2: proto.GameWorld.Register:input_type -> proto.AuthInfo + 1, // 3: proto.GameWorld.Login:input_type -> proto.AuthInfo + 4, // 4: proto.GameWorld.Commands:input_type -> proto.Command + 2, // 5: proto.GameWorld.State:input_type -> proto.SessionInfo + 2, // 6: proto.GameWorld.Messages:input_type -> proto.SessionInfo + 2, // 7: proto.GameWorld.Map:input_type -> proto.SessionInfo + 2, // 8: proto.GameWorld.Ping:input_type -> proto.SessionInfo + 2, // 9: proto.GameWorld.Register:output_type -> proto.SessionInfo + 2, // 10: proto.GameWorld.Login:output_type -> proto.SessionInfo + 5, // 11: proto.GameWorld.Commands:output_type -> proto.CommandAck + 3, // 12: proto.GameWorld.State:output_type -> proto.StateUpdate + 6, // 13: proto.GameWorld.Messages:output_type -> proto.ClientMessage + 7, // 14: proto.GameWorld.Map:output_type -> proto.MapData + 8, // 15: proto.GameWorld.Ping:output_type -> proto.Pong + 9, // [9:16] is the sub-list for method output_type + 2, // [2:9] is the sub-list for method input_type + 2, // [2:2] is the sub-list for extension type_name + 2, // [2:2] is the sub-list for extension extendee + 0, // [0:2] is the sub-list for field type_name +} + +func init() { file_proto_hermeticum_proto_init() } +func file_proto_hermeticum_proto_init() { + if File_proto_hermeticum_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_proto_hermeticum_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AuthInfo); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_hermeticum_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SessionInfo); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_hermeticum_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*StateUpdate); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_hermeticum_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Command); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_hermeticum_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CommandAck); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_hermeticum_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ClientMessage); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_hermeticum_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MapData); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_hermeticum_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Pong); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + file_proto_hermeticum_proto_msgTypes[5].OneofWrappers = []interface{}{} + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_proto_hermeticum_proto_rawDesc, + NumEnums: 1, + NumMessages: 8, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_proto_hermeticum_proto_goTypes, + DependencyIndexes: file_proto_hermeticum_proto_depIdxs, + EnumInfos: file_proto_hermeticum_proto_enumTypes, + MessageInfos: file_proto_hermeticum_proto_msgTypes, + }.Build() + File_proto_hermeticum_proto = out.File + file_proto_hermeticum_proto_rawDesc = nil + file_proto_hermeticum_proto_goTypes = nil + file_proto_hermeticum_proto_depIdxs = nil +} diff --git a/proto/hermeticum.proto b/proto/hermeticum.proto index 3194c75..56f8d47 100644 --- a/proto/hermeticum.proto +++ b/proto/hermeticum.proto @@ -43,7 +43,7 @@ message StateUpdate { } message Command { - string sessionInfo = 1; + SessionInfo sessionInfo = 1; string verb = 2; string rest = 3; } diff --git a/proto/hermeticum_grpc.pb.go b/proto/hermeticum_grpc.pb.go new file mode 100644 index 0000000..1375905 --- /dev/null +++ b/proto/hermeticum_grpc.pb.go @@ -0,0 +1,408 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.2.0 +// - protoc v3.19.4 +// source: proto/hermeticum.proto + +package proto + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +// GameWorldClient is the client API for GameWorld service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type GameWorldClient interface { + Register(ctx context.Context, in *AuthInfo, opts ...grpc.CallOption) (*SessionInfo, error) + Login(ctx context.Context, in *AuthInfo, opts ...grpc.CallOption) (*SessionInfo, error) + Commands(ctx context.Context, opts ...grpc.CallOption) (GameWorld_CommandsClient, error) + State(ctx context.Context, in *SessionInfo, opts ...grpc.CallOption) (GameWorld_StateClient, error) + Messages(ctx context.Context, in *SessionInfo, opts ...grpc.CallOption) (GameWorld_MessagesClient, error) + Map(ctx context.Context, in *SessionInfo, opts ...grpc.CallOption) (*MapData, error) + Ping(ctx context.Context, in *SessionInfo, opts ...grpc.CallOption) (*Pong, error) +} + +type gameWorldClient struct { + cc grpc.ClientConnInterface +} + +func NewGameWorldClient(cc grpc.ClientConnInterface) GameWorldClient { + return &gameWorldClient{cc} +} + +func (c *gameWorldClient) Register(ctx context.Context, in *AuthInfo, opts ...grpc.CallOption) (*SessionInfo, error) { + out := new(SessionInfo) + err := c.cc.Invoke(ctx, "/proto.GameWorld/Register", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *gameWorldClient) Login(ctx context.Context, in *AuthInfo, opts ...grpc.CallOption) (*SessionInfo, error) { + out := new(SessionInfo) + err := c.cc.Invoke(ctx, "/proto.GameWorld/Login", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *gameWorldClient) Commands(ctx context.Context, opts ...grpc.CallOption) (GameWorld_CommandsClient, error) { + stream, err := c.cc.NewStream(ctx, &GameWorld_ServiceDesc.Streams[0], "/proto.GameWorld/Commands", opts...) + if err != nil { + return nil, err + } + x := &gameWorldCommandsClient{stream} + return x, nil +} + +type GameWorld_CommandsClient interface { + Send(*Command) error + Recv() (*CommandAck, error) + grpc.ClientStream +} + +type gameWorldCommandsClient struct { + grpc.ClientStream +} + +func (x *gameWorldCommandsClient) Send(m *Command) error { + return x.ClientStream.SendMsg(m) +} + +func (x *gameWorldCommandsClient) Recv() (*CommandAck, error) { + m := new(CommandAck) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *gameWorldClient) State(ctx context.Context, in *SessionInfo, opts ...grpc.CallOption) (GameWorld_StateClient, error) { + stream, err := c.cc.NewStream(ctx, &GameWorld_ServiceDesc.Streams[1], "/proto.GameWorld/State", opts...) + if err != nil { + return nil, err + } + x := &gameWorldStateClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type GameWorld_StateClient interface { + Recv() (*StateUpdate, error) + grpc.ClientStream +} + +type gameWorldStateClient struct { + grpc.ClientStream +} + +func (x *gameWorldStateClient) Recv() (*StateUpdate, error) { + m := new(StateUpdate) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *gameWorldClient) Messages(ctx context.Context, in *SessionInfo, opts ...grpc.CallOption) (GameWorld_MessagesClient, error) { + stream, err := c.cc.NewStream(ctx, &GameWorld_ServiceDesc.Streams[2], "/proto.GameWorld/Messages", opts...) + if err != nil { + return nil, err + } + x := &gameWorldMessagesClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type GameWorld_MessagesClient interface { + Recv() (*ClientMessage, error) + grpc.ClientStream +} + +type gameWorldMessagesClient struct { + grpc.ClientStream +} + +func (x *gameWorldMessagesClient) Recv() (*ClientMessage, error) { + m := new(ClientMessage) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *gameWorldClient) Map(ctx context.Context, in *SessionInfo, opts ...grpc.CallOption) (*MapData, error) { + out := new(MapData) + err := c.cc.Invoke(ctx, "/proto.GameWorld/Map", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *gameWorldClient) Ping(ctx context.Context, in *SessionInfo, opts ...grpc.CallOption) (*Pong, error) { + out := new(Pong) + err := c.cc.Invoke(ctx, "/proto.GameWorld/Ping", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// GameWorldServer is the server API for GameWorld service. +// All implementations must embed UnimplementedGameWorldServer +// for forward compatibility +type GameWorldServer interface { + Register(context.Context, *AuthInfo) (*SessionInfo, error) + Login(context.Context, *AuthInfo) (*SessionInfo, error) + Commands(GameWorld_CommandsServer) error + State(*SessionInfo, GameWorld_StateServer) error + Messages(*SessionInfo, GameWorld_MessagesServer) error + Map(context.Context, *SessionInfo) (*MapData, error) + Ping(context.Context, *SessionInfo) (*Pong, error) + mustEmbedUnimplementedGameWorldServer() +} + +// UnimplementedGameWorldServer must be embedded to have forward compatible implementations. +type UnimplementedGameWorldServer struct { +} + +func (UnimplementedGameWorldServer) Register(context.Context, *AuthInfo) (*SessionInfo, error) { + return nil, status.Errorf(codes.Unimplemented, "method Register not implemented") +} +func (UnimplementedGameWorldServer) Login(context.Context, *AuthInfo) (*SessionInfo, error) { + return nil, status.Errorf(codes.Unimplemented, "method Login not implemented") +} +func (UnimplementedGameWorldServer) Commands(GameWorld_CommandsServer) error { + return status.Errorf(codes.Unimplemented, "method Commands not implemented") +} +func (UnimplementedGameWorldServer) State(*SessionInfo, GameWorld_StateServer) error { + return status.Errorf(codes.Unimplemented, "method State not implemented") +} +func (UnimplementedGameWorldServer) Messages(*SessionInfo, GameWorld_MessagesServer) error { + return status.Errorf(codes.Unimplemented, "method Messages not implemented") +} +func (UnimplementedGameWorldServer) Map(context.Context, *SessionInfo) (*MapData, error) { + return nil, status.Errorf(codes.Unimplemented, "method Map not implemented") +} +func (UnimplementedGameWorldServer) Ping(context.Context, *SessionInfo) (*Pong, error) { + return nil, status.Errorf(codes.Unimplemented, "method Ping not implemented") +} +func (UnimplementedGameWorldServer) mustEmbedUnimplementedGameWorldServer() {} + +// UnsafeGameWorldServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to GameWorldServer will +// result in compilation errors. +type UnsafeGameWorldServer interface { + mustEmbedUnimplementedGameWorldServer() +} + +func RegisterGameWorldServer(s grpc.ServiceRegistrar, srv GameWorldServer) { + s.RegisterService(&GameWorld_ServiceDesc, srv) +} + +func _GameWorld_Register_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(AuthInfo) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GameWorldServer).Register(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/proto.GameWorld/Register", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GameWorldServer).Register(ctx, req.(*AuthInfo)) + } + return interceptor(ctx, in, info, handler) +} + +func _GameWorld_Login_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(AuthInfo) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GameWorldServer).Login(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/proto.GameWorld/Login", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GameWorldServer).Login(ctx, req.(*AuthInfo)) + } + return interceptor(ctx, in, info, handler) +} + +func _GameWorld_Commands_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(GameWorldServer).Commands(&gameWorldCommandsServer{stream}) +} + +type GameWorld_CommandsServer interface { + Send(*CommandAck) error + Recv() (*Command, error) + grpc.ServerStream +} + +type gameWorldCommandsServer struct { + grpc.ServerStream +} + +func (x *gameWorldCommandsServer) Send(m *CommandAck) error { + return x.ServerStream.SendMsg(m) +} + +func (x *gameWorldCommandsServer) Recv() (*Command, error) { + m := new(Command) + if err := x.ServerStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func _GameWorld_State_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(SessionInfo) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(GameWorldServer).State(m, &gameWorldStateServer{stream}) +} + +type GameWorld_StateServer interface { + Send(*StateUpdate) error + grpc.ServerStream +} + +type gameWorldStateServer struct { + grpc.ServerStream +} + +func (x *gameWorldStateServer) Send(m *StateUpdate) error { + return x.ServerStream.SendMsg(m) +} + +func _GameWorld_Messages_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(SessionInfo) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(GameWorldServer).Messages(m, &gameWorldMessagesServer{stream}) +} + +type GameWorld_MessagesServer interface { + Send(*ClientMessage) error + grpc.ServerStream +} + +type gameWorldMessagesServer struct { + grpc.ServerStream +} + +func (x *gameWorldMessagesServer) Send(m *ClientMessage) error { + return x.ServerStream.SendMsg(m) +} + +func _GameWorld_Map_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SessionInfo) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GameWorldServer).Map(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/proto.GameWorld/Map", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GameWorldServer).Map(ctx, req.(*SessionInfo)) + } + return interceptor(ctx, in, info, handler) +} + +func _GameWorld_Ping_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SessionInfo) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GameWorldServer).Ping(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/proto.GameWorld/Ping", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GameWorldServer).Ping(ctx, req.(*SessionInfo)) + } + return interceptor(ctx, in, info, handler) +} + +// GameWorld_ServiceDesc is the grpc.ServiceDesc for GameWorld service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var GameWorld_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "proto.GameWorld", + HandlerType: (*GameWorldServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Register", + Handler: _GameWorld_Register_Handler, + }, + { + MethodName: "Login", + Handler: _GameWorld_Login_Handler, + }, + { + MethodName: "Map", + Handler: _GameWorld_Map_Handler, + }, + { + MethodName: "Ping", + Handler: _GameWorld_Ping_Handler, + }, + }, + Streams: []grpc.StreamDesc{ + { + StreamName: "Commands", + Handler: _GameWorld_Commands_Handler, + ServerStreams: true, + ClientStreams: true, + }, + { + StreamName: "State", + Handler: _GameWorld_State_Handler, + ServerStreams: true, + }, + { + StreamName: "Messages", + Handler: _GameWorld_Messages_Handler, + ServerStreams: true, + }, + }, + Metadata: "proto/hermeticum.proto", +} diff --git a/server/cmd/main.go b/server/cmd/main.go index 680481b..33987ce 100644 --- a/server/cmd/main.go +++ b/server/cmd/main.go @@ -4,6 +4,7 @@ import ( "context" "flag" "fmt" + "io" "log" "net" "time" @@ -62,6 +63,27 @@ func newServer() *gameWorldServer { return s } +func (s *gameWorldServer) Commands(stream proto.GameWorld_CommandsServer) error { + for { + cmd, err := stream.Recv() + if err == io.EOF { + // TODO end session + return nil + } + if err != nil { + return err + } + fmt.Printf("DBG %#v\n", cmd) + + // TODO FOR NOW, just find the session's associated message stream and do an echo (which requires doing a session storage solution first) + + // TODO find the user who ran action via SessionInfo + // TODO get area of effect, which should include the sender + // TODO dispatch the command to each affected object + } + return nil +} + func (s *gameWorldServer) Ping(ctx context.Context, _ *proto.SessionInfo) (*proto.Pong, error) { pong := &proto.Pong{ When: "TODO",