func addPCToTile(scene *Scene, x, y int, pc *PlayerCreature, agent *Agent) { for sum := 0; sum < 20; sum++ { for i := -10; i < 10; i++ { for j := -10; j < 10; j++ { if abs(i)+abs(j) < sum { if x+i >= int(scene.Width) || x+i < 0 { continue } if y+i >= int(scene.Height) || y+i < 0 { continue } tile := scene.Tile(x+i, y+j) if !tile.HasCreature(pc.MoveMode) { tile.addCreature(agent) log.Debugf("login player: %d to (%d %d) tile=%#v\n", pc.ObjectID, x+i, y+j, tile) pc.X = ZoneCoord_t(x + i) pc.Y = ZoneCoord_t(y + j) return } } } } } panic("should not reach here!!") }
func InitPlayer(player *Player, conn net.Conn) { player.PlayerStatus = GPS_BEGIN_SESSION player.conn = conn read := make(chan packet.Packet, 1) write := make(chan packet.Packet, 1) player.send = write player.client = read go func() { reader := packet.NewReader() player.packetReader = reader for { data, err := reader.Read(player.conn) if err != nil { if _, ok := err.(packet.NotImplementError); ok { log.Errorln("读到一个未实现的包:", data.PacketID()) } else { if err == io.EOF { log.Infoln("后台gouroutine读客户端失败了:", err) player.conn.Close() // 关闭读channel会使得agent的goroutine退出,回收资源 close(read) return } else { log.Errorln("这是一个严重的错误:", err) return } } } log.Debugln("读到了一个packet:", data) read <- data } }() go func() { writer := packet.NewWriter() player.packetWriter = writer for { pkt, ok := <-write if !ok { // 关闭使读goroutine退出 player.conn.Close() return } log.Debugf("write channel get a pkt: %#v\n", pkt) err := writer.Write(player.conn, pkt) if err != nil { log.Errorln(err) continue } } }() }
func (zone *Zone) moveCreatureBroadcast(creature CreatureInterface, x1 ZoneCoord_t, y1 ZoneCoord_t, x2 ZoneCoord_t, y2 ZoneCoord_t) { inst := creature.CreatureInstance() for ix, endx := max(0, int(x2)-int(MaxViewportWidth)-1), min(int(zone.Width)-1, int(x2)+int(MaxViewportWidth)+1); ix <= endx; ix++ { for iy, endy := max(0, int(y2)-int(MaxViewportUpperHeight)-1), min(int(zone.Height)-1, int(y2)+int(MaxViewportLowerHeight)+1); iy <= endy; iy++ { tile := zone.Tile(ix, iy) for _, obj := range tile.Objects { if agent, ok := obj.(*Agent); ok { pc := agent.PlayerCreatureInstance() log.Debugf("agent id=%d x=%d y=%d\n", pc.ObjectID, ix, iy) prevVS := getVisionState(pc.X, pc.Y, x1, y1) currVS := getVisionState(pc.X, pc.Y, x2, y2) if prevVS == OUT_OF_SIGHT && currVS == IN_SIGHT { if monster, ok := creature.(*Monster); ok { agent.sendPacket(&packet.GCAddMonster{ ObjectID: monster.ObjectID, MonsterType: monster.MonsterType, MonsterName: monster.Name, MainColor: monster.MainColor, SubColor: monster.SubColor, X: Coord_t(monster.X), Y: Coord_t(monster.Y), Dir: monster.Dir, // EffectInfo []EffectInfo CurrentHP: monster.HP[ATTR_CURRENT], MaxHP: monster.HP[ATTR_MAX], // FromFlag byte }) } } else if prevVS == IN_SIGHT && currVS == IN_SIGHT { move := &packet.GCMovePacket{ ObjectID: inst.ObjectID, X: Coord_t(inst.X), Y: Coord_t(inst.Y), Dir: inst.Dir, } agent.sendPacket(move) log.Debugln("broadcast a GCMovePacket", move) } else if prevVS == IN_SIGHT && currVS == OUT_OF_SIGHT { agent.sendPacket(&packet.GCDeleteObjectPacket{ ObjectID: inst.ObjectID, }) } } } } } }
// moveMonster func (zone *Zone) moveCreature(creature CreatureInterface, nx ZoneCoord_t, ny ZoneCoord_t, dir Dir_t) { inst := creature.CreatureInstance() cx := inst.X cy := inst.Y tile := zone.Tile(int(cx), int(cy)) newTile := zone.Tile(int(nx), int(ny)) newTile.addCreature(creature) tile.deleteCreature(inst.ObjectID) log.Debugf("monster %d move: (%d,%d)->(%d,%d) zone=%p scene=%p\n", inst.ObjectID, cx, cy, nx, ny, zone, inst.Scene) log.Debugln("tile:", newTile) inst.X = nx inst.Y = ny inst.Dir = dir // checkMine(this, pCreature, nx, ny); // checkTrap(this, pCreature); zone.moveCreatureBroadcast(creature, cx, cy, nx, ny) }