Пример #1
0
def request_hexinfo(_cls, _self, _data):
    """ヘックスの情報を取得"""

    payload = {"event": "response_hexinfo", "data": {}}

    data = {"hex_info": {}}

    # 取得しているプレイヤーの情報
    self_id = _self.get_secure_cookie("user_id").decode('utf-8')
    self_info = get_playerinfo_by_id(self_id)

    # ヘックスの情報
    hex_info = get_hexinfo(_data["col"], _data["row"])
    if hex_info == None:
        logging.error("failed to retrieve hex_info : " + str(data["col"]) +
                      " , " + str(data["row"]))
        _cls.send_error(_self, "エラーでキャンセルされた")

    data["hex_info"]["type"] = hex_info["type"]
    if hex_info[self_info["visibility"]] > 0:
        # 可視範囲ならより詳細な情報取得
        data["hex_info"]["food"] = hex_info["food"]
        data["hex_info"]["money"] = hex_info["money"]

    # 在中プレイヤーの情報
    other_player = get_players_by_visibility(self_info["visibility"], True,
                                             [{
                                                 "col": _data["col"],
                                                 "row": _data["row"]
                                             }])
    if len(other_player) != 0:

        # プレイヤー情報
        data["player_info"] = {}
        other_player = other_player[0]
        data["player_info"]["player_name"] = other_player["user_name"]
        country_id = other_player["country_id"]
        country_info = get_countryinfo_by_id(other_player["country_id"])
        data["player_info"]["country_name"] = country_info["country_name"]

    # 部隊情報
    division_info = get_division_info_by_colrow(_data["col"], _data["row"])
    if division_info:
        branch_info = get_branch_info(division_info["branch_id"])
        data["division_info"] = {}
        data["division_info"]["division_name"] = division_info["division_name"]
        data["division_info"]["status"] = division_info["status"]
        data["division_info"]["level"] = division_info["level"]
        data["division_info"]["quantity"] = division_info["quantity"]
        data["division_info"]["branch_name"] = branch_info["branch_name"]

    payload["data"] = data
    _self.send_you(payload)
    def open(self):
        #TODO: トークン付与

        user_id = self.get_secure_cookie("user_id").decode('utf-8')
        country = None

        try:
            player = player_controller.get_playerinfo_by_id(user_id)

            if player["country_id"] is None:
                raise DBError(u"国IDが設定されていない。")

            if player["visibility"] is None:
                raise DBError(u"可視権が設定されていない")

        except DBError as e:
            self.on_error(u"国が特定できなかった。" + e.message)

        BJSocketHandler.members[user_id] = {
            "socket": self,
            "country_id": player["country_id"],
            "visibility": player["visibility"]
        }
        logging.debug(user_id + " connected")
    def run(self):
        """
        内政をする
        :return: 成功 ? True : False
        """

        self._logger.debug("enter EventDomestic run")
        self._logger.debug("event_record=", self._event_record)

        # 例外処理用
        user_id = None
        division_id = None
        try:
            # デコード
            if self._decode_recode() is False:
                raise Exception("デコード失敗")
                return False

            # プレイヤー、部隊情報
            player_info = player_controller.get_playerinfo_by_id(self._user_id)
            division_info = division_controller.get_division_info(
                self._division_id)

            # 内政中でないならキャンセル(本来はイベントレコード自体がキャンセルされるべき
            if player_info["status"] != "domestic":
                raise Exception("プレイヤーの状態がdomesticではない")
                return

            # 移動中でないならキャンセル(本来はイベントレコード自体がキャンセルされるべき)
            if division_info["status"] != "domestic":
                raise Exception("部隊の状態がdomesticではない")
                return

            # エラーに備えて本処理前にプレイヤーと部隊の状態を初期化する
            player_controller.update_user_status(self._user_id, "ready")
            division_controller.update_division_status(self._division_id,
                                                       "ready")

            # 現在時刻
            now = BJTime.get_time_now()

            # ヘックス情報
            hex = hexgrid_controller.get_hexinfo(self._domestic_col,
                                                 self._domestic_row)

            # 対象ヘックスの国籍が変わっていれば失敗
            if hex["country_id"] != player_info["country_id"]:
                BJSocketHandler.BJSocketHandler.send_member_by_id(
                    player_info["user_id"], {
                        "event": "cancel",
                        "data": {
                            "title": "内政キャンセル",
                            "reason": "対象ヘックスの国籍が違う"
                        }
                    })
                return

            # 内政実行
            # TODO : ステータスなどに合わせた変化

            gm = GameMain.GameMain()
            message = "(" + str(self._domestic_col) + "," + str(
                self._domestic_row) + ")\n "  # 結果メッセージ

            isSuccessed = False

            # 最大値増量
            if self._type == "foster_food":
                new_food = gm.get_affair().get_op_food_lv() + hex["food"]
                if not hexgrid_controller.update_hex(
                        hex["col"], hex["row"], food=new_food):
                    message = message + "エラー。農業生産失敗"
                else:
                    message = message + "農業生産 " + str(
                        hex["food"]) + " → " + str(new_food)
                    isSuccessed = True
            elif self._type == "foster_money":
                new_money = gm.get_affair().get_op_food_lv() + hex["money"]
                if not hexgrid_controller.update_hex(
                        hex["col"], hex["row"], money=new_money):
                    message = message + "エラー。商業生産失敗"
                else:
                    message = message + "商業生産 " + str(
                        hex["money"]) + " → " + str(new_money)
                    isSuccessed = True

            # 徴税
            elif self._type == "get_food":
                new_food = hex["food"] + division_info["food"]
                if not division_controller.update_division(
                        division_info["division_id"], food=new_food):
                    message = message + "エラー。農業徴税失敗"
                else:
                    message = message + "領地から" + str(
                        hex["food"]) + "の食糧を部隊に徴税した"
                    isSuccessed = True
            elif self._type == "get_money":
                new_money = hex["money"] + division_info["money"]
                if not division_controller.update_division(
                        division_info["division_id"], money=new_money):
                    message = message + "エラー。商業徴税失敗"
                else:
                    message = message + "領地から" + str(
                        hex["money"]) + "の資金を部隊に徴税した"
                    isSuccessed = True

            # 内政に失敗していればメッセージ送信
            if not isSuccessed:
                BJSocketHandler.BJSocketHandler.send_member_by_id(
                    player_info["user_id"], {
                        "event": "cancel",
                        "data": {
                            "title": "内政失敗",
                            "reason": "不明な内政種類"
                        }
                    })
                return

            # 内政に成功。結果をプレイヤーに通知
            BJSocketHandler.BJSocketHandler.send_member_by_id(
                player_info["user_id"], {
                    "event": "notify",
                    "data": {
                        "title": "内政成功",
                        "message": message
                    }
                })
        except DBError as e:
            logging.error("EventMove::run: caught DBError: " + e.message)

        except Exception as e:

            # 状態を初期化しておく
            player_controller.update_user_status(user_id, "ready")
            division_controller.update_division_status(division_id, "ready")

            logging.error(e)

            # プレイヤーにエラーを通知
            payload = {
                "event": "cancel",
                "data": {
                    "title": "内政キャンセル",
                    "reason": "内部エラー"
                }
            }
            BJSocketHandler.BJSocketHandler.send_member_by_id(
                self._user_id, payload)
