From 9610fc53227ca17aa5af9485bad683b8e9365849 Mon Sep 17 00:00:00 2001 From: iegod Date: Wed, 11 Dec 2024 07:41:21 -0500 Subject: [PATCH] Messages now using envelopes. --- client/client/client.go | 87 ++++-------- client/game/game.go | 91 +++++-------- client/pb/clientdata.pb.go | 264 ++++++++++++++++++++++++++++++++++--- server/pb/clientdata.pb.go | 264 ++++++++++++++++++++++++++++++++++--- server/server/server.go | 178 +++++++++---------------- 5 files changed, 617 insertions(+), 267 deletions(-) diff --git a/client/client/client.go b/client/client/client.go index 9918186..8ee4bea 100644 --- a/client/client/client.go +++ b/client/client/client.go @@ -7,7 +7,7 @@ import ( "io" "net" - "github.com/golang/protobuf/proto" + "google.golang.org/protobuf/proto" ) type Client struct { @@ -37,7 +37,7 @@ func (c *Client) SendProtoData(coords *pb.ClientCoordinates) { data, err := proto.Marshal(coords) if err != nil { - fmt.Println("We fucked the serialization. ", err) + fmt.Println("Couldn't serialize. ", err) return } @@ -47,71 +47,23 @@ func (c *Client) SendProtoData(coords *pb.ClientCoordinates) { binary.BigEndian.PutUint32(buf[:4], length) copy(buf[4:], data) + c.SendBuffer(c.conn, buf) +} + +func (c *Client) SendBuffer(conn net.Conn, buf []byte) { // Ensure complete write totalWritten := 0 for totalWritten < len(buf) { - n, err := c.conn.Write(buf[totalWritten:]) + n, err := conn.Write(buf[totalWritten:]) if err != nil { fmt.Printf("Error writing to connection: %v\n", err) return } totalWritten += n } - } -func (c *Client) SendData(msg string) { - // Send input to the server - //fmt.Fprintf(c.conn, msg) - _, err := c.conn.Write([]byte(msg)) - if err != nil { - fmt.Println("Error writing to connection:", err) - return - } -} - -func (c *Client) GetIdentity() int { - lengthBuf := make([]byte, 4) - _, err := io.ReadFull(c.conn, lengthBuf) - if err != nil { - fmt.Println("failed to read length prefix: ", err) - return 0 - } - - length := binary.BigEndian.Uint32(lengthBuf) - - data := make([]byte, length) - _, err = io.ReadFull(c.conn, data) - if err != nil { - fmt.Println("failed to read data: ", err) - return 0 - } - - var identity pb.ClientIdentity - err = proto.Unmarshal(data, &identity) - if err != nil { - fmt.Println("Error deserializing: ", err) - return 0 - } - - return int(identity.Id) - -} - -func (c *Client) ReadData(callback func(*pb.AllClients)) { - - /* - for { - message, err := bufio.NewReader(c.conn).ReadString('\n') - if err != nil { - fmt.Println("Error reading from server:", err) - return - } - - if callback != nil { - callback(message) - } - }*/ +func (c *Client) ReadData(callback func(*pb.ServerEnvelope)) { for { lengthBuf := make([]byte, 4) @@ -130,15 +82,15 @@ func (c *Client) ReadData(callback func(*pb.AllClients)) { return } - var allclients pb.AllClients - err = proto.Unmarshal(data, &allclients) + var envelope pb.ServerEnvelope + err = proto.Unmarshal(data, &envelope) if err != nil { - fmt.Println("Error deserializing: ", err) + fmt.Println("Couldn't deserialize envelope : ", err) return } if callback != nil { - callback(&allclients) + callback(&envelope) } } @@ -157,3 +109,18 @@ func (c *Client) Disconnect() { c.conn.Close() c.connected = false } + +func (c *Client) SendMessage(msg *pb.ClientEnvelope) { + data, err := proto.Marshal(msg) + if err != nil { + fmt.Println("error serializing: ", err) + return + } + + length := len(data) + buf := make([]byte, length+4) + binary.BigEndian.PutUint32(buf[:4], uint32(length)) + copy(buf[4:], data) + + c.SendBuffer(c.conn, buf) +} diff --git a/client/game/game.go b/client/game/game.go index 81b30e1..40f214c 100644 --- a/client/game/game.go +++ b/client/game/game.go @@ -6,6 +6,7 @@ import ( "client/fonts" "client/gamedata" "client/pb" + "fmt" "maps" "sync" "time" @@ -59,7 +60,7 @@ func NewGame() *Game { } g.clients = make(map[string]ClientData) - g.gameId = g.gameclient.GetIdentity() + //g.gameId = g.gameclient.GetIdentity() go g.gameclient.ReadData(g.HandleServerData) return g } @@ -85,7 +86,15 @@ func (g *Game) Update() error { }, } - g.gameclient.SendProtoData(cd) + envelope := &pb.ClientEnvelope{ + Payload: &pb.ClientEnvelope_Coordinates{ + Coordinates: cd, + }, + } + + g.gameclient.SendMessage(envelope) + + //g.gameclient.SendProtoData(cd) /* cd := *client.ClientData{ Name: g.name, @@ -144,66 +153,34 @@ func (g *Game) Layout(outsideWidth, outsideHeight int) (screenwidth, screenheigh return screenWidth, screenHeight } -func (g *Game) HandleServerData(allclients *pb.AllClients) { +func (g *Game) HandleServerData(envelope *pb.ServerEnvelope) { - for _, client := range allclients.Clients { - //fmt.Println(client.Coordinates.X) + switch payload := envelope.Payload.(type) { + case *pb.ServerEnvelope_Broadcast: + //fmt.Println("Here comes the broadcast!") - //localaddr := g.gameclient.GetLocalAddr() - if client.Id != int32(g.gameId) { - update := ClientData{ - Address: client.Address, - Name: client.Name, - Position: gamedata.Coordinates{ - X: client.Coordinates.X, - Y: client.Coordinates.Y, - }, - } - - g.mu.Lock() - g.clients[update.Address] = update - g.mu.Unlock() - } - } - - //log.Println(data) - /* - - raw := data[1 : len(data)-1] - clientinfo := strings.Split(raw, ";") - for _, info := range clientinfo { - subdata := strings.Split(info, ",") - - if len(subdata) == 4 { - - if g.gameclient.GetLocalAddr() != subdata[0] { - - x, err := strconv.Atoi(subdata[2]) - if err != nil { - x = 0 - } - - y, err := strconv.Atoi(subdata[3]) - if err != nil { - y = 0 - } - - update := ClientData{ - Address: subdata[0], - Name: subdata[1], - Position: gamedata.Coordinates{ - X: float64(x), - Y: float64(y), - }, - } - - g.mu.Lock() - g.clients[update.Address] = update - g.mu.Unlock() + for _, client := range payload.Broadcast.Clients { + if client.Id != int32(g.gameId) { + update := ClientData{ + Id: int(client.Id), + Address: client.Address, + Name: client.Name, + Position: gamedata.Coordinates{ + X: client.Coordinates.X, + Y: client.Coordinates.Y, + }, } + + g.mu.Lock() + g.clients[update.Address] = update + g.mu.Unlock() } } - */ + + case *pb.ServerEnvelope_Identity: + fmt.Println("Server is trying to give us our id.") + g.gameId = int(payload.Identity.Id) + } } func (g *Game) CleanupClients() { diff --git a/client/pb/clientdata.pb.go b/client/pb/clientdata.pb.go index c7abd06..0dadcb9 100644 --- a/client/pb/clientdata.pb.go +++ b/client/pb/clientdata.pb.go @@ -20,6 +20,55 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) +type MessageType int32 + +const ( + MessageType_MSG_TYPE_BROADCAST MessageType = 0 + MessageType_MSG_TYPE_IDENTITY MessageType = 1 + MessageType_MSG_TYPE_COORDINATES MessageType = 2 +) + +// Enum value maps for MessageType. +var ( + MessageType_name = map[int32]string{ + 0: "MSG_TYPE_BROADCAST", + 1: "MSG_TYPE_IDENTITY", + 2: "MSG_TYPE_COORDINATES", + } + MessageType_value = map[string]int32{ + "MSG_TYPE_BROADCAST": 0, + "MSG_TYPE_IDENTITY": 1, + "MSG_TYPE_COORDINATES": 2, + } +) + +func (x MessageType) Enum() *MessageType { + p := new(MessageType) + *p = x + return p +} + +func (x MessageType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (MessageType) Descriptor() protoreflect.EnumDescriptor { + return file_clientdata_proto_enumTypes[0].Descriptor() +} + +func (MessageType) Type() protoreflect.EnumType { + return &file_clientdata_proto_enumTypes[0] +} + +func (x MessageType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use MessageType.Descriptor instead. +func (MessageType) EnumDescriptor() ([]byte, []int) { + return file_clientdata_proto_rawDescGZIP(), []int{0} +} + type Coordinates struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -285,6 +334,150 @@ func (x *ClientIdentity) GetId() int32 { return 0 } +type ClientEnvelope struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Types that are assignable to Payload: + // + // *ClientEnvelope_Coordinates + Payload isClientEnvelope_Payload `protobuf_oneof:"Payload"` +} + +func (x *ClientEnvelope) Reset() { + *x = ClientEnvelope{} + mi := &file_clientdata_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ClientEnvelope) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ClientEnvelope) ProtoMessage() {} + +func (x *ClientEnvelope) ProtoReflect() protoreflect.Message { + mi := &file_clientdata_proto_msgTypes[5] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ClientEnvelope.ProtoReflect.Descriptor instead. +func (*ClientEnvelope) Descriptor() ([]byte, []int) { + return file_clientdata_proto_rawDescGZIP(), []int{5} +} + +func (m *ClientEnvelope) GetPayload() isClientEnvelope_Payload { + if m != nil { + return m.Payload + } + return nil +} + +func (x *ClientEnvelope) GetCoordinates() *ClientCoordinates { + if x, ok := x.GetPayload().(*ClientEnvelope_Coordinates); ok { + return x.Coordinates + } + return nil +} + +type isClientEnvelope_Payload interface { + isClientEnvelope_Payload() +} + +type ClientEnvelope_Coordinates struct { + Coordinates *ClientCoordinates `protobuf:"bytes,1,opt,name=coordinates,proto3,oneof"` +} + +func (*ClientEnvelope_Coordinates) isClientEnvelope_Payload() {} + +type ServerEnvelope struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Types that are assignable to Payload: + // + // *ServerEnvelope_Identity + // *ServerEnvelope_Broadcast + Payload isServerEnvelope_Payload `protobuf_oneof:"Payload"` +} + +func (x *ServerEnvelope) Reset() { + *x = ServerEnvelope{} + mi := &file_clientdata_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ServerEnvelope) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ServerEnvelope) ProtoMessage() {} + +func (x *ServerEnvelope) ProtoReflect() protoreflect.Message { + mi := &file_clientdata_proto_msgTypes[6] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ServerEnvelope.ProtoReflect.Descriptor instead. +func (*ServerEnvelope) Descriptor() ([]byte, []int) { + return file_clientdata_proto_rawDescGZIP(), []int{6} +} + +func (m *ServerEnvelope) GetPayload() isServerEnvelope_Payload { + if m != nil { + return m.Payload + } + return nil +} + +func (x *ServerEnvelope) GetIdentity() *ClientIdentity { + if x, ok := x.GetPayload().(*ServerEnvelope_Identity); ok { + return x.Identity + } + return nil +} + +func (x *ServerEnvelope) GetBroadcast() *AllClients { + if x, ok := x.GetPayload().(*ServerEnvelope_Broadcast); ok { + return x.Broadcast + } + return nil +} + +type isServerEnvelope_Payload interface { + isServerEnvelope_Payload() +} + +type ServerEnvelope_Identity struct { + Identity *ClientIdentity `protobuf:"bytes,1,opt,name=identity,proto3,oneof"` +} + +type ServerEnvelope_Broadcast struct { + Broadcast *AllClients `protobuf:"bytes,2,opt,name=broadcast,proto3,oneof"` +} + +func (*ServerEnvelope_Identity) isServerEnvelope_Payload() {} + +func (*ServerEnvelope_Broadcast) isServerEnvelope_Payload() {} + var File_clientdata_proto protoreflect.FileDescriptor var file_clientdata_proto_rawDesc = []byte{ @@ -311,8 +504,28 @@ var file_clientdata_proto_rawDesc = []byte{ 0x0b, 0x32, 0x10, 0x2e, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x44, 0x61, 0x74, 0x61, 0x52, 0x07, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x20, 0x0a, 0x0e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x0e, - 0x0a, 0x02, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x49, 0x64, 0x42, 0x06, - 0x5a, 0x04, 0x2e, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x0a, 0x02, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x49, 0x64, 0x22, 0x58, + 0x0a, 0x0e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, + 0x12, 0x3b, 0x0a, 0x0b, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x43, 0x6c, 0x69, + 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x48, 0x00, + 0x52, 0x0b, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x42, 0x09, 0x0a, + 0x07, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0x81, 0x01, 0x0a, 0x0e, 0x53, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x12, 0x32, 0x0a, 0x08, 0x69, + 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, + 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, + 0x69, 0x74, 0x79, 0x48, 0x00, 0x52, 0x08, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, + 0x30, 0x0a, 0x09, 0x62, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x41, 0x6c, 0x6c, 0x43, 0x6c, 0x69, + 0x65, 0x6e, 0x74, 0x73, 0x48, 0x00, 0x52, 0x09, 0x62, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, + 0x74, 0x42, 0x09, 0x0a, 0x07, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x2a, 0x56, 0x0a, 0x0b, + 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x12, 0x4d, + 0x53, 0x47, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x42, 0x52, 0x4f, 0x41, 0x44, 0x43, 0x41, 0x53, + 0x54, 0x10, 0x00, 0x12, 0x15, 0x0a, 0x11, 0x4d, 0x53, 0x47, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, + 0x49, 0x44, 0x45, 0x4e, 0x54, 0x49, 0x54, 0x59, 0x10, 0x01, 0x12, 0x18, 0x0a, 0x14, 0x4d, 0x53, + 0x47, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x49, 0x4e, 0x41, 0x54, + 0x45, 0x53, 0x10, 0x02, 0x42, 0x06, 0x5a, 0x04, 0x2e, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -327,23 +540,30 @@ func file_clientdata_proto_rawDescGZIP() []byte { return file_clientdata_proto_rawDescData } -var file_clientdata_proto_msgTypes = make([]protoimpl.MessageInfo, 5) +var file_clientdata_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_clientdata_proto_msgTypes = make([]protoimpl.MessageInfo, 7) var file_clientdata_proto_goTypes = []any{ - (*Coordinates)(nil), // 0: main.Coordinates - (*ClientData)(nil), // 1: main.ClientData - (*ClientCoordinates)(nil), // 2: main.ClientCoordinates - (*AllClients)(nil), // 3: main.AllClients - (*ClientIdentity)(nil), // 4: main.ClientIdentity + (MessageType)(0), // 0: main.MessageType + (*Coordinates)(nil), // 1: main.Coordinates + (*ClientData)(nil), // 2: main.ClientData + (*ClientCoordinates)(nil), // 3: main.ClientCoordinates + (*AllClients)(nil), // 4: main.AllClients + (*ClientIdentity)(nil), // 5: main.ClientIdentity + (*ClientEnvelope)(nil), // 6: main.ClientEnvelope + (*ServerEnvelope)(nil), // 7: main.ServerEnvelope } var file_clientdata_proto_depIdxs = []int32{ - 0, // 0: main.ClientData.coordinates:type_name -> main.Coordinates - 0, // 1: main.ClientCoordinates.coordinates:type_name -> main.Coordinates - 1, // 2: main.AllClients.Clients:type_name -> main.ClientData - 3, // [3:3] is the sub-list for method output_type - 3, // [3:3] is the sub-list for method input_type - 3, // [3:3] is the sub-list for extension type_name - 3, // [3:3] is the sub-list for extension extendee - 0, // [0:3] is the sub-list for field type_name + 1, // 0: main.ClientData.coordinates:type_name -> main.Coordinates + 1, // 1: main.ClientCoordinates.coordinates:type_name -> main.Coordinates + 2, // 2: main.AllClients.Clients:type_name -> main.ClientData + 3, // 3: main.ClientEnvelope.coordinates:type_name -> main.ClientCoordinates + 5, // 4: main.ServerEnvelope.identity:type_name -> main.ClientIdentity + 4, // 5: main.ServerEnvelope.broadcast:type_name -> main.AllClients + 6, // [6:6] is the sub-list for method output_type + 6, // [6:6] is the sub-list for method input_type + 6, // [6:6] is the sub-list for extension type_name + 6, // [6:6] is the sub-list for extension extendee + 0, // [0:6] is the sub-list for field type_name } func init() { file_clientdata_proto_init() } @@ -351,18 +571,26 @@ func file_clientdata_proto_init() { if File_clientdata_proto != nil { return } + file_clientdata_proto_msgTypes[5].OneofWrappers = []any{ + (*ClientEnvelope_Coordinates)(nil), + } + file_clientdata_proto_msgTypes[6].OneofWrappers = []any{ + (*ServerEnvelope_Identity)(nil), + (*ServerEnvelope_Broadcast)(nil), + } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_clientdata_proto_rawDesc, - NumEnums: 0, - NumMessages: 5, + NumEnums: 1, + NumMessages: 7, NumExtensions: 0, NumServices: 0, }, GoTypes: file_clientdata_proto_goTypes, DependencyIndexes: file_clientdata_proto_depIdxs, + EnumInfos: file_clientdata_proto_enumTypes, MessageInfos: file_clientdata_proto_msgTypes, }.Build() File_clientdata_proto = out.File diff --git a/server/pb/clientdata.pb.go b/server/pb/clientdata.pb.go index c7abd06..0dadcb9 100644 --- a/server/pb/clientdata.pb.go +++ b/server/pb/clientdata.pb.go @@ -20,6 +20,55 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) +type MessageType int32 + +const ( + MessageType_MSG_TYPE_BROADCAST MessageType = 0 + MessageType_MSG_TYPE_IDENTITY MessageType = 1 + MessageType_MSG_TYPE_COORDINATES MessageType = 2 +) + +// Enum value maps for MessageType. +var ( + MessageType_name = map[int32]string{ + 0: "MSG_TYPE_BROADCAST", + 1: "MSG_TYPE_IDENTITY", + 2: "MSG_TYPE_COORDINATES", + } + MessageType_value = map[string]int32{ + "MSG_TYPE_BROADCAST": 0, + "MSG_TYPE_IDENTITY": 1, + "MSG_TYPE_COORDINATES": 2, + } +) + +func (x MessageType) Enum() *MessageType { + p := new(MessageType) + *p = x + return p +} + +func (x MessageType) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (MessageType) Descriptor() protoreflect.EnumDescriptor { + return file_clientdata_proto_enumTypes[0].Descriptor() +} + +func (MessageType) Type() protoreflect.EnumType { + return &file_clientdata_proto_enumTypes[0] +} + +func (x MessageType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use MessageType.Descriptor instead. +func (MessageType) EnumDescriptor() ([]byte, []int) { + return file_clientdata_proto_rawDescGZIP(), []int{0} +} + type Coordinates struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -285,6 +334,150 @@ func (x *ClientIdentity) GetId() int32 { return 0 } +type ClientEnvelope struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Types that are assignable to Payload: + // + // *ClientEnvelope_Coordinates + Payload isClientEnvelope_Payload `protobuf_oneof:"Payload"` +} + +func (x *ClientEnvelope) Reset() { + *x = ClientEnvelope{} + mi := &file_clientdata_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ClientEnvelope) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ClientEnvelope) ProtoMessage() {} + +func (x *ClientEnvelope) ProtoReflect() protoreflect.Message { + mi := &file_clientdata_proto_msgTypes[5] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ClientEnvelope.ProtoReflect.Descriptor instead. +func (*ClientEnvelope) Descriptor() ([]byte, []int) { + return file_clientdata_proto_rawDescGZIP(), []int{5} +} + +func (m *ClientEnvelope) GetPayload() isClientEnvelope_Payload { + if m != nil { + return m.Payload + } + return nil +} + +func (x *ClientEnvelope) GetCoordinates() *ClientCoordinates { + if x, ok := x.GetPayload().(*ClientEnvelope_Coordinates); ok { + return x.Coordinates + } + return nil +} + +type isClientEnvelope_Payload interface { + isClientEnvelope_Payload() +} + +type ClientEnvelope_Coordinates struct { + Coordinates *ClientCoordinates `protobuf:"bytes,1,opt,name=coordinates,proto3,oneof"` +} + +func (*ClientEnvelope_Coordinates) isClientEnvelope_Payload() {} + +type ServerEnvelope struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Types that are assignable to Payload: + // + // *ServerEnvelope_Identity + // *ServerEnvelope_Broadcast + Payload isServerEnvelope_Payload `protobuf_oneof:"Payload"` +} + +func (x *ServerEnvelope) Reset() { + *x = ServerEnvelope{} + mi := &file_clientdata_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ServerEnvelope) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ServerEnvelope) ProtoMessage() {} + +func (x *ServerEnvelope) ProtoReflect() protoreflect.Message { + mi := &file_clientdata_proto_msgTypes[6] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ServerEnvelope.ProtoReflect.Descriptor instead. +func (*ServerEnvelope) Descriptor() ([]byte, []int) { + return file_clientdata_proto_rawDescGZIP(), []int{6} +} + +func (m *ServerEnvelope) GetPayload() isServerEnvelope_Payload { + if m != nil { + return m.Payload + } + return nil +} + +func (x *ServerEnvelope) GetIdentity() *ClientIdentity { + if x, ok := x.GetPayload().(*ServerEnvelope_Identity); ok { + return x.Identity + } + return nil +} + +func (x *ServerEnvelope) GetBroadcast() *AllClients { + if x, ok := x.GetPayload().(*ServerEnvelope_Broadcast); ok { + return x.Broadcast + } + return nil +} + +type isServerEnvelope_Payload interface { + isServerEnvelope_Payload() +} + +type ServerEnvelope_Identity struct { + Identity *ClientIdentity `protobuf:"bytes,1,opt,name=identity,proto3,oneof"` +} + +type ServerEnvelope_Broadcast struct { + Broadcast *AllClients `protobuf:"bytes,2,opt,name=broadcast,proto3,oneof"` +} + +func (*ServerEnvelope_Identity) isServerEnvelope_Payload() {} + +func (*ServerEnvelope_Broadcast) isServerEnvelope_Payload() {} + var File_clientdata_proto protoreflect.FileDescriptor var file_clientdata_proto_rawDesc = []byte{ @@ -311,8 +504,28 @@ var file_clientdata_proto_rawDesc = []byte{ 0x0b, 0x32, 0x10, 0x2e, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x44, 0x61, 0x74, 0x61, 0x52, 0x07, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x20, 0x0a, 0x0e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x0e, - 0x0a, 0x02, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x49, 0x64, 0x42, 0x06, - 0x5a, 0x04, 0x2e, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x0a, 0x02, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x49, 0x64, 0x22, 0x58, + 0x0a, 0x0e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, + 0x12, 0x3b, 0x0a, 0x0b, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x43, 0x6c, 0x69, + 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x48, 0x00, + 0x52, 0x0b, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x42, 0x09, 0x0a, + 0x07, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0x81, 0x01, 0x0a, 0x0e, 0x53, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x12, 0x32, 0x0a, 0x08, 0x69, + 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, + 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, + 0x69, 0x74, 0x79, 0x48, 0x00, 0x52, 0x08, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, + 0x30, 0x0a, 0x09, 0x62, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x41, 0x6c, 0x6c, 0x43, 0x6c, 0x69, + 0x65, 0x6e, 0x74, 0x73, 0x48, 0x00, 0x52, 0x09, 0x62, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, + 0x74, 0x42, 0x09, 0x0a, 0x07, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x2a, 0x56, 0x0a, 0x0b, + 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x12, 0x4d, + 0x53, 0x47, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x42, 0x52, 0x4f, 0x41, 0x44, 0x43, 0x41, 0x53, + 0x54, 0x10, 0x00, 0x12, 0x15, 0x0a, 0x11, 0x4d, 0x53, 0x47, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, + 0x49, 0x44, 0x45, 0x4e, 0x54, 0x49, 0x54, 0x59, 0x10, 0x01, 0x12, 0x18, 0x0a, 0x14, 0x4d, 0x53, + 0x47, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x49, 0x4e, 0x41, 0x54, + 0x45, 0x53, 0x10, 0x02, 0x42, 0x06, 0x5a, 0x04, 0x2e, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -327,23 +540,30 @@ func file_clientdata_proto_rawDescGZIP() []byte { return file_clientdata_proto_rawDescData } -var file_clientdata_proto_msgTypes = make([]protoimpl.MessageInfo, 5) +var file_clientdata_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_clientdata_proto_msgTypes = make([]protoimpl.MessageInfo, 7) var file_clientdata_proto_goTypes = []any{ - (*Coordinates)(nil), // 0: main.Coordinates - (*ClientData)(nil), // 1: main.ClientData - (*ClientCoordinates)(nil), // 2: main.ClientCoordinates - (*AllClients)(nil), // 3: main.AllClients - (*ClientIdentity)(nil), // 4: main.ClientIdentity + (MessageType)(0), // 0: main.MessageType + (*Coordinates)(nil), // 1: main.Coordinates + (*ClientData)(nil), // 2: main.ClientData + (*ClientCoordinates)(nil), // 3: main.ClientCoordinates + (*AllClients)(nil), // 4: main.AllClients + (*ClientIdentity)(nil), // 5: main.ClientIdentity + (*ClientEnvelope)(nil), // 6: main.ClientEnvelope + (*ServerEnvelope)(nil), // 7: main.ServerEnvelope } var file_clientdata_proto_depIdxs = []int32{ - 0, // 0: main.ClientData.coordinates:type_name -> main.Coordinates - 0, // 1: main.ClientCoordinates.coordinates:type_name -> main.Coordinates - 1, // 2: main.AllClients.Clients:type_name -> main.ClientData - 3, // [3:3] is the sub-list for method output_type - 3, // [3:3] is the sub-list for method input_type - 3, // [3:3] is the sub-list for extension type_name - 3, // [3:3] is the sub-list for extension extendee - 0, // [0:3] is the sub-list for field type_name + 1, // 0: main.ClientData.coordinates:type_name -> main.Coordinates + 1, // 1: main.ClientCoordinates.coordinates:type_name -> main.Coordinates + 2, // 2: main.AllClients.Clients:type_name -> main.ClientData + 3, // 3: main.ClientEnvelope.coordinates:type_name -> main.ClientCoordinates + 5, // 4: main.ServerEnvelope.identity:type_name -> main.ClientIdentity + 4, // 5: main.ServerEnvelope.broadcast:type_name -> main.AllClients + 6, // [6:6] is the sub-list for method output_type + 6, // [6:6] is the sub-list for method input_type + 6, // [6:6] is the sub-list for extension type_name + 6, // [6:6] is the sub-list for extension extendee + 0, // [0:6] is the sub-list for field type_name } func init() { file_clientdata_proto_init() } @@ -351,18 +571,26 @@ func file_clientdata_proto_init() { if File_clientdata_proto != nil { return } + file_clientdata_proto_msgTypes[5].OneofWrappers = []any{ + (*ClientEnvelope_Coordinates)(nil), + } + file_clientdata_proto_msgTypes[6].OneofWrappers = []any{ + (*ServerEnvelope_Identity)(nil), + (*ServerEnvelope_Broadcast)(nil), + } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_clientdata_proto_rawDesc, - NumEnums: 0, - NumMessages: 5, + NumEnums: 1, + NumMessages: 7, NumExtensions: 0, NumServices: 0, }, GoTypes: file_clientdata_proto_goTypes, DependencyIndexes: file_clientdata_proto_depIdxs, + EnumInfos: file_clientdata_proto_enumTypes, MessageInfos: file_clientdata_proto_msgTypes, }.Build() File_clientdata_proto = out.File diff --git a/server/server/server.go b/server/server/server.go index 0641a7f..79ad6c6 100644 --- a/server/server/server.go +++ b/server/server/server.go @@ -73,40 +73,7 @@ func (s *Server) HandleClient(conn net.Conn, id int) { }() //before we add the client to the clientlist, let's send them their unique id first - identifier := &pb.ClientIdentity{ - Id: int32(id), - } - - data, err := proto.Marshal(identifier) - if err != nil { - fmt.Println("serialization of id failed: ", err) - return - } - - length := len(data) - buf := make([]byte, 4+length) - binary.BigEndian.PutUint32(buf[:4], uint32(length)) - copy(buf[4:], data) - - totalWritten := 0 - for totalWritten < len(buf) { - n, err := conn.Write(buf[totalWritten:]) - if err != nil { - fmt.Println("Error assigning id: ", err) - return - } - totalWritten += n - } - - //create the outline of client data, so far we know only - //their addr, then add it to our client list - clientdata := ClientData{ - Address: conn.RemoteAddr().String(), - } - s.mu.Lock() - //s.clientlist[conn] = conn.RemoteAddr().String() - s.clientlist[conn] = clientdata - s.mu.Unlock() + s.SendClientIdentity(conn, id) for { // Read data from the client @@ -129,63 +96,28 @@ func (s *Server) HandleClient(conn net.Conn, id int) { return } - // Deserialize the protobuf data - var coords pb.ClientCoordinates - err = proto.Unmarshal(data, &coords) + var clientenvelope pb.ClientEnvelope + err = proto.Unmarshal(data, &clientenvelope) if err != nil { fmt.Println("failed to deserialize: ", err) return } - //fmt.Println(coords.Name) + switch payload := clientenvelope.Payload.(type) { + case *pb.ClientEnvelope_Coordinates: + cd := ClientData{ + Id: id, + Address: conn.RemoteAddr().String(), + Name: payload.Coordinates.Name, + Position: gamedata.Coordinates{X: payload.Coordinates.Coordinates.X, Y: payload.Coordinates.Coordinates.Y}, + } - cd := ClientData{ - Id: id, - Address: conn.RemoteAddr().String(), - Name: coords.Name, - Position: gamedata.Coordinates{X: coords.Coordinates.X, Y: coords.Coordinates.Y}, + //update the client list + s.mu.Lock() + s.clientlist[conn] = cd + s.mu.Unlock() } - s.mu.Lock() - s.clientlist[conn] = cd - s.mu.Unlock() - - /* - data, err := bufio.NewReader(conn).ReadString('\n') - if err != nil { - return // Exit the Goroutine when the client disconnects - } - */ - /* - fmt.Println("Received:", string(data)) - data = data[:len(data)-1] - //s.BroadcastMessage(conn, string(data)) - - //now we update our information with their data: - serverinfo := strings.Split(string(data), ",") - if len(serverinfo) == 3 { - - x, err := strconv.Atoi(serverinfo[1]) - if err != nil { - x = 0 - } - - y, err := strconv.Atoi(serverinfo[2]) - if err != nil { - y = 0 - } - - cd := ClientData{ - Address: conn.RemoteAddr().String(), - Name: serverinfo[0], - Position: gamedata.Coordinates{X: float64(x), Y: float64(y)}, - } - - s.mu.Lock() - s.clientlist[conn] = cd - s.mu.Unlock() - } - */ } } @@ -210,43 +142,18 @@ func (s *Server) ManageBroadcast() { broadcastmsg := s.BuildBroadcastMessage() - data, err := proto.Marshal(broadcastmsg) - if err != nil { - fmt.Println("Error serializing the broadcastmsg: ", err) - return + envelope := &pb.ServerEnvelope{ + Payload: &pb.ServerEnvelope_Broadcast{ + Broadcast: broadcastmsg, + }, } - length := uint32(len(data)) - buf := make([]byte, 4+len(data)) - binary.BigEndian.PutUint32(buf[:4], length) - copy(buf[4:], data) - s.mu.Lock() - for client, clientinfo := range s.clientlist { - // Ensure complete write - totalWritten := 0 - for totalWritten < len(buf) { - n, err := client.Write(buf[totalWritten:]) - if err != nil { - fmt.Printf("Error writing to connection: %s %v\n", err, clientinfo.Address) - return - } - totalWritten += n - } + for client := range s.clientlist { + s.SendMessage(client, envelope) } s.mu.Unlock() - /* - s.mu.Lock() - for client, data := range s.clientlist { - _, err := client.Write([]byte(broadcastmsg)) - if err != nil { - fmt.Println("Error sending message to ", data.Address, ": ", err) - } - } - s.mu.Unlock() - //fmt.Println("Broadcasting:: ", broadcastmsg) - */ time.Sleep(time.Millisecond * 30) } } @@ -277,3 +184,46 @@ func (s *Server) BuildBroadcastMessage() *pb.AllClients { func (s *Server) Disconnect() { } + +func (s *Server) SendMessage(conn net.Conn, details *pb.ServerEnvelope) { + data, err := proto.Marshal(details) + if err != nil { + fmt.Println("error serializing msg details: ", err) + return + } + + //prepend message length + length := len(data) + buf := make([]byte, 4+length) + binary.BigEndian.PutUint32(buf[:4], uint32(length)) + copy(buf[4:], data) + + s.SendBuffer(conn, buf) +} + +func (s *Server) SendBuffer(conn net.Conn, buf []byte) { + //write until entire buffer transmitted + totalWritten := 0 + for totalWritten < len(buf) { + n, err := conn.Write(buf[totalWritten:]) + if err != nil { + fmt.Println("error writing to connection ", err) + return + } + totalWritten += n + } +} + +func (s *Server) SendClientIdentity(conn net.Conn, id int) { + identifier := &pb.ClientIdentity{ + Id: int32(id), + } + + envelope := &pb.ServerEnvelope{ + Payload: &pb.ServerEnvelope_Identity{ + Identity: identifier, + }, + } + + s.SendMessage(conn, envelope) +}