def IfThenElse(name, predicate, then_subcon, else_subcon): """An if-then-else conditional construct: if the predicate indicates True, `then_subcon` will be used; otherwise `else_subcon` :param name: the name of the construct :param predicate: a function taking the context as an argument and returning True or False :param then_subcon: the subcon that will be used if the predicate returns True :param else_subcon: the subcon that will be used if the predicate returns False """ return Switch(name, lambda ctx: bool(predicate(ctx)), { True: then_subcon, False: else_subcon, })
enter_vent = Struct('vent_id' / Byte) rpc = Struct( 'rpc_target_id' / VarInt, 'rpc_action' / Enum(Byte, RPCAction), 'data' / Switch( lambda this: int(this.rpc_action), { RPCAction.SENDCHAT: send_chat, RPCAction.SETSTARTCOUNTER: set_start_counter, RPCAction.SETCOLOR: set_color, RPCAction.SETHAT: set_hat, RPCAction.SETSKIN: set_skin, RPCAction.SETPET: set_pet, RPCAction.SETNAME: set_name, RPCAction.STARTMEETING: start_meeting, RPCAction.VOTINGCOMPLETE: voting_complete, RPCAction.SENDCHATNOTE: send_chat_note, RPCAction.REPORTDEADBODY: report_dead_body, RPCAction.UPDATEGAMEDATA: update_game_data, RPCAction.COMPLETETASK: complete_task, RPCAction.MURDERPLAYER: murder_player, RPCAction.SETINFECTED: set_infected, RPCAction.SETTASKS: set_tasks, RPCAction.CHECKNAME: check_name, RPCAction.SYNCSETTINGS: sync_settings, RPCAction.EXILED: exiled, RPCAction.CASTVOTE: cast_vote, RPCAction.ADDVOTE: add_vote, RPCAction.SNAPTO: snap_to, RPCAction.ENTERVENT: enter_vent, }))
unknown1 = Struct( 'data' / Array(construct.this._.content_size, Byte) ) game_data = Struct( 'content_size' / Int16ul, 'type' / Enum(Byte, GameDataType), 'data' / Switch(lambda this: int(this.type), { GameDataType.DATA.value: data, GameDataType.RPC.value: rpc, GameDataType.SPAWN.value: spawn, GameDataType.DESPAWN.value: despawn, GameDataType.SCENE_CHANGE: scene_change, GameDataType.CHANGE_SETTINGS: change_settings, GameDataType.UNKNOWN1: unknown1, } ), ) room_message = Struct( 'content_size' / Int16ul, 'type' / Enum(Byte, RoomMessageType), 'room_code' / Int32ul, 'messages' / GreedyRange(game_data) )