Пример #4
0
    def run(self):
        """
        プレイヤーを移動させる
        終了後はmove_playerイベントを送信する
        :return: 成功 ? True : False
        """

        self._logger.debug("enter run")
        self._logger.debug("event_record=", self._event_record)

        # 例外処理用
        user_id = None
        division_id = None
        try:
            # デコード
            if self._decode_recode() is False:
                raise Exception("デコード失敗")
                return False

            # プレイヤー情報
            player = player_controller.get_playerinfo_by_id(self._user_id)
            user_id = player["user_id"]
            moving_player_info = {
                "user_id": player["user_id"],
                "country_id": player["country_id"],
                "ex_col": player["col"],
                "ex_row": player["row"],
                "new_col": self._dest_col,
                "new_row": self._dest_row,
                "icon": player["icon_id"]
            }

            # 移動中でないならキャンセル(本来はイベントレコード自体がキャンセルされるべき
            if player["status"] != "moving":
                raise Exception("プレイヤーの状態がmovingではない")
                return

            # 部隊情報
            division = division_controller.get_division_info(
                player["division_id"])

            # 移動中でないならキャンセル(本来はイベントレコード自体がキャンセルされるべき)
            if division["status"] != "moving":
                raise Exception("部隊の状態がmovingではない")
                return

            # エラーに備えて本処理前にプレイヤーと部隊の状態を初期化する
            player_controller.update_user_status(self._user_id, "ready")
            division_controller.update_division_status(self._division_id,
                                                       "ready")

            # 現在時刻
            now = BJTime.get_time_now()
            """
            移動先に既に他の部隊がいる場合
            """
            division_dest = division_controller.get_division_info_by_colrow(
                self._dest_col, self._dest_row)
            if division_dest:

                # 味方なら移動キャンセルイベント
                if division_dest["country_id"] == player["country_id"]:
                    data = {
                        "event": "cancel",
                        "data": {
                            "reason": "移動先に味方の部隊がいるため、移動はキャンセルされた"
                        }
                    }
                    BJSocketHandler.BJSocketHandler.send_member_by_id(
                        player["user_id"], data)
                    return

                # 敵なら戦闘開始
                if division_dest["country_id"] != player["country_id"]:
                    return
            """
            移動
            """
            # 移動前の可視領域減算
            if not hexgrid_controller.update_visible_area(
                    visibility=player["visibility"],
                    division_id=division["division_id"],
                    switch=False):
                raise Exception("可視領域減算に失敗")

            # 移動(部隊)
            if not division_controller.move_division(
                    self._division_id, self._dest_col, self._dest_row):
                self._logger.error("部隊の移動に失敗")
                raise Exception("部隊の移動に失敗")

            # 移動(プレイヤー)
            if not player_controller.move_user(self._user_id, self._dest_col,
                                               self._dest_row):
                self._logger.error("プレイヤーの移動に失敗")
                raise Exception("プレイヤーの移動に失敗")

            # 移動後のヘックスを国の支配下に
            if not hexgrid_controller.update_hex(
                    self._dest_col,
                    self._dest_row,
                    country_id=player["country_id"]):
                self._logging.error("移動後の支配に失敗")
                raise Exception("移動後の支配に失敗")

            # 移動後の可視領域可算
            if not hexgrid_controller.update_visible_area(
                    visibility=player["visibility"],
                    division_id=division["division_id"],
                    switch=True):
                self._logging.error("移動後の可視領域可算に失敗")
                raise Exception("移動後の可視領域可算に失敗")

            # 可視範囲を共有する通信中のプレイヤー(移動するプレイヤーも含む)にプレイヤーの移動を通知
            notify_move_player(moving_player_info, player["visibility"], now)

        except DBError as e:
            logging.error("EventMove::run: caught DBError: " + e.message)

        except Exception as e:

            # 状態を初期化しておく
            player_controller.update_user_status(user_id, "ready")
            division_controller.update_division_status(division_id, "ready")

            logging.error(e)

            # プレイヤーにエラーを通知
            payload = {"event": "error", "data": {"message": "進軍はキャンセルされた"}}
            BJSocketHandler.send_member_by_id(self._user_id, payload)
