示例#1
0
// List items in Player's inventory
func Action_Inventory(gs *GameServer, cp *ClientPacket) {
	plobj := cp.Client.Player

	inv := plobj.GetSubObjects().Chan()

	if len(inv) == 0 {
		cp.Reply(gnet.NewPacket("Rchat", "You have 0 items."))
	} else {
		counts := make(map[string]int)
		for sub := range inv {
			n := sub.GetName()
			if _, ok := counts[n]; ok {
				counts[n]++
			} else {
				counts[n] = 1
			}
		}

		for n, c := range counts {
			if c == 1 {
				cp.Reply(gnet.NewPacket("Rchat", fmt.Sprintf("You have a %s.", n)))
			} else {
				cp.Reply(gnet.NewPacket("Rchat", fmt.Sprintf("You have %d %ss.", c, n)))
			}

		}
	}

}
示例#2
0
// handle per-client packets
func (ws *WorldSession) ReceiveProc() {
	defer func() {
		if err := recover(); err != nil {
			log.Printf("WorldSession: ReceiveProc: %s", err)
		}
	}()

	for x := range ws.ClientRChan {
		p, ok := x.(*gnet.Packet)
		if !ok {
			log.Printf("WorldSession: ReceiveProc: bad packet %#v from %s", x, ws.Con.RemoteAddr())
			continue
		}

		cp := &ClientPacket{ws, p}

		ws.World.PacketChan <- cp
	}

	dis := &ClientPacket{ws, gnet.NewPacket("Tdisconnect", nil)}

	ws.World.PacketChan <- dis

	log.Printf("WorldSession: ReceiveProc: Channel closed %s", ws)
}
示例#3
0
// Player drops the item indicated by the ID from their inventory
// TODO: this drops all items right now. make it drop individual items
func Action_ItemDrop(gs *GameServer, cp *ClientPacket) {
	p := cp.Client.Player
	for sub := range p.GetSubObjects().Chan() {
		log.Printf("GameServer: Action_ItemDrop: %s dropping %s", p, sub)

		// remove item from player
		p.RemoveSubObject(sub)
		// put it where the player was
		sub.SetPos(p.GetPos())
		// make it visible
		sub.SetTag("visible", true)
		sub.SetTag("gettable", true)

		// update clients with the new state of this object
		gs.SendPacketAll(gnet.NewPacket("Raction", sub))
		cp.Reply(gnet.NewPacket("Rchat", fmt.Sprintf("You drop a %s.", sub.GetName())))
	}
}
示例#4
0
// Prevent User from re-adding / picking up item
// Disassociate item with map after action successful
func Action_ItemPickup(gs *GameServer, cp *ClientPacket) {
	p := cp.Client.Player

	// we assume our cp.Data is a game.Action of type ACTION_ITEM_PICKUP
	// act accordingly

	for o := range gs.Objects.Chan() {
		// if same pos.. and gettable
		if game.SamePos(o, p) && o.GetTag("gettable") {
			// pickup item.
			log.Printf("GameServer: Action_ItemPickup: %s picking up %s", p, o)
			o.SetTag("visible", false)
			o.SetTag("gettable", false)
			o.SetPos(0, 0)
			p.AddSubObject(o)

			// update clients with the new state of this object
			gs.SendPacketAll(gnet.NewPacket("Raction", o))
			cp.Reply(gnet.NewPacket("Rchat", fmt.Sprintf("You pick up a %s.", o.GetName())))
		}
	}
}
示例#5
0
func (c *ChatPanel) HandleInput(ev termbox.Event) {
	c.m.Lock()
	defer c.m.Unlock()
	switch ev.Type {
	case termbox.EventKey:
		if ev.Ch != 0 {
			c.WriteRune(ev.Ch)
		} else {
			switch ev.Key {
			case termbox.KeySpace:
				// just add a space
				c.WriteRune(' ')

			case termbox.KeyBackspace:
				fallthrough

			case termbox.KeyBackspace2:
				// on backspace, remove the last rune in the buffer
				if c.Len() > 0 {
					_, size := utf8.DecodeLastRune(c.Bytes())
					c.Truncate(c.Len() - size)
				}

			case termbox.KeyCtrlU:
				// clear the buffer, like a UNIX terminal
				c.Reset()

			case termbox.KeyEnter:
				// input confirmed, send it
				if c.Len() > 0 {
					c.g.SendPacket(gnet.NewPacket("Tchat", c.String()))
					c.Reset()
					c.term.SetInputHandler(nil)

				}
			case termbox.KeyEsc:
				// input cancelled
				c.Reset()
				c.term.SetInputHandler(nil)
			}
		}
	case termbox.EventResize:
		w, h := termbox.Size()
		r := image.Rect(w-1, h-2, w/2, h-1)
		c.Buffered = panel.NewBuffered(r, termbox.Cell{'s', termbox.ColorGreen, 0})

	}

}
示例#6
0
// Top level handler for Taction packets
func (gs *GameServer) HandleActionPacket(cp *ClientPacket) {
	action := cp.Data.(game.Action)
	p := cp.Client.Player

	_, isdir := game.DirTable[action]
	if isdir {
		gs.HandleMovementPacket(cp)
	}

	// check if this action is in our Actions table, if so execute it
	if f, ok := Actions[action]; ok {
		f(gs, cp)
	}

	gs.SendPacketAll(gnet.NewPacket("Raction", p))
}
示例#7
0
// deal with gnet.Packets received from the server
func (g *Game) HandlePacket(pk *gnet.Packet) {
	defer func() {
		if err := recover(); err != nil {
			log.Printf("Game: HandlePacket: %s", err)
		}
	}()

	log.Printf("Game: HandlePacket: %s", pk)
	switch pk.Tag {

	// Rchat: we got a text message
	case "Rchat":
		chatline := pk.Data.(string)
		io.WriteString(g.logpanel, chatline)

	// Raction: something moved on the server
	// Need to update the objects (sync client w/ srv)
	case "Raction":
		robj := pk.Data.(game.Object) // remote object

		for o := range g.Objects.Chan() {
			if o.GetID() == robj.GetID() {
				o.SetPos(robj.GetPos())
			} /*else if o.GetTag("item") {
				item := g.Objects.FindObjectByID(o.GetID())
				if item.GetTag("gettable") {
					item.SetPos(o.GetPos())
				} else {
					g.Objects.RemoveObject(item)
				}
			}	*/
		}

		// Rnewobject: new object we need to track
	case "Rnewobject":
		obj := pk.Data.(game.Object)
		g.Objects.Add(obj)

		// Rdelobject: some object went away
	case "Rdelobject":
		obj := pk.Data.(game.Object)
		g.Objects.RemoveObject(obj)

		// Rgetplayer: find out who we control
	case "Rgetplayer":
		playerid := pk.Data.(int)

		pl := g.Objects.FindObjectByID(playerid)
		if pl != nil {
			g.pm.Lock()
			g.player = pl
			g.pm.Unlock()
		} else {
			log.Printf("Game: HandlePacket: can't find our player %s", playerid)

			// just try again
			// XXX: find a better way
			time.AfterFunc(50*time.Millisecond, func() {
				g.ServerWChan <- gnet.NewPacket("Tgetplayer", nil)
			})
		}

		// Rloadmap: get the map data from the server
	case "Rloadmap":
		gmap := pk.Data.(*game.MapChunk)
		g.Map = gmap

	default:
		log.Printf("bad packet tag %s", pk.Tag)
	}

}
示例#8
0
func (g *Game) Start() {
	log.Print("Game: Starting")

	// network setup
	server, err := g.config.Get("server", reflect.String)
	if err != nil {
		log.Fatal("Game: Start: missing server in config: %s", err)
	}

	con, err := net.Dial("tcp", server.(string))
	if err != nil {
		log.Fatalf("Game: Start: Dial: %s", err)
	}

	g.ServerCon = con

	g.ServerRChan = chanio.NewReader(g.ServerCon)
	g.ServerWChan = chanio.NewWriter(g.ServerCon)

	if g.ServerRChan == nil || g.ServerWChan == nil {
		log.Fatal("Game: Start: can't establish channels")
	}

	// login
	username, err := g.config.Get("username", reflect.String)
	if err != nil {
		log.Fatal("Game: Start: missing username in config: %s", err)
	}

	g.ServerWChan <- gnet.NewPacket("Tconnect", username)

	// request the map from server
	g.ServerWChan <- gnet.NewPacket("Tloadmap", nil)

	// request the object we control
	// XXX: the delay is to fix a bug regarding ordering of packets.
	// if the client gets the response to this before he is notified
	// that the object exists, it will barf, so we delay this request.
	time.AfterFunc(50*time.Millisecond, func() {
		g.ServerWChan <- gnet.NewPacket("Tgetplayer", nil)
	})

	// anonymous function that reads packets from the server
	go func(r <-chan interface{}) {
		for x := range r {
			p, ok := x.(*gnet.Packet)
			if !ok {
				log.Printf("Game: Read: Bogus server packet %#v", x)
				continue
			}

			g.HandlePacket(p)
		}
		log.Println("Game: Read: Disconnected from server!")
		io.WriteString(g.logpanel, "Disconnected from server!")
	}(g.ServerRChan)

	// terminal/keyhandling setup
	g.Terminal.Start()

	// chat dialog
	//g.TermLog = NewTermLog(image.Pt(g.Terminal.Rect.Width-VIEW_START_X-VIEW_PAD_X, 5))

	// ESC to quit
	g.HandleKey(termbox.KeyEsc, func(ev termbox.Event) { g.CloseChan <- false })

	// Enter to chat
	g.HandleKey(termbox.KeyEnter, func(ev termbox.Event) { g.SetInputHandler(g.chatpanel) })

	// convert to func SetupDirections()
	for k, v := range CARDINALS {
		func(c rune, d game.Action) {
			g.HandleRune(c, func(_ termbox.Event) {
				// lol collision
				p := &gnet.Packet{"Taction", CARDINALS[c]}
				g.SendPacket(p)
				offset := game.DirTable[d]
				g.pm.Lock()
				defer g.pm.Unlock()
				oldposx, oldposy := g.player.GetPos()
				newpos := image.Pt(oldposx+offset.X, oldposy+offset.Y)
				if g.Map.CheckCollision(nil, newpos) {
					g.player.SetPos(newpos.X, newpos.Y)
				}
			})

			/*
				      scale := PLAYER_RUN_SPEED
							upperc := unicode.ToUpper(c)
							g.HandleRune(upperc, func(_ termbox.Event) {
								for i := 0; i < scale; i++ {
									g.Player.Move(d)
								}
							})
			*/
		}(k, v)
	}

}
示例#9
0
// Handle Directionals
func (gs *GameServer) HandleMovementPacket(cp *ClientPacket) {
	action := cp.Data.(game.Action)
	p := cp.Client.Player
	offset := game.DirTable[action]
	oldposx, oldposy := p.GetPos()
	newpos := image.Pt(oldposx+offset.X, oldposy+offset.Y)
	valid := true

	// check terrain collision
	if !gs.Map.CheckCollision(nil, newpos) {
		valid = false
		cp.Reply(gnet.NewPacket("Rchat", "Ouch! You bump into a wall."))
	}

	// check gameobject collision
	for o := range gs.Objects.Chan() {

		// check if collision with Item and item name is flag
		px, py := o.GetPos()
		if px == newpos.X && py == newpos.Y {
			collfn := luar.NewLuaObjectFromName(gs.Lua, "collide")
			res, err := collfn.Call(p, o)
			if err != nil {
				log.Printf("GameServer: HandleMovementPacket: Lua error: %s", err)
				return
			}

			// only update position if collide returns true
			if thebool, ok := res.(bool); !ok || !thebool {
				log.Printf("GameServer: HandleMovementPacket: Lua collision failed")
				valid = false
			} else {
				// tell everyone that the colliders changed
				gs.SendPacketAll(gnet.NewPacket("Raction", o))
			}

			if o.GetTag("player") {
				cp.Reply(gnet.NewPacket("Rchat", fmt.Sprintf("Ouch! You bump into %s.", o.GetName())))

				// check if other player's got the goods
				for sub := range o.GetSubObjects().Chan() {
					if sub.GetTag("item") == true {
						// swap pop'n'lock

						// remove item from player
						swap := o.RemoveSubObject(sub)
						p.AddSubObject(swap)
						cp.Reply(gnet.NewPacket("Rchat", fmt.Sprintf("You steal a %s!", swap.GetName())))
					}
				}
			}

			if o.GetTag("item") && o.GetTag("gettable") && valid {
				cp.Reply(gnet.NewPacket("Rchat", fmt.Sprintf("You see a %s here.", o.GetName())))
			}
		}
	}

	if valid {
		cp.Client.Player.SetPos(newpos.X, newpos.Y)
		//gs.SendPacketAll(gnet.NewPacket("Raction", p))
	}

}
示例#10
0
func (gs *GameServer) HandlePacket(cp *ClientPacket) {

	switch cp.Tag {

	// Tchat: chat message from a client
	case "Tchat":
		// broadcast chat
		chatline := cp.Data.(string)
		gs.SendPacketAll(gnet.NewPacket("Rchat", fmt.Sprintf("[chat] %s: %s", cp.Client.Username, chatline)))

		// Taction: movement request
	case "Taction":
		gs.HandleActionPacket(cp)

		// Tconnect: user establishes new connection
	case "Tconnect":
		username, ok := cp.Data.(string)

		if !ok {
			cp.Reply(gnet.NewPacket("Rerror", "invalid username or conversion failed"))
			break
		} else {
			cp.Client.Username = username
		}

		// make new player for client
		var newplayer game.Object
		newplayer = game.NewGameObject(username)
		newplayer.SetTag("player", true)
		newplayer.SetTag("visible", true)

		// setting this lets players pick up other players, lol
		//newplayer.SetTag("gettable", true)
		newplayer.SetGlyph(game.GLYPH_HUMAN)
		newplayer.SetPos(256/2, 256/2)

		// set the session's object
		cp.Client.Player = newplayer

		// put player object in world
		gs.Objects.Add(newplayer)

		// tell client about all other objects
		for o := range gs.Objects.Chan() {
			if o.GetID() != newplayer.GetID() {
				cp.Reply(gnet.NewPacket("Rnewobject", o))
			}
		}

		// tell all clients about the new player
		gs.SendPacketAll(gnet.NewPacket("Rnewobject", newplayer))

		// greet our new player
		cp.Reply(gnet.NewPacket("Rchat", "Welcome to Goland!"))

	case "Tdisconnect":
		// notify clients this player went away
		Action_ItemDrop(gs, cp)
		gs.Objects.RemoveObject(cp.Client.Player)
		gs.Detach(cp.Client)
		gs.SendPacketAll(gnet.NewPacket("Rdelobject", cp.Client.Player))

	case "Tgetplayer":
		if cp.Client.Player != nil {
			cp.Reply(gnet.NewPacket("Rgetplayer", cp.Client.Player.GetID()))
		} else {
			cp.Reply(gnet.NewPacket("Rerror", "nil Player in WorldSession"))
		}

	case "Tloadmap":
		cp.Reply(gnet.NewPacket("Rloadmap", gs.Map))

	default:
		log.Printf("GameServer: HandlePacket: unknown packet type %s", cp.Tag)
	}
}
示例#11
0
func (gs *GameServer) SendPkStrAll(tag string, data interface{}) {
	gs.SendPacketAll(gnet.NewPacket(tag, data))
}