Example #1
0
File: demo.py Project: minjit/skadi
def fast_forward(prologue, demo_io, tick=None):
    full_packets, remaining_packets = [], []

    world = w.construct(prologue.recv_tables)
    string_tables = copy.deepcopy(prologue.string_tables)

    if tick:
        iter_bootstrap = iter(demo_io)

        try:
            while True:
                p, m = next(iter_bootstrap)

                if p.kind == pb_d.DEM_FullPacket:
                    full_packets.append((p, m))
                    remaining_packets = []
                else:
                    remaining_packets.append((p, m))

                if p.tick > tick - 2:  # hack?
                    break
        except StopIteration:
            raise EOFError()

    if full_packets:
        for peek, message in full_packets:
            full_packet = d_io.parse(peek.kind, peek.compressed, message)

            for table in full_packet.string_table.tables:
                assert not table.items_clientside

                entries = [(_i, e.str, e.data)
                           for _i, e in enumerate(table.items)]
                string_tables[table.table_name].update_all(entries)

        peek, message = full_packets[-1]
        pbmsg = d_io.parse(peek.kind, peek.compressed, message)
        packet = i.construct(p_io.construct(pbmsg.packet.data))

        peek, message = packet.find(pb_n.svc_PacketEntities)
        pe = p_io.parse(peek.kind, message)
        ct = pe.updated_entries
        bs = b_io.construct(pe.entity_data)
        unpacker = u_ent.construct(bs, -1, ct, False, prologue.class_bits,
                                   world)

        for index, mode, (cls, serial, diff) in unpacker:
            data = string_tables['instancebaseline'].get(cls)[1]
            bs = b_io.construct(data)
            unpacker = u_ent.construct(bs, -1, 1, False, prologue.class_bits,
                                       world)

            state = unpacker.unpack_baseline(prologue.recv_tables[cls])
            state.update(diff)

            try:
                world.create(cls, index, serial, state)
            except AssertionError, e:
                # TODO: log here.
                pass
Example #2
0
File: demo.py Project: minjit/skadi
  def advance(self, tick, pbmsg):
    packet = i.construct(p_io.construct(pbmsg.data))
    all_ust = packet.find_all(pb_n.svc_UpdateStringTable)

    for _pbmsg in [p_io.parse(p.kind, m) for p, m in all_ust]:
      key = self.string_tables.keys()[_pbmsg.table_id]
      _st = self.string_tables[key]

      bs = b_io.construct(_pbmsg.string_data)
      ne = _pbmsg.num_changed_entries
      eb, sf, sb = _st.entry_bits, _st.size_fixed, _st.size_bits

      for entry in u_st.construct(bs, ne, eb, sf, sb):
        _st.update(entry)

    p, m = packet.find(pb_n.svc_PacketEntities)
    pe = p_io.parse(p.kind, m)
    ct = pe.updated_entries
    bs = b_io.construct(pe.entity_data)

    class_bits = self.prologue.class_bits
    recv_tables = self.prologue.recv_tables

    unpacker = u_ent.construct(bs, -1, ct, False, class_bits, self.world)

    for index, mode, context in unpacker:
      if mode & u_ent.PVS.Entering:
        cls, serial, diff = context

        data = self.string_tables['instancebaseline'].get(cls)[1]
        bs = b_io.construct(data)
        unpacker = u_ent.construct(bs, -1, 1, False, class_bits, self.world)

        state = unpacker.unpack_baseline(self.prologue.recv_tables[cls])
        state.update(diff)

        self.world.create(cls, index, serial, state)
      elif mode & u_ent.PVS.Deleting:
        self.world.delete(index)
      elif mode ^ u_ent.PVS.Leaving:
        state = {} if self.sparse else dict(self.world.find_index(index))
        state.update(context)

        self.world.update(index, state)

    all_um = packet.find_all(pb_n.svc_UserMessage)
    user_messages = [e_um.parse(p_io.parse(p.kind, m)) for p, m in all_um]

    all_ge = packet.find_all(pb_n.svc_GameEvent)
    gel = self.prologue.game_event_list
    game_events = [e_ge.parse(p_io.parse(p.kind, m), gel) for p, m in all_ge]

    modifiers = self.string_tables['ActiveModifiers'].observer

    _, gamerules = self.world.find_by_dt('DT_DOTAGamerulesProxy')
    modifiers.expire(gamerules[('DT_DOTAGamerules', 'm_fGameTime')])

    return tick, user_messages, game_events, self.world, modifiers