Пример #5
0
def request_domestic(_cls, _self, data):
    """
    内政要求
    """
    payload = {"event": "response_ask_domestic", "data": {}}

    player_info = player_controller.get_playerinfo_by_id(
        _self.get_secure_cookie("user_id").decode('utf-8'))
    col = data["col"]
    row = data["row"]

    # プレイヤーは行動可能か
    if not player_info["status"] == "ready":
        _cls.send_member_by_id(player_info["user_id"], {
            "event": "cancel",
            "data": {
                "title": "内政キャンセル",
                "reason": "行動中"
            }
        })
        return

    # 内政可能な半径か
    adjacent_area = hexgrid_controller.get_adjacent_area(
        player_info["col"], player_info["row"])
    if not (col == player_info["col"]
            and row == player_info["row"]) and not ({
                "col": col,
                "row": row
            } in adjacent_area):
        _cls.send_member_by_id(
            player_info["user_id"], {
                "event": "cancel",
                "data": {
                    "title": "内政キャンセル",
                    "reason": "内政可能な半径ではない"
                }
            })
        return

    # 現在のヘックスの状態
    target_hex = hexgrid_controller.get_hexinfo(col, row)
    if target_hex == None:
        _cls.send_member_by_id(
            player_info["user_id"], {
                "event": "cancel",
                "data": {
                    "title": "内政キャンセル",
                    "reason": "存在しないヘックス。"
                }
            })

    # イベント登録
    # TODO : プレイヤーのステータスなどによる処理
    gm = GameMain()
    finish_time = BJTime.add_time(BJTime.get_time_now(),
                                  gm.get_affair().get_op_domestic_speed())
    event = EventDomestic.create_recode(user_id=player_info["user_id"],
                                        division_id=player_info["division_id"],
                                        col=col,
                                        row=row,
                                        type=data["type"],
                                        datetime=finish_time)
    add_event(event)

    # プレイヤーと部隊の状態を変更
    division_controller.update_division_status(player_info["division_id"],
                                               "domestic")
    player_controller.update_user_status(player_info["user_id"], "domestic")

    # メインエンジンにイベントの実行時を通知
    gm = GameMain()
    gm.set_event_timestamp(finish_time)
