async def load_location(sid, location): sid_data = state.sid_map[sid] user = sid_data["user"] room = sid_data["room"] sid_data["location"] = location data = {} data["locations"] = [l.name for l in room.locations] if user == room.creator: data["layers"] = [ l.as_dict(user, True) for l in location.layers.order_by(Layer.index) ] else: data["layers"] = [ l.as_dict(user, False) for l in location.layers.order_by(Layer.index).where(Layer.player_visible) ] client_options = user.as_dict() client_options.update( **LocationUserOption.get(user=user, location=location).as_dict() ) await sio.emit("Board.Set", data, room=sid, namespace="/planarally") await sio.emit( "Location.Set", location.as_dict(), room=sid, namespace="/planarally" ) await sio.emit( "Client.Options.Set", client_options, room=sid, namespace="/planarally" ) await sio.emit( "Notes.Set", [ note.as_dict() for note in Note.select().where((Note.user == user) & (Note.room == room)) ], room=sid, namespace="/planarally", ) sorted_initiatives = [ init.as_dict() for init in Initiative.select() .join(Shape, JOIN.LEFT_OUTER, on=(Initiative.uuid == Shape.uuid)) .join(Layer) .where((Layer.location == location)) .order_by(Initiative.index) ] location_data = InitiativeLocationData.get_or_none(location=location) if location_data: await send_client_initiatives(room, location, user) await sio.emit( "Initiative.Round.Update", location_data.round, room=sid, namespace="/planarally", ) await sio.emit( "Initiative.Turn.Set", location_data.turn, room=sid, namespace="/planarally" )
async def load_location(sid: int, location: Location): pr: PlayerRoom = game_state.get(sid) if pr.active_location != location: pr.active_location = location pr.save() data = {} data["locations"] = [ {"id": l.id, "name": l.name} for l in pr.room.locations.order_by(Location.index) ] data["floors"] = [ f.as_dict(pr.player, pr.player == pr.room.creator) for f in location.floors.order_by(Floor.index) ] client_options = pr.player.as_dict() client_options.update( **LocationUserOption.get(user=pr.player, location=location).as_dict() ) await sio.emit("Board.Set", data, room=sid, namespace=GAME_NS) await sio.emit("Location.Set", location.as_dict(), room=sid, namespace=GAME_NS) await sio.emit("Client.Options.Set", client_options, room=sid, namespace=GAME_NS) 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, ) 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, ) location_data = InitiativeLocationData.get_or_none(location=location) if location_data: await send_client_initiatives(pr, pr.player) await sio.emit( "Initiative.Round.Update", location_data.round, room=sid, namespace=GAME_NS, ) await sio.emit( "Initiative.Turn.Set", location_data.turn, room=sid, namespace=GAME_NS )
async def load_location(sid, location): sid_data = state.sid_map[sid] user = sid_data["user"] room = sid_data["room"] sid_data["location"] = location data = {} data["locations"] = [l.name for l in room.locations] data["floors"] = [ f.as_dict(user, user == room.creator) for f in location.floors.order_by(Floor.index) ] client_options = user.as_dict() client_options.update( **LocationUserOption.get(user=user, location=location).as_dict()) await sio.emit("Board.Set", data, room=sid, namespace="/planarally") await sio.emit("Location.Set", location.as_dict(), room=sid, namespace="/planarally") await sio.emit("Client.Options.Set", client_options, room=sid, namespace="/planarally") await sio.emit( "Notes.Set", [ note.as_dict() for note in Note.select().where((Note.user == user) & (Note.room == room)) ], room=sid, namespace="/planarally", ) location_data = InitiativeLocationData.get_or_none(location=location) if location_data: await send_client_initiatives(room, location, user) await sio.emit( "Initiative.Round.Update", location_data.round, room=sid, namespace="/planarally", ) await sio.emit("Initiative.Turn.Set", location_data.turn, room=sid, namespace="/planarally")
def get_client_initiatives(user, location): location_data = InitiativeLocationData.get_or_none(location=location) if location_data is None: return [] initiatives = Initiative.select().where( Initiative.location_data == location_data) if location.room.creator != user: initiatives = (initiatives.join( ShapeOwner, JOIN.LEFT_OUTER, on=Initiative.uuid == ShapeOwner.shape).where( (Initiative.visible == True) | (ShapeOwner.user == user)).distinct()) return [i.as_dict() for i in initiatives.order_by(Initiative.index)]
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)
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)
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 = InitiativeLocationData.get_or_none(location=location) if location_data: await send_client_initiatives(pr, pr.player) await sio.emit( "Initiative.Round.Update", location_data.round, room=sid, namespace=GAME_NS, ) await sio.emit("Initiative.Turn.Set", location_data.turn, 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 if complete: 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, )
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)