Example #3
0
File: demo.py Project: minjit/skadi
def fast_forward(prologue, demo_io, tick=None):
  full_packets, remaining_packets = [], []

  world = w.construct(prologue.recv_tables)
  string_tables = copy.deepcopy(prologue.string_tables)

  if tick:
    iter_bootstrap = iter(demo_io)

    try:
      while True:
        p, m = next(iter_bootstrap)

        if p.kind == pb_d.DEM_FullPacket:
          full_packets.append((p, m))
          remaining_packets = []
        else:
          remaining_packets.append((p, m))

        if p.tick > tick - 2: # hack?
          break
    except StopIteration:
      raise EOFError()

  if full_packets:
    for peek, message in full_packets:
      full_packet = d_io.parse(peek.kind, peek.compressed, message)

      for table in full_packet.string_table.tables:
        assert not table.items_clientside

        entries = [(_i, e.str, e.data) for _i, e in enumerate(table.items)]
        string_tables[table.table_name].update_all(entries)

    peek, message = full_packets[-1]
    pbmsg = d_io.parse(peek.kind, peek.compressed, message)
    packet = i.construct(p_io.construct(pbmsg.packet.data))

    peek, message = packet.find(pb_n.svc_PacketEntities)
    pe = p_io.parse(peek.kind, message)
    ct = pe.updated_entries
    bs = b_io.construct(pe.entity_data)
    unpacker = u_ent.construct(bs, -1, ct, False, prologue.class_bits, world)

    for index, mode, (cls, serial, diff) in unpacker:
      data = string_tables['instancebaseline'].get(cls)[1]
      bs = b_io.construct(data)
      unpacker = u_ent.construct(bs, -1, 1, False, prologue.class_bits, world)

      state = unpacker.unpack_baseline(prologue.recv_tables[cls])
      state.update(diff)

      try:
        world.create(cls, index, serial, state)
      except AssertionError, e:
        # TODO: log here.
        pass
Example #4
0
def reconstitute(full_packets, class_bits, recv_tables, string_tables):
    w = e_w.construct(recv_tables)
    st = string_tables

    st_mn = st['ModifierNames']
    st_am = st['ActiveModifiers']
    m = e_m.construct(st_mn, baseline=st_am)

    for _, fp in full_packets:
        for table in fp.string_table.tables:
            assert not table.items_clientside

            entries = [(_i, e.str, e.data) for _i, e in enumerate(table.items)]
            st[table.table_name].update_all(entries)

            if table.table_name == 'ActiveModifiers':
                m.reset()
                [m.note(e) for e in entries]

    if full_packets:
        _, fp = full_packets[-1]
        packet = ie_packet.construct(p_io.construct(fp.packet.data))

        _, pe = packet.svc_packet_entities
        ct = pe.updated_entries
        bs = b_io.construct(pe.entity_data)
        unpacker = u_ent.construct(bs, -1, ct, False, class_bits, w)

        for index, mode, (cls, serial, diff) in unpacker:
            data = st['instancebaseline'].get(cls)[1]
            bs = b_io.construct(data)
            unpacker = u_ent.construct(bs, -1, 1, False, class_bits, w)

            state = unpacker.unpack_baseline(recv_tables[cls])
            state.update(diff)

            w.create(cls, index, serial, state, dict(diff))

    return w, m, st
Example #5
0
def reconstitute(full_packets, class_bits, recv_tables, string_tables):
  w = e_w.construct(recv_tables)
  st = string_tables

  st_mn = st['ModifierNames']
  st_am = st['ActiveModifiers']
  m = e_m.construct(st_mn, baseline=st_am)

  for _, fp in full_packets:
    for table in fp.string_table.tables:
      assert not table.items_clientside

      entries = [(_i, e.str, e.data) for _i, e in enumerate(table.items)]
      st[table.table_name].update_all(entries)

      if table.table_name == 'ActiveModifiers':
        m.reset()
        [m.note(e) for e in entries]

  if full_packets:
    _, fp = full_packets[-1]
    packet = ie_packet.construct(p_io.construct(fp.packet.data))

    _, pe = packet.svc_packet_entities
    ct = pe.updated_entries
    bs = b_io.construct(pe.entity_data)
    unpacker = u_ent.construct(bs, -1, ct, False, class_bits, w)

    for index, mode, (cls, serial, diff) in unpacker:
      data = st['instancebaseline'].get(cls)[1]
      bs = b_io.construct(data)
      unpacker = u_ent.construct(bs, -1, 1, False, class_bits, w)

      state = unpacker.unpack_baseline(recv_tables[cls])
      state.update(diff)

      w.create(cls, index, serial, state, dict(diff))

  return w, m, st
