Esempio n. 1
0
async def update_initiative_option(sid: str, data: ServerInitiativeOption):
    pr: PlayerRoom = game_state.get(sid)

    shape = Shape.get_or_none(uuid=data["shape"])

    if not has_ownership(shape, pr):
        logger.warning(
            f"{pr.player.name} attempted to change initiative of an asset it does not own"
        )
        return

    location_data = Initiative.get_or_none(location=pr.active_location)
    if location_data is None:
        logger.error(
            "Initiative updated for location without initiative tracking")
        return

    json_data = json.loads(location_data.data)

    with db.atomic():
        for i, initiative_data in enumerate(json_data):
            if initiative_data["shape"] == data["shape"]:
                json_data[i][data["option"]] = data["value"]
                break

        location_data.data = json.dumps(json_data)
        location_data.save()

    await sio.emit(
        "Initiative.Option.Set",
        data,
        skip_sid=sid,
        room=pr.active_location.get_path(),
        namespace=GAME_NS,
    )
Esempio n. 2
0
async def remove_initiative(sid: int, data: Dict[str, Any]):
    pr: PlayerRoom = game_state.get(sid)

    shape = Shape.get_or_none(uuid=data)

    if shape is not None and not has_ownership(shape, pr):
        logger.warning(
            f"{pr.player.name} attempted to remove initiative of an asset it does not own"
        )
        return

    initiative = Initiative.get_or_none(uuid=data)
    location_data = InitiativeLocationData.get_or_none(
        location=pr.active_location)

    if initiative:
        with db.atomic():
            Initiative.update(
                index=Initiative.index -
                1).where((Initiative.location_data == location_data)
                         & (Initiative.index >= initiative.index))
            initiative.delete_instance(True)

        await send_client_initiatives(pr)
Esempio n. 3
0
async def update_initiative(sid: int, data: Dict[str, Any]):
    pr: PlayerRoom = game_state.get(sid)

    shape = Shape.get_or_none(uuid=data["uuid"])

    if not has_ownership(shape, pr):
        logger.warning(
            f"{pr.player.name} attempted to change initiative of an asset it does not own"
        )
        return

    location_data = InitiativeLocationData.get_or_none(
        location=pr.active_location)
    if location_data is None:
        location_data = InitiativeLocationData.create(
            location=pr.active_location, turn=data["uuid"], round=1)
    initiatives = Initiative.select().where(
        Initiative.location_data == location_data)

    initiative = Initiative.get_or_none(uuid=data["uuid"])

    # Create new initiative
    if initiative is None:
        with db.atomic():
            # Update indices
            try:
                index = (initiatives.where(
                    Initiative.initiative >= data["initiative"]).order_by(
                        -Initiative.index)[0].index + 1)
            except IndexError:
                index = 0
            else:
                Initiative.update(
                    index=Initiative.index +
                    1).where((Initiative.location_data == location_data)
                             & (Initiative.index >= index))
            # Create model instance
            initiative = dict_to_model(Initiative,
                                       reduce_data_to_model(Initiative, data))
            initiative.location_data = location_data
            initiative.index = index
            initiative.save(force_insert=True)
    # Update initiative
    else:
        with db.atomic():
            if data["initiative"] != initiative.initiative:
                # Update indices
                old_index = initiative.index
                try:
                    new_index = (initiatives.where(
                        Initiative.initiative >= data["initiative"]).order_by(
                            -Initiative.index)[0].index)
                except IndexError:
                    new_index = 0
                else:
                    if new_index < old_index:
                        new_index += 1
                if old_index != new_index:
                    # SIGN=1 IF old_index > new_index WHICH MEANS the initiative is increased
                    # SIGN=-1 IF old_index < new_index WHICH MEANS the initiative is decreased
                    sign = (old_index - new_index) // abs(old_index -
                                                          new_index)
                    indices = [0, old_index, new_index]
                    update = Initiative.update(
                        index=Initiative.index +
                        sign).where((Initiative.location_data == location_data)
                                    & (Initiative.index <= indices[sign])
                                    & (Initiative.index >= indices[-sign]))
                    update.execute()
                data["index"] = new_index
            # Update model instance
            update_model_from_dict(initiative,
                                   reduce_data_to_model(Initiative, data))
            initiative.save()

    data["index"] = initiative.index

    await send_client_initiatives(pr)
