Fix merge conflict. Very minor difference.
This commit is contained in:
commit
c7e8692964
|
@ -235,11 +235,11 @@ class Context:
|
|||
with open(multidatapath, 'rb') as f:
|
||||
data = f.read()
|
||||
|
||||
self._load(self._decompress(data), use_embedded_server_options)
|
||||
self._load(self.decompress(data), use_embedded_server_options)
|
||||
self.data_filename = multidatapath
|
||||
|
||||
@staticmethod
|
||||
def _decompress(data: bytes) -> dict:
|
||||
def decompress(data: bytes) -> dict:
|
||||
format_version = data[0]
|
||||
if format_version != 1:
|
||||
raise Exception("Incompatible multidata.")
|
||||
|
|
11
SNIClient.py
11
SNIClient.py
|
@ -523,10 +523,13 @@ def launch_sni(ctx: Context):
|
|||
if not os.path.isdir(sni_path):
|
||||
sni_path = Utils.local_path(sni_path)
|
||||
if os.path.isdir(sni_path):
|
||||
for file in os.listdir(sni_path):
|
||||
lower_file = file.lower()
|
||||
if (lower_file.startswith("sni.") and not lower_file.endswith(".proto")) or lower_file == "sni":
|
||||
sni_path = os.path.join(sni_path, file)
|
||||
dir_entry: os.DirEntry
|
||||
for dir_entry in os.scandir(sni_path):
|
||||
if dir_entry.is_file():
|
||||
lower_file = dir_entry.name.lower()
|
||||
if (lower_file.startswith("sni.") and not lower_file.endswith(".proto")) or (lower_file == "sni"):
|
||||
sni_path = dir_entry.path
|
||||
break
|
||||
|
||||
if os.path.isfile(sni_path):
|
||||
snes_logger.info(f"Attempting to start {sni_path}")
|
||||
|
|
|
@ -76,7 +76,7 @@ class WebHostContext(Context):
|
|||
else:
|
||||
self.port = get_random_port()
|
||||
|
||||
return self._load(self._decompress(room.seed.multidata), True)
|
||||
return self._load(self.decompress(room.seed.multidata), True)
|
||||
|
||||
@db_session
|
||||
def init_save(self, enabled: bool = True):
|
||||
|
|
|
@ -37,8 +37,6 @@ def create():
|
|||
}
|
||||
|
||||
for game_name, world in AutoWorldRegister.world_types.items():
|
||||
if (world.hidden):
|
||||
continue
|
||||
|
||||
all_options = {**world.options, **Options.per_game_common_options}
|
||||
res = Template(open(os.path.join("WebHostLib", "templates", "options.yaml")).read()).render(
|
||||
|
@ -99,13 +97,14 @@ def create():
|
|||
os.makedirs(os.path.join(target_folder, 'player-settings'), exist_ok=True)
|
||||
|
||||
with open(os.path.join(target_folder, 'player-settings', game_name + ".json"), "w") as f:
|
||||
f.write(json.dumps(player_settings, indent=2, separators=(',', ': ')))
|
||||
json.dump(player_settings, f, indent=2, separators=(',', ': '))
|
||||
|
||||
weighted_settings["baseOptions"]["game"][game_name] = 0
|
||||
weighted_settings["games"][game_name] = {}
|
||||
weighted_settings["games"][game_name]["gameSettings"] = game_options
|
||||
weighted_settings["games"][game_name]["gameItems"] = tuple(world.item_name_to_id.keys())
|
||||
weighted_settings["games"][game_name]["gameLocations"] = tuple(world.location_name_to_id.keys())
|
||||
if not world.hidden:
|
||||
weighted_settings["baseOptions"]["game"][game_name] = 0
|
||||
weighted_settings["games"][game_name] = {}
|
||||
weighted_settings["games"][game_name]["gameSettings"] = game_options
|
||||
weighted_settings["games"][game_name]["gameItems"] = tuple(world.item_names)
|
||||
weighted_settings["games"][game_name]["gameLocations"] = tuple(world.location_names)
|
||||
|
||||
with open(os.path.join(target_folder, 'weighted-settings.json'), "w") as f:
|
||||
f.write(json.dumps(weighted_settings, indent=2, separators=(',', ': ')))
|
||||
json.dump(weighted_settings, f, indent=2, separators=(',', ': '))
|
||||
|
|
|
@ -252,7 +252,7 @@ def get_static_room_data(room: Room):
|
|||
result = _multidata_cache.get(room.seed.id, None)
|
||||
if result:
|
||||
return result
|
||||
multidata = Context._decompress(room.seed.multidata)
|
||||
multidata = Context.decompress(room.seed.multidata)
|
||||
# in > 100 players this can take a bit of time and is the main reason for the cache
|
||||
locations: Dict[int, Dict[int, Tuple[int, int]]] = multidata['locations']
|
||||
names: Dict[int, Dict[int, str]] = multidata["names"]
|
||||
|
|
|
@ -67,7 +67,7 @@ def upload_zip_to_db(zfile: zipfile.ZipFile, owner=None, meta={"race": False}, s
|
|||
multidata = None
|
||||
|
||||
if multidata:
|
||||
decompressed_multidata = MultiServer.Context._decompress(multidata)
|
||||
decompressed_multidata = MultiServer.Context.decompress(multidata)
|
||||
player_names = {slot.player_name for slot in slots}
|
||||
leftover_names = [(name, index) for index, name in
|
||||
enumerate((name for name in decompressed_multidata["names"][0]), start=1)]
|
||||
|
@ -100,7 +100,7 @@ def uploads():
|
|||
if file.filename == '':
|
||||
flash('No selected file')
|
||||
elif file and allowed_file(file.filename):
|
||||
if file.filename.endswith(".zip"):
|
||||
if zipfile.is_zipfile(file.filename):
|
||||
with zipfile.ZipFile(file, 'r') as zfile:
|
||||
res = upload_zip_to_db(zfile)
|
||||
if type(res) == str:
|
||||
|
@ -108,12 +108,12 @@ def uploads():
|
|||
elif res:
|
||||
return redirect(url_for("view_seed", seed=res.id))
|
||||
else:
|
||||
# noinspection PyBroadException
|
||||
try:
|
||||
multidata = file.read()
|
||||
MultiServer.Context._decompress(multidata)
|
||||
MultiServer.Context.decompress(multidata)
|
||||
except:
|
||||
flash("Could not load multidata. File may be corrupted or incompatible.")
|
||||
raise
|
||||
else:
|
||||
seed = Seed(multidata=multidata, owner=session["_id"])
|
||||
flush() # place into DB and generate ids
|
||||
|
|
|
@ -55,13 +55,13 @@ Sent to clients when they connect to an Archipelago server.
|
|||
#### Arguments
|
||||
| Name | Type | Notes |
|
||||
| ---- | ---- | ----- |
|
||||
| version | NetworkVersion | Object denoting the version of Archipelago which the server is running. See [NetworkVersion](#NetworkVersion) for more details. |
|
||||
| version | [NetworkVersion](#NetworkVersion) | Object denoting the version of Archipelago which the server is running. |
|
||||
| tags | list\[str\] | Denotes special features or capabilities that the sender is capable of. Example: `WebHost` |
|
||||
| password | bool | Denoted whether a password is required to join this room.|
|
||||
| permissions | dict\[str, Permission\[int\]\] | Mapping of permission name to [Permission](#Permission), keys are: "forfeit", "collect" and "remaining". |
|
||||
| permissions | dict\[str, [Permission](#Permission)\[int\]\] | Mapping of permission name to [Permission](#Permission), keys are: "forfeit", "collect" and "remaining". |
|
||||
| hint_cost | int | The amount of points it costs to receive a hint from the server. |
|
||||
| location_check_points | int | The amount of hint points you receive per item/location check completed. ||
|
||||
| players | list\[NetworkPlayer\] | Sent only if the client is properly authenticated (see [Archipelago Connection Handshake](#Archipelago-Connection-Handshake)). Information on the players currently connected to the server. See [NetworkPlayer](#NetworkPlayer) for more details. |
|
||||
| players | list\[[NetworkPlayer](#NetworkPlayer)\] | Sent only if the client is properly authenticated (see [Archipelago Connection Handshake](#Archipelago-Connection-Handshake)). Information on the players currently connected to the server. |
|
||||
| games | list\[str\] | sorted list of game names for the players, so first player's game will be games\[0\]. Matches game names in datapackage. |
|
||||
| datapackage_version | int | Data version of the [data package](#Data-Package-Contents) the server will send. Used to update the client's (optional) local cache. |
|
||||
| datapackage_versions | dict\[str, int\] | Data versions of the individual games' data packages the server will send. |
|
||||
|
@ -114,7 +114,7 @@ Sent to clients when the connection handshake is successfully completed.
|
|||
| ---- | ---- | ----- |
|
||||
| team | int | Your team number. See [NetworkPlayer](#NetworkPlayer) for more info on team number. |
|
||||
| slot | int | Your slot number on your team. See [NetworkPlayer](#NetworkPlayer) for more info on the slot number. |
|
||||
| players | list\[NetworkPlayer\] | List denoting other players in the multiworld, whether connected or not. See [NetworkPlayer](#NetworkPlayer) for info on the format. |
|
||||
| players | list\[[NetworkPlayer](#NetworkPlayer)\] | List denoting other players in the multiworld, whether connected or not. |
|
||||
| missing_locations | list\[int\] | Contains ids of remaining locations that need to be checked. Useful for trackers, among other things. |
|
||||
| checked_locations | list\[int\] | Contains ids of all locations that have been checked. Useful for trackers, among other things. |
|
||||
| slot_data | dict | Contains a json object for slot related data, differs per game. Empty if not required. |
|
||||
|
@ -125,14 +125,14 @@ Sent to clients when they receive an item.
|
|||
| Name | Type | Notes |
|
||||
| ---- | ---- | ----- |
|
||||
| index | int | The next empty slot in the list of items for the receiving client. |
|
||||
| items | list\[NetworkItem\] | The items which the client is receiving. See [NetworkItem](#NetworkItem) for more details. |
|
||||
| items | list\[[NetworkItem](#NetworkItem)\] | The items which the client is receiving. |
|
||||
|
||||
### LocationInfo
|
||||
Sent to clients to acknowledge a received [LocationScouts](#LocationScouts) packet and responds with the item in the location(s) being scouted.
|
||||
#### Arguments
|
||||
| Name | Type | Notes |
|
||||
| ---- | ---- | ----- |
|
||||
| locations | list\[NetworkItem\] | Contains list of item(s) in the location(s) scouted. See [NetworkItem](#NetworkItem) for more details. |
|
||||
| locations | list\[[NetworkItem](#NetworkItem)\] | Contains list of item(s) in the location(s) scouted. |
|
||||
|
||||
### RoomUpdate
|
||||
Sent when there is a need to update information about the present game session. Generally useful for async games.
|
||||
|
@ -143,7 +143,7 @@ The arguments for RoomUpdate are identical to [RoomInfo](#RoomInfo) barring:
|
|||
| Name | Type | Notes |
|
||||
| ---- | ---- | ----- |
|
||||
| hint_points | int | New argument. The client's current hint points. |
|
||||
| players | list\[NetworkPlayer\] | Changed argument. Always sends all players, whether connected or not. |
|
||||
| players | list\[[NetworkPlayer](#NetworkPlayer)\] | Changed argument. Always sends all players, whether connected or not. |
|
||||
| checked_locations | list\[int\] | May be a partial update, containing new locations that were checked, especially from a coop partner in the same slot. |
|
||||
| missing_locations | list\[int\] | Should never be sent as an update, if needed is the inverse of checked_locations. |
|
||||
|
||||
|
@ -161,10 +161,10 @@ Sent to clients purely to display a message to the player. This packet differs f
|
|||
#### Arguments
|
||||
| Name | Type | Notes |
|
||||
| ---- | ---- | ----- |
|
||||
| data | list\[JSONMessagePart\] | See [JSONMessagePart](#JSONMessagePart) for more details on this type. |
|
||||
| data | list\[[JSONMessagePart](#JSONMessagePart)\] | Type of this part of the message. |
|
||||
| type | str | May be present to indicate the nature of this message. Known types are Hint and ItemSend. |
|
||||
| receiving | int | Is present if type is Hint or ItemSend and marks the destination player's ID. |
|
||||
| item | NetworkItem | Is present if type is Hint or ItemSend and marks the source player id, location id and item id. |
|
||||
| item | [NetworkItem](#NetworkItem) | Is present if type is Hint or ItemSend and marks the source player id, location id and item id. |
|
||||
| found | bool | Is present if type is Hint, denotes whether the location hinted for was checked. |
|
||||
|
||||
### DataPackage
|
||||
|
@ -173,7 +173,7 @@ Sent to clients to provide what is known as a 'data package' which contains info
|
|||
#### Arguments
|
||||
| Name | Type | Notes |
|
||||
| ---- | ---- | ----- |
|
||||
| data | DataPackageObject | The data package as a JSON object. More details on its contents may be found at [Data Package Contents](#Data-Package-Contents) |
|
||||
| data | [DataPackageObject](#Data-Package-Contents) | The data package as a JSON object. |
|
||||
|
||||
### Bounced
|
||||
Sent to clients after a client requested this message be sent to them, more info in the Bounce package.
|
||||
|
@ -213,7 +213,7 @@ Sent by the client to initiate a connection to an Archipelago game session.
|
|||
| game | str | The name of the game the client is playing. Example: `A Link to the Past` |
|
||||
| name | str | The player name for this client. |
|
||||
| uuid | str | Unique identifier for player client. |
|
||||
| version | NetworkVersion | An object representing the Archipelago version this client supports. |
|
||||
| version | [NetworkVersion](#NetworkVersion) | An object representing the Archipelago version this client supports. |
|
||||
| tags | list\[str\] | Denotes special features or capabilities that the sender is capable of. [Tags](#Tags) |
|
||||
|
||||
#### Authentication
|
||||
|
|
|
@ -217,7 +217,34 @@ def get_locations(world: Optional[MultiWorld], player: Optional[int]) -> Tuple[L
|
|||
LocationData('Left Side forest Caves', 'Cantoran', 1337176),
|
||||
)
|
||||
|
||||
# 1337177 - 1337236 Reserved for future use
|
||||
# 1337177 - 1337198 Lore Checks
|
||||
if not world or is_option_enabled(world, player, "LoreChecks"):
|
||||
location_table += (
|
||||
LocationData('Lower lake desolation', 'Memory - Coyote Jump (Time Messenger)', 1337177),
|
||||
LocationData('Library', 'Memory - Waterway (A Message)', 1337178),
|
||||
LocationData('Library top', 'Memory - Library Gap (Lachiemi Sun)', 1337179),
|
||||
LocationData('Library top', 'Memory - Mr. Hat Portrait (Moonlit Night)', 1337180),
|
||||
LocationData('Varndagroth tower left', 'Memory - Left Elevator (Nomads)', 1337181, lambda state: state.has('Elevator Keycard', player)),
|
||||
LocationData('Varndagroth tower right (lower)', 'Memory - Siren Elevator (Childhood)', 1337182, lambda state: state._timespinner_has_keycard_B(world, player)),
|
||||
LocationData('Varndagroth tower right (lower)', 'Memory - Varndagroth Right Bottom (Faron)', 1337183),
|
||||
LocationData('Military Fortress', 'Memory - Bomber Climb (A Solution)', 1337184, lambda state: state.has('Timespinner Wheel', player) and state._timespinner_has_doublejump_of_npc(world, player)),
|
||||
LocationData('The lab', 'Memory - Genza\'s Secret Stash 1 (An Old Friend)', 1337185, lambda state: state._timespinner_can_break_walls(world, player)),
|
||||
LocationData('The lab', 'Memory - Genza\'s Secret Stash 2 (Twilight Dinner)', 1337186, lambda state: state._timespinner_can_break_walls(world, player)),
|
||||
LocationData('Emperors tower', 'Memory - Way Up There (Final Circle)', 1337187),
|
||||
LocationData('Forest', 'Journal - Forest Rats (Lachiem Expedition)', 1337188),
|
||||
LocationData('Forest', 'Journal - Forest Bat Jump Ledge (Peace Treaty)', 1337189, lambda state: state._timespinner_has_doublejump_of_npc(world, player) or state._timespinner_has_forwarddash_doublejump(world, player) or state._timespinner_has_fastjump_on_npc(world, player)),
|
||||
LocationData('Castle Ramparts', 'Journal - Floating in Moat (Prime Edicts)', 1337190),
|
||||
LocationData('Castle Ramparts', 'Journal - Archer + Knight (Declaration of Independence)', 1337191),
|
||||
LocationData('Castle Keep', 'Journal - Under the Twins (Letter of Reference)', 1337192),
|
||||
LocationData('Castle Keep', 'Journal - Castle Loop Giantess (Political Advice)', 1337193),
|
||||
LocationData('Royal towers (lower)', 'Journal - Aleana\'s Room (Diplomatic Missive)', 1337194, lambda state: state._timespinner_has_pink(world, player)),
|
||||
LocationData('Royal towers (upper)', 'Journal - Top Struggle Juggle Base (War of the Sisters)', 1337195),
|
||||
LocationData('Royal towers (upper)', 'Journal - Aleana Boss (Stained Letter)', 1337196),
|
||||
LocationData('Royal towers', 'Journal - Near Bottom Struggle Juggle (Mission Findings)', 1337197),
|
||||
LocationData('Caves of Banishment (Maw)', 'Journal - Lower Left Maw Caves (Naivety)', 1337198)
|
||||
)
|
||||
|
||||
# 1337199 - 1337236 Reserved for future use
|
||||
|
||||
# 1337237 - 1337245 GyreArchives
|
||||
if not world or is_option_enabled(world, player, "GyreArchives"):
|
||||
|
|
|
@ -50,6 +50,10 @@ class Cantoran(Toggle):
|
|||
"Cantoran's fight and check are available upon revisiting his room"
|
||||
display_name = "Cantoran"
|
||||
|
||||
class LoreChecks(Toggle):
|
||||
"Memories and journal entries contain items."
|
||||
display_name = "Lore Checks"
|
||||
|
||||
class DamageRando(Toggle):
|
||||
"Each orb has a high chance of having lower base damage and a low chance of having much higher base damage."
|
||||
display_name = "Damage Rando"
|
||||
|
@ -68,6 +72,7 @@ timespinner_options: Dict[str, Toggle] = {
|
|||
#"StinkyMaw": StinkyMaw,
|
||||
"GyreArchives": GyreArchives,
|
||||
"Cantoran": Cantoran,
|
||||
"LoreChecks": LoreChecks,
|
||||
"DamageRando": DamageRando,
|
||||
"DeathLink": DeathLink,
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ class TimespinnerWorld(World):
|
|||
game = "Timespinner"
|
||||
topology_present = True
|
||||
remote_items = False
|
||||
data_version = 5
|
||||
data_version = 6
|
||||
|
||||
item_name_to_id = {name: data.code for name, data in item_table.items()}
|
||||
location_name_to_id = {location.name: location.code for location in get_locations(None, None)}
|
||||
|
|
Loading…
Reference in New Issue