Пример #6
0
def ask_domestic(_cls, _self, data):
    """内政可能なヘックスの問い合わせに対する応答"""

    payload = {"event": "response_ask_domestic", "data": {}}

    player_info = player_controller.get_playerinfo_by_id(
        _self.get_secure_cookie("user_id").decode('utf-8'))
    col = data["col"]
    row = data["row"]

    # 内政可能な半径か
    adjacent_area = hexgrid_controller.get_adjacent_area(
        player_info["col"], player_info["row"])
    if not (col == player_info["col"]
            and row == player_info["row"]) and not ({
                "col": col,
                "row": row
            } in adjacent_area):
        _cls.send_member_by_id(
            player_info["user_id"], {
                "event": "cancel",
                "data": {
                    "title": "内政キャンセル",
                    "reason": "内政可能な半径ではない"
                }
            })
        return

    # 現在のヘックスの状態
    target_hex = hexgrid_controller.get_hexinfo(col, row)

    if target_hex is None:
        _cls.send_member_by_id(player_info["user_id"], {
            "event": "cancel",
            "data": {
                "title": "内政キャンセル",
                "reason": "存在しないヘックス"
            }
        })
        return

    # 自国のヘックスか
    if not target_hex["country_id"] == player_info["country_id"]:
        _cls.send_member_by_id(
            player_info["user_id"], {
                "event": "cancel",
                "data": {
                    "title": "内政キャンセル",
                    "reason": "自国のヘックスではない"
                }
            })
        return
    # TODO : プレイヤーのステータスなどによる処理
    # 内政後の予想結果と
    gm = GameMain()
    food_result = target_hex["food"] + gm.get_affair().get_op_food_lv()
    money_result = target_hex["money"] + gm.get_affair().get_op_money_lv()
    required_time = gm.get_affair().get_op_domestic_speed()

    data = {
        "response": True,
        "food_result": int(food_result),
        "money_result": int(money_result),
        "required_time": int(required_time)
    }
    payload["data"] = data
    _cls.send_member_by_id(player_info["user_id"], payload)
