v6,sm64ex: Add support for offline singeplayer seeds (#301)
This commit is contained in:
parent
15e0763ed5
commit
97b1ae5ee9
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue