package core import ( "anvil/shared" "errors" "net" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo/options" ) /* func (gs *AeGameServer) LobbyCheckIn(ip net.IP, inSocketPort int32) { gs.lock.Lock() defer gs.lock.Unlock() gs.LobbyIp = ip gs.LobbyPort = inSocketPort } func (gs *AeGameServer) GetUrlLobbyChekedIn() string { gs.lock.Lock() defer gs.lock.Unlock() if len(gs.LobbyIp) != 0 { return fmt.Sprintf("%s:%d", gs.LobbyIp.String(), gs.LobbyPort) } else { return "" } } func (gs *AeGameServer) WorldCheckIn(ip net.IP, inSocketPort int32) { gs.lock.Lock() defer gs.lock.Unlock() gs.WorldIp = ip gs.WorldPort = inSocketPort } func (gs *AeGameServer) GetUrlWorldChekedIn() string { gs.lock.Lock() defer gs.lock.Unlock() if len(gs.WorldIp) != 0 { return fmt.Sprintf("%s:%d", gs.WorldIp.String(), gs.LobbyPort) } else { return "" } } */ func (gs *AeGameServer) FindDsCheckedIn(Type int32, Version string) string { gs.lock.Lock() defer gs.lock.Unlock() var priority float32 = 0 url := "" for _, s := range gs.sockets { if s.IsCompatible(Type, Version) { if tmpUrl := s.GetUrlChekedIn(); tmpUrl != "" { tmpPriority := s.GetPriority() if tmpPriority >= priority { url = tmpUrl priority = tmpPriority } } } } return url } func (tx *transaction) Hello() shared.RPCReturnType { tx.gs.Logger.Println("hello, too") return shared.MakeRPCReturn("hello, too.", nil) } func externalIP() (net.IP, error) { ifaces, err := net.Interfaces() if err != nil { return nil, err } for _, iface := range ifaces { if iface.Flags&net.FlagUp == 0 { continue // interface down } if iface.Flags&net.FlagLoopback != 0 { continue // loopback interface } addrs, err := iface.Addrs() if err != nil { return nil, err } for _, addr := range addrs { var ip net.IP switch v := addr.(type) { case *net.IPNet: ip = v.IP case *net.IPAddr: ip = v.IP } if ip == nil || ip.IsLoopback() { continue } ip = ip.To4() if ip == nil { continue // not an ipv4 address } return ip, nil } } return nil, errors.New("are you connected to the network?") } /* func (tx *transaction) LobbyCheckIn(inSocketPort int32) shared.RPCReturnType { // list.Append(test) tx.gs.Logger.Printf("remoteaddr %s : %d", tx.r.RemoteAddr, inSocketPort) ip, _, err := net.SplitHostPort(tx.r.RemoteAddr) if err != nil { tx.gs.Logger.Printf("userip: %q is not IP:port", tx.r.RemoteAddr) return shared.MakeRPCReturn(nil, errors.New("IP invalid")) } userIP := net.ParseIP(ip) if userIP == nil { tx.gs.Logger.Printf("userip: %q is not IP:port", tx.r.RemoteAddr) return shared.MakeRPCReturn(nil, errors.New("IP invalid")) } if userIP.IsLoopback() { if tmpIp, err := externalIP(); err == nil { userIP = tmpIp } else { return shared.MakeRPCReturn(nil, errors.New("IP invalid")) } } tx.gs.LobbyCheckIn(userIP, inSocketPort) return shared.MakeRPCReturn("lobby checked in.", nil) } func (tx *transaction) WorldCheckIn(inSocketPort int32) shared.RPCReturnType { // list.Append(test) tx.gs.Logger.Printf("remoteaddr %s : %d", tx.r.RemoteAddr, inSocketPort) ip, _, err := net.SplitHostPort(tx.r.RemoteAddr) if err != nil { tx.gs.Logger.Printf("userip: %q is not IP:port", tx.r.RemoteAddr) return shared.MakeRPCReturn(nil, errors.New("IP invalid")) } userIP := net.ParseIP(ip) if userIP == nil { tx.gs.Logger.Printf("userip: %q is not IP:port", tx.r.RemoteAddr) return shared.MakeRPCReturn(nil, errors.New("IP invalid")) } if userIP.IsLoopback() { if tmpIp, err := externalIP(); err == nil { userIP = tmpIp } else { return shared.MakeRPCReturn(nil, errors.New("IP invalid")) } } tx.gs.WorldCheckIn(userIP, inSocketPort) return shared.MakeRPCReturn("world checked in.", nil) } */ func (tx *transaction) GetCheckedIn(Type int32, Version string) shared.RPCReturnType { // url := tx.gs.GetUrlLobbyChekedIn() url := tx.gs.FindDsCheckedIn(Type, Version) tx.gs.Logger.Println("lobby url checked in : ", url) if url == "" { return shared.MakeRPCReturn(nil, errors.New("no url")) } else { return shared.MakeRPCReturn(url, nil) } } // func (tx *transaction) GetLobbyCheckedIn() shared.RPCReturnType { // // url := tx.gs.GetUrlLobbyChekedIn() // url := tx.gs.FindDsCheckedIn(2) // tx.gs.Logger.Println("lobby url checked in : ", url) // if url == "" { // return shared.MakeRPCReturn(nil, errors.New("no url")) // } else { // return shared.MakeRPCReturn(url, nil) // } // } // func (tx *transaction) GetWorldCheckedIn() shared.RPCReturnType { // // url := tx.gs.GetUrlWorldChekedIn() // url := tx.gs.FindDsCheckedIn(1) // tx.gs.Logger.Println("world url checked in : ", url) // if url == "" { // return shared.MakeRPCReturn(nil, errors.New("no url")) // } else { // return shared.MakeRPCReturn(url, nil) // } // } func (tx *transaction) ReadDB(collection string, _id interface{}) shared.RPCReturnType { raw, err := tx.gs.mongoClient.FindOneAndUpdate(shared.CollectionName(collection), bson.M{"_id": _id}, bson.M{ "$setOnInsert": bson.M{"_id": _id}, }, options.FindOneAndUpdate().SetProjection(bson.M{"_id": 0, "_ts": 0}), options.FindOneAndUpdate().SetReturnDocument(options.After), options.FindOneAndUpdate().SetUpsert(true)) tx.gs.Logger.Println("db read : ", _id, raw) return shared.MakeRPCReturn(raw, err) } func (tx *transaction) ReadMany(collection string, in []interface{}) shared.RPCReturnType { raw, err := tx.gs.mongoClient.FindAll(shared.CollectionName(collection), bson.M{"_id": bson.M{"$in": in}}, options.Find().SetProjection(bson.M{"_ts": 0})) tx.gs.Logger.Println("db read : ", raw) return shared.MakeRPCReturn(raw, err) } func (tx *transaction) WriteDB(collection string, raw map[string]interface{}) shared.RPCReturnType { tx.gs.Logger.Println("db access in collection : ", collection, raw) _, _, err := tx.gs.mongoClient.Update(shared.CollectionName(collection), bson.M{"_id": raw["_id"]}, bson.M{ "$currentDate": bson.M{"_ts": true}, "$set": raw, }, options.Update().SetUpsert(true)) return shared.MakeRPCReturn(nil, err) } func (tx *transaction) RemoveDB(collection string, keys []interface{}) shared.RPCReturnType { count, err := tx.gs.mongoClient.DeleteMany(shared.CollectionName(collection), bson.M{"_id": bson.M{"$in": keys}}) return shared.MakeRPCReturn(count, err) } func (tx *transaction) UpdatePlayerInfo(raw map[string]interface{}) shared.RPCReturnType { var playerid string if v, ok := tx.r.Header["Player-Id"]; ok && len(v) > 0 { playerid = v[0] } else { return shared.MakeRPCReturn(nil, errors.New("no player id")) } tx.gs.Logger.Println("db write : ", playerid, raw) _, _, err := tx.gs.mongoClient.Update("PlayerInfo", bson.M{"_id": playerid}, bson.M{ "$currentDate": bson.M{"_ts": true}, "$set": raw, }, options.Update().SetUpsert(true)) if err == nil { return shared.MakeRPCReturn("update success", err) } else { return shared.MakeRPCReturn(nil, errors.New("invalid body")) } } func (tx *transaction) GetPlayerInfo() shared.RPCReturnType { var playerid string if v, ok := tx.r.Header["Player-Id"]; ok && len(v) > 0 { playerid = v[0] } else { return shared.MakeRPCReturn(nil, errors.New("no player id")) } raw, err := tx.gs.mongoClient.FindOneAndUpdate("PlayerInfo", bson.M{"_id": playerid}, bson.M{ "$setOnInsert": bson.M{"_id": playerid, "charId": 101}, }, options.FindOneAndUpdate().SetProjection(bson.M{"_id": 0, "_ts": 0}), options.FindOneAndUpdate().SetReturnDocument(options.After), options.FindOneAndUpdate().SetUpsert(true)) tx.gs.Logger.Println("db read : ", playerid, raw) if err == nil { return shared.MakeRPCReturn(raw, err) } else { return shared.MakeRPCReturn(nil, errors.New("not matched")) } } func (tx *transaction) UpdateInventory(charId int32, raw map[string]interface{}) shared.RPCReturnType { var playerid string if v, ok := tx.r.Header["Player-Id"]; ok && len(v) > 0 { playerid = v[0] } else { return shared.MakeRPCReturn(nil, errors.New("no player id")) } tx.gs.Logger.Println("inventory write : ", playerid, raw) var err error q, _ := tx.gs.mongoClient.FindOne("Inventory", bson.M{"_id": playerid, "inven.charId": charId}, options.FindOne().SetProjection(bson.M{"inven.$": 1})) if q == nil { _, _, err = tx.gs.mongoClient.Update("Inventory", bson.M{"_id": playerid}, bson.M{ "$currentDate": bson.M{"_ts": true}, "$addToSet": bson.M{"inven": bson.M{"charId": charId, "slots": raw}}, }, options.Update().SetUpsert(true)) } else { // _, _, err = tx.gs.mongoClient.Update("Inventory", // bson.M{"_id": playerid}, // bson.M{ // "$currentDate": bson.M{"_ts": true}, // "$set": bson.M{"inven.$[x].slots": raw}, // }, // options.Update().SetArrayFilters(options.ArrayFilters{Filters: bson.A{bson.M{"x.charId": charId}}}), // options.Update().SetUpsert(true)) slots := q["inven"].(bson.A)[0].(map[string]interface{})["slots"].(map[string]interface{}) tx.gs.Logger.Println("current inventory", slots) for k, v := range raw { slots[k] = v } tx.gs.Logger.Println("new inventory", slots) _, _, err = tx.gs.mongoClient.Update("Inventory", bson.M{"_id": playerid, "inven.charId": charId}, bson.M{ "$currentDate": bson.M{"_ts": true}, "$set": bson.M{"inven.$.slots": slots}, }) } if err == nil { tx.gs.Logger.Println("inventory write success") return shared.MakeRPCReturn(raw, err) } else { return shared.MakeRPCReturn(nil, errors.New("invalid body")) } } func (tx *transaction) GetInventory(charId int32) shared.RPCReturnType { var playerid string if v, ok := tx.r.Header["Player-Id"]; ok && len(v) > 0 { playerid = v[0] } else { return shared.MakeRPCReturn(nil, errors.New("no player id")) } raw, err := tx.gs.mongoClient.FindOne("Inventory", bson.M{"_id": playerid, "inven.charId": charId}, options.FindOne().SetProjection(bson.M{"inven.$": 1})) if raw == nil { _, err = tx.gs.mongoClient.FindOneAndUpdate("Inventory", bson.M{"_id": playerid}, bson.M{ "$setOnInsert": bson.M{"_id": playerid, "inven": bson.A{}}, }, options.FindOneAndUpdate().SetUpsert(true)) raw, err = tx.gs.mongoClient.FindOneAndUpdate("Inventory", bson.M{"_id": playerid}, bson.M{ "$currentDate": bson.M{"_ts": true}, "$addToSet": bson.M{"inven": bson.M{"charId": charId, "slots": bson.M{}}}, }, options.FindOneAndUpdate().SetProjection(bson.M{"inven": bson.M{"$elemMatch": bson.M{"charId": charId}}}), options.FindOneAndUpdate().SetReturnDocument(options.After), options.FindOneAndUpdate().SetUpsert(true)) } // raw, err := tx.gs.mongoClient.FindOneAndUpdate("Inventory", // bson.M{"_id": playerid, "inven.charId": charId}, // bson.M{ // "$setOnInsert": bson.M{"_id": playerid, "inven": bson.A{bson.M{"charId": charId, "slots": bson.M{}}}}, // }, // options.FindOneAndUpdate().SetProjection(bson.M{"inven.$": 1}), // options.FindOneAndUpdate().SetReturnDocument(options.After), // options.FindOneAndUpdate().SetUpsert(true)) if err == nil { slots := raw["inven"].(bson.A)[0].(map[string]interface{})["slots"] tx.gs.Logger.Println("inventory read : ", playerid, slots) return shared.MakeRPCReturn(slots, err) } else { return shared.MakeRPCReturn(nil, errors.New("not matched")) } }