Пример #7
0
def ask_move(_cls, _self, data):
    """進軍可能な進路を問い合わせに対する応答"""

    payload = {"event" : "response_ask_move",
               "data" : {}}
    try:

        db = DBSingleton()
        user_id = _self.get_secure_cookie("user_id").decode('utf-8')

        # プレイヤーの状態
        player = get_playerinfo_by_id(user_id)

        # プレイヤーが待機中でないと移動できない
        if player["status"] != "ready":
            payload["data"] = {"response" : "deny",
                                "reason"   : "行動中"}
            _self.send_you(payload)
            return True

        # 配下の師団がセットされていないと移動できない
        if not player["division_id"]:
            payload["data"] = {"response" : "deny",
                                "reason"   : "配下の部隊がセットされていない"}
            _self.send_you(payload)
            return True

        # 配下の師団取得
        division = get_division_info(player["division_id"])

        # 師団の兵科情報取得
        branch_info = get_branch_info(division["branch_id"])

        # 師団がヘックスに移動可能かどうか
        ajacent_area = get_adjacent_area(division["col"], division["row"])
        isMovable = False
        for ajacent_hex in ajacent_area:
            if ajacent_hex["col"] == data["col"] and ajacent_hex["row"] == data["row"]:
                isMovable = True
                break
        if not isMovable:
            payload["data"] = {"response" : "deny",
                                "reason" : "移動可能半径ではない"}
            _self.send_you(payload)
            return True

        # ゲームレベルから設定値を取得
        gm = GameMain()
        op_food_lv = gm.get_affair().get_op_food_lv()
        op_money_lv = gm.get_affair().get_op_money_lv()
        op_speed_lv = gm.get_affair().get_op_speed_lv()


        # 運用に必要な食糧と金 : 師団規模 * 兵科固定値 * ゲームレベル
        food_needed = division["quantity"] * branch_info["op_food"] * op_food_lv
        money_needed = division["quantity"] * branch_info["op_money"] * op_money_lv

        # 資金と食糧、それぞれ足りなければ移動不可
        if division["food"] < food_needed:
            payload["data"] = {"response" : "deny",
                                "reason"   : ("部隊の運用食糧が足りない",
                                               "部隊の保持食糧 : " + str(division["food"]) ,
                                               "必要な食糧 = 師団規模(" + str(division["quantity"]),
                                               ")×兵科補正(" + str(branch_info["op_food"]) ,
                                               ")×情勢補正(" + str(op_food_lv) + ") = " + str(food_needed))}
            _self.send_you(payload)
            return True

        elif division["money"] < money_needed:
            payload["data"] = {"response" : "deny",
                                "reason"   : ("部隊の運用資金が足りない",
                                               "部隊の保持資金 : " + str(division["money"]),
                                               "必要な資金 = 師団規模(" + str(division["quantity"]),
                                               ")×兵科補正(" + str(branch_info["op_money"]),
                                               ")×情勢補正(" + str(op_money_lv) + ") = " + str(money_needed))}
            _self.send_you(payload)
            return True

        # ヘックス情報
        hex_info = get_hexinfo(data["col"], data["row"])

        # 地形情報
        terrian_info = get_terrian_info(hex_info["type"])

        # 所要時間 = 地形補正 * 兵科速度 * ゲーム速度
        required_time = terrian_info[division["branch_id"]] * branch_info["speed"] * op_speed_lv

        payload["data"]["response"] = "accept"
        payload["data"]["food"] = food_needed
        payload["data"]["money"] = money_needed
        payload["data"]["required_time"] = int(required_time)
        _self.send_you(payload)
        return True

    except DBError as e:
        logging.error("move_query失敗" + e.message)
        _self.send_error("サーバーエラー : 進軍可能な範囲の問い合わせに失敗。行動はキャンセルされた")
        return False

    except Exception as e:
        logging.error(e)
        payload["data"] = {"response" : "deny",
                            "reason"   : "サーバーエラー"}
        _self.send_error("サーバーエラー : ハンドルされていないエラー。行動はキャンセルされた")
        return False

    assert False
