Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package main
- import (
- "bufio"
- "encoding/json"
- "errors"
- "fmt"
- "math/rand"
- "net"
- )
- type PlayerMovement struct {
- ID int `json:"id,omitempty"`
- X int `json:"x"`
- Y int `json:"y"`
- Command string `json:"cmd"`
- }
- type PlayerJoin struct {
- ID int `json:"id"`
- X int `json:"x"`
- Y int `json:"y"`
- R int `json:"r"`
- Command string `json:"cmd"`
- }
- type PlayerInit struct {
- ID int `json:"id"`
- X int `json:"x"`
- Y int `json:"y"`
- R int `json:"r"`
- WW int `json:"ww"`
- WH int `json:"wh"`
- Command string `json:"cmd"`
- }
- type PlayerExit struct {
- ID int `json:"id"`
- Command string `json:"cmd"`
- }
- type Player struct {
- ID int `json:"id"`
- X int `json:"x"`
- Y int `json:"y"`
- Connection net.Conn
- SendChan chan []byte
- Closed bool
- }
- func NewPlayer(conn net.Conn, id int, x int, y int) *Player {
- return &Player{
- ID: id,
- X: x,
- Y: y,
- Connection: conn,
- SendChan: make(chan []byte, 128),
- }
- }
- func (player *Player) Sender() {
- writer := bufio.NewWriter(player.Connection)
- for packet := range player.SendChan {
- writer.Write(packet)
- writer.WriteByte('\x00')
- writer.Flush()
- }
- }
- func (player *Player) Send(packet []byte) error {
- if player.Closed {
- return errors.New("closed")
- }
- select {
- case player.SendChan <- packet:
- return nil
- default:
- return errors.New("send queue full")
- }
- }
- func (player *Player) Run() {
- reader := bufio.NewReader(player.Connection)
- go player.Sender()
- for {
- data, err := reader.ReadSlice('\x00')
- if err == nil {
- var mv PlayerMovement
- err = json.Unmarshal(data[0:len(data)-1], &mv)
- if err == nil {
- mv.ID = player.ID
- moves <- mv
- } else {
- exits <- player
- break
- }
- } else {
- exits <- player
- break
- }
- }
- }
- func (player *Player) Close() {
- if !player.Closed {
- player.Closed = true
- close(player.SendChan)
- player.Connection.Close()
- }
- }
- const (
- WindowWidth = 700
- WindowHeight = 500
- RSize = 30
- )
- var (
- joins = make(chan *Player)
- exits = make(chan *Player)
- moves = make(chan PlayerMovement)
- )
- func netLoop() {
- listener, err := net.Listen("tcp", ":5588")
- if err != nil {
- panic(err)
- }
- counter := 0
- for {
- conn, err := listener.Accept()
- if err == nil {
- counter++
- joins <- NewPlayer(conn, counter, 0, 0)
- }
- }
- }
- func gameLoop() {
- players := make(map[int]*Player, 0)
- for {
- select {
- case joining := <-joins:
- fmt.Println("Joining", joining.Connection.RemoteAddr())
- go joining.Run()
- joining.X = rand.Intn(500-100) + 100
- joining.Y = rand.Intn(500-100) + 100
- join := PlayerJoin{
- ID: joining.ID,
- X: joining.X,
- Y: joining.Y,
- R: RSize,
- Command: "join",
- }
- init := PlayerInit{
- ID: joining.ID,
- X: joining.X,
- Y: joining.Y,
- R: RSize,
- WW: WindowWidth,
- WH: WindowHeight,
- Command: "init",
- }
- jpacket, _ := json.Marshal(&join)
- ipacket, _ := json.Marshal(&init)
- if joining.Send(ipacket) != nil {
- joining.Close()
- break
- }
- for _, player := range players {
- if player.Send(jpacket) != nil {
- player.Close()
- }
- oldJoin := PlayerJoin{
- ID: player.ID,
- X: player.X,
- Y: player.Y,
- R: RSize,
- Command: "join",
- }
- opacket, _ := json.Marshal(oldJoin)
- if joining.Send(opacket) != nil {
- joining.Close()
- break
- }
- }
- players[joining.ID] = joining
- case leaving := <-exits:
- fmt.Println("Leaving", leaving.Connection.RemoteAddr())
- delete(players, leaving.ID)
- exit := PlayerExit{ID: leaving.ID, Command: "exit"}
- packet, _ := json.Marshal(&exit)
- for _, player := range players {
- if player.Send(packet) != nil {
- player.Close()
- }
- }
- leaving.Close()
- case movement := <-moves:
- packet, _ := json.Marshal(&movement)
- player := players[movement.ID]
- player.X = movement.X
- player.Y = movement.Y
- for _, player := range players {
- if player.Send(packet) != nil {
- player.Close()
- }
- }
- }
- }
- }
- func main() {
- go netLoop()
- gameLoop()
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement