Пример #1
0
func (handler *RequestHandler) HandleRequest(request []byte) []byte {
	command, requestJson := splitOnce(request)
	logger.Infof("Got command %s and request json %s", string(command), string(requestJson))
	if handler.sessionGameWrapper == nil {
		if string(command) == api.COMMAND_NEW {
			response, game := newRequest(requestJson)
			handler.sessionGameWrapper = game
			logger.Infof("After new game request, game is now %t nil", (handler.sessionGameWrapper == nil))
			return buildResponse(command, response)
		} else {
			return buildResponse(command, respondUnknownRequest("Need new game request"))
		}
	} else {
		fun, ok := handler.gameRequest[string(command)]
		if ok {
			playerId, requestJsonNoPlayerId := splitOnce(requestJson)
			playerIdInt, err := strconv.Atoi(string(playerId))
			if err != nil {
				logger.Warnf("Not a playerId %s (%s)", playerId, err.Error())
				return buildResponse(command, respondMalformed("playerId not an int"))
			}
			logger.Infof("request for playerId %d", playerIdInt)
			response := fun(requestJsonNoPlayerId, playerIdInt, handler.sessionGameWrapper)
			return buildResponse(command, response)
		} else {
			logger.Warnf("Unknown Command %s", string(command))
			return buildResponse(command, respondUnknownRequest("Unknown command"))
		}
	}
}
Пример #2
0
func (gameWrapper *GameWrapper) verifyValidMove(unitId int, player *game.Player, locations []game.Location) error {
	if len(locations) < 1 {
		message := "must supply more than zero locations"
		logger.Warnf(message)
		return errors.New(message)
	}

	tiles := make([]game.Terrain, len(locations))
	terrain := gameWrapper.world.GetTerrain()
	for i, location := range locations {
		tiles[i] = terrain[location.GetX()][location.GetY()]
	}
	for _, location := range locations[1:] {
		err := gameWrapper.world.IsUnitAtLocation(location)
		if err != nil {
			logger.Warn(err)
			return errors.New(fmt.Sprintf("Cannot pass through units at (%d, %d)", location.GetX(), location.GetY()))
		}
	}
	unit, err := gameWrapper.world.GetAndVerifyOwnedUnit(player, unitId)
	if err != nil {
		return err
	}
	return game.ValidMove(unit.GetMovement().GetDistance(), unit.GetMovement(), tiles, locations)
}
Пример #3
0
func CommandMarshal(cmd string, payload interface{}) []byte {
	body, err := json.Marshal(payload)
	if err != nil {
		logger.Warnf("Error marshalling json: ", err)
		return nil
	}
	return append([]byte(cmd+":"), body...)
}
Пример #4
0
func (world *World) verifyOwnedUnit(player *Player, unit *Unit) error {
	if unit.nation != player.nation {
		logger.Warnf("Unit owned by %d is not owned by the current player (%d)", unit.nation, player.nation)
		return errors.New("Unit is not owned by the current player")
	} else {
		return nil
	}
}
Пример #5
0
func (gh *game_hub) handleNewGame(message string, cconn *clientConnection) {
	ng := newGame{}
	err := json.Unmarshal([]byte(message), &ng)
	if err != nil {
		logger.Warnf("Error unmarshalling json: %s", err)
		return
	}
	ng.cconn = cconn
	logger.Infof("Got new game %s", ng)
	gh.gameRequests <- &ng
}
Пример #6
0
func (gh *game_hub) handleWebsocket(message []byte, cconn *clientConnection) {
	cmds := strings.SplitN(string(message), ":", 2)
	if len(cmds) == 2 {
		if fun, ok := gh.localHandlers[cmds[0]]; ok {
			fun(cmds[1], cconn)
		} else {
			logger.Warnf("Unrecognized command: %s", cmds[0])
			cconn.toClient <- []byte("unrecognized:")
		}
	} else {
		logger.Errorf("Malformed command: %s", cmds)
	}
}
Пример #7
0
func handleConnection(netConn net.Conn) error {
	conn := connection.NewSocketConn(netConn)
	handler := request_handler.NewRequestHandler()
	for {
		logger.Infof("Handling a connection")
		request, err := conn.Read()
		if err != nil {
			logger.Warnf("Error reading request (%s)", err.Error())
			conn.Close()
			return err
		}
		logger.Debugf("Got request %s", string(request))
		response := handler.HandleRequest(request)
		logger.Debugf("Sent response %s", string(response))
		err = conn.Write(response)
		if err != nil {
			logger.Warnf("Error writing response (%s)", err.Error())
			conn.Close()
			return err
		}
	}
}
Пример #8
0
func listenForever(port int) error {
	ln, err := net.Listen("tcp", fmt.Sprintf("localhost:%d", port))
	if err != nil {
		panic(err)
	}
	for {
		conn, err := ln.Accept()
		if err != nil {
			logger.Warnf("Error accepting connection (%s)", err.Error())
			continue
		}
		go handleConnection(conn)
	}
}
Пример #9
0
func generateResponse(payload interface{}, status int) []byte {
	response, err := json.Marshal(api.ResponseType{Status: status, Payload: payload})
	if err != nil {
		logger.Warnf("Could not generate response: %s", err.Error())
		backupResponse, err := json.Marshal(api.ResponseType{
			Status:  api.STATUS_UNSERIALIZEABLE_RESPONSE,
			Payload: "problem"})
		if err != nil {
			return []byte("Really bad")
		}
		logger.Infof("Generating response with status %d", status)
		logger.Debugf("Full message %s", string(response))
		return backupResponse
	}
	logger.Infof("Generating response with status %d", status)
	logger.Debugf("Full message %s", string(response))
	return response
}
Пример #10
0
func (gh *game_hub) handleClientInfo(message string, cconn *clientConnection) {
	ci := clientInfo{}
	resp := response{0, nil}
	// I hate repeating this unmarshalling code, does Go allow something more general?
	err := json.Unmarshal([]byte(message), &ci)
	if err != nil {
		logger.Warnf("Error unmarshalling json: %s", err)
		return
	}
	userid, err := getClientIdFromToken(ci.Token)
	if err != nil {
		logger.Errorf("Error querying database: %s", err)
		resp.Status = -1
		cconn.toClient <- CommandMarshal("clientInfo", resp)
		return
	}
	ci.id = userid
	cconn.info = ci
	cconn.toClient <- CommandMarshal("clientInfo", resp)
}
Пример #11
0
func (world *World) AddUnit(
	location Location, name string, nation nation,
	health int, attacks []*attack, armor *armor, movement *Movement) error {
	logger.Infof("Adding unit at (x: %d, y: %d)", location.x, location.y)
	unitId := world.nextUnitId
	_, okUnitLocation := world.unitMap[location]
	_, okUnitId := world.units[unitId]
	if !(okUnitLocation && okUnitId) {
		newUnit := NewUnit(
			name, unitId, nation, health, attacks, armor, movement)
		world.unitMap[location] = newUnit
		world.units[unitId] = newUnit
		world.nextUnitId += 1
		logger.Infof("Added unit with id %d at (x: %d, y: %d)", unitId, location.x, location.y)
		return nil
	} else {
		logger.Warnf("Failed to add unit with id %d at (x: %d, y: %d)", unitId, location.x, location.y)
		return errors.New("location already occupied")
	}
}
Пример #12
0
func serveWs(w http.ResponseWriter, r *http.Request) {
	if r.Method != "GET" {
		http.Error(w, "Method not allowed", 405)
		return
	}
	if strings.Split(r.Header.Get("Origin"), ":")[1] != strings.Split("http://"+r.Host, ":")[1] {
		logger.Warnf("Cross origin problem: %s", r.Host)
		http.Error(w, "Origin not allowed", 403)
		return
	}
	ws, err := websocket.Upgrade(w, r, nil, 1024, 1024)
	if _, ok := err.(websocket.HandshakeError); ok {
		http.Error(w, "Not a websocket handshake", 400)
		return
	} else if err != nil {
		logger.Errorf("Websocket upgrade error: %s", err)
		return
	}
	ws.SetReadLimit(RECV_BUF_LEN)
	conn := NewWebsocketConn(ws)
	gamehub.connRegister <- conn
}
Пример #13
0
func (gh *game_hub) processNewGameRequests() {
	for ng := range gh.gameRequests {
		// look for an existing game to satisfy the new request
		gm, err := gh.findGame(ng)
		// an error here implies duplicate player ids in game requests
		if err != nil {
			logger.Warnf("Player with id %d attempted a \"self\" game", ng.cconn.info.id)
			return
		}
		// create a game if one can't be found
		if gm == nil {
			logger.Info("Couldn't find an available game. Creating a new one")
			gm = gh.makeGame(ng.NumPlayers)
		} else {
			logger.Info("Found existing game. Slotting in")
		}
		gm.proxy.slotClientConnection(gm.currentPlayers, ng.cconn)
		gm.currentPlayers += 1
		if gm.currentPlayers == gm.numPlayers {
			gh.commitGame(gm)
		}
	}
}
Пример #14
0
func (world *World) MoveUnitFromTo(unitId int, start Location, end Location) error {
	unit, err := world.GetUnitAtLocation(start)
	if err != nil {
		return err
	}
	verifiedUnit, err := world.GetUnitFromId(unitId)
	if err != nil {
		return err
	}
	if unit != verifiedUnit {
		message := fmt.Sprintf("Unit with given unitId (%d) isn't at the specified location (%d, %d)", unitId, start.x, start.y)
		logger.Warnf(message)
		return errors.New(message)
	}
	unit.canMove = false
	err = world.IsUnitAtLocation(end)
	if err != nil {
		return err
	} else {
		world.unitMap[end] = unit
		delete(world.unitMap, start)
		return nil
	}
}
Пример #15
0
func NewWorld(playerIds []int, worldId int) (*World, error) {
	db, err := newDatabase()
	if err != nil {
		logger.Errorf("DB is open and cannot be used (%s)", err.Error())
		return nil, err
	}
	defer db.Close()
	terrains, err := loadTerrains(db)
	if err != nil {
		return nil, err
	}
	nations, err := loadNations(db)
	if err != nil {
		return nil, err
	}
	numPlayers := len(playerIds)
	if numPlayers > 4 || numPlayers < 1 {
		logger.Warnf("Must have between 1 and 4 players, got %d", numPlayers)
		return nil, errors.New("must have between 1 and 4 players")
	}
	if len(nations) < numPlayers {
		logger.Errorf("Not enough nations were loaded, must have at least 2, got %s", nations)
		return nil, errors.New("Not enough nations were loaded, must have at least 2")
	}
	players := make([]*Player, numPlayers)
	for i, playerId := range playerIds {
		players[i] = NewPlayer(playerId, nations[i], team(i))
	}

	if len(terrains) < 2 {
		return nil, errors.New("No terrains were loadable")
	}
	plains := terrains[0]
	roads := terrains[1]

	ret_world := &World{
		terrain: [][]Terrain{
			[]Terrain{plains, roads, plains, plains, plains, plains, plains, plains},
			[]Terrain{plains, roads, plains, plains, plains, plains, plains, plains},
			[]Terrain{roads, roads, roads, plains, plains, plains, plains, plains},
			[]Terrain{plains, plains, roads, plains, plains, plains, plains, plains},
			[]Terrain{plains, plains, roads, plains, plains, plains, plains, plains},
			[]Terrain{plains, plains, plains, plains, plains, plains, plains, plains}},
		unitMap:    make(map[Location]*Unit),
		units:      make(map[int]*Unit),
		players:    players,
		numPlayers: numPlayers,
		turnOwner:  0,
		nextUnitId: 0}
	if worldId == 0 {
		name := "warrior"
		dbHealth, dbAttacks, dbArmor, dbMovement, err := loadUnit(db, name)
		if err != nil {
			return nil, err
		}
		ret_world.AddUnit(NewLocation(0, 0), name, nations[0], dbHealth, dbAttacks, dbArmor, dbMovement)
		name = "mage"
		dbHealth, dbAttacks, dbArmor, dbMovement, err = loadUnit(db, name)
		if err != nil {
			return nil, err
		}
		ret_world.AddUnit(NewLocation(3, 3), name, nations[0], dbHealth, dbAttacks, dbArmor, dbMovement)
		if numPlayers == 2 {
			ret_world.AddUnit(NewLocation(0, 3), name, nations[1], dbHealth, dbAttacks, dbArmor, dbMovement)
		}
	}
	return ret_world, nil
}