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)
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")
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)