Esempio n. 1
0
async def update_shape(sid, data):
    sid_data = state.sid_map[sid]
    user = sid_data["user"]
    room = sid_data["room"]
    location = sid_data["location"]

    shape, layer = await _get_shape(data, location, user)

    if not await has_ownership(layer, room, data, user, shape):
        return

    # Overwrite the old data with the new data
    if not data["temporary"]:
        with db.atomic():
            data["shape"]["layer"] = Layer.get(location=location,
                                               name=data["shape"]["layer"])
            # Shape
            update_model_from_dict(shape,
                                   reduce_data_to_model(Shape, data["shape"]))
            shape.save()
            # Subshape
            type_table = get_table(shape.type_)
            type_instance = type_table.get(uuid=shape.uuid)
            # no backrefs on these tables
            update_model_from_dict(type_instance,
                                   data["shape"],
                                   ignore_unknown=True)
            type_instance.save()
            # Owners
            old_owners = {owner.user.name for owner in shape.owners}
            new_owners = set(data["shape"]["owners"])
            for owner in old_owners ^ new_owners:
                if owner == "":
                    continue
                delta_owner = User.by_name(owner)
                if owner in new_owners:
                    ShapeOwner.create(shape=shape, user=delta_owner)
                else:
                    ShapeOwner.get(shape=shape,
                                   user=delta_owner).delete_instance(True)
                await send_client_initiatives(room, location, delta_owner)
            # Trackers
            for tracker in data["shape"]["trackers"]:
                tracker_db = Tracker.get_or_none(uuid=tracker["uuid"])
                reduced = reduce_data_to_model(Tracker, tracker)
                reduced["shape"] = shape
                if tracker_db:
                    update_model_from_dict(tracker_db, reduced)
                    tracker_db.save()
                else:
                    Tracker.create(**reduced)
            # Auras
            for aura in data["shape"]["auras"]:
                aura_db = Aura.get_or_none(uuid=aura["uuid"])
                reduced = reduce_data_to_model(Aura, aura)
                reduced["shape"] = shape
                if aura_db:
                    update_model_from_dict(aura_db, reduced)
                    aura_db.save()
                else:
                    Aura.create(**reduced)

    await sync_shape_update(layer, room, data, sid, shape)
Esempio n. 2
0
async def update_shape(sid, data):
    sid_data = state.sid_map[sid]
    user = sid_data["user"]
    room = sid_data["room"]
    location = sid_data["location"]

    # We're first gonna retrieve the existing server side shape for some validation checks
    if data["temporary"]:
        # This stuff is not stored so we cannot do any server side validation /shrug
        shape = data["shape"]
        layer = location.layers.where(Layer.name == data["shape"]["layer"])[0]
    else:
        # Use the server version of the shape.
        try:
            shape = Shape.get(uuid=data["shape"]["uuid"])
        except Shape.DoesNotExist:
            logger.warning(f"Attempt to update unknown shape by {user.name}")
            return
        layer = shape.layer

    # Ownership validatation
    if room.creator != user:
        if not layer.player_editable:
            logger.warning(
                f"{user.name} attempted to move a shape on a dm layer")
            return

        if data["temporary"]:
            if user.name not in shape["owners"]:
                logger.warning(
                    f"{user.name} attempted to move asset it does not own")
                return
        else:
            if not ShapeOwner.get_or_none(shape=shape, user=user):
                logger.warning(
                    f"{user.name} attempted to move asset it does not own")
                return

    # Overwrite the old data with the new data
    if not data["temporary"]:
        with db.atomic():
            data["shape"]["layer"] = Layer.get(location=location,
                                               name=data["shape"]["layer"])
            # Shape
            update_model_from_dict(shape,
                                   reduce_data_to_model(Shape, data["shape"]))
            shape.save()
            # Subshape
            type_table = get_table(shape.type_)
            type_instance = type_table.get(uuid=shape.uuid)
            # no backrefs on these tables
            update_model_from_dict(type_instance,
                                   data["shape"],
                                   ignore_unknown=True)
            type_instance.save()
            # Owners
            old_owners = {owner.user.name for owner in shape.owners}
            new_owners = set(data["shape"]["owners"])
            for owner in old_owners ^ new_owners:
                if owner == "":
                    continue
                delta_owner = User.by_name(owner)
                if owner in new_owners:
                    ShapeOwner.create(shape=shape, user=delta_owner)
                else:
                    ShapeOwner.get(shape=shape,
                                   user=delta_owner).delete_instance(True)
                await send_client_initiatives(room, location, delta_owner)
            # Trackers
            for tracker in data["shape"]["trackers"]:
                tracker_db = Tracker.get_or_none(uuid=tracker['uuid'])
                reduced = reduce_data_to_model(Tracker, tracker)
                reduced['shape'] = shape
                if tracker_db:
                    update_model_from_dict(tracker_db, reduced)
                    tracker_db.save()
                else:
                    Tracker.create(**reduced)
            # Auras
            for aura in data["shape"]["auras"]:
                aura_db = Aura.get_or_none(uuid=aura['uuid'])
                reduced = reduce_data_to_model(Aura, aura)
                reduced['shape'] = shape
                if aura_db:
                    update_model_from_dict(aura_db, reduced)
                    aura_db.save()
                else:
                    Aura.create(**reduced)

    # Send to players
    if layer.player_visible:
        for room_player in room.players:
            for psid in state.get_sids(user=room_player.player, room=room):
                if psid == sid:
                    continue
                if not data["temporary"]:
                    data["shape"] = shape.as_dict(room_player.player, False)
                await sio.emit("Shape.Update",
                               data,
                               room=psid,
                               namespace="/planarally")

    # Send to DM
    for csid in state.get_sids(user=room.creator, room=room):
        if csid == sid:
            continue
        if not data["temporary"]:
            data["shape"] = shape.as_dict(room.creator, True)
        await sio.emit("Shape.Update",
                       data,
                       room=csid,
                       namespace="/planarally")
