Added player identification
This commit is contained in:
9
server/game/Account.go
Normal file
9
server/game/Account.go
Normal file
@ -0,0 +1,9 @@
|
||||
package game
|
||||
|
||||
// Account represents a player account
|
||||
type Account struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Password string `json:"password"`
|
||||
Position Vector3 `json:"position"`
|
||||
}
|
33
server/game/Database.go
Normal file
33
server/game/Database.go
Normal file
@ -0,0 +1,33 @@
|
||||
package game
|
||||
|
||||
var accounts = map[string]*Account{
|
||||
"user0": {
|
||||
ID: "4J6qpK1ve",
|
||||
Name: "user0",
|
||||
Password: "password",
|
||||
Position: Vector3{5, 0, 0},
|
||||
},
|
||||
"user1": {
|
||||
ID: "I_vyeZamg",
|
||||
Name: "user1",
|
||||
Password: "password",
|
||||
Position: Vector3{-5, 0, 0},
|
||||
},
|
||||
"user2": {
|
||||
ID: "VJOK1ckvx",
|
||||
Name: "user2",
|
||||
Password: "password",
|
||||
Position: Vector3{0, 0, 5},
|
||||
},
|
||||
"user3": {
|
||||
ID: "EkCcqbwFl",
|
||||
Name: "user3",
|
||||
Password: "password",
|
||||
Position: Vector3{0, 0, -5},
|
||||
},
|
||||
}
|
||||
|
||||
// GetAccountByName retrieves the account with the given name.
|
||||
func GetAccountByName(name string) *Account {
|
||||
return accounts[name]
|
||||
}
|
@ -3,61 +3,75 @@ package game
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net"
|
||||
"server/game/packet"
|
||||
)
|
||||
|
||||
var (
|
||||
LoginSuccess = []byte{0}
|
||||
LoginFailure = []byte{1}
|
||||
const (
|
||||
Success = 0
|
||||
Failure = 1
|
||||
)
|
||||
|
||||
// Login checks the account credentials and gives a network peer access to an account.
|
||||
func (game *Game) Login(data []byte, address *net.UDPAddr, server *Server) error {
|
||||
if game.players.Get(address) != nil {
|
||||
server.Send(packet.Login, []byte{Failure}, address)
|
||||
return errors.New("already logged in")
|
||||
}
|
||||
|
||||
username, password, err := getLoginData(data)
|
||||
|
||||
if err != nil {
|
||||
server.Send(packet.Login, LoginFailure, address)
|
||||
server.Send(packet.Login, []byte{Failure}, address)
|
||||
return err
|
||||
}
|
||||
|
||||
account := GetAccountByName(username)
|
||||
|
||||
if account == nil {
|
||||
server.Send(packet.Login, []byte{Failure}, address)
|
||||
return errors.New("unknown account name")
|
||||
}
|
||||
|
||||
if password != "password" {
|
||||
server.Send(packet.Login, LoginFailure, address)
|
||||
server.Send(packet.Login, []byte{Failure}, address)
|
||||
return errors.New("login failure")
|
||||
}
|
||||
|
||||
player := game.players.Get(address)
|
||||
player.AuthToken = createAuthToken()
|
||||
player.Name = username
|
||||
player := game.players.Add(address, account)
|
||||
player.authToken = createAuthToken()
|
||||
player.KeepAlive()
|
||||
|
||||
if username == "user0" {
|
||||
player.Position.X = 5.0
|
||||
}
|
||||
response := []byte{Success}
|
||||
response = appendString(response, account.ID)
|
||||
response = appendString(response, player.authToken)
|
||||
server.Send(packet.Login, response, address)
|
||||
|
||||
if username == "user1" {
|
||||
player.Position.X = -5.0
|
||||
}
|
||||
game.onLogin(player)
|
||||
return nil
|
||||
}
|
||||
|
||||
if username == "user2" {
|
||||
player.Position.Z = -5.0
|
||||
}
|
||||
|
||||
if username == "user3" {
|
||||
player.Position.Z = 5.0
|
||||
}
|
||||
|
||||
server.Send(packet.Login, append(LoginSuccess, []byte(player.AuthToken)...), address)
|
||||
player.OnConnect()
|
||||
func appendString(data []byte, str string) []byte {
|
||||
data = binary.LittleEndian.AppendUint32(data, uint32(len(str)))
|
||||
data = append(data, []byte(str)...)
|
||||
return data
|
||||
}
|
||||
|
||||
// Inform the newly logged in player about existing players.
|
||||
// Also inform existing players about the newly logged in player.
|
||||
func (game *Game) onLogin(player *Player) {
|
||||
game.players.Each(func(other *Player) bool {
|
||||
server.Send(packet.PlayerState, other.State(), address)
|
||||
game.server.Send(packet.PlayerAdd, other.State(), player.address)
|
||||
|
||||
if other != player {
|
||||
game.server.Send(packet.PlayerAdd, player.State(), other.address)
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getLoginData(data []byte) (string, string, error) {
|
||||
|
@ -8,16 +8,16 @@ import (
|
||||
|
||||
// Player represents a logged in client.
|
||||
type Player struct {
|
||||
Name string `json:"name"`
|
||||
Position Vector3 `json:"position"`
|
||||
AuthToken string
|
||||
*Account
|
||||
authToken string
|
||||
address *net.UDPAddr
|
||||
lastPacket time.Time
|
||||
}
|
||||
|
||||
// NewClient creates a new client.
|
||||
func NewClient(address *net.UDPAddr) *Player {
|
||||
// NewPlayer creates a new player.
|
||||
func NewPlayer(account *Account, address *net.UDPAddr) *Player {
|
||||
return &Player{
|
||||
Account: account,
|
||||
address: address,
|
||||
}
|
||||
}
|
||||
@ -37,9 +37,11 @@ func (c *Player) Tick() {
|
||||
// ...
|
||||
}
|
||||
|
||||
// State returns the player state (name and position).
|
||||
// State returns the player state (ID, name and position).
|
||||
func (player *Player) State() []byte {
|
||||
state := []byte(player.Name + "\u0000")
|
||||
state := []byte{}
|
||||
state = appendString(state, player.ID)
|
||||
state = appendString(state, player.Name)
|
||||
state = appendVector3(state, player.Position)
|
||||
return state
|
||||
}
|
||||
|
@ -43,9 +43,18 @@ func NewPlayerManager() *PlayerManager {
|
||||
return m
|
||||
}
|
||||
|
||||
// Add adds a new player with the given address and account.
|
||||
func (m *PlayerManager) Add(address *net.UDPAddr, account *Account) *Player {
|
||||
player := NewPlayer(account, address)
|
||||
m.players.Store(address.String(), player)
|
||||
m.count.Add(1)
|
||||
player.OnConnect()
|
||||
return player
|
||||
}
|
||||
|
||||
// Contains tells you whether the address is already a registered client.
|
||||
func (m *PlayerManager) Contains(addr *net.UDPAddr) bool {
|
||||
_, exists := m.players.Load(addr.String())
|
||||
func (m *PlayerManager) Contains(address *net.UDPAddr) bool {
|
||||
_, exists := m.players.Load(address.String())
|
||||
return exists
|
||||
}
|
||||
|
||||
@ -62,15 +71,12 @@ func (m *PlayerManager) Each(callback func(*Player) bool) {
|
||||
}
|
||||
|
||||
// Get either returns a new or existing client for the requested address.
|
||||
func (m *PlayerManager) Get(addr *net.UDPAddr) *Player {
|
||||
obj, exists := m.players.Load(addr.String())
|
||||
func (m *PlayerManager) Get(address *net.UDPAddr) *Player {
|
||||
obj, exists := m.players.Load(address.String())
|
||||
|
||||
if exists {
|
||||
return obj.(*Player)
|
||||
if !exists {
|
||||
return nil
|
||||
}
|
||||
|
||||
client := NewClient(addr)
|
||||
m.players.Store(addr.String(), client)
|
||||
m.count.Add(1)
|
||||
return client
|
||||
return obj.(*Player)
|
||||
}
|
||||
|
@ -1,8 +1,10 @@
|
||||
package packet
|
||||
|
||||
const (
|
||||
Ping = 1
|
||||
Login = 2
|
||||
Logout = 3
|
||||
PlayerState = 10
|
||||
Ping = 1
|
||||
Login = 2
|
||||
Logout = 3
|
||||
PlayerAdd = 10
|
||||
PlayerRemove = 11
|
||||
PlayerMove = 12
|
||||
)
|
||||
|
Reference in New Issue
Block a user