Example #6
0
    def advance(self, tick, pbmsg):
        self.tick = tick

        packet = ie_packet.construct(p_io.construct(pbmsg.data))
        am_entries = []

        for _, _pbmsg in packet.all_svc_update_string_table:
            key = self.string_tables.keys()[_pbmsg.table_id]
            _st = self.string_tables[key]

            bs = b_io.construct(_pbmsg.string_data)
            ne = _pbmsg.num_changed_entries
            eb, sf, sb = _st.entry_bits, _st.size_fixed, _st.size_bits

            entries = u_st.construct(bs, ne, eb, sf, sb)
            if key == 'ActiveModifiers':
                am_entries = list(entries)
            else:
                [_st.update(e) for e in entries]

        um = packet.find_all(pb_n.svc_UserMessage)
        self.user_messages = [e_um.parse(p_io.parse(p.kind, m)) for p, m in um]

        ge = packet.find_all(pb_n.svc_GameEvent)
        gel = self.prologue.game_event_list
        self.game_events = [
            e_ge.parse(p_io.parse(p.kind, m), gel) for p, m in ge
        ]

        p, m = packet.find(pb_n.svc_PacketEntities)
        pe = p_io.parse(p.kind, m)
        ct = pe.updated_entries
        bs = b_io.construct(pe.entity_data)

        class_bits = self.prologue.class_bits
        recv_tables = self.prologue.recv_tables

        unpacker = u_ent.construct(bs, -1, ct, False, class_bits, self.world)

        for index, mode, context in unpacker:
            if mode & u_ent.PVS.Entering:
                cls, serial, diff = context

                data = self.string_tables['instancebaseline'].get(cls)[1]
                bs = b_io.construct(data)
                unpacker = u_ent.construct(bs, -1, 1, False, class_bits,
                                           self.world)

                state = unpacker.unpack_baseline(
                    self.prologue.recv_tables[cls])
                state.update(diff)

                self.world.create(cls, index, serial, state, dict(diff))
            elif mode & u_ent.PVS.Deleting:
                self.world.delete(index)
            elif mode ^ u_ent.PVS.Leaving:
                state = dict(context) if self.sparse else dict(
                    self.world.find_index(index), **context)
                diff = state if self.sparse else dict(context)

                self.world.update(index, state, diff)

        [self.modifiers.note(e) for e in am_entries]
        self.modifiers.limit(self.world)

        _, gamerules = self.world.find_by_dt('DT_DOTAGamerulesProxy')
        game_time_key = ('DT_DOTAGamerulesProxy',
                         'DT_DOTAGamerules.m_fGameTime')
        self.modifiers.expire(gamerules[game_time_key])