Esempio n. 3
0
def respond_message(message):

    if message.text.startswith('/start'):
        register_user(message)

    message.text = emoji.demojize(message.text)
    t = Tracker.get_or_none(Tracker.id == message.chat.id)
    user = User.get_or_none(id=message.chat.id)

    if not t or not user:
        send_message(
            message.chat.id,
            ":cross_mark: Not a registered user. Please click on /start.")
        return

    # update the username with every message
    # this is important as it is the only way to find out the user identity
    User.update(username=message.chat.username, ).where(
        User.id == message.chat.id).execute()

    # ------------------------------------
    # HOST a game
    # ------------------------------------
    if t.state == 'start' and message.text == ":desktop_computer: Host a Game":
        host_start(message, user)

    # end game
    elif t.state == 'host_game' and message.text == ":cross_mark: Leave":
        host_leave(message, user)

    # select from a list of roles
    elif t.state == 'host_game' and message.text == ":right_arrow: Next":
        # FIXME: poll is deactivated. inline keyboard is used now.
        # host_select_roles_with_poll(message, user)
        host_select_roles(message, user)

    # select from a list of roles
    elif t.state == 'host_game' and message.text == ":envelope: Send Roles":
        host_send_roles(message, user)

    # ------------------------------------
    # New Game
    # ------------------------------------
    join_code_pattern = r"^/start (?P<code>\w{4})$"
    match = re.match(join_code_pattern, message.text)
    if match:
        code = match.group("code")
        message.text = code

    if t.state == 'start' and message.text == ":game_die: Join a Game":
        player_leave(message, user)

    elif t.state == 'join_game':
        player_start(message, user)

    elif t.state == 'start' and match:
        player_start(message, user)

    # ------------------------------------
    # Change Name
    # ------------------------------------
    if t.state == 'start' and message.text == ":bust_in_silhouette: Change Name":
        update_state(user, 'change_name')
        text = f":bust_in_silhouette: Current name: <b>{f2p(user.name)}</b>\n\n"
        text += ":input_latin_letters: Enter your new name:"
        send_message(user.id,
                     text,
                     reply_markup=create_keyboard([":cross_mark: Discard"]))

    elif t.state == 'change_name' and message.text == ":cross_mark: Discard":
        update_state(user, 'start')
        send_message(user.id,
                     ":cross_mark: Discard",
                     reply_markup=keyboards.main)

    elif t.state == 'change_name':
        if len(message.text) > 100:
            send_message(user.id,
                         "Name length must be less than 100 characters.")
            return

        User.update(name=message.text).where(User.id == user.id).execute()
        update_state(user, 'start')
        send_message(
            user.id,
            f":white_heavy_check_mark: Your Name is updated now to: <b>{message.text}</b>",
            reply_markup=keyboards.main)

    # ------------------------------------
    # Settings
    # ------------------------------------
    if t.state == 'start' and message.text == ":gear_selector: Settings":
        edit_game_settings(message, user)