xy 14 órája
szülő
commit
fca54ea686

+ 37 - 0
bin/client_msg/common.proto

@@ -289,4 +289,41 @@ message ResLudoRoomInfo{
 
 message BuyShopItem{
   string id = 1;
+}
+
+message RequestAddFriendItem{
+  int32 id = 1;
+  string RequestID = 2;
+  string FromUserID = 3;
+  string ToUserID = 4;
+  int32 Status = 5;
+  string Message = 6;
+}
+
+message ReqFriendList{
+  string user_id = 1;
+}
+
+message ResFriendList{
+  bool success = 1;
+  MsgError err_msg = 2;
+  repeated RequestAddFriendItem list = 3;
+}
+
+
+message ReqAddFriend{
+  string ToUserID = 1;
+  string msg = 2;
+}
+
+message RecvAddFriendRequest{
+  UserInfo info = 1;
+}
+
+message OptAddFriendRequest{
+  RequestAddFriendItem info = 1;
+}
+
+message NotifyOptFriend{
+  RequestAddFriendItem info = 1;
 }

+ 145 - 0
src/server/datacenter/request_add_friend/request_add_friend.go

@@ -0,0 +1,145 @@
+package requestaddfriend
+
+import (
+	"fmt"
+	"server/console"
+	usercenter "server/datacenter"
+	mysqlmgr "server/db/mysql"
+	"time"
+)
+
+type FriendRequest struct {
+	ID            int        `json:"id" db:"id"`
+	CreateTime    time.Time  `json:"create_time" db:"create_time"`
+	RequestID     string     `json:"request_id" db:"request_id"`
+	FromUserID    string     `json:"from_user_id" db:"from_user_id"`
+	ToUserID      string     `json:"to_user_id" db:"to_user_id"`
+	Status        int        `json:"status" db:"status"` // 0=Pending, 1=Accepted, 2=Rejected
+	Message       string     `json:"message" db:"message"`
+	ProcessedTime *time.Time `json:"processed_time,omitempty" db:"processed_time"`
+}
+
+// 状态常量
+const (
+	RequestStatusPending = iota
+	RequestStatusAccepted
+	RequestStatusRejected
+)
+
+func CreateFriendRequest(fromUserID, toUserID, message string) (*FriendRequest, error) {
+	RequestID := fmt.Sprintf("%s_%s_%d", fromUserID, toUserID, RequestStatusPending)
+	request_data, _ := GetRequestByID(RequestID)
+	if request_data != nil {
+		return nil, fmt.Errorf("创建好友请求失败")
+	}
+	request := &FriendRequest{
+		RequestID:  RequestID,
+		FromUserID: fromUserID,
+		ToUserID:   toUserID,
+		Status:     RequestStatusPending,
+		Message:    message,
+	}
+
+	_, err := mysqlmgr.Insert(`
+		INSERT INTO request_add_friend 
+		(request_id, from_user_id, to_user_id, status, message) 
+		VALUES (?, ?, ?, ?, ?)`,
+		request.RequestID,
+		request.FromUserID,
+		request.ToUserID,
+		request.Status,
+		request.Message,
+	)
+
+	if err != nil {
+		return nil, fmt.Errorf("创建好友请求失败: %v", err)
+	}
+
+	return request, nil
+}
+
+func GetRequestByID(requestID string) (*FriendRequest, error) {
+	var req FriendRequest
+	err := mysqlmgr.QueryRow(`
+        SELECT request_id, from_user_id, to_user_id, status
+        FROM request_add_friend
+        WHERE request_id = ?`,
+		requestID,
+	).Scan(
+		&req.RequestID,
+		&req.FromUserID,
+		&req.ToUserID,
+		&req.Status,
+	)
+
+	if err != nil {
+		return nil, err
+	}
+	return &req, nil
+}
+
+func ProcessFriendRequest(requestID string, status int) (*FriendRequest, error) {
+
+	request_data, err := GetRequestByID(requestID)
+	if err != nil {
+		return nil, err
+	}
+	processedTime := time.Now()
+	_, err = mysqlmgr.Update(`UPDATE request_add_friend SET status = ?, processed_time = ? WHERE request_id = ? AND status = ? `,
+		status,
+		processedTime,
+		requestID,
+		RequestStatusPending,
+	)
+
+	if err != nil {
+		return nil, fmt.Errorf("处理请求失败: %v", err)
+	}
+
+	toUserID := request_data.ToUserID
+	FromUserID := request_data.FromUserID
+	if status == RequestStatusAccepted {
+		user_data, err := usercenter.GetUserByID(toUserID)
+		if err == nil {
+			err = user_data.AddFriend(FromUserID)
+			if err != nil {
+				console.Log(err.Error())
+			}
+		}
+	} else if status == RequestStatusRejected {
+
+	}
+	return request_data, nil
+}
+
+func GetPendingRequests(userID string) ([]*FriendRequest, error) {
+	rows, err := mysqlmgr.Query(`
+		SELECT id, create_time, request_id, from_user_id, to_user_id, message
+		FROM request_add_friend
+		WHERE to_user_id = ? AND status = ? LIMIT 100 `,
+		userID,
+		RequestStatusPending,
+	)
+	if err != nil {
+		return nil, err
+	}
+	defer rows.Close()
+
+	var requests []*FriendRequest
+	for rows.Next() {
+		var req FriendRequest
+		if err := rows.Scan(
+			&req.ID,
+			&req.CreateTime,
+			&req.RequestID,
+			&req.FromUserID,
+			&req.ToUserID,
+			&req.Message,
+		); err != nil {
+			return nil, err
+		}
+		requests = append(requests, &req)
+	}
+
+	return requests, nil
+}

+ 194 - 0
src/server/datacenter/users.go

@@ -0,0 +1,194 @@
+package usercenter
+
+import (
+	"encoding/json"
+	"fmt"
+	mysqlmgr "server/db/mysql"
+	"time"
+)
+
+type User struct {
+	ID         int             `json:"id" db:"id"`
+	CreateTime time.Time       `json:"create_time" db:"create_time"`
+	UserID     string          `json:"user_id" db:"user_id"`
+	FriendIDs  json.RawMessage `json:"friend_ids" db:"friend_ids"` // 使用json.RawMessage处理JSON数据
+	Head       string          `json:"head" db:"head"`
+	Coin       int             `json:"coin" db:"coin"`
+	Name       string          `json:"name" db:"name"`
+	Account    string          `json:"account" db:"account"`
+	Password   string          `json:"-" db:"password"` // json:"-" 表示不序列化密码
+}
+
+func GetUserByID(userID string) (*User, error) {
+	var user User
+	var friendData []byte // 接收数据库中的JSON原始数据
+
+	// SQL查询(实际执行数据库操作)
+	err := mysqlmgr.QueryRow(`
+        SELECT id, user_id, friend_ids, name 
+        FROM users WHERE user_id = ?`,
+		userID,
+	).Scan(
+		&user.ID,
+		&user.UserID,
+		&friendData, // 扫描JSON数据到[]byte
+		&user.Name,
+		&user.Head,
+	)
+
+	if err != nil {
+		return nil, err
+	}
+
+	// 将原始JSON数据存入结构体
+	user.FriendIDs = json.RawMessage(friendData)
+	return &user, nil
+}
+
+func GetUserByAccountAndPassword(Account string, Password string) (*User, error) {
+	var user User
+	var friendData []byte // 接收数据库中的JSON原始数据
+
+	// SQL查询(实际执行数据库操作)
+	err := mysqlmgr.QueryRow(`
+        SELECT id, user_id, friend_ids, name 
+        FROM users WHERE account = ? AND password = ? LIMIT 1`,
+		Account, Password,
+	).Scan(
+		&user.ID,
+		&user.UserID,
+		&friendData, // 扫描JSON数据到[]byte
+		&user.Name,
+		&user.Head,
+	)
+
+	if err != nil {
+		return nil, err
+	}
+
+	// 将原始JSON数据存入结构体
+	user.FriendIDs = json.RawMessage(friendData)
+	return &user, nil
+}
+
+func CreateUser(user *User) (int64, error) {
+	result, err := mysqlmgr.Insert(`
+		INSERT INTO users 
+		(create_time, user_id, friend_ids, head, coin, name, account, password)
+		VALUES (NOW(), ?, ?, ?, ?, ?, ?, ?)`,
+		user.UserID,
+		user.FriendIDs, // 直接传入json.RawMessage
+		user.Head,
+		user.Coin,
+		user.Name,
+		user.Account,
+		user.Password,
+	)
+
+	if err != nil {
+		return 0, fmt.Errorf("创建用户失败: %v", err)
+	}
+	return result, err
+}
+
+func (u *User) SetFriendIDs(friendIDs []string) error {
+	jsonData, err := json.Marshal(friendIDs)
+	if err != nil {
+		return err
+	}
+	u.FriendIDs = jsonData
+	return nil
+}
+
+// 获取好友ID列表
+func (u *User) GetFriendIDs() ([]string, error) {
+	var friends []string
+	if len(u.FriendIDs) == 0 {
+		return friends, nil
+	}
+	err := json.Unmarshal(u.FriendIDs, &friends)
+	return friends, err
+}
+
+// 添加好友
+func (u *User) AddFriend(friendID string) error {
+	friends, err := u.GetFriendIDs()
+	if err != nil {
+		return fmt.Errorf("获取好友列表失败: %v", err)
+	}
+
+	// 检查是否已是好友
+	for _, id := range friends {
+		if id == friendID {
+			return fmt.Errorf("该用户已是好友")
+		}
+	}
+
+	// 添加新好友
+	friends = append(friends, friendID)
+	u.SetFriendIDs(friends)
+	return u.UpdateFriends(friends)
+}
+
+// 删除好友
+func (u *User) RemoveFriend(friendID string) error {
+	friends, err := u.GetFriendIDs()
+	if err != nil {
+		return fmt.Errorf("获取好友列表失败: %v", err)
+	}
+
+	// 查找并删除
+	newFriends := make([]string, 0, len(friends))
+	found := false
+	for _, id := range friends {
+		if id == friendID {
+			found = true
+			continue
+		}
+		newFriends = append(newFriends, id)
+	}
+
+	if !found {
+		return fmt.Errorf("该用户不是好友")
+	}
+	u.SetFriendIDs(newFriends)
+	return u.UpdateFriends(newFriends)
+}
+
+// 更新好友列表(内部方法)
+func (u *User) UpdateFriends(friends []string) error {
+	// 1. 转换为JSON
+	jsonData, err := json.Marshal(friends)
+	if err != nil {
+		return fmt.Errorf("JSON编码失败: %v", err)
+	}
+
+	// 2. 更新数据库
+	_, err = mysqlmgr.Update(`
+        UPDATE users 
+        SET friend_ids = ? 
+        WHERE user_id = ?`,
+		jsonData,
+		u.UserID,
+	)
+	if err != nil {
+		return fmt.Errorf("数据库更新失败: %v", err)
+	}
+
+	// 3. 更新内存数据
+	u.FriendIDs = jsonData
+	return nil
+}
+func (u *User) UpdateFriendsToDB() error {
+	_, err := mysqlmgr.Update(`
+        UPDATE users 
+        SET friend_ids = ? 
+        WHERE user_id = ?`,
+		u.FriendIDs, // 使用已转换的JSON数据
+		u.UserID,
+	)
+	if err != nil {
+		return fmt.Errorf("数据库更新失败: %v", err)
+	}
+	return nil
+}

+ 5 - 0
src/server/gate/router.go

@@ -13,6 +13,11 @@ func init() {
 
 	msg.Processor.SetRouter(&msg.BuyShopItem{}, hall.ChanRPC)
 	msg.Processor.SetRouter(&msg.EnterHall{}, hall.ChanRPC)
+	msg.Processor.SetRouter(&msg.ReqFriendList{}, hall.ChanRPC)
+	msg.Processor.SetRouter(&msg.ReqAddFriend{}, hall.ChanRPC)
+
+	msg.Processor.SetRouter(&msg.RecvAddFriendRequest{}, hall.ChanRPC)
+	msg.Processor.SetRouter(&msg.OptAddFriendRequest{}, hall.ChanRPC)
 
 	msg.Processor.SetRouter(&msg.ReqHeartBeat{}, game.ChanRPC)
 	msg.Processor.SetRouter(&msg.SendColorSz{}, game.ChanRPC)

+ 1 - 0
src/server/go.mod

@@ -25,6 +25,7 @@ require (
 	github.com/go-playground/validator/v10 v10.26.0 // indirect
 	github.com/goccy/go-json v0.10.5 // indirect
 	github.com/golang/protobuf v1.5.4 // indirect
+	github.com/google/uuid v1.6.0 // indirect
 	github.com/gorilla/websocket v1.5.3 // indirect
 	github.com/json-iterator/go v1.1.12 // indirect
 	github.com/klauspost/cpuid/v2 v2.2.10 // indirect

+ 2 - 0
src/server/go.sum

@@ -36,6 +36,8 @@ github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp
 github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
 github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
+github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
 github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
 github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=

+ 99 - 0
src/server/hall/friends/friends.go

@@ -0,0 +1,99 @@
+package friends
+
+import (
+	requestaddfriend "server/datacenter/request_add_friend"
+	agentmanager "server/game/agentManager"
+	"server/msg"
+
+	"github.com/name5566/leaf/gate"
+)
+
+// 获取用户的好友列表
+func GetFriendsListByUserId(args []interface{}) {
+	m := args[0].(*msg.ReqFriendList)
+	a := args[1].(gate.Agent)
+	list, err := requestaddfriend.GetPendingRequests(m.UserId)
+	if err != nil {
+		a.WriteMsg(&msg.ResFriendList{
+			Success: false,
+			ErrMsg: &msg.MsgError{
+				ErrorCode: 101,
+				ErrorMsg:  err.Error(),
+			},
+		})
+		return
+	}
+	var temp = make([]*msg.RequestAddFriendItem, 0)
+	for _, v := range list {
+		temp = append(temp, &msg.RequestAddFriendItem{
+			Id:         int32(v.ID),
+			RequestID:  v.RequestID,
+			FromUserID: v.FromUserID,
+			ToUserID:   v.ToUserID,
+			Status:     int32(v.Status),
+			Message:    v.Message,
+		})
+	}
+	a.WriteMsg(&msg.ResFriendList{
+		Success: true,
+		ErrMsg:  nil,
+		List:    temp,
+	})
+
+}
+
+// 添加好友请求
+func AddFriendrRquest(args []interface{}) {
+	m := args[0].(*msg.ReqAddFriend)
+	a := args[1].(gate.Agent)
+	FromUserID := a.UserData().(*msg.UserInfo).UserId
+	ToUserID := m.ToUserID
+	requestaddfriend.CreateFriendRequest(FromUserID, ToUserID, m.Msg)
+	NotifyFriendAddFriend(ToUserID)
+}
+
+// 通知添加好友请求
+func NotifyFriendAddFriend(ToUserID string) {
+	ag := agentmanager.GetAgentByUserID(ToUserID)
+	if ag != nil {
+		ToUserInfo := ag.UserData().(*msg.UserInfo)
+		ag.WriteMsg(&msg.RecvAddFriendRequest{
+			Info: &msg.UserInfo{
+				MHead:  ToUserInfo.MHead,
+				Name:   ToUserInfo.Name,
+				UserId: ToUserInfo.UserId,
+			},
+		})
+	}
+}
+
+// 反馈操作好友请求
+func OptFriendrRquest(args []interface{}) {
+	m := args[0].(*msg.OptAddFriendRequest)
+	request_data, err := requestaddfriend.ProcessFriendRequest(m.Info.RequestID, int(m.Info.Status))
+	if err != nil {
+		request_data.Status = int(m.Info.Status)
+		NotifyOptFriend(m.Info.FromUserID, request_data)
+	}
+}
+
+// 通知好友操作的结果
+func NotifyOptFriend(FromUserID string, request_data *requestaddfriend.FriendRequest) {
+	ag := agentmanager.GetAgentByUserID(FromUserID)
+	if ag != nil {
+		ag.WriteMsg(&msg.NotifyOptFriend{
+			Info: &msg.RequestAddFriendItem{
+				Status:   int32(request_data.Status),
+				ToUserID: request_data.ToUserID,
+			},
+		})
+	}
+}
+
+// 通知给在线的好友自己上线
+
+// 通知给在线的好友自己下线
+
+// 发送好友聊天消息
+
+// 筛选在线的好友

+ 4 - 0
src/server/hall/internal/handler.go

@@ -3,6 +3,7 @@ package internal
 import (
 	"reflect"
 	redismgr "server/db/redis"
+	"server/hall/friends"
 	"server/hall/shop"
 
 	agentmanager "server/game/agentManager"
@@ -22,6 +23,9 @@ func init() {
 	HandleMsg(&msg.EnterHall{}, enterHall)
 	HandleMsg(&msg.LeaveHall{}, leaveHall)
 	HandleMsg(&msg.BuyShopItem{}, shop.OnBuy)
+	HandleMsg(&msg.ReqFriendList{}, friends.GetFriendsListByUserId)
+	HandleMsg(&msg.ReqAddFriend{}, friends.AddFriendrRquest)
+
 }
 
 func enterHall(args []interface{}) {

+ 416 - 8
src/server/msg/common.pb.go

@@ -2652,6 +2652,378 @@ func (x *BuyShopItem) GetId() string {
 	return ""
 }
 
+type RequestAddFriendItem struct {
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Id            int32                  `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
+	RequestID     string                 `protobuf:"bytes,2,opt,name=RequestID,proto3" json:"RequestID,omitempty"`
+	FromUserID    string                 `protobuf:"bytes,3,opt,name=FromUserID,proto3" json:"FromUserID,omitempty"`
+	ToUserID      string                 `protobuf:"bytes,4,opt,name=ToUserID,proto3" json:"ToUserID,omitempty"`
+	Status        int32                  `protobuf:"varint,5,opt,name=Status,proto3" json:"Status,omitempty"`
+	Message       string                 `protobuf:"bytes,6,opt,name=Message,proto3" json:"Message,omitempty"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
+}
+
+func (x *RequestAddFriendItem) Reset() {
+	*x = RequestAddFriendItem{}
+	mi := &file_common_proto_msgTypes[38]
+	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+	ms.StoreMessageInfo(mi)
+}
+
+func (x *RequestAddFriendItem) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*RequestAddFriendItem) ProtoMessage() {}
+
+func (x *RequestAddFriendItem) ProtoReflect() protoreflect.Message {
+	mi := &file_common_proto_msgTypes[38]
+	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 RequestAddFriendItem.ProtoReflect.Descriptor instead.
+func (*RequestAddFriendItem) Descriptor() ([]byte, []int) {
+	return file_common_proto_rawDescGZIP(), []int{38}
+}
+
+func (x *RequestAddFriendItem) GetId() int32 {
+	if x != nil {
+		return x.Id
+	}
+	return 0
+}
+
+func (x *RequestAddFriendItem) GetRequestID() string {
+	if x != nil {
+		return x.RequestID
+	}
+	return ""
+}
+
+func (x *RequestAddFriendItem) GetFromUserID() string {
+	if x != nil {
+		return x.FromUserID
+	}
+	return ""
+}
+
+func (x *RequestAddFriendItem) GetToUserID() string {
+	if x != nil {
+		return x.ToUserID
+	}
+	return ""
+}
+
+func (x *RequestAddFriendItem) GetStatus() int32 {
+	if x != nil {
+		return x.Status
+	}
+	return 0
+}
+
+func (x *RequestAddFriendItem) GetMessage() string {
+	if x != nil {
+		return x.Message
+	}
+	return ""
+}
+
+type ReqFriendList struct {
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	UserId        string                 `protobuf:"bytes,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
+}
+
+func (x *ReqFriendList) Reset() {
+	*x = ReqFriendList{}
+	mi := &file_common_proto_msgTypes[39]
+	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+	ms.StoreMessageInfo(mi)
+}
+
+func (x *ReqFriendList) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ReqFriendList) ProtoMessage() {}
+
+func (x *ReqFriendList) ProtoReflect() protoreflect.Message {
+	mi := &file_common_proto_msgTypes[39]
+	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 ReqFriendList.ProtoReflect.Descriptor instead.
+func (*ReqFriendList) Descriptor() ([]byte, []int) {
+	return file_common_proto_rawDescGZIP(), []int{39}
+}
+
+func (x *ReqFriendList) GetUserId() string {
+	if x != nil {
+		return x.UserId
+	}
+	return ""
+}
+
+type ResFriendList struct {
+	state         protoimpl.MessageState  `protogen:"open.v1"`
+	Success       bool                    `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"`
+	ErrMsg        *MsgError               `protobuf:"bytes,2,opt,name=err_msg,json=errMsg,proto3" json:"err_msg,omitempty"`
+	List          []*RequestAddFriendItem `protobuf:"bytes,3,rep,name=list,proto3" json:"list,omitempty"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
+}
+
+func (x *ResFriendList) Reset() {
+	*x = ResFriendList{}
+	mi := &file_common_proto_msgTypes[40]
+	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+	ms.StoreMessageInfo(mi)
+}
+
+func (x *ResFriendList) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ResFriendList) ProtoMessage() {}
+
+func (x *ResFriendList) ProtoReflect() protoreflect.Message {
+	mi := &file_common_proto_msgTypes[40]
+	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 ResFriendList.ProtoReflect.Descriptor instead.
+func (*ResFriendList) Descriptor() ([]byte, []int) {
+	return file_common_proto_rawDescGZIP(), []int{40}
+}
+
+func (x *ResFriendList) GetSuccess() bool {
+	if x != nil {
+		return x.Success
+	}
+	return false
+}
+
+func (x *ResFriendList) GetErrMsg() *MsgError {
+	if x != nil {
+		return x.ErrMsg
+	}
+	return nil
+}
+
+func (x *ResFriendList) GetList() []*RequestAddFriendItem {
+	if x != nil {
+		return x.List
+	}
+	return nil
+}
+
+type ReqAddFriend struct {
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	ToUserID      string                 `protobuf:"bytes,1,opt,name=ToUserID,proto3" json:"ToUserID,omitempty"`
+	Msg           string                 `protobuf:"bytes,2,opt,name=msg,proto3" json:"msg,omitempty"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
+}
+
+func (x *ReqAddFriend) Reset() {
+	*x = ReqAddFriend{}
+	mi := &file_common_proto_msgTypes[41]
+	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+	ms.StoreMessageInfo(mi)
+}
+
+func (x *ReqAddFriend) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ReqAddFriend) ProtoMessage() {}
+
+func (x *ReqAddFriend) ProtoReflect() protoreflect.Message {
+	mi := &file_common_proto_msgTypes[41]
+	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 ReqAddFriend.ProtoReflect.Descriptor instead.
+func (*ReqAddFriend) Descriptor() ([]byte, []int) {
+	return file_common_proto_rawDescGZIP(), []int{41}
+}
+
+func (x *ReqAddFriend) GetToUserID() string {
+	if x != nil {
+		return x.ToUserID
+	}
+	return ""
+}
+
+func (x *ReqAddFriend) GetMsg() string {
+	if x != nil {
+		return x.Msg
+	}
+	return ""
+}
+
+type RecvAddFriendRequest struct {
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Info          *UserInfo              `protobuf:"bytes,1,opt,name=info,proto3" json:"info,omitempty"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
+}
+
+func (x *RecvAddFriendRequest) Reset() {
+	*x = RecvAddFriendRequest{}
+	mi := &file_common_proto_msgTypes[42]
+	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+	ms.StoreMessageInfo(mi)
+}
+
+func (x *RecvAddFriendRequest) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*RecvAddFriendRequest) ProtoMessage() {}
+
+func (x *RecvAddFriendRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_common_proto_msgTypes[42]
+	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 RecvAddFriendRequest.ProtoReflect.Descriptor instead.
+func (*RecvAddFriendRequest) Descriptor() ([]byte, []int) {
+	return file_common_proto_rawDescGZIP(), []int{42}
+}
+
+func (x *RecvAddFriendRequest) GetInfo() *UserInfo {
+	if x != nil {
+		return x.Info
+	}
+	return nil
+}
+
+type OptAddFriendRequest struct {
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Info          *RequestAddFriendItem  `protobuf:"bytes,1,opt,name=info,proto3" json:"info,omitempty"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
+}
+
+func (x *OptAddFriendRequest) Reset() {
+	*x = OptAddFriendRequest{}
+	mi := &file_common_proto_msgTypes[43]
+	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+	ms.StoreMessageInfo(mi)
+}
+
+func (x *OptAddFriendRequest) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*OptAddFriendRequest) ProtoMessage() {}
+
+func (x *OptAddFriendRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_common_proto_msgTypes[43]
+	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 OptAddFriendRequest.ProtoReflect.Descriptor instead.
+func (*OptAddFriendRequest) Descriptor() ([]byte, []int) {
+	return file_common_proto_rawDescGZIP(), []int{43}
+}
+
+func (x *OptAddFriendRequest) GetInfo() *RequestAddFriendItem {
+	if x != nil {
+		return x.Info
+	}
+	return nil
+}
+
+type NotifyOptFriend struct {
+	state         protoimpl.MessageState `protogen:"open.v1"`
+	Info          *RequestAddFriendItem  `protobuf:"bytes,1,opt,name=info,proto3" json:"info,omitempty"`
+	unknownFields protoimpl.UnknownFields
+	sizeCache     protoimpl.SizeCache
+}
+
+func (x *NotifyOptFriend) Reset() {
+	*x = NotifyOptFriend{}
+	mi := &file_common_proto_msgTypes[44]
+	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+	ms.StoreMessageInfo(mi)
+}
+
+func (x *NotifyOptFriend) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*NotifyOptFriend) ProtoMessage() {}
+
+func (x *NotifyOptFriend) ProtoReflect() protoreflect.Message {
+	mi := &file_common_proto_msgTypes[44]
+	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 NotifyOptFriend.ProtoReflect.Descriptor instead.
+func (*NotifyOptFriend) Descriptor() ([]byte, []int) {
+	return file_common_proto_rawDescGZIP(), []int{44}
+}
+
+func (x *NotifyOptFriend) GetInfo() *RequestAddFriendItem {
+	if x != nil {
+		return x.Info
+	}
+	return nil
+}
+
 var File_common_proto protoreflect.FileDescriptor
 
 const file_common_proto_rawDesc = "" +
@@ -2821,7 +3193,31 @@ const file_common_proto_rawDesc = "" +
 	"\aerr_msg\x18\x02 \x01(\v2\t.MsgErrorR\x06errMsg\x12\x1d\n" +
 	"\x04info\x18\x03 \x01(\v2\t.RoomInfoR\x04info\"\x1d\n" +
 	"\vBuyShopItem\x12\x0e\n" +
-	"\x02id\x18\x01 \x01(\tR\x02id*K\n" +
+	"\x02id\x18\x01 \x01(\tR\x02id\"\xb2\x01\n" +
+	"\x14RequestAddFriendItem\x12\x0e\n" +
+	"\x02id\x18\x01 \x01(\x05R\x02id\x12\x1c\n" +
+	"\tRequestID\x18\x02 \x01(\tR\tRequestID\x12\x1e\n" +
+	"\n" +
+	"FromUserID\x18\x03 \x01(\tR\n" +
+	"FromUserID\x12\x1a\n" +
+	"\bToUserID\x18\x04 \x01(\tR\bToUserID\x12\x16\n" +
+	"\x06Status\x18\x05 \x01(\x05R\x06Status\x12\x18\n" +
+	"\aMessage\x18\x06 \x01(\tR\aMessage\"(\n" +
+	"\rReqFriendList\x12\x17\n" +
+	"\auser_id\x18\x01 \x01(\tR\x06userId\"x\n" +
+	"\rResFriendList\x12\x18\n" +
+	"\asuccess\x18\x01 \x01(\bR\asuccess\x12\"\n" +
+	"\aerr_msg\x18\x02 \x01(\v2\t.MsgErrorR\x06errMsg\x12)\n" +
+	"\x04list\x18\x03 \x03(\v2\x15.RequestAddFriendItemR\x04list\"<\n" +
+	"\fReqAddFriend\x12\x1a\n" +
+	"\bToUserID\x18\x01 \x01(\tR\bToUserID\x12\x10\n" +
+	"\x03msg\x18\x02 \x01(\tR\x03msg\"5\n" +
+	"\x14RecvAddFriendRequest\x12\x1d\n" +
+	"\x04info\x18\x01 \x01(\v2\t.UserInfoR\x04info\"@\n" +
+	"\x13OptAddFriendRequest\x12)\n" +
+	"\x04info\x18\x01 \x01(\v2\x15.RequestAddFriendItemR\x04info\"<\n" +
+	"\x0fNotifyOptFriend\x12)\n" +
+	"\x04info\x18\x01 \x01(\v2\x15.RequestAddFriendItemR\x04info*K\n" +
 	"\broleType\x12\x15\n" +
 	"\x11ROLE_TYPE_UNKNOWN\x10\x00\x12\a\n" +
 	"\x03RED\x10\x01\x12\b\n" +
@@ -2872,7 +3268,7 @@ func file_common_proto_rawDescGZIP() []byte {
 }
 
 var file_common_proto_enumTypes = make([]protoimpl.EnumInfo, 7)
-var file_common_proto_msgTypes = make([]protoimpl.MessageInfo, 38)
+var file_common_proto_msgTypes = make([]protoimpl.MessageInfo, 45)
 var file_common_proto_goTypes = []any{
 	(RoleType)(0),                // 0: roleType
 	(OptType)(0),                 // 1: OptType
@@ -2919,6 +3315,13 @@ var file_common_proto_goTypes = []any{
 	(*ReqLudoRoomInfo)(nil),      // 42: ReqLudoRoomInfo
 	(*ResLudoRoomInfo)(nil),      // 43: ResLudoRoomInfo
 	(*BuyShopItem)(nil),          // 44: BuyShopItem
+	(*RequestAddFriendItem)(nil), // 45: RequestAddFriendItem
+	(*ReqFriendList)(nil),        // 46: ReqFriendList
+	(*ResFriendList)(nil),        // 47: ResFriendList
+	(*ReqAddFriend)(nil),         // 48: ReqAddFriend
+	(*RecvAddFriendRequest)(nil), // 49: RecvAddFriendRequest
+	(*OptAddFriendRequest)(nil),  // 50: OptAddFriendRequest
+	(*NotifyOptFriend)(nil),      // 51: NotifyOptFriend
 }
 var file_common_proto_depIdxs = []int32{
 	0,  // 0: round.m_color:type_name -> roleType
@@ -2971,11 +3374,16 @@ var file_common_proto_depIdxs = []int32{
 	39, // 47: ResLudoHistory.list:type_name -> HistoryRecord
 	31, // 48: ResLudoRoomInfo.err_msg:type_name -> MsgError
 	8,  // 49: ResLudoRoomInfo.info:type_name -> RoomInfo
-	50, // [50:50] is the sub-list for method output_type
-	50, // [50:50] is the sub-list for method input_type
-	50, // [50:50] is the sub-list for extension type_name
-	50, // [50:50] is the sub-list for extension extendee
-	0,  // [0:50] is the sub-list for field type_name
+	31, // 50: ResFriendList.err_msg:type_name -> MsgError
+	45, // 51: ResFriendList.list:type_name -> RequestAddFriendItem
+	21, // 52: RecvAddFriendRequest.info:type_name -> UserInfo
+	45, // 53: OptAddFriendRequest.info:type_name -> RequestAddFriendItem
+	45, // 54: NotifyOptFriend.info:type_name -> RequestAddFriendItem
+	55, // [55:55] is the sub-list for method output_type
+	55, // [55:55] is the sub-list for method input_type
+	55, // [55:55] is the sub-list for extension type_name
+	55, // [55:55] is the sub-list for extension extendee
+	0,  // [0:55] is the sub-list for field type_name
 }
 
 func init() { file_common_proto_init() }
@@ -2989,7 +3397,7 @@ func file_common_proto_init() {
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
 			RawDescriptor: unsafe.Slice(unsafe.StringData(file_common_proto_rawDesc), len(file_common_proto_rawDesc)),
 			NumEnums:      7,
-			NumMessages:   38,
+			NumMessages:   45,
 			NumExtensions: 0,
 			NumServices:   0,
 		},

+ 9 - 0
src/server/msg/msg.go

@@ -54,6 +54,15 @@ func init() {
 	Processor.Register(&ReqLudoRoomInfo{})
 	Processor.Register(&ResLudoRoomInfo{})
 
+	Processor.Register(&ReqFriendList{})
+	Processor.Register(&ResFriendList{})
+
+	Processor.Register(&ReqAddFriend{})
+
+	Processor.Register(&RecvAddFriendRequest{})
+
+	Processor.Register(&OptAddFriendRequest{})
+
 	Processor.Range(func(id uint16, t reflect.Type) {
 		log.Debug("消息ID: %d, 消息类型: %s\n", id, t.Elem().Name())
 		msgList = append(msgList, MsgInfo{

+ 5 - 6
src/server/user/user.go

@@ -1,7 +1,6 @@
 package user
 
 import (
-	mongodbmgr "server/db/mongodb"
 	redismgr "server/db/redis"
 	agentmanager "server/game/agentManager"
 	"server/msg"
@@ -40,11 +39,11 @@ func GetUserInfoById(userId string) *msg.UserInfo {
 		}
 
 		// 保存到 MongoDB 和 Redis
-		err = mongodbmgr.AddUser(userData)
-		if err != nil {
-			log.Debug("Error saving new user to MongoDB:", err)
-			return nil
-		}
+		// err = mongodbmgr.AddUser(userData)
+		// if err != nil {
+		// 	log.Debug("Error saving new user to MongoDB:", err)
+		// 	return nil
+		// }
 
 		err = redismgr.SaveUserInfoToRedis(userData)
 		if err != nil {

+ 25 - 9
src/server/webserver/login.go

@@ -2,6 +2,8 @@ package main
 
 import (
 	"net/http"
+	"server/console"
+	usercenter "server/datacenter"
 	redismgr "server/db/redis"
 	"server/msg"
 	"server/user"
@@ -13,16 +15,30 @@ func ReqLogin(c *gin.Context) {
 	req := c.MustGet("protobuf_data").(*msg.ReqLogin)
 	UserId, err := redismgr.GetUserIDFromRedisByAP(req.Account, req.Password)
 	if err != nil {
+		var user_data *usercenter.User
+		user_data, err = usercenter.GetUserByAccountAndPassword(req.Account, req.Password)
+		//再从sql查询如果查到了,先写入redis,再返回。否则正常返回错误
+		// err = mysqlmgr.QueryRow("  SELECT * FROM users WHERE account = ? AND password = ? LIMIT 1", req.Account, req.Password).Scan(user.Coin, user.Head, user.Name, user.UserID)
+		if err != nil {
+			console.Log("Query error:", err)
+			c.ProtoBuf(http.StatusOK, &msg.ResLogin{
+				NikeName: "",
+				UserId:   "",
+				ErrMsg: &msg.MsgError{
+					ErrorCode: 101,
+					ErrorMsg:  "Password or Account is error!",
+				},
+			})
+			return
+		} else {
+			redismgr.SaveUserInfoToRedis(&msg.UserInfo{
+				UserId: user_data.UserID,
+				MHead:  user_data.Head,
+				MCoin:  int32(user_data.Coin),
+				Name:   user_data.Name,
+			})
+		}
 
-		c.ProtoBuf(http.StatusOK, &msg.ResLogin{
-			NikeName: "",
-			UserId:   "",
-			ErrMsg: &msg.MsgError{
-				ErrorCode: 101,
-				ErrorMsg:  "Password or Account is error!",
-			},
-		})
-		return
 	}
 	// 获取用户信息 ,如果新用户则创建一个
 	userData := user.GetUserInfoById(UserId)

+ 17 - 0
src/server/webserver/register.go

@@ -2,6 +2,8 @@ package main
 
 import (
 	"net/http"
+	"server/console"
+	usercenter "server/datacenter"
 	redismgr "server/db/redis"
 	"server/msg"
 
@@ -38,6 +40,21 @@ func ReqRegister(c *gin.Context) {
 		})
 		return
 	}
+	newUser := &usercenter.User{
+		UserID:   userId,
+		Head:     req.MHead,
+		Coin:     100,
+		Name:     req.NikeName,
+		Account:  req.Account,
+		Password: req.Password, // 注意: 实际使用中应该存储哈希值
+	}
+
+	// 设置好友列表
+	if err := newUser.SetFriendIDs([]string{"friend1", "friend2"}); err != nil {
+		console.Log(err.Error())
+	}
+
+	usercenter.CreateUser(newUser)
 
 	redismgr.SaveUserInfoToRedis(&msg.UserInfo{
 		UserId: userId,