Example #7
0
  def advance(self, tick, pbmsg):
    self.tick = tick

    packet = ie_packet.construct(p_io.construct(pbmsg.data))
    am_entries = []

    for _, _pbmsg in packet.all_svc_update_string_table:
      key = self.string_tables.keys()[_pbmsg.table_id]
      _st = self.string_tables[key]

      bs = b_io.construct(_pbmsg.string_data)
      ne = _pbmsg.num_changed_entries
      eb, sf, sb = _st.entry_bits, _st.size_fixed, _st.size_bits

      entries = u_st.construct(bs, ne, eb, sf, sb)
      if key == 'ActiveModifiers':
        am_entries = list(entries)
      else:
        [_st.update(e) for e in entries]

    um = packet.find_all(pb_n.svc_UserMessage)
    self.user_messages = [e_um.parse(p_io.parse(p.kind, m)) for p, m in um]

    ge = packet.find_all(pb_n.svc_GameEvent)
    gel = self.prologue.game_event_list
    self.game_events = [e_ge.parse(p_io.parse(p.kind, m), gel) for p, m in ge]

    p, m = packet.find(pb_n.svc_PacketEntities)
    pe = p_io.parse(p.kind, m)
    ct = pe.updated_entries
    bs = b_io.construct(pe.entity_data)

    class_bits = self.prologue.class_bits
    recv_tables = self.prologue.recv_tables

    unpacker = u_ent.construct(bs, -1, ct, False, class_bits, self.world)

    for index, mode, context in unpacker:
      if mode & u_ent.PVS.Entering:
        cls, serial, diff = context

        data = self.string_tables['instancebaseline'].get(cls)[1]
        bs = b_io.construct(data)
        unpacker = u_ent.construct(bs, -1, 1, False, class_bits, self.world)

        state = unpacker.unpack_baseline(self.prologue.recv_tables[cls])
        state.update(diff)

        self.world.create(cls, index, serial, state, dict(diff))
      elif mode & u_ent.PVS.Deleting:
        self.world.delete(index)
      elif mode ^ u_ent.PVS.Leaving:
        state = dict(context) if self.sparse else dict(self.world.find_index(index), **context)
        diff = state if self.sparse else dict(context)

        self.world.update(index, state, diff)

    [self.modifiers.note(e) for e in am_entries]
    self.modifiers.limit(self.world)

    _, gamerules = self.world.find_by_dt('DT_DOTAGamerulesProxy')
    game_time_key = ('DT_DOTAGamerulesProxy', 'DT_DOTAGamerules.m_fGameTime')
    self.modifiers.expire(gamerules[game_time_key])
Example #8
0
File: demo.py Project: minjit/skadi
    def advance(self, tick, pbmsg):
        packet = i.construct(p_io.construct(pbmsg.data))
        all_ust = packet.find_all(pb_n.svc_UpdateStringTable)

        for _pbmsg in [p_io.parse(p.kind, m) for p, m in all_ust]:
            key = self.string_tables.keys()[_pbmsg.table_id]
            _st = self.string_tables[key]

            bs = b_io.construct(_pbmsg.string_data)
            ne = _pbmsg.num_changed_entries
            eb, sf, sb = _st.entry_bits, _st.size_fixed, _st.size_bits

            for entry in u_st.construct(bs, ne, eb, sf, sb):
                _st.update(entry)

        p, m = packet.find(pb_n.svc_PacketEntities)
        pe = p_io.parse(p.kind, m)
        ct = pe.updated_entries
        bs = b_io.construct(pe.entity_data)

        class_bits = self.prologue.class_bits
        recv_tables = self.prologue.recv_tables

        unpacker = u_ent.construct(bs, -1, ct, False, class_bits, self.world)

        for index, mode, context in unpacker:
            if mode & u_ent.PVS.Entering:
                cls, serial, diff = context

                data = self.string_tables['instancebaseline'].get(cls)[1]
                bs = b_io.construct(data)
                unpacker = u_ent.construct(bs, -1, 1, False, class_bits,
                                           self.world)

                state = unpacker.unpack_baseline(
                    self.prologue.recv_tables[cls])
                state.update(diff)

                self.world.create(cls, index, serial, state)
            elif mode & u_ent.PVS.Deleting:
                self.world.delete(index)
            elif mode ^ u_ent.PVS.Leaving:
                state = {} if self.sparse else dict(
                    self.world.find_index(index))
                state.update(context)

                self.world.update(index, state)

        all_um = packet.find_all(pb_n.svc_UserMessage)
        user_messages = [e_um.parse(p_io.parse(p.kind, m)) for p, m in all_um]

        all_ge = packet.find_all(pb_n.svc_GameEvent)
        gel = self.prologue.game_event_list
        game_events = [
            e_ge.parse(p_io.parse(p.kind, m), gel) for p, m in all_ge
        ]

        modifiers = self.string_tables['ActiveModifiers'].observer

        _, gamerules = self.world.find_by_dt('DT_DOTAGamerulesProxy')
        modifiers.expire(gamerules[('DT_DOTAGamerules', 'm_fGameTime')])

        return tick, user_messages, game_events, self.world, modifiers
