diff --git a/habbgo/database/room_repo.go b/habbgo/database/room_repo.go index 11c3d95..bec6c19 100644 --- a/habbgo/database/room_repo.go +++ b/habbgo/database/room_repo.go @@ -1,6 +1,10 @@ package database -import "database/sql" +import ( + "database/sql" + "github.com/jtieri/HabbGo/habbgo/game/model" + "log" +) type RoomRepo struct { database *sql.DB @@ -9,3 +13,39 @@ type RoomRepo struct { func NewRoomRepo(db *sql.DB) *RoomRepo { return &RoomRepo{database: db} } + +func (rr *RoomRepo) RoomsByPlayerId(id int) []*model.Room { + stmt, err := rr.database.Prepare("SELECT r.id, r.cat_id, r.name, r.`desc`, r.ccts, r.wallpaper, r.floor, r.landscape, r.owner_id, r.owner_name, r.show_owner, r.sudo_users, r.access_type, r.password, r.current_visitors, r.max_visitors, r.rating FROM rooms r WHERE r.owner_id = ?") + if err != nil { + log.Printf("%v", err) + } + defer stmt.Close() + + rows, err := stmt.Query(id) + if err != nil { + log.Printf("%v", err) + } + defer rows.Close() + + var rooms []*model.Room + for rows.Next() { + room := new(model.Room) + room.Details = new(model.Data) + + err := rows.Scan(&room.Details.Id, &room.Details.CatId, &room.Details.Name, &room.Details.Desc, &room.Details.CCTs, + &room.Details.Wallpaper, &room.Details.Floor, &room.Details.Landscape, &room.Details.Owner_Id, &room.Details.Owner_Name, + &room.Details.ShowOwner, &room.Details.SudoUsers, &room.Details.AccessType, &room.Details.Password, + &room.Details.CurrentVisitors, &room.Details.MaxVisitors, &room.Details.Rating) + if err != nil { + log.Printf("%v", err) + } + + rooms = append(rooms, room) + } + + return rooms +} + +func (rr *RoomRepo) fillData(data *model.Data) { + +} \ No newline at end of file diff --git a/habbgo/game/model/room.go b/habbgo/game/model/room.go index 92af7b2..ecb3273 100644 --- a/habbgo/game/model/room.go +++ b/habbgo/game/model/room.go @@ -3,7 +3,7 @@ package model type Room struct { Details *Data Model *Model - Map *Map + //Map *Map } type Data struct { @@ -25,8 +25,6 @@ type Data struct { CurrentVisitors int MaxVisitors int Rating int - CreatedAt string - UpdatedAt string ChildRooms []*Room } diff --git a/habbgo/game/service/navigator_service.go b/habbgo/game/service/navigator_service.go index 5de485f..2a51de6 100644 --- a/habbgo/game/service/navigator_service.go +++ b/habbgo/game/service/navigator_service.go @@ -63,3 +63,27 @@ func (ns *navService) CategoriesByParentId(pid int) []*model.Category { return categories } + +func CurrentVisitors(cat *model.Category) int { + visitors := 0 + + for _, room := range RoomService().Rooms() { + if room.Details.CatId == cat.Id { + visitors += room.Details.CurrentVisitors + } + } + + return visitors +} + +func MaxVisitors(cat *model.Category) int { + visitors := 0 + + for _, room := range RoomService().Rooms() { + if room.Details.CatId == cat.Id { + visitors += room.Details.MaxVisitors + } + } + + return visitors +} diff --git a/habbgo/game/service/player_service.go b/habbgo/game/service/player_service.go index 7648b55..4dbd635 100644 --- a/habbgo/game/service/player_service.go +++ b/habbgo/game/service/player_service.go @@ -3,7 +3,6 @@ package service import ( "github.com/jtieri/HabbGo/habbgo/database" "github.com/jtieri/HabbGo/habbgo/game/model" - "github.com/jtieri/HabbGo/habbgo/protocol/composers" ) func Login(player *model.Player) { @@ -15,7 +14,6 @@ func Login(player *model.Player) { // Log IP address to Conn database.LoadBadges(player) - go player.Session.Send(composers.ComposeLoginOk()) // If Config has alerts enabled, send player ALERT diff --git a/habbgo/game/service/room_service.go b/habbgo/game/service/room_service.go index 873ad88..b6cf5fd 100644 --- a/habbgo/game/service/room_service.go +++ b/habbgo/game/service/room_service.go @@ -4,22 +4,24 @@ import ( "database/sql" "github.com/jtieri/HabbGo/habbgo/database" "github.com/jtieri/HabbGo/habbgo/game/model" + "strings" "sync" ) var rs *roomService var ronce sync.Once +const PublicRoomOffset = 1000 type roomService struct { repo *database.RoomRepo - rooms []*model.Room + rooms map[int]*model.Room } func RoomService() *roomService { ronce.Do(func() { rs = &roomService{ repo: nil, - rooms: make([]*model.Room, 50), + rooms: make(map[int]*model.Room, 50), } }) @@ -29,3 +31,103 @@ func RoomService() *roomService { func (rs *roomService) SetDBConn(db *sql.DB) { rs.repo = database.NewRoomRepo(db) } + +func (rs *roomService) Rooms() []*model.Room { + var rooms []*model.Room + for _, room := range rs.rooms { + rooms = append(rooms, room) + } + return rooms +} + +func (rs *roomService) RoomById(id int) *model.Room { + if room, ok := rs.rooms[id]; ok { + return room + } + return nil +} + +func (rs *roomService) RoomsByPlayerId(id int) []*model.Room { + return rs.repo.RoomsByPlayerId(id) +} + +func (rs *roomService) RoomByModelName(name string) *model.Room { + return &model.Room{} +} + +func (rs *roomService) ReplaceRooms(queryRooms []*model.Room) []*model.Room { + var rooms []*model.Room + + for _, room := range queryRooms { + if _, ok := rs.rooms[room.Details.Id]; ok { + rooms = append(rooms, rs.RoomById(room.Details.Id)) + } else { + rooms = append(rooms, room) + } + } + + return rooms +} + +func AccessType(accessId int) string { + switch accessId { + case 1: + return "closed" + case 2: + return "password" + default: + return "open" + } +} + +func (rs *roomService) PublicRoom(room *model.Room) bool { + if room.Details.Owner_Id == 0 { + return true + } else { + return false + } +} + +func (rs *roomService) PublicName(room *model.Room) string { + if rs.PublicRoom(room) { + if strings.HasPrefix(room.Details.Name, "Upper Hallways") { + return "Upper Hallways" + } + + if strings.HasPrefix(room.Details.Name, "Lower Hallways") { + return "Lower Hallways" + } + + if strings.HasPrefix(room.Details.Name, "Club Massiva") { + return "Club Massiva" + } + + if strings.HasPrefix(room.Details.Name, "The Chromide Club") { + return "The Chromide Club" + } + + if room.Details.CCTs == "hh_room_gamehall,hh_games" { + return "Cunning Fox Gamehall" + } + } + + return room.Details.Name +} + +func (rs *roomService) CurrentVisitors() int { + var visitors int + + return visitors +} + +func (rs *roomService) MaxVisitors() int { + var visitors int + + return visitors +} + +func (rs *roomService) LoadChildRooms(room *model.Room) { + if room.Model.Name == "gate_park" { + room.Details.ChildRooms = append(room.Details.ChildRooms, ) + } +} \ No newline at end of file diff --git a/habbgo/protocol/composers/navigator_composers.go b/habbgo/protocol/composers/navigator_composers.go index 8f0019c..0bc597d 100644 --- a/habbgo/protocol/composers/navigator_composers.go +++ b/habbgo/protocol/composers/navigator_composers.go @@ -2,66 +2,87 @@ package composers import ( "github.com/jtieri/HabbGo/habbgo/game/model" + "github.com/jtieri/HabbGo/habbgo/game/service" "github.com/jtieri/HabbGo/habbgo/protocol/packets" + "strconv" + "strings" ) -func ComposeNavNodeInfo(player *model.Player, cat *model.Category, nodeMask bool) *packets.OutgoingPacket { +func ComposeNavNodeInfo(player *model.Player, cat *model.Category, nodeMask bool, subcats []*model.Category, rooms []*model.Room, currentVisitors int, maxVisitors int) *packets.OutgoingPacket { p := packets.NewOutgoing(220) // Base64 Header C\ - // player - // category - // rooms - // nodemask - // subCategories - // currentVisitors - // maxVisitors - // accessRank + p.WriteBool(nodeMask) // hideCategory + p.WriteInt(cat.Id) - p.WriteBool(nodeMask) // writeBool NodeMask - p.WriteInt(cat.Id) // writeInt CategoryId - p.WriteBool(cat.Public) // writeBool publicSpace - p.WriteString(cat.Name) // writeString CategoryName - // writeInt categoryCurrentVisitors - // writeInt categoryMaxVisitors - // writeInt parentCategoryId - - // if category is for public rooms writeInt numberOfRooms if cat.Public { - + p.WriteInt(0) + } else { + p.WriteInt(2) } - // iterate over rooms - // if room is public - // writeInt roomId - // writeInt 1 - // writeString roomName - // writeInt currentVisitors - // writeInt maxVisitors - // writeInt catId - // writeString roomDesc - // writeInt roomId - // writeInt door - // writeString roomCCTs - // writeInt 0 - // writeInt 1 + p.WriteString(cat.Name) + p.WriteInt(currentVisitors) + p.WriteInt(maxVisitors) + p.WriteInt(cat.Pid) - // if room is not private - // writeInt roomId - // writeString roomName - // writeString ownerName or - - // writeString accessType - // writeInt currentVisitors - // writeInt maxVisitors - // writeString roomDesc + if !cat.Public { + p.WriteInt(len(rooms)) + } + + for _, room := range rooms { + if room.Details.Owner_Id == 0 { // if room is public + desc := room.Details.Desc + + var door int + if strings.Contains(desc, "/") { + data := strings.Split(desc, "/") + desc = data[0] + door, _ = strconv.Atoi(data[1]) + } + + p.WriteInt(room.Details.Id + service.PublicRoomOffset)// writeInt roomId + p.WriteInt(1) // writeInt 1 + p.WriteString(room.Details.Name)// writeString roomName + p.WriteInt(room.Details.CurrentVisitors) // writeInt currentVisitors + p.WriteInt(room.Details.MaxVisitors) // writeInt maxVisitors + p.WriteInt(room.Details.CatId) // writeInt catId + p.WriteString(desc)// writeString roomDesc + p.WriteInt(room.Details.Id) // writeInt roomId + p.WriteInt(door) // writeInt door + p.WriteString(room.Details.CCTs)// writeString roomCCTs + p.WriteInt(0) // writeInt 0 + p.WriteInt(1) // writeInt 1 + } else { + p.WriteInt(room.Details.Id) + p.WriteString(room.Details.Name) + + // TODO check that player is owner of room, that room is showing owner name, or that player has right SEE_ALL_ROOMOWNERS + if player.Details.Username == room.Details.Owner_Name { + p.WriteString(room.Details.Owner_Name) + } else { + p.WriteString("-") + } + + p.WriteString(service.AccessType(room.Details.AccessType)) + p.WriteInt(room.Details.CurrentVisitors) + p.WriteInt(room.Details.MaxVisitors) + p.WriteString(room.Details.Desc) + } + } // iterate over sub-categories - // if user can access sub-cats - // writeInt subCategoryId - // writeInt 0 - // writeString subCatName - // writeInt currentVisitors - // writeInt maxVisitors - // writeInt categoryId + for _, subcat := range subcats { + if subcat.MinRankAccess > 1 { + continue + } + + p.WriteInt(subcat.Id) + p.WriteInt(0) + p.WriteString(subcat.Name) + p.WriteInt(service.CurrentVisitors(subcat))// writeInt currentVisitors + p.WriteInt(service.MaxVisitors(subcat))// writeInt maxVisitors + p.WriteInt(cat.Id) + } return p } diff --git a/habbgo/protocol/handlers/handshake_handlers.go b/habbgo/protocol/handlers/handshake_handlers.go index 4a9d3cd..2c7a282 100644 --- a/habbgo/protocol/handlers/handshake_handlers.go +++ b/habbgo/protocol/handlers/handshake_handlers.go @@ -37,6 +37,7 @@ func HandleTryLogin(player *model.Player, packet *packets.IncomingPacket) { if database.Login(player, username, password) { service.Login(player) + player.Session.Send(composers.ComposeLoginOk()) } else { // TODO send LOCALISED ERROR } diff --git a/habbgo/protocol/handlers/navigator_handlers.go b/habbgo/protocol/handlers/navigator_handlers.go index a7a4cdb..fad21c7 100644 --- a/habbgo/protocol/handlers/navigator_handlers.go +++ b/habbgo/protocol/handlers/navigator_handlers.go @@ -8,23 +8,43 @@ import ( ) func HandleNavigate(player *model.Player, packet *packets.IncomingPacket) { - nodeMask := packet.ReadBool() + roomService := service.RoomService() + + nodeMask := packet.ReadInt()==1 catId := packet.ReadInt() - // get category using catID + if catId >= service.PublicRoomOffset { + room := roomService.RoomById(catId - service.PublicRoomOffset) + if room != nil { + catId = room.Details.CatId + } + } + category := service.NavigatorService().CategoryById(catId) + // TODO also check that access rank isnt higher than players rank if category == nil { return } - // if minrank for cat is > playerRank then return without sending response - - // get sub categories of category + subCategories := service.NavigatorService().CategoriesByParentId(category.Id) // sort categories by player count - // get category currentvisitors - // get category maxvisitors + currentVisitors := service.CurrentVisitors(category) + maxVisitors := service.MaxVisitors(category) - player.Session.Send(composers.ComposeNavNodeInfo(player, category, nodeMask)) + var rooms []*model.Room + if category.Public { + for _, room := range roomService.ReplaceRooms(roomService.RoomsByPlayerId(0)) { + if room.Details.CatId == category.Id && (!nodeMask) && room.Details.CurrentVisitors < room.Details.MaxVisitors { + rooms = append(rooms, room) + } + } + } else { + // TODO finish private room logic + } + + // TODO sort rooms by player count before sending NavNodeInfo + + player.Session.Send(composers.ComposeNavNodeInfo(player, category, nodeMask, subCategories, rooms, currentVisitors, maxVisitors)) }