Пример #8
0
def request_move(_cls, _self, data):
    """
    行軍イベントをセットする
    :param _cls: BJSocketHandlerのクラス
    :param _self: BJSocketHandlerのインスタンス
    :param data: クライアントから受信したデータ
    :return:
    """

    user_id = _self.get_secure_cookie("user_id").decode('utf-8')
    payload = {"event" : "response_request_move" ,
               "data"  : {}}



    try:

        """
        move_queryの焼き増しな部分があるが、queryとrequestの時間差または不正防止のため
        再度移動可能かどうか調べる
        """

        # 目的地
        dest_col = data["col"]
        dest_row = data["row"]

        # プレイヤーの状態
        user_id = _self.get_secure_cookie("user_id").decode('utf-8')
        player = get_playerinfo_by_id(user_id)

        # プレイヤーが待機中でないと移動できない
        if player["status"] != "ready":

            payload["data"] = {"response" : "deny",
                                "reason"   : "行動中"}
            _self.send_you(payload)
            return

        # 配下の部隊の状態
        division = get_division_info(player["division_id"])

        # 部隊がセットされていないと移動できない
        if not division:
            payload["data"] = {"response" : "deny",
                                "reason"   : "配下の師団がセットされていない"}
            _self.send_you(payload)

        # 部隊の移動半径内でないと移動できない
        movable_area = get_movable_area_by_division_id(division["division_id"], player["col"], player["row"])

        required_time = False # 所要時間
        for hex in movable_area:
            if hex["col"] == dest_col and hex["row"] == dest_row:
                required_time = hex["time"]

        if not required_time:
            payload["data"] = {"response" : "deny",
                               "reason"   :  "[" + str(dest_col) + "," + str(dest_row) + "]は移動可能半径外"}
            _cls.send_player(user_id, payload)

        # 師団の兵科情報取得
        branch_info = get_branch_info(division["branch_id"])

        # ゲームレベルから設定値を取得
        gm = GameMain()
        op_food_lv = gm.get_affair().get_op_food_lv()
        op_money_lv = gm.get_affair().get_op_money_lv()
        op_speed_lv = gm.get_affair().get_op_speed_lv()

        # 運用に必要な食糧と金 : 師団規模 * 兵科固定値 * ゲームレベル
        food_needed = division["quantity"] * branch_info["op_food"] * op_food_lv
        money_needed = division["quantity"] * branch_info["op_money"] * op_money_lv

        # 資金と食糧、それぞれ足りなければ移動不可
        if division["food"] < food_needed:
            payload["data"] = {"response" : "deny",
                                "reason"   : "部隊の運用食糧が足りない。<br>" +
                                             "部隊の保持食糧 : " + str(division["food"]) + "<br>" +
                                             "必要な食糧 = 師団規模(" + division["quantity"] +
                                            ")×兵科補正(" + str(branch_info["op_food"]) +
                                             ")×情勢補正(" + str(op_food_lv) + ") = " + str(food_needed)}
            _self.send_you(payload)
            return False

        elif division["money"] < money_needed:
            payload["data"] = {"response" : "deny",
                                "reason"   : "部隊の運用資金が足りない。<br>" +
                                             "部隊の保持資金 : " + str(division["money"]) + "<br>" +
                                             "必要な資金 = 師団規模(" + division["quantity"] +
                                            ")×兵科補正(" + str(branch_info["op_money"]) +
                                             ")×情勢補正(" + str(op_money_lv) + ") = " + str(money_needed)}
            _self.send_you(payload)
            return False

        """
       チェックが終わったのでプレイヤー情報等を更新し、行軍イベントをセットする
        """

        # 到着予定時刻計算
        required_time = required_time * op_speed_lv # ゲームレベル適用
        current_time = BJTime.get_time_now()
        arrival_time = BJTime.add_time(current_time, required_time)

        # TODO: チェックと次の処理の間に状態が変更される可能性がある

        # 行軍のイベントレコードを作成
        event_record = EventMove.create_recode(user_id=player["user_id"],
                                               division_id=division["division_id"],
                                               dest_col=dest_col,
                                               dest_row=dest_row,
                                               datetime=arrival_time)
        # レコードの作成に失敗していれば失敗
        if event_record is None:
             payload["data"] = {"response" : "deny",
                                "reason"   : "イベントレコードの作成に失敗した。管理者に連絡して下さい。"}
             _self.send_you(payload)
             return

        # レコードをDBに登録
        add_event(event_record)

        # メインエンジンにイベントの実行時を通知
        gm = GameMain()
        gm.set_event_timestamp(arrival_time)

        # プレイヤーの状態を更新
        update_user_before_move(user_id=player["user_id"],
                                wait_untill=arrival_time)
        update_user_status(player["user_id"],"moving")

        # 部隊の状態を更新
        update_division_before_move(division_id=division["division_id"],
                                    food=food_needed,
                                    money=money_needed)
        update_division_status(division["division_id"], "moving")

        # クライアントに通知
        payload["data"] =  { "response" : "approval",
                              "arrival_time" : arrival_time.strftime("%Y-%m-%d %H:%M:%S")}

        _self.send_you(payload)
        return

    except Exception as e:
        logging.error(e)
        _self.send_error(e.message);
        return

    assert False