Beispiel #1
0
func (player *Player) mainLoop() {
	defer func() {
		// Close the transmitLoop and receiveLoop cleanly.
		player.txQueue <- nil
		player.conn.Close()

		player.onDisconnect <- player.EntityId

		if player.ping.timer != nil {
			player.ping.timer.Stop()
		}

		buf := new(bytes.Buffer)
		proto.WriteUserListItem(buf, player.name, false, 0)
		player.game.BroadcastPacket(buf.Bytes())
	}()

	expVarPlayerConnectionCount.Add(1)
	defer expVarPlayerDisconnectionCount.Add(1)

	player.chunkSubs.Init(player)
	defer player.chunkSubs.Close()

	// Start the keep-alive/latency pings.
	player.pingNew()

	player.sendChatMessage(fmt.Sprintf("%s has joined", player.name), false)

MAINLOOP:
	for {
		select {
		case _ = <-player.stopPlayer:
			break MAINLOOP

		case f, ok := <-player.mainQueue:
			if !ok {
				return
			}
			player.runQueuedCall(f)

		case _ = <-player.ping.timer.C:
			player.pingTimeout()

		case err := <-player.rxErrChan:
			log.Printf("%v: receive loop failed: %v", player, err)
			player.Stop()

		case err := <-player.txErrChan:
			log.Printf("%v: send loop failed: %v", player, err)
			player.Stop()
		}
	}
}
Beispiel #2
0
// pingReceived is called when a keep alive packet is received.
func (player *Player) pingReceived(id int32) {
	if id == 0 {
		// Client-initiated keep-alive.
		return
	}

	if *playerPingNoCheck {
		if !player.ping.running {
			return
		}
	} else {
		if !player.ping.running {
			log.Printf("%v: Received keep-alive id=%d when none was running", player, id)
			player.Stop()
			return
		} else if id != player.ping.id {
			log.Printf("%v: Bad keep alive ID received", player)
			player.Stop()
			return
		}
	}

	// Received valid keep-alive.
	now := time.Now()

	if player.ping.timer != nil {
		player.ping.timer.Stop()
	}

	latencyNs := now.Sub(time.Unix(0, player.ping.timestampNs))
	// Check that there wasn't an apparent time-shift on this before broadcasting
	// this latency value.
	if latencyNs >= 0 && latencyNs < PingTimeoutNs {
		buf := new(bytes.Buffer)
		proto.WriteUserListItem(buf, player.name, true, int16(latencyNs/1e6))
		player.game.BroadcastPacket(buf.Bytes())
	}

	player.ping.running = false
	player.ping.id = 0
	player.ping.timer = time.NewTimer(PingIntervalNs)
}