Example #9
0
def load(io, tick=0):
  demo_io = d_io.construct(io)
  prologue = id_prologue.construct(demo_io)

  # mash all packet svc messages together, then index them
  signon_packets = list(prologue.all_dem_signon_packet)
  data = ''.join([pb.data for _, pb in signon_packets])
  packet = ie_packet.construct(p_io.construct(data))

  # meta: file header
  _, pbmsg = prologue.dem_file_header
  file_header = FileHeader(*[getattr(pbmsg, a) for a in FileHeader._fields])

  # meta: server info
  _, pbmsg = packet.svc_server_info
  server_info = ServerInfo(*[getattr(pbmsg, a) for a in ServerInfo._fields])

  # meta: voice init
  _, pbmsg = packet.svc_voice_init
  voice_init = VoiceInit(*[getattr(pbmsg, a) for a in VoiceInit._fields])

  # prologue: meta
  meta = Meta(file_header, server_info, voice_init)

  # prologue: send tables
  _, pbmsg = prologue.dem_send_tables
  _send_tables = ie_send_tables.construct(p_io.construct(pbmsg.data))
  send_tables = c.OrderedDict()

  for pbmsg in [pb for _, pb in _send_tables.all_svc_send_table]:
    if pbmsg.is_end:
      break

    send_table = _parse_cdemo_send_table(pbmsg)
    send_tables[send_table.dt] = send_table

  # prologue: recv tables
  flattener = Flattener(send_tables)
  recv_tables = c.OrderedDict()

  _, pbmsg = prologue.dem_class_info
  class_info = c.OrderedDict()

  for cls in pbmsg.classes:
    _id, dt, name = str(cls.class_id), cls.table_name, cls.network_name
    class_info[_id] = (dt, name)

  for st in filter(test_needs_decoder, send_tables.values()):
    props = flattener.flatten(st)
    cls = next(_id for _id, (dt, _) in class_info.items() if dt == st.dt)
    recv_tables[cls] = dt_r.construct(st.dt, props)

  # prologue: string tables
  pbmsgs = [pb for _, pb in packet.all_svc_create_string_table]
  string_tables = _parse_all_csvc_create_string_tables(pbmsgs)

  # prologue: game event list
  _, pbmsg = packet.svc_game_event_list
  game_event_list = c.OrderedDict()

  for desc in pbmsg.descriptors:
    _id, name = desc.eventid, desc.name
    keys = [(k.type, k.name) for k in desc.keys]
    game_event_list[_id] = (name, keys)

  # prologue: class bits
  class_bits = server_info.max_classes.bit_length()

  return Prologue(meta, recv_tables, string_tables, game_event_list, class_bits)
Example #10
0
def load(io, tick=0):
    demo_io = d_io.construct(io)
    prologue = id_prologue.construct(demo_io)

    # mash all packet svc messages together, then index them
    signon_packets = list(prologue.all_dem_signon_packet)
    data = ''.join([pb.data for _, pb in signon_packets])
    packet = ie_packet.construct(p_io.construct(data))

    # meta: file header
    _, pbmsg = prologue.dem_file_header
    file_header = FileHeader(*[getattr(pbmsg, a) for a in FileHeader._fields])

    # meta: server info
    _, pbmsg = packet.svc_server_info
    server_info = ServerInfo(*[getattr(pbmsg, a) for a in ServerInfo._fields])

    # meta: voice init
    _, pbmsg = packet.svc_voice_init
    voice_init = VoiceInit(*[getattr(pbmsg, a) for a in VoiceInit._fields])

    # prologue: meta
    meta = Meta(file_header, server_info, voice_init)

    # prologue: send tables
    _, pbmsg = prologue.dem_send_tables
    _send_tables = ie_send_tables.construct(p_io.construct(pbmsg.data))
    send_tables = c.OrderedDict()

    for pbmsg in [pb for _, pb in _send_tables.all_svc_send_table]:
        if pbmsg.is_end:
            break

        send_table = _parse_cdemo_send_table(pbmsg)
        send_tables[send_table.dt] = send_table

    # prologue: recv tables
    flattener = Flattener(send_tables)
    recv_tables = c.OrderedDict()

    _, pbmsg = prologue.dem_class_info
    class_info = c.OrderedDict()

    for cls in pbmsg.classes:
        _id, dt, name = str(cls.class_id), cls.table_name, cls.network_name
        class_info[_id] = (dt, name)

    for st in filter(test_needs_decoder, send_tables.values()):
        props = flattener.flatten(st)
        cls = next(_id for _id, (dt, _) in class_info.items() if dt == st.dt)
        recv_tables[cls] = dt_r.construct(st.dt, props)

    # prologue: string tables
    pbmsgs = [pb for _, pb in packet.all_svc_create_string_table]
    string_tables = _parse_all_csvc_create_string_tables(pbmsgs)

    # prologue: game event list
    _, pbmsg = packet.svc_game_event_list
    game_event_list = c.OrderedDict()

    for desc in pbmsg.descriptors:
        _id, name = desc.eventid, desc.name
        keys = [(k.type, k.name) for k in desc.keys]
        game_event_list[_id] = (name, keys)

    # prologue: class bits
    class_bits = server_info.max_classes.bit_length()

    return Prologue(meta, recv_tables, string_tables, game_event_list,
                    class_bits)
