ValvePython/dota2

How can i create a lobby and start it manually?

Closed this issue · 6 comments

I'm new to gevent, sorry for this simple question.

I wanna create a lobby, invite some people, and start it manually,

How can I do this since I have to use client.run_forever()

I think using while loop and input like this may help, like this

@dota.on('lobby_new')
def on_dota_lobby_new(lobby):
    print('lobby {} created'.format(lobby.lobby_id))

    while True:
        in_num = input('''Input:
        1: invite all player not in lobby
        2: start game
        ''')
        if in_num == '1':
            for player in [SteamID(i) for i in Players]:
                print('invite player {}'.format(player))
                dota.invite_to_lobby(player)
        if in_num == '2':
            dota.launch_practice_lobby()

but I cannot create and invite , my code:

client = SteamClient()
client.set_credential_location('./steam_credentials')
dota = Dota2Client(client)


@client.on('logged_on')
def start_dota():
    print('starting dota2...')
    dota.launch()
    print('dota2 started')


@dota.on('ready')
def create_lobby():
    print('creating lobby')
    dota.create_practice_lobby(
        lobby_password,
        lobby_options,
    )
    dota.sleep(1)


@dota.on('lobby_new')
def on_dota_lobby_new(lobby):
    print('lobby {} created'.format(lobby.lobby_id))

    while True:
        in_num = input('''Input:
        1: invite all player not in lobby
        2: start game
        ''')
        if in_num == '1':
            for player in [SteamID(i) for i in Players]:
                print('invite player {}'.format(player))
                dota.invite_to_lobby(player)
        if in_num == '2':
            dota.launch_practice_lobby()


################################################################################

################################################################################
# client.cli_login()
client.login(username=username, password=password)

client.run_forever()

logs:

[2021-05-16 16:11:16,157] DEBUG SteamClient: Outgoing: <MsgProto(<EMsg.ClientToGC: 5452> | CMsgGCClient)>
[2021-05-16 16:11:16,591] DEBUG SteamClient: Incoming: <MsgProto(<EMsg.Multi: 1> | CMsgMulti)>
[2021-05-16 16:11:16,591] DEBUG SteamClient: Emit event: <EMsg.Multi: 1>
[2021-05-16 16:11:16,592] DEBUG SteamClient: Multi: Unpacking
[2021-05-16 16:11:16,592] DEBUG SteamClient: Multi: Decompressing payload (240 -> 243)
[2021-05-16 16:11:16,592] DEBUG SteamClient: Incoming: <MsgProto(<EMsg.ClientFromGC: 5453> | CMsgGCClient)>
[2021-05-16 16:11:16,592] DEBUG SteamClient: Emit event: <EMsg.ClientFromGC: 5453>
[2021-05-16 16:11:16,593] DEBUG Dota2Client: Incoming: <ESOMsg.CacheSubscribed: 24>
[2021-05-16 16:11:16,593] DEBUG Dota2Client: Emit event: <ESOMsg.CacheSubscribed: 24>
[2021-05-16 16:11:16,593] DEBUG Dota2Client.socache: Emit event: ('new', <ESOType.CSODOTALobby: 2004>)
[2021-05-16 16:11:16,594] DEBUG Dota2Client: Emit event: 'lobby_new'
lobby 27194914185633053 created
Input:
        1: invite all player not in lobby
        2: start game
        1
invite player 76561198079699992
[2021-05-16 16:11:18,459] DEBUG Dota2Client: Outgoing: <EGCBaseMsg.EMsgGCInviteToLobby: 4512>
[2021-05-16 16:11:18,459] DEBUG SteamClient: Outgoing: <MsgProto(<EMsg.ClientToGC: 5452> | CMsgGCClient)>
invite player 76561198299762733
[2021-05-16 16:11:18,459] DEBUG Dota2Client: Outgoing: <EGCBaseMsg.EMsgGCInviteToLobby: 4512>
[2021-05-16 16:11:18,459] DEBUG SteamClient: Outgoing: <MsgProto(<EMsg.ClientToGC: 5452> | CMsgGCClient)>
Input:
        1: invite all player not in lobby
        2: start game
        2
[2021-05-16 16:11:49,286] DEBUG Dota2Client: Outgoing: <EDOTAGCMsg.EMsgGCPracticeLobbyLaunch: 7041>
[2021-05-16 16:11:49,287] DEBUG SteamClient: Outgoing: <MsgProto(<EMsg.ClientToGC: 5452> | CMsgGCClient)>

there' nothing happens, whats wrong with my code?

You never yielded to gevent event loop. You've essentially queued 3 messages. You have to either wait, sleep, or idle or do any io to yield. I would do the code serially first as it would be easier to work with.

from steam.enums import EResult

client = SteamClient()
client.set_credential_location('./steam_credentials')
dota = Dota2Client(client)

# result = client.cli_login()
result = client.login(username=username, password=password)  # yield internally

if result != EResult.OK
  raise RuntimeException("Login failed")

print('starting dota2...')
dota.launch()
dota.wait_event('ready') # explicit yield (ideally you want to have a timeout and handling for it)

dota.create_practice_lobby(lobby_password, lobby_options)
dota.wait_event('lobby_new') # explicit yield
print('lobby {} created'.format(dota.lobby.lobby_id))

# i get what you are trying to do here, but because input blocks it won't work
# unfortunately, this is not trivial problem to solve
while True:
    # input blocks the entire thread
    in_num = input('''Input:
    1: invite all player not in lobby
    2: start game
    3: wait 15s
    4: run forever
    ''')
    if in_num == '1':
        for player in (SteamID(p) for p in Players):
            print('invite player {}'.format(player))
            dota.invite_to_lobby(player)
    if in_num == '2':
        dota.launch_practice_lobby()
    if in_num == '4':
        client.run_forever()

    # this would work for playing about, but its stupid
    client.sleep(15) # yield for 15 seconds, and re-prompt

thanks