v6,sm64ex: Add support for offline singeplayer seeds (#301)

This commit is contained in:
Yussur Mustafa Oraji 2022-03-12 22:05:54 +01:00 committed by GitHub
parent 15e0763ed5
commit 97b1ae5ee9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 78 additions and 3 deletions

View File

@ -53,6 +53,10 @@ def download_slot_file(room_id, player_id: int):
fname = name.rsplit("/", 1)[0]+".zip"
elif slot_data.game == "Ocarina of Time":
fname = f"AP_{app.jinja_env.filters['suuid'](room_id)}_P{slot_data.player_id}_{slot_data.player_name}.apz5"
elif slot_data.game == "VVVVVV":
fname = f"AP_{app.jinja_env.filters['suuid'](room_id)}_SP.apv6"
elif slot_data.game == "Super Mario 64":
fname = f"AP_{app.jinja_env.filters['suuid'](room_id)}_SP.apsm64ex"
else:
return "Game download not supported."
return send_file(io.BytesIO(slot_data.data), as_attachment=True, attachment_filename=fname)

View File

@ -54,13 +54,19 @@ In case you are using the Archipelago Website, the IP should be `archipelago.gg`
If everything worked out, you will see a textbox informing you the connection has been established after the story intro.
# Playing offline
To play offline, first generate a seed on the game's settings page.
Create a room and download the `.apsm64ex` file, and start the game with the `--sm64ap_file FileName` launch argument.
## Installation Troubleshooting
Start the game from the command line to view helpful messages regarding SM64EX.
### Game doesn't start after compiling
Most likely you forgot to set the launch options. `--sm64ap_name YourName` and `--sm64ap_ip ServerIP:Port` are required for startup.
Most likely you forgot to set the launch options. `--sm64ap_name YourName` and `--sm64ap_ip ServerIP:Port` are required for startup for Multiworlds, and
`--sm64ap_file FileName` is required for (offline) singleplayer.
If your Name or Password have spaces in them, surround them in quotes.
## Game Troubleshooting

View File

@ -20,13 +20,19 @@ In case you are using the Archipelago Website, the IP should be `archipelago.gg`
If everything worked out, you will see a textbox informing you the connection has been established after the story intro.
# Playing offline
To play offline, first generate a seed on the game's settings page.
Create a room and download the `.apv6` file, and start the game with the `-v6ap_file FileName` launch argument.
## Installation Troubleshooting
Start the game from the command line to view helpful messages regarding V6AP. These will look something like "V6AP: Message"
### Game no longer starts after copying the .exe
Most likely you forgot to set the launch options. `-v6ap_name YourName` and `-v6ap_ip ServerIP:Port` are required for startup.
Most likely you forgot to set the launch options. `-v6ap_name YourName` and `-v6ap_ip ServerIP:Port` are required for startup for Multiworlds, and
`-v6ap_file FileName` is required for (offline) singleplayer.
If your Name or Password have spaces in them, surround them in quotes.
## Game Troubleshooting

View File

@ -34,6 +34,12 @@
{% elif patch.game == "Ocarina of Time" %}
<a href="{{ url_for("download_slot_file", room_id=room.id, player_id=patch.player_id) }}" download>
Download APZ5 File...</a>
{% elif patch.game == "VVVVVV" and room.seed.slots|length == 1 %}
<a href="{{ url_for("download_slot_file", room_id=room.id, player_id=patch.player_id) }}" download>
Download APV6 File...</a>
{% elif patch.game == "Super Mario 64" and room.seed.slots|length == 1 %}
<a href="{{ url_for("download_slot_file", room_id=room.id, player_id=patch.player_id) }}" download>
Download APSM64EX File...</a>
{% elif patch.game in ["A Link to the Past", "Secret of Evermore", "Super Metroid"] %}
<a href="{{ url_for("download_patch", patch_id=patch.id, room_id=room.id) }}" download>
Download Patch File...</a>

View File

@ -47,6 +47,15 @@ def upload_zip_to_db(zfile: zipfile.ZipFile, owner=None, meta={"race": False}, s
player_id=metadata["player_id"],
game="Minecraft"))
elif file.filename.endswith(".apv6"):
_, seed_name, slot_id, slot_name = file.filename.split('.')[0].split('_', 3)
slots.add(Slot(data=zfile.open(file, "r").read(), player_name=slot_name,
player_id=int(slot_id[1:]), game="VVVVVV"))
elif file.filename.endswith(".apsm64ex"):
_, seed_name, slot_id, slot_name = file.filename.split('.')[0].split('_', 3)
slots.add(Slot(data=zfile.open(file, "r").read(), player_name=slot_name,
player_id=int(slot_id[1:]), game="Super Mario 64"))
elif file.filename.endswith(".zip"):
# Factorio mods need a specific name or they do not function
_, seed_name, slot_id, slot_name = file.filename.rsplit("_", 1)[0].split("-", 3)

View File

@ -1,4 +1,6 @@
import typing
import os
import json
from .Items import item_table, cannon_item_table, SM64Item
from .Locations import location_table, SM64Location
from .Options import sm64_options
@ -87,3 +89,24 @@ class SM64World(World):
"StarsToFinish": self.world.StarsToFinish[self.player].value,
"DeathLink": self.world.DeathLink[self.player].value,
}
def generate_output(self, output_directory: str):
if self.world.players != 1:
return
data = {
"slot_data": self.fill_slot_data(),
"location_to_item": {self.location_name_to_id[i] : item_table[self.world.get_location(i, self.player).item.name] for i in self.location_name_to_id},
"data_package": {
"data": {
"games": {
self.game: {
"item_name_to_id": self.item_name_to_id,
"location_name_to_id": self.location_name_to_id
}
}
}
}
}
filename = f"AP_{self.world.seed_name}_P{self.player}_{self.world.get_player_name(self.player)}.apsm64ex"
with open(os.path.join(output_directory, filename), 'w') as f:
json.dump(data, f)

View File

@ -1,5 +1,5 @@
import typing
import os, json
from .Items import item_table, V6Item
from .Locations import location_table, V6Location
from .Options import v6_options
@ -61,3 +61,24 @@ class V6World(World):
"DeathLink": self.world.DeathLink[self.player].value,
"DeathLink_Amnesty": self.world.DeathLinkAmnesty[self.player].value
}
def generate_output(self, output_directory: str):
if self.world.players != 1:
return
data = {
"slot_data": self.fill_slot_data(),
"location_to_item": {self.location_name_to_id[i] : item_table[self.world.get_location(i, self.player).item.name] for i in self.location_name_to_id},
"data_package": {
"data": {
"games": {
self.game: {
"item_name_to_id": self.item_name_to_id,
"location_name_to_id": self.location_name_to_id
}
}
}
}
}
filename = f"AP_{self.world.seed_name}_P{self.player}_{self.world.get_player_name(self.player)}.apv6"
with open(os.path.join(output_directory, filename), 'w') as f:
json.dump(data, f)