Example #11
0
def load(io, tick=0):
    demo_io = d_io.construct(io)
    prologue = i_p.construct(demo_io)

    # mash all packet svc messages together, then index them
    signon_packets = list(prologue.signon_packets)
    pbmsgs = [d_io.parse(p.kind, p.compressed, m) for p, m in signon_packets]
    data = ''.join([p.data for p in pbmsgs])
    packet_io = p_io.construct(data)
    packet = i.construct(packet_io)

    # class info
    peek, message = prologue.class_info
    pbmsg = d_io.parse(peek.kind, peek.compressed, message)
    class_info = c.OrderedDict()

    for _c in pbmsg.classes:
        _id, dt, name = str(_c.class_id), _c.table_name, _c.network_name
        class_info[_id] = (dt, name)

    # send tables
    peek, message = prologue.send_tables
    pbmsg = d_io.parse(peek.kind, peek.compressed, message)
    send_tables = c.OrderedDict()

    for peek, message in p_io.construct(pbmsg.data):
        pbmsg = p_io.parse(peek.kind, message)
        if pbmsg.is_end:
            break

        send_table = _parse_cdemo_send_table(pbmsg)
        send_tables[send_table.dt] = send_table

    # recv tables
    flattener = Flattener(send_tables)
    recv_tables = c.OrderedDict()

    for st in filter(test_needs_decoder, send_tables.values()):
        props = flattener.flatten(st)
        cls = next(_id for _id, (dt, _) in class_info.items() if dt == st.dt)
        recv_tables[cls] = dt_r.construct(st.dt, props)

    # game event list
    peek, message = packet.find(pb_n.svc_GameEventList)
    pbmsg = p_io.parse(peek.kind, message)
    game_event_list = c.OrderedDict()

    for desc in pbmsg.descriptors:
        _id, name = desc.eventid, desc.name
        keys = [(k.type, k.name) for k in desc.keys]
        game_event_list[_id] = (name, keys)

    # string tables
    entries = packet.find_all(pb_n.svc_CreateStringTable)
    pbmsgs = [p_io.parse(p.kind, m) for p, m in entries]
    string_tables = _parse_all_csvc_create_string_tables(pbmsgs)

    # meta: file header
    peek, message = prologue.file_header
    pbmsg = d_io.parse(peek.kind, peek.compressed, message)
    file_header = FileHeader(*[getattr(pbmsg, a) for a in FileHeader._fields])

    # meta: server_info
    peek, message = packet.find(pb_n.svc_ServerInfo)
    pbmsg = p_io.parse(peek.kind, message)
    server_info = ServerInfo(*[getattr(pbmsg, a) for a in ServerInfo._fields])

    # meta: class bits
    class_bits = server_info.max_classes.bit_length()

    # meta: voice init
    peek, message = packet.find(pb_n.svc_VoiceInit)
    pbmsg = p_io.parse(peek.kind, message)
    voice_init = VoiceInit(*[getattr(pbmsg, a) for a in VoiceInit._fields])

    meta = Meta(file_header, server_info, voice_init)

    return Prologue(meta, recv_tables, string_tables, game_event_list,
                    class_bits)