Second commit
This commit is contained in:
parent
ac81bfc747
commit
4cc571f9d5
1 changed files with 86 additions and 9 deletions
|
@ -8,6 +8,12 @@ import websocket
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
|
||||||
|
def first(iterable, default=None):
|
||||||
|
for x in iterable:
|
||||||
|
return x
|
||||||
|
return default
|
||||||
|
|
||||||
|
|
||||||
# WS data to server: https://github.com/iasoon/pw3-moz2/blob/prototype/src/websocket.rs#L27
|
# WS data to server: https://github.com/iasoon/pw3-moz2/blob/prototype/src/websocket.rs#L27
|
||||||
# WS data from server: https://github.com/iasoon/pw3-moz2/blob/prototype/src/lobby_manager.rs#L244
|
# WS data from server: https://github.com/iasoon/pw3-moz2/blob/prototype/src/lobby_manager.rs#L244
|
||||||
# HTTP: https://github.com/iasoon/pw3-moz2/blob/prototype/src/main.rs#L451
|
# HTTP: https://github.com/iasoon/pw3-moz2/blob/prototype/src/main.rs#L451
|
||||||
|
@ -32,6 +38,7 @@ class Lobby:
|
||||||
|
|
||||||
self.own_player_id = None
|
self.own_player_id = None
|
||||||
self.players = None
|
self.players = None
|
||||||
|
self.proposals = None
|
||||||
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -43,6 +50,10 @@ class Lobby:
|
||||||
return ("https://" if self.tls else "http://") + self.url_base + f"/api/lobbies/{self.lobby_id}"
|
return ("https://" if self.tls else "http://") + self.url_base + f"/api/lobbies/{self.lobby_id}"
|
||||||
|
|
||||||
|
|
||||||
|
def get_player_by_name(self, name):
|
||||||
|
return first(p["id"] for p in self.players.values() if p["name"] == name)
|
||||||
|
|
||||||
|
|
||||||
def open_websocket(self, on_message, on_error, **kwargs):
|
def open_websocket(self, on_message, on_error, **kwargs):
|
||||||
|
|
||||||
def on_open(ws):
|
def on_open(ws):
|
||||||
|
@ -64,6 +75,13 @@ class Lobby:
|
||||||
int(player_id): data
|
int(player_id): data
|
||||||
for player_id, data in data["data"]["players"].items()
|
for player_id, data in data["data"]["players"].items()
|
||||||
}
|
}
|
||||||
|
self.proposals = data["data"]["proposals"]
|
||||||
|
|
||||||
|
elif data["type"] == "playerData":
|
||||||
|
self.players[data["data"]["id"]] = data["data"]
|
||||||
|
|
||||||
|
elif data["type"] == "proposalData":
|
||||||
|
self.proposals[data["data"]["id"]] = data["data"]
|
||||||
|
|
||||||
on_message(ws, data)
|
on_message(ws, data)
|
||||||
|
|
||||||
|
@ -73,7 +91,8 @@ class Lobby:
|
||||||
)
|
)
|
||||||
|
|
||||||
self.thread = threading.Thread(
|
self.thread = threading.Thread(
|
||||||
target=self.ws.run_forever
|
target=self.ws.run_forever,
|
||||||
|
daemon=True
|
||||||
)
|
)
|
||||||
self.thread.start()
|
self.thread.start()
|
||||||
|
|
||||||
|
@ -99,10 +118,21 @@ class Lobby:
|
||||||
self.own_player_id = own_player_data["id"]
|
self.own_player_id = own_player_data["id"]
|
||||||
|
|
||||||
|
|
||||||
|
def create_proposal(self, map_name, max_turns, players):
|
||||||
|
self._post(f"/proposals", {
|
||||||
|
"config": { "mapName": map_name, "maxTurns": max_turns },
|
||||||
|
"players": players
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
def accept_proposal(self, proposal_id):
|
def accept_proposal(self, proposal_id):
|
||||||
self._post(f"/proposals/{proposal_id}/accept", {"status": "Accepted"})
|
self._post(f"/proposals/{proposal_id}/accept", {"status": "Accepted"})
|
||||||
|
|
||||||
|
|
||||||
|
def start_proposal(self, proposal_id):
|
||||||
|
self._post(f"/proposals/{proposal_id}/start", None)
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_lobby_url(url, bot_name, token) -> "Lobby":
|
def from_lobby_url(url, bot_name, token) -> "Lobby":
|
||||||
"""
|
"""
|
||||||
|
@ -118,12 +148,17 @@ class Lobby:
|
||||||
|
|
||||||
return Lobby(lobby_id, bot_name, token, url_base, tls)
|
return Lobby(lobby_id, bot_name, token, url_base, tls)
|
||||||
|
|
||||||
def on_error(ws, error):
|
|
||||||
__import__("pprint").pprint(error)
|
|
||||||
|
|
||||||
|
def main():
|
||||||
if __name__ == "__main__":
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
if len(sys.argv) < 4 or sys.argv[1] in ("--help", "-h"):
|
||||||
|
print("MOZAIC receptionist -- manage MOZAIC matches from the comfort of your terminal",
|
||||||
|
file=sys.stderr)
|
||||||
|
print(f"Usage: {sys.argv[0]} <lobby_url> <bot_token> <bot_name>", file=sys.stderr)
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
lobby_url = sys.argv[1]
|
lobby_url = sys.argv[1]
|
||||||
bot_token = sys.argv[2]
|
bot_token = sys.argv[2]
|
||||||
bot_name = " ".join(sys.argv[3:])
|
bot_name = " ".join(sys.argv[3:])
|
||||||
|
@ -152,14 +187,56 @@ if __name__ == "__main__":
|
||||||
if can_answer(proposal) and owner_participates(proposal):
|
if can_answer(proposal) and owner_participates(proposal):
|
||||||
proposal_id = proposal["id"]
|
proposal_id = proposal["id"]
|
||||||
owner_name = lobby.players[proposal["owner_id"]]["name"]
|
owner_name = lobby.players[proposal["owner_id"]]["name"]
|
||||||
print(f"Accepting proposal from {owner_name}")
|
|
||||||
lobby.accept_proposal(proposal_id)
|
lobby.accept_proposal(proposal_id)
|
||||||
|
print(f"[Note: accepted proposal from {owner_name}]")
|
||||||
|
|
||||||
|
def start_match_if_possible(proposal):
|
||||||
|
if lobby.own_player_id == proposal["owner_id"] and proposal["status"] == "pending" and all(
|
||||||
|
(
|
||||||
|
p["status"] == "Accepted" and
|
||||||
|
# Everyone's bot must be connected
|
||||||
|
lobby.players[p["player_id"]]["client_connected"]
|
||||||
|
) for p in proposal["players"]
|
||||||
|
):
|
||||||
|
lobby.start_proposal(proposal["id"])
|
||||||
|
print(f"[Note: started match]")
|
||||||
|
|
||||||
def on_message(ws, msg):
|
def on_message(ws, msg):
|
||||||
if msg["type"] == "proposalData":
|
if msg["type"] == "proposalData":
|
||||||
accept_if_possible_and_owner_participates(msg["data"])
|
accept_if_possible_and_owner_participates(msg["data"])
|
||||||
elif msg["type"] == "lobbyState":
|
start_match_if_possible(msg["data"])
|
||||||
for proposal in msg["data"]["proposals"].values():
|
|
||||||
|
if msg["type"] == "lobbyState":
|
||||||
|
for proposal in lobby.proposals.values():
|
||||||
accept_if_possible_and_owner_participates(proposal)
|
accept_if_possible_and_owner_participates(proposal)
|
||||||
|
|
||||||
lobby.open_websocket(on_message, on_error)
|
# Be prepared to start a match as soon as the last bot comes online
|
||||||
|
if msg["type"] in ("lobbyState", "playerData"):
|
||||||
|
for proposal in lobby.proposals.values():
|
||||||
|
start_match_if_possible(proposal)
|
||||||
|
|
||||||
|
lobby.open_websocket(on_message, print)
|
||||||
|
|
||||||
|
try:
|
||||||
|
print("Note: auto-accepting and auto-starting in the background.")
|
||||||
|
while True:
|
||||||
|
print("To create new game, press enter.")
|
||||||
|
input()
|
||||||
|
print(" NEW GAME")
|
||||||
|
print()
|
||||||
|
map_name = input(" Map> ")
|
||||||
|
# FIXME Race: player data may not be received yet
|
||||||
|
print(" P1> " + lobby.players[lobby.own_player_id]["name"])
|
||||||
|
|
||||||
|
p2 = lobby.get_player_by_name(input(" P2> "))
|
||||||
|
while not p2:
|
||||||
|
print("User not found")
|
||||||
|
p2 = lobby.get_player_by_name(input(" P2> "))
|
||||||
|
|
||||||
|
lobby.create_proposal(map_name, 500, [lobby.own_player_id, p2])
|
||||||
|
except (KeyboardInterrupt, EOFError):
|
||||||
|
print(" Quitting")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|
Loading…
Reference in a new issue