Exemple #1
0
func getPlayerKick(login, message string) (*Player, error) {
	filename := loginToFilename(login)

	f, err := os.Open(filename)
	if err != nil {
		return nil, err
	}
	defer f.Close()

	g, err := gzip.NewReader(f)
	if err != nil {
		panic(err)
	}
	defer g.Close()

	var data interface{}
	err = gob.NewDecoder(g).Decode(&data)
	if err != nil {
		panic(err)
	}

	p := world.LoadConvert(data).(*Player)

	if o, ok := onlinePlayers[p.login]; ok {
		p = o
		savePlayer(p)
		p.Kick(message)
		delete(onlinePlayers, p.login)
	}

	return p, nil
}
Exemple #2
0
func (p *Player) Impersonate(o world.Visible) {
	if o == nil || o == p {
		if pos := p.Position(); pos != nil {
			pos.Zone().Impersonate(p, nil)
		}

		p.mtx.Lock()
		if p.impersonating != nil {
			p.impersonating = nil
			p.mtx.Unlock()
			if pos := p.Position(); pos != nil {
				pos.Zone().Update(pos, p)
			}
		} else {
			p.mtx.Unlock()
		}

		return
	}

	if other, ok := o.(*Player); ok {
		h := other.Hero
		o = &h
	}

	// copy the object
	o = world.LoadConvert(world.SaveConvert(o)).(world.Visible)

	if pos := p.Position(); pos != nil {
		pos.Zone().Impersonate(p, o)
	}

	p.mtx.Lock()
	p.impersonating = o
	p.mtx.Unlock()
	if pos := p.Position(); pos != nil {
		pos.Zone().Update(pos, p)
	}
}
Exemple #3
0
// Login returns a non-nil player and an empty error string OR a nil player
// and an error to show to the user.
func Login(addr string, packet *LoginPacket) (*Player, string) {
	login := strings.TrimSpace(packet.Login)
	if login == "" {
		return nil, "A username is required."
	}
	pass := []byte(packet.Pass)
	if len(pass) <= 2 {
		return nil, "A password is required."
	}
	filename := loginToFilename(login)

	loginLock.Lock()
	defer loginLock.Unlock()

	loginAttempts[addr]++
	if loginAttempts[addr] == 5 {
		loginAttempts[addr] += 60
	}
	if loginAttempts[addr] > 5 {
		return nil, fmt.Sprintf("Too many login attempts. Come back in %d minutes.", loginAttempts[addr]-5)
	}

	f, err := os.Open(filename)
	if err != nil {
		hashedPass, err := bcrypt.GenerateFromPassword(pass, CryptoCost)
		if err != nil {
			panic(err)
		}
		p := &Player{
			Hero:              *GenerateHero(rand.New(rand.NewSource(rand.Int63()))),
			characterCreation: true,
			tileX:             127,
			tileY:             127,
			login:             login,
			password:          hashedPass,
			firstAddr:         addr,
			registered:        time.Now().UTC(),
			lastAddr:          addr,
			lastLogin:         time.Now().UTC(),
		}
		world.InitObject(p)
		for _, e := range p.Hero.equipped {
			e.wearer = p
		}
		savePlayer(p)
		onlinePlayers[login] = p
		return p, ""
	}
	defer f.Close()

	g, err := gzip.NewReader(f)
	if err != nil {
		panic(err)
	}
	defer g.Close()

	var data interface{}
	err = gob.NewDecoder(g).Decode(&data)
	if err != nil {
		panic(err)
	}

	p := world.LoadConvert(data).(*Player)

	if bcrypt.CompareHashAndPassword(p.password, pass) != nil {
		return nil, "Username or password incorrect."
	}

	loginAttempts[addr]--

	if other, ok := onlinePlayers[p.login]; ok {
		savePlayer(other)
		other.Kick("Logged in from a different location.")
		_, err = f.Seek(0, 0)
		if err != nil {
			panic(err)
		}

		g, err = gzip.NewReader(f)
		if err != nil {
			panic(err)
		}
		defer g.Close()

		data = nil
		err = gob.NewDecoder(g).Decode(&data)
		if err != nil {
			panic(err)
		}
		p = world.LoadConvert(data).(*Player)
	}

	cost, err := bcrypt.Cost(p.password)
	if err != nil {
		panic(err)
	}
	if cost != CryptoCost {
		p.password, err = bcrypt.GenerateFromPassword(pass, CryptoCost)
		if err != nil {
			panic(err)
		}
		savePlayer(p)
	}

	onlinePlayers[p.login] = p

	return p, ""
}