Esempio n. 4
0
async def load_location(sid: str, location: Location, *, complete=False):
    pr: PlayerRoom = game_state.get(sid)
    if pr.active_location != location:
        pr.active_location = location
        pr.save()

    # 1. Load client options

    client_options = pr.player.as_dict()
    client_options["location_user_options"] = LocationUserOption.get(
        user=pr.player, location=location).as_dict()
    client_options["default_user_options"] = pr.player.default_options.as_dict(
    )

    if pr.user_options:
        client_options["room_user_options"] = pr.user_options.as_dict()

    await sio.emit("Client.Options.Set",
                   client_options,
                   room=sid,
                   namespace=GAME_NS)

    # 2. Load room info

    if complete:
        await sio.emit(
            "Room.Info.Set",
            {
                "name":
                pr.room.name,
                "creator":
                pr.room.creator.name,
                "invitationCode":
                str(pr.room.invitation_code),
                "isLocked":
                pr.room.is_locked,
                "default_options":
                pr.room.default_options.as_dict(),
                "players": [{
                    "id": rp.player.id,
                    "name": rp.player.name,
                    "location": rp.active_location.id,
                    "role": rp.role,
                } for rp in pr.room.players],
                "publicName":
                config.get("General", "public_name", fallback=""),
            },
            room=sid,
            namespace=GAME_NS,
        )

    # 3. Load location

    await sio.emit("Location.Set",
                   location.as_dict(),
                   room=sid,
                   namespace=GAME_NS)

    # 4. Load all location settings (DM)

    if complete and pr.role == Role.DM:
        await sio.emit(
            "Locations.Settings.Set",
            {
                l.id: {} if l.options is None else l.options.as_dict()
                for l in pr.room.locations
            },
            room=sid,
            namespace=GAME_NS,
        )

    # 5. Load Board

    locations = [{
        "id": l.id,
        "name": l.name,
        "archived": l.archived
    } for l in pr.room.locations.order_by(Location.index)]
    await sio.emit("Board.Locations.Set",
                   locations,
                   room=sid,
                   namespace=GAME_NS)

    floors = [floor for floor in location.floors.order_by(Floor.index)]

    if "active_floor" in client_options["location_user_options"]:
        index = next(i for i, f in enumerate(floors) if f.name ==
                     client_options["location_user_options"]["active_floor"])
        lower_floors = floors[index - 1::-1] if index > 0 else []
        higher_floors = floors[index + 1:] if index < len(floors) else []
        floors = [floors[index], *lower_floors, *higher_floors]

    for floor in floors:
        await sio.emit(
            "Board.Floor.Set",
            floor.as_dict(pr.player, pr.role == Role.DM),
            room=sid,
            namespace=GAME_NS,
        )

    # 6. Load Initiative

    location_data = Initiative.get_or_none(location=location)
    if location_data:
        await sio.emit("Initiative.Set",
                       location_data.as_dict(),
                       room=sid,
                       namespace=GAME_NS)

    # 7. Load labels

    if complete:
        labels = Label.select().where((Label.user == pr.player)
                                      | (Label.visible == True))
        label_filters = LabelSelection.select().where(
            (LabelSelection.user == pr.player)
            & (LabelSelection.room == pr.room))

        await sio.emit(
            "Labels.Set",
            [l.as_dict() for l in labels],
            room=sid,
            namespace=GAME_NS,
        )
        await sio.emit(
            "Labels.Filters.Set",
            [l.label.uuid for l in label_filters],
            room=sid,
            namespace=GAME_NS,
        )

    # 8. Load Notes

    await sio.emit(
        "Notes.Set",
        [
            note.as_dict()
            for note in Note.select().where((Note.user == pr.player)
                                            & (Note.room == pr.room))
        ],
        room=sid,
        namespace=GAME_NS,
    )

    # 9. Load Markers

    await sio.emit(
        "Markers.Set",
        [
            marker.as_string()
            for marker in Marker.select(Marker.shape_id).where(
                (Marker.user == pr.player) & (Marker.location == location))
        ],
        room=sid,
        namespace=GAME_NS,
    )

    # 10. Load Assets

    if complete:
        await sio.emit(
            "Asset.List.Set",
            Asset.get_user_structure(pr.player),
            room=sid,
            namespace=GAME_NS,
        )
