regain basic WebHost functionality
This commit is contained in:
parent
c5ff962ea1
commit
b82d6cec31
|
@ -7,7 +7,7 @@ from concurrent.futures import ThreadPoolExecutor
|
||||||
|
|
||||||
import colorama
|
import colorama
|
||||||
import asyncio
|
import asyncio
|
||||||
from queue import Queue, Empty
|
from queue import Queue
|
||||||
from CommonClient import CommonContext, server_loop, console_loop, ClientCommandProcessor, logger
|
from CommonClient import CommonContext, server_loop, console_loop, ClientCommandProcessor, logger
|
||||||
from MultiServer import mark_raw
|
from MultiServer import mark_raw
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
|
import json
|
||||||
import pickle
|
import pickle
|
||||||
|
|
||||||
from uuid import UUID
|
from uuid import UUID
|
||||||
|
|
||||||
from . import api_endpoints
|
from . import api_endpoints
|
||||||
|
@ -46,7 +48,7 @@ def generate_api():
|
||||||
gen = Generation(
|
gen = Generation(
|
||||||
options=pickle.dumps({name: vars(options) for name, options in gen_options.items()}),
|
options=pickle.dumps({name: vars(options) for name, options in gen_options.items()}),
|
||||||
# convert to json compatible
|
# convert to json compatible
|
||||||
meta=pickle.dumps({"race": race}), state=STATE_QUEUED,
|
meta=json.dumps({"race": race}), state=STATE_QUEUED,
|
||||||
owner=session["_id"])
|
owner=session["_id"])
|
||||||
commit()
|
commit()
|
||||||
return {"text": f"Generation of seed {gen.id} started successfully.",
|
return {"text": f"Generation of seed {gen.id} started successfully.",
|
||||||
|
@ -55,7 +57,8 @@ def generate_api():
|
||||||
"wait_api_url": url_for("api.wait_seed_api", seed=gen.id, _external=True),
|
"wait_api_url": url_for("api.wait_seed_api", seed=gen.id, _external=True),
|
||||||
"url": url_for("wait_seed", seed=gen.id, _external=True)}, 201
|
"url": url_for("wait_seed", seed=gen.id, _external=True)}, 201
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return {"text": "Uncaught Exception:" + str(e)}, 500
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@api_endpoints.route('/status/<suuid:seed>')
|
@api_endpoints.route('/status/<suuid:seed>')
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
import logging
|
import logging
|
||||||
|
import json
|
||||||
import multiprocessing
|
import multiprocessing
|
||||||
from datetime import timedelta, datetime
|
from datetime import timedelta, datetime
|
||||||
import concurrent.futures
|
import concurrent.futures
|
||||||
|
@ -9,6 +10,8 @@ import time
|
||||||
|
|
||||||
from pony.orm import db_session, select, commit
|
from pony.orm import db_session, select, commit
|
||||||
|
|
||||||
|
from Utils import restricted_loads
|
||||||
|
|
||||||
|
|
||||||
class CommonLocker():
|
class CommonLocker():
|
||||||
"""Uses a file lock to signal that something is already running"""
|
"""Uses a file lock to signal that something is already running"""
|
||||||
|
@ -78,13 +81,20 @@ def handle_generation_failure(result: BaseException):
|
||||||
|
|
||||||
|
|
||||||
def launch_generator(pool: multiprocessing.pool.Pool, generation: Generation):
|
def launch_generator(pool: multiprocessing.pool.Pool, generation: Generation):
|
||||||
options = generation.options
|
try:
|
||||||
|
meta = json.loads(generation.meta)
|
||||||
|
options = restricted_loads(generation.options)
|
||||||
logging.info(f"Generating {generation.id} for {len(options)} players")
|
logging.info(f"Generating {generation.id} for {len(options)} players")
|
||||||
|
|
||||||
meta = generation.meta
|
|
||||||
pool.apply_async(gen_game, (options,),
|
pool.apply_async(gen_game, (options,),
|
||||||
{"race": meta["race"], "sid": generation.id, "owner": generation.owner},
|
{"race": meta["race"],
|
||||||
|
"sid": generation.id,
|
||||||
|
"owner": generation.owner},
|
||||||
handle_generation_success, handle_generation_failure)
|
handle_generation_success, handle_generation_failure)
|
||||||
|
except:
|
||||||
|
generation.state = STATE_ERROR
|
||||||
|
commit()
|
||||||
|
raise
|
||||||
|
else:
|
||||||
generation.state = STATE_STARTED
|
generation.state = STATE_STARTED
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import os
|
import os
|
||||||
import tempfile
|
import tempfile
|
||||||
import random
|
import random
|
||||||
|
import json
|
||||||
from collections import Counter
|
from collections import Counter
|
||||||
|
|
||||||
from flask import request, flash, redirect, url_for, session, render_template
|
from flask import request, flash, redirect, url_for, session, render_template
|
||||||
|
@ -94,10 +95,6 @@ def gen_game(gen_options, race=False, owner=None, sid=None):
|
||||||
|
|
||||||
erargs.names = ",".join(erargs.name[i] for i in range(1, playercount + 1))
|
erargs.names = ",".join(erargs.name[i] for i in range(1, playercount + 1))
|
||||||
del (erargs.name)
|
del (erargs.name)
|
||||||
|
|
||||||
erargs.skip_progression_balancing = {player: not balanced for player, balanced in
|
|
||||||
erargs.progression_balancing.items()}
|
|
||||||
del (erargs.progression_balancing)
|
|
||||||
ERmain(erargs, seed)
|
ERmain(erargs, seed)
|
||||||
|
|
||||||
return upload_to_db(target.name, owner, sid, race)
|
return upload_to_db(target.name, owner, sid, race)
|
||||||
|
@ -107,7 +104,11 @@ def gen_game(gen_options, race=False, owner=None, sid=None):
|
||||||
gen = Generation.get(id=sid)
|
gen = Generation.get(id=sid)
|
||||||
if gen is not None:
|
if gen is not None:
|
||||||
gen.state = STATE_ERROR
|
gen.state = STATE_ERROR
|
||||||
gen.meta = (e.__class__.__name__ + ": "+ str(e)).encode()
|
meta = json.loads(gen.meta)
|
||||||
|
meta["error"] = (e.__class__.__name__ + ": "+ str(e))
|
||||||
|
gen.meta = json.dumps(meta)
|
||||||
|
|
||||||
|
commit()
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
@ -122,7 +123,7 @@ def wait_seed(seed: UUID):
|
||||||
if not generation:
|
if not generation:
|
||||||
return "Generation not found."
|
return "Generation not found."
|
||||||
elif generation.state == STATE_ERROR:
|
elif generation.state == STATE_ERROR:
|
||||||
return render_template("seedError.html", seed_error=generation.meta.decode())
|
return render_template("seedError.html", seed_error=generation.meta)
|
||||||
return render_template("waitSeed.html", seed_id=seed_id)
|
return render_template("waitSeed.html", seed_id=seed_id)
|
||||||
|
|
||||||
|
|
||||||
|
@ -147,10 +148,10 @@ def upload_to_db(folder, owner, sid, race:bool):
|
||||||
with db_session:
|
with db_session:
|
||||||
if sid:
|
if sid:
|
||||||
seed = Seed(multidata=multidata, spoiler=spoiler, patches=patches, owner=owner,
|
seed = Seed(multidata=multidata, spoiler=spoiler, patches=patches, owner=owner,
|
||||||
id=sid, meta={"tags": ["generated"]})
|
id=sid, meta=json.dumps({"tags": ["generated"]}))
|
||||||
else:
|
else:
|
||||||
seed = Seed(multidata=multidata, spoiler=spoiler, patches=patches, owner=owner,
|
seed = Seed(multidata=multidata, spoiler=spoiler, patches=patches, owner=owner,
|
||||||
meta={"tags": ["generated"]})
|
meta=json.dumps({"tags": ["generated"]}))
|
||||||
for patch in patches:
|
for patch in patches:
|
||||||
patch.seed = seed
|
patch.seed = seed
|
||||||
if sid:
|
if sid:
|
||||||
|
|
|
@ -39,7 +39,7 @@ class Seed(db.Entity):
|
||||||
creation_time = Required(datetime, default=lambda: datetime.utcnow())
|
creation_time = Required(datetime, default=lambda: datetime.utcnow())
|
||||||
patches = Set(Patch)
|
patches = Set(Patch)
|
||||||
spoiler = Optional(LongStr, lazy=True)
|
spoiler = Optional(LongStr, lazy=True)
|
||||||
meta = Required(Json, lazy=True, default=lambda: {}) # additional meta information/tags
|
meta = Required(str, default=lambda: "{\"race\": false}") # additional meta information/tags
|
||||||
|
|
||||||
|
|
||||||
class Command(db.Entity):
|
class Command(db.Entity):
|
||||||
|
@ -51,6 +51,6 @@ class Command(db.Entity):
|
||||||
class Generation(db.Entity):
|
class Generation(db.Entity):
|
||||||
id = PrimaryKey(UUID, default=uuid4)
|
id = PrimaryKey(UUID, default=uuid4)
|
||||||
owner = Required(UUID)
|
owner = Required(UUID)
|
||||||
options = Required(Json, lazy=True)
|
options = Required(buffer, lazy=True)
|
||||||
meta = Required(Json, lazy=True)
|
meta = Required(str, default=lambda: "{\"race\": false}")
|
||||||
state = Required(int, default=0, index=True)
|
state = Required(int, default=0, index=True)
|
||||||
|
|
|
@ -39,7 +39,7 @@
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><img src="{{ icons["Pegasus Boots"] }}" class="{{ 'acquired' if "Pegasus Boots" in acquired_items }}" /></td>
|
<td><img src="{{ icons["Pegasus Boots"] }}" class="{{ 'acquired' if "Pegasus Boots" in acquired_items }}" /></td>
|
||||||
<td><img src="{{ gloves_url }}" class="{{ 'acquired' if gloves_acquired }}" /></td>
|
<td><img src="{{ glove_url }}" class="{{ 'acquired' if glove_acquired }}" /></td>
|
||||||
<td><img src="{{ icons["Flippers"] }}" class="{{ 'acquired' if "Flippers" in acquired_items }}" /></td>
|
<td><img src="{{ icons["Flippers"] }}" class="{{ 'acquired' if "Flippers" in acquired_items }}" /></td>
|
||||||
<td><img src="{{ icons["Moon Pearl"] }}" class="{{ 'acquired' if "Moon Pearl" in acquired_items }}" /></td>
|
<td><img src="{{ icons["Moon Pearl"] }}" class="{{ 'acquired' if "Moon Pearl" in acquired_items }}" /></td>
|
||||||
<td><img src="{{ icons["Mushroom"] }}" class="{{ 'acquired' if "Mushroom" in acquired_items }}" /></td>
|
<td><img src="{{ icons["Mushroom"] }}" class="{{ 'acquired' if "Mushroom" in acquired_items }}" /></td>
|
||||||
|
|
|
@ -31,10 +31,7 @@
|
||||||
<tr>
|
<tr>
|
||||||
<td><a href="{{ url_for("viewSeed", seed=room.seed.id) }}">{{ room.seed.id|suuid }}</a></td>
|
<td><a href="{{ url_for("viewSeed", seed=room.seed.id) }}">{{ room.seed.id|suuid }}</a></td>
|
||||||
<td><a href="{{ url_for("hostRoom", room=room.id) }}">{{ room.id|suuid }}</a></td>
|
<td><a href="{{ url_for("hostRoom", room=room.id) }}">{{ room.id|suuid }}</a></td>
|
||||||
<td
|
<td>>={{ room.seed.patches|length }}</td>
|
||||||
class="center"
|
|
||||||
data-tooltip="{{ room.seed.multidata.names[0]|join(", ")|truncate(256, False, " ...") }}"
|
|
||||||
>{{ room.seed.multidata.names[0]|length }}</td>
|
|
||||||
<td>{{ room.creation_time.strftime("%Y-%m-%d %H:%M") }}</td>
|
<td>{{ room.creation_time.strftime("%Y-%m-%d %H:%M") }}</td>
|
||||||
<td>{{ room.last_activity.strftime("%Y-%m-%d %H:%M") }}</td>
|
<td>{{ room.last_activity.strftime("%Y-%m-%d %H:%M") }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -59,11 +56,7 @@
|
||||||
{% for seed in seeds %}
|
{% for seed in seeds %}
|
||||||
<tr>
|
<tr>
|
||||||
<td><a href="{{ url_for("viewSeed", seed=seed.id) }}">{{ seed.id|suuid }}</a></td>
|
<td><a href="{{ url_for("viewSeed", seed=seed.id) }}">{{ seed.id|suuid }}</a></td>
|
||||||
<td class="center"
|
<td>{% if seed.multidata %}>={{ seed.patches|length }}{% else %}1{% endif %}
|
||||||
{% if seed.multidata %}
|
|
||||||
data-tooltip="{{ seed.multidata.names[0]|join(", ")|truncate(256, False, " ...") }}"
|
|
||||||
{% endif %}
|
|
||||||
>{% if seed.multidata %}{{ seed.multidata.names[0]|length }}{% else %}1{% endif %}
|
|
||||||
</td>
|
</td>
|
||||||
<td>{{ seed.creation_time.strftime("%Y-%m-%d %H:%M") }}</td>
|
<td>{{ seed.creation_time.strftime("%Y-%m-%d %H:%M") }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
@ -266,6 +266,7 @@ def attribute_item(inventory, team, recipient, item):
|
||||||
|
|
||||||
|
|
||||||
def attribute_item_solo(inventory, item):
|
def attribute_item_solo(inventory, item):
|
||||||
|
"""Adds item to inventory counter, converts everything to progressive."""
|
||||||
target_item = links.get(item, item)
|
target_item = links.get(item, item)
|
||||||
if item in levels: # non-progressive
|
if item in levels: # non-progressive
|
||||||
inventory[target_item] = max(inventory[target_item], levels[item])
|
inventory[target_item] = max(inventory[target_item], levels[item])
|
||||||
|
@ -319,10 +320,11 @@ def get_static_room_data(room: Room):
|
||||||
|
|
||||||
player_big_key_locations = {playernumber: set() for playernumber in range(1, len(names[0]) + 1)}
|
player_big_key_locations = {playernumber: set() for playernumber in range(1, len(names[0]) + 1)}
|
||||||
player_small_key_locations = {playernumber: set() for playernumber in range(1, len(names[0]) + 1)}
|
player_small_key_locations = {playernumber: set() for playernumber in range(1, len(names[0]) + 1)}
|
||||||
for _, (item_id, item_player) in locations.items():
|
for loc_data in locations.values():
|
||||||
|
for item_id, item_player in loc_data.values():
|
||||||
if item_id in ids_big_key:
|
if item_id in ids_big_key:
|
||||||
player_big_key_locations[item_player].add(ids_big_key[item_id])
|
player_big_key_locations[item_player].add(ids_big_key[item_id])
|
||||||
if item_id in ids_small_key:
|
elif item_id in ids_small_key:
|
||||||
player_small_key_locations[item_player].add(ids_small_key[item_id])
|
player_small_key_locations[item_player].add(ids_small_key[item_id])
|
||||||
|
|
||||||
result = locations, names, use_door_tracker, player_checks_in_area, player_location_to_area, \
|
result = locations, names, use_door_tracker, player_checks_in_area, player_location_to_area, \
|
||||||
|
@ -332,7 +334,7 @@ def get_static_room_data(room: Room):
|
||||||
|
|
||||||
|
|
||||||
@app.route('/tracker/<suuid:tracker>/<int:tracked_team>/<int:tracked_player>')
|
@app.route('/tracker/<suuid:tracker>/<int:tracked_team>/<int:tracked_player>')
|
||||||
@cache.memoize(timeout=15)
|
@cache.memoize(timeout=60) # multisave is currently created at most every minute
|
||||||
def getPlayerTracker(tracker: UUID, tracked_team: int, tracked_player: int):
|
def getPlayerTracker(tracker: UUID, tracked_team: int, tracked_player: int):
|
||||||
# Team and player must be positive and greater than zero
|
# Team and player must be positive and greater than zero
|
||||||
if tracked_team < 0 or tracked_player < 1:
|
if tracked_team < 0 or tracked_player < 1:
|
||||||
|
@ -362,17 +364,15 @@ def getPlayerTracker(tracker: UUID, tracked_team: int, tracked_player: int):
|
||||||
multisave = {}
|
multisave = {}
|
||||||
|
|
||||||
# Add items to player inventory
|
# Add items to player inventory
|
||||||
for (ms_team, ms_player), locations_checked in multisave.get("location_checks", {}):
|
for (ms_team, ms_player), locations_checked in multisave.get("location_checks", {}).items():
|
||||||
# logging.info(f"{ms_team}, {ms_player}, {locations_checked}")
|
# logging.info(f"{ms_team}, {ms_player}, {locations_checked}")
|
||||||
# Skip teams and players not matching the request
|
# Skip teams and players not matching the request
|
||||||
|
player_locations = locations[ms_player]
|
||||||
if ms_team == tracked_team:
|
if ms_team == tracked_team:
|
||||||
# If the player does not have the item, do nothing
|
# If the player does not have the item, do nothing
|
||||||
for location in locations_checked:
|
for location in locations_checked:
|
||||||
if (location, ms_player) not in locations:
|
if location in player_locations:
|
||||||
continue
|
item, recipient = player_locations[location]
|
||||||
|
|
||||||
item, recipient = locations[location, ms_player]
|
|
||||||
if recipient == tracked_player: # a check done for the tracked player
|
if recipient == tracked_player: # a check done for the tracked player
|
||||||
attribute_item_solo(inventory, item)
|
attribute_item_solo(inventory, item)
|
||||||
if ms_player == tracked_player: # a check done by the tracked player
|
if ms_player == tracked_player: # a check done by the tracked player
|
||||||
|
@ -380,18 +380,10 @@ def getPlayerTracker(tracker: UUID, tracked_team: int, tracked_player: int):
|
||||||
checks_done["Total"] += 1
|
checks_done["Total"] += 1
|
||||||
|
|
||||||
# Note the presence of the triforce item
|
# Note the presence of the triforce item
|
||||||
for (ms_team, ms_player), game_state in multisave.get("client_game_state", []):
|
game_state = multisave.get("client_game_state", {}).get((tracked_team, tracked_player), 0)
|
||||||
# Skip teams and players not matching the request
|
if game_state == 30:
|
||||||
if ms_team != tracked_team or ms_player != tracked_player:
|
|
||||||
continue
|
|
||||||
|
|
||||||
if game_state:
|
|
||||||
inventory[106] = 1 # Triforce
|
inventory[106] = 1 # Triforce
|
||||||
|
|
||||||
acquired_items = []
|
|
||||||
for itm in inventory:
|
|
||||||
acquired_items.append(get_item_name_from_id(itm))
|
|
||||||
|
|
||||||
# Progressive items need special handling for icons and class
|
# Progressive items need special handling for icons and class
|
||||||
progressive_items = {
|
progressive_items = {
|
||||||
"Progressive Sword": 94,
|
"Progressive Sword": 94,
|
||||||
|
@ -400,86 +392,42 @@ def getPlayerTracker(tracker: UUID, tracked_team: int, tracked_player: int):
|
||||||
"Progressive Mail": 96,
|
"Progressive Mail": 96,
|
||||||
"Progressive Shield": 95,
|
"Progressive Shield": 95,
|
||||||
}
|
}
|
||||||
|
progressive_names = {
|
||||||
|
"Progressive Sword": [None, 'Fighter Sword', 'Master Sword', 'Tempered Sword', 'Golden Sword'],
|
||||||
|
"Progressive Glove": [None, 'Power Glove', 'Titan Mitts'],
|
||||||
|
"Progressive Bow": [None, "Bow", "Silver Bow"],
|
||||||
|
"Progressive Mail": ["Green Mail", "Blue Mail", "Red Mail"],
|
||||||
|
"Progressive Shield": [None, "Blue Shield", "Red Shield", "Mirror Shield"]
|
||||||
|
}
|
||||||
|
|
||||||
# Determine which icon to use for the sword
|
# Determine which icon to use
|
||||||
sword_url = icons["Fighter Sword"]
|
display_data = {}
|
||||||
sword_acquired = False
|
for item_name, item_id in progressive_items.items():
|
||||||
sword_names = ['Fighter Sword', 'Master Sword', 'Tempered Sword', 'Golden Sword']
|
level = min(inventory[item_id], len(progressive_names[item_name]))
|
||||||
if "Progressive Sword" in acquired_items:
|
display_name = progressive_names[item_name][level]
|
||||||
sword_url = icons[sword_names[min(inventory[progressive_items["Progressive Sword"]], 4) - 1]]
|
acquired = True
|
||||||
sword_acquired = True
|
if not display_name:
|
||||||
else:
|
acquired = False
|
||||||
for sword in reversed(sword_names):
|
display_name = progressive_names[item_name][level+1]
|
||||||
if sword in acquired_items:
|
base_name = item_name.split(maxsplit=1)[1].lower()
|
||||||
sword_url = icons[sword]
|
display_data[base_name+"_acquired"] = acquired
|
||||||
sword_acquired = True
|
display_data[base_name+"_url"] = icons[display_name]
|
||||||
break
|
|
||||||
|
|
||||||
gloves_url = icons["Power Glove"]
|
|
||||||
gloves_acquired = False
|
|
||||||
glove_names = ["Power Glove", "Titan Mitts"]
|
|
||||||
if "Progressive Glove" in acquired_items:
|
|
||||||
gloves_url = icons[glove_names[min(inventory[progressive_items["Progressive Glove"]], 2) - 1]]
|
|
||||||
gloves_acquired = True
|
|
||||||
else:
|
|
||||||
for glove in reversed(glove_names):
|
|
||||||
if glove in acquired_items:
|
|
||||||
gloves_url = icons[glove]
|
|
||||||
gloves_acquired = True
|
|
||||||
break
|
|
||||||
|
|
||||||
bow_url = icons["Bow"]
|
|
||||||
bow_acquired = False
|
|
||||||
bow_names = ["Bow", "Silver Bow"]
|
|
||||||
if "Progressive Bow" in acquired_items:
|
|
||||||
bow_url = icons[bow_names[min(inventory[progressive_items["Progressive Bow"]], 2) - 1]]
|
|
||||||
bow_acquired = True
|
|
||||||
else:
|
|
||||||
for bow in reversed(bow_names):
|
|
||||||
if bow in acquired_items:
|
|
||||||
bow_url = icons[bow]
|
|
||||||
bow_acquired = True
|
|
||||||
break
|
|
||||||
|
|
||||||
mail_url = icons["Green Mail"]
|
|
||||||
mail_names = ["Blue Mail", "Red Mail"]
|
|
||||||
if "Progressive Mail" in acquired_items:
|
|
||||||
mail_url = icons[mail_names[min(inventory[progressive_items["Progressive Mail"]], 2) - 1]]
|
|
||||||
else:
|
|
||||||
for mail in reversed(mail_names):
|
|
||||||
if mail in acquired_items:
|
|
||||||
mail_url = icons[mail]
|
|
||||||
break
|
|
||||||
|
|
||||||
shield_url = icons["Blue Shield"]
|
|
||||||
shield_acquired = False
|
|
||||||
shield_names = ["Blue Shield", "Red Shield", "Mirror Shield"]
|
|
||||||
if "Progressive Shield" in acquired_items:
|
|
||||||
shield_url = icons[shield_names[min(inventory[progressive_items["Progressive Shield"]], 3) - 1]]
|
|
||||||
shield_acquired = True
|
|
||||||
else:
|
|
||||||
for shield in reversed(shield_names):
|
|
||||||
if shield in acquired_items:
|
|
||||||
shield_url = icons[shield]
|
|
||||||
shield_acquired = True
|
|
||||||
break
|
|
||||||
|
|
||||||
# The single player tracker doesn't care about overworld, underworld, and total checks. Maybe it should?
|
# The single player tracker doesn't care about overworld, underworld, and total checks. Maybe it should?
|
||||||
sp_areas = ordered_areas[2:15]
|
sp_areas = ordered_areas[2:15]
|
||||||
|
|
||||||
return render_template("playerTracker.html", inventory=inventory, get_item_name_from_id=get_item_name_from_id,
|
return render_template("playerTracker.html", inventory=inventory, get_item_name_from_id=get_item_name_from_id,
|
||||||
player_name=player_name, room=room, icons=icons, checks_done=checks_done,
|
player_name=player_name, room=room, icons=icons, checks_done=checks_done,
|
||||||
checks_in_area=seed_checks_in_area, acquired_items=acquired_items,
|
checks_in_area=seed_checks_in_area, acquired_items={Items.lookup_id_to_name[id] for id in inventory},
|
||||||
sword_url=sword_url, sword_acquired=sword_acquired, gloves_url=gloves_url,
|
|
||||||
gloves_acquired=gloves_acquired, bow_url=bow_url, bow_acquired=bow_acquired,
|
|
||||||
small_key_ids=small_key_ids, big_key_ids=big_key_ids, sp_areas=sp_areas,
|
small_key_ids=small_key_ids, big_key_ids=big_key_ids, sp_areas=sp_areas,
|
||||||
key_locations=player_small_key_locations[tracked_player],
|
key_locations=player_small_key_locations[tracked_player],
|
||||||
big_key_locations=player_big_key_locations[tracked_player],
|
big_key_locations=player_big_key_locations[tracked_player],
|
||||||
mail_url=mail_url, shield_url=shield_url, shield_acquired=shield_acquired)
|
**display_data)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/tracker/<suuid:tracker>')
|
@app.route('/tracker/<suuid:tracker>')
|
||||||
@cache.memoize(timeout=30) # update every 30 seconds
|
@cache.memoize(timeout=60) # multisave is currently created at most every minute
|
||||||
def getTracker(tracker: UUID):
|
def getTracker(tracker: UUID):
|
||||||
room = Room.get(tracker=tracker)
|
room = Room.get(tracker=tracker)
|
||||||
if not room:
|
if not room:
|
||||||
|
@ -500,26 +448,27 @@ def getTracker(tracker: UUID):
|
||||||
else:
|
else:
|
||||||
multisave = {}
|
multisave = {}
|
||||||
if "hints" in multisave:
|
if "hints" in multisave:
|
||||||
for key, hintdata in multisave["hints"]:
|
|
||||||
for hint in hintdata:
|
|
||||||
hints[key[0]].add(Hint(*hint))
|
|
||||||
|
|
||||||
for (team, player), locations_checked in multisave.get("location_checks", {}):
|
for (team, slot), slot_hints in multisave["hints"].items():
|
||||||
|
hints[team] |= set(slot_hints)
|
||||||
|
|
||||||
|
for (team, player), locations_checked in multisave.get("location_checks", {}).items():
|
||||||
|
player_locations = locations[player]
|
||||||
if precollected_items:
|
if precollected_items:
|
||||||
precollected = precollected_items[player]
|
precollected = precollected_items[player]
|
||||||
for item_id in precollected:
|
for item_id in precollected:
|
||||||
attribute_item(inventory, team, player, item_id)
|
attribute_item(inventory, team, player, item_id)
|
||||||
for location in locations_checked:
|
for location in locations_checked:
|
||||||
if (location, player) not in locations or location not in player_location_to_area[player]:
|
if location not in player_locations or location not in player_location_to_area[player]:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
item, recipient = locations[location, player]
|
item, recipient = player_locations[location]
|
||||||
attribute_item(inventory, team, recipient, item)
|
attribute_item(inventory, team, recipient, item)
|
||||||
checks_done[team][player][player_location_to_area[player][location]] += 1
|
checks_done[team][player][player_location_to_area[player][location]] += 1
|
||||||
checks_done[team][player]["Total"] += 1
|
checks_done[team][player]["Total"] += 1
|
||||||
|
|
||||||
for (team, player), game_state in multisave.get("client_game_state", []):
|
for (team, player), game_state in multisave.get("client_game_state", {}).items():
|
||||||
if game_state:
|
if game_state == 30:
|
||||||
inventory[team][player][106] = 1 # Triforce
|
inventory[team][player][106] = 1 # Triforce
|
||||||
|
|
||||||
group_big_key_locations = set()
|
group_big_key_locations = set()
|
||||||
|
|
|
@ -362,6 +362,7 @@ def parse_arguments(argv, no_defaults=False):
|
||||||
create a binary patch file from which the randomized rom can be recreated using MultiClient.''')
|
create a binary patch file from which the randomized rom can be recreated using MultiClient.''')
|
||||||
parser.add_argument('--disable_glitch_boots', default=defval(False), action='store_true', help='''\
|
parser.add_argument('--disable_glitch_boots', default=defval(False), action='store_true', help='''\
|
||||||
turns off starting with Pegasus Boots in glitched modes.''')
|
turns off starting with Pegasus Boots in glitched modes.''')
|
||||||
|
parser.add_argument('--start_hints')
|
||||||
if multiargs.multi:
|
if multiargs.multi:
|
||||||
for player in range(1, multiargs.multi + 1):
|
for player in range(1, multiargs.multi + 1):
|
||||||
parser.add_argument(f'--p{player}', default=defval(''), help=argparse.SUPPRESS)
|
parser.add_argument(f'--p{player}', default=defval(''), help=argparse.SUPPRESS)
|
||||||
|
@ -405,7 +406,7 @@ def parse_arguments(argv, no_defaults=False):
|
||||||
'ow_palettes', 'uw_palettes', 'sprite', 'disablemusic', 'quickswap', 'fastmenu', 'heartcolor',
|
'ow_palettes', 'uw_palettes', 'sprite', 'disablemusic', 'quickswap', 'fastmenu', 'heartcolor',
|
||||||
'heartbeep', "progression_balancing", "triforce_pieces_available",
|
'heartbeep', "progression_balancing", "triforce_pieces_available",
|
||||||
"triforce_pieces_required", "shop_shuffle", "shop_shuffle_slots",
|
"triforce_pieces_required", "shop_shuffle", "shop_shuffle_slots",
|
||||||
"required_medallions",
|
"required_medallions", "start_hints",
|
||||||
"plando_items", "plando_texts", "plando_connections", "er_seeds",
|
"plando_items", "plando_texts", "plando_connections", "er_seeds",
|
||||||
'progressive', 'dungeon_counters', 'glitch_boots', 'killable_thieves',
|
'progressive', 'dungeon_counters', 'glitch_boots', 'killable_thieves',
|
||||||
'tile_shuffle', 'bush_shuffle', 'shuffle_prizes', 'sprite_pool', 'dark_room_logic',
|
'tile_shuffle', 'bush_shuffle', 'shuffle_prizes', 'sprite_pool', 'dark_room_logic',
|
||||||
|
|
Loading…
Reference in New Issue