Esempio n. 5
0
async def update_initiative(sid, data):
    sid_data = state.sid_map[sid]
    user = sid_data["user"]
    room = sid_data["room"]
    location = sid_data["location"]

    shape = Shape.get_or_none(uuid=data["uuid"])
    owner = ShapeOwner.get_or_none(shape=shape, user=user) is not None

    if room.creator != user and not owner:
        logger.warning(
            f"{user.name} attempted to change initiative of an asset it does not own"
        )
        return

    used_to_be_visible = False

    location_data = InitiativeLocationData.get_or_none(location=location)
    if location_data is None:
        location_data = InitiativeLocationData.create(location=location,
                                                      turn=data["uuid"],
                                                      round=1)
    initiatives = Initiative.select().where(
        Initiative.location_data == location_data)

    initiative = Initiative.get_or_none(uuid=data["uuid"])

    # Create new initiative
    if initiative is None:
        with db.atomic():
            # Update indices
            try:
                index = (initiatives.where(
                    Initiative.initiative >= data["initiative"]).order_by(
                        -Initiative.index)[0].index + 1)
            except IndexError:
                index = 0
            else:
                Initiative.update(
                    index=Initiative.index +
                    1).where((Initiative.location_data == location_data)
                             & (Initiative.index >= index))
            # Create model instance
            initiative = dict_to_model(Initiative,
                                       reduce_data_to_model(Initiative, data))
            initiative.location_data = location_data
            initiative.index = index
            initiative.save(force_insert=True)
    # Remove initiative
    elif "initiative" not in data:
        with db.atomic():
            Initiative.update(
                index=Initiative.index -
                1).where((Initiative.location_data == location_data)
                         & (Initiative.index >= initiative.index))
            initiative.delete_instance(True)
    # Update initiative
    else:
        used_to_be_visible = initiative.visible

        with db.atomic():
            if data["initiative"] != initiative.initiative:
                # Update indices
                old_index = initiative.index
                try:
                    new_index = (initiatives.where(
                        Initiative.initiative >= data["initiative"]).order_by(
                            -Initiative.index)[0].index)
                except IndexError:
                    new_index = 0
                else:
                    if new_index < old_index:
                        new_index += 1
                if old_index != new_index:
                    # SIGN=1 IF old_index > new_index WHICH MEANS the initiative is increased
                    # SIGN=-1 IF old_index < new_index WHICH MEANS the initiative is decreased
                    sign = (old_index - new_index) // abs(old_index -
                                                          new_index)
                    indices = [0, old_index, new_index]
                    update = Initiative.update(
                        index=Initiative.index +
                        sign).where((Initiative.location_data == location_data)
                                    & (Initiative.index <= indices[sign])
                                    & (Initiative.index >= indices[-sign]))
                    update.execute()
                data["index"] = new_index
            # Update model instance
            update_model_from_dict(initiative,
                                   reduce_data_to_model(Initiative, data))
            initiative.save()

    data["index"] = initiative.index

    await send_client_initiatives(room, location)