Merge branch 'main' into main
This commit is contained in:
		
						commit
						ac915d00fc
					
				| 
						 | 
					@ -213,9 +213,8 @@ class MultiWorld():
 | 
				
			||||||
        except KeyError as e:
 | 
					        except KeyError as e:
 | 
				
			||||||
            raise KeyError('No such dungeon %s for player %d' % (dungeonname, player)) from e
 | 
					            raise KeyError('No such dungeon %s for player %d' % (dungeonname, player)) from e
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_all_state(self, keys=False) -> CollectionState:
 | 
					    def get_all_state(self) -> CollectionState:
 | 
				
			||||||
        key = f"_all_state_{keys}"
 | 
					        cached = getattr(self, "_all_state", None)
 | 
				
			||||||
        cached = getattr(self, key, None)
 | 
					 | 
				
			||||||
        if cached:
 | 
					        if cached:
 | 
				
			||||||
            return cached.copy()
 | 
					            return cached.copy()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -223,27 +222,12 @@ class MultiWorld():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for item in self.itempool:
 | 
					        for item in self.itempool:
 | 
				
			||||||
            self.worlds[item.player].collect(ret, item)
 | 
					            self.worlds[item.player].collect(ret, item)
 | 
				
			||||||
 | 
					        from worlds.alttp.Dungeons import get_dungeon_item_pool
 | 
				
			||||||
        if keys:
 | 
					        for item in get_dungeon_item_pool(self):
 | 
				
			||||||
            for p in self.get_game_players("A Link to the Past"):
 | 
					            subworld = self.worlds[item.player]
 | 
				
			||||||
                world = self.worlds[p]
 | 
					            if item.name in subworld.dungeon_local_item_names:
 | 
				
			||||||
                from worlds.alttp.Items import ItemFactory
 | 
					                subworld.collect(ret, item)
 | 
				
			||||||
                for item in ItemFactory(
 | 
					 | 
				
			||||||
                        ['Small Key (Hyrule Castle)', 'Big Key (Eastern Palace)', 'Big Key (Desert Palace)',
 | 
					 | 
				
			||||||
                         'Small Key (Desert Palace)', 'Big Key (Tower of Hera)', 'Small Key (Tower of Hera)',
 | 
					 | 
				
			||||||
                         'Small Key (Agahnims Tower)', 'Small Key (Agahnims Tower)',
 | 
					 | 
				
			||||||
                         'Big Key (Palace of Darkness)'] + ['Small Key (Palace of Darkness)'] * 6 + [
 | 
					 | 
				
			||||||
                            'Big Key (Thieves Town)', 'Small Key (Thieves Town)', 'Big Key (Skull Woods)'] + [
 | 
					 | 
				
			||||||
                            'Small Key (Skull Woods)'] * 3 + ['Big Key (Swamp Palace)',
 | 
					 | 
				
			||||||
                                                              'Small Key (Swamp Palace)', 'Big Key (Ice Palace)'] + [
 | 
					 | 
				
			||||||
                            'Small Key (Ice Palace)'] * 2 + ['Big Key (Misery Mire)', 'Big Key (Turtle Rock)',
 | 
					 | 
				
			||||||
                                                             'Big Key (Ganons Tower)'] + [
 | 
					 | 
				
			||||||
                            'Small Key (Misery Mire)'] * 3 + ['Small Key (Turtle Rock)'] * 4 + [
 | 
					 | 
				
			||||||
                            'Small Key (Ganons Tower)'] * 4,
 | 
					 | 
				
			||||||
                        p):
 | 
					 | 
				
			||||||
                    world.collect(ret, item)
 | 
					 | 
				
			||||||
        ret.sweep_for_events()
 | 
					        ret.sweep_for_events()
 | 
				
			||||||
        setattr(self, key, ret)
 | 
					 | 
				
			||||||
        return ret
 | 
					        return ret
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_items(self) -> list:
 | 
					    def get_items(self) -> list:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										12
									
								
								Options.py
								
								
								
								
							
							
						
						
									
										12
									
								
								Options.py
								
								
								
								
							| 
						 | 
					@ -57,11 +57,12 @@ class Option(metaclass=AssembleOptions):
 | 
				
			||||||
        """For display purposes."""
 | 
					        """For display purposes."""
 | 
				
			||||||
        return self.get_option_name(self.value)
 | 
					        return self.get_option_name(self.value)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_option_name(self, value: typing.Any) -> str:
 | 
					    @classmethod
 | 
				
			||||||
        if self.autodisplayname:
 | 
					    def get_option_name(cls, value: typing.Any) -> str:
 | 
				
			||||||
            return self.name_lookup[self.value].replace("_", " ").title()
 | 
					        if cls.autodisplayname:
 | 
				
			||||||
 | 
					            return cls.name_lookup[value].replace("_", " ").title()
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            return self.name_lookup[self.value]
 | 
					            return cls.name_lookup[value]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __int__(self) -> int:
 | 
					    def __int__(self) -> int:
 | 
				
			||||||
        return self.value
 | 
					        return self.value
 | 
				
			||||||
| 
						 | 
					@ -114,7 +115,8 @@ class Toggle(Option):
 | 
				
			||||||
    def __int__(self):
 | 
					    def __int__(self):
 | 
				
			||||||
        return int(self.value)
 | 
					        return int(self.value)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_option_name(self, value):
 | 
					    @classmethod
 | 
				
			||||||
 | 
					    def get_option_name(cls, value):
 | 
				
			||||||
        return ["No", "Yes"][int(value)]
 | 
					        return ["No", "Yes"][int(value)]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class DefaultOnToggle(Toggle):
 | 
					class DefaultOnToggle(Toggle):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,6 +8,7 @@ from pony.flask import Pony
 | 
				
			||||||
from flask import Flask, request, redirect, url_for, render_template, Response, session, abort, send_from_directory
 | 
					from flask import Flask, request, redirect, url_for, render_template, Response, session, abort, send_from_directory
 | 
				
			||||||
from flask_caching import Cache
 | 
					from flask_caching import Cache
 | 
				
			||||||
from flask_compress import Compress
 | 
					from flask_compress import Compress
 | 
				
			||||||
 | 
					from worlds.AutoWorld import AutoWorldRegister
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from .models import *
 | 
					from .models import *
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -81,54 +82,6 @@ def page_not_found(err):
 | 
				
			||||||
    return render_template('404.html'), 404
 | 
					    return render_template('404.html'), 404
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
games_list = {
 | 
					 | 
				
			||||||
    "A Link to the Past": ("The Legend of Zelda: A Link to the Past",
 | 
					 | 
				
			||||||
                           """
 | 
					 | 
				
			||||||
                           The Legend of Zelda: A Link to the Past is an action/adventure game. Take on the role of
 | 
					 | 
				
			||||||
                           Link, a boy who is destined to save the land of Hyrule. Delve through three palaces and nine
 | 
					 | 
				
			||||||
                           dungeons on your quest to rescue the descendents of the seven wise men and defeat the evil
 | 
					 | 
				
			||||||
                           Ganon!"""),
 | 
					 | 
				
			||||||
    "Factorio": ("Factorio",
 | 
					 | 
				
			||||||
                 """
 | 
					 | 
				
			||||||
                 Factorio is a game about automation. You play as an engineer who has crash landed on the planet
 | 
					 | 
				
			||||||
                 Nauvis, an inhospitable world filled with dangerous creatures called biters. Build a factory,
 | 
					 | 
				
			||||||
                 research new technologies, and become more efficient in your quest to build a rocket and return home.
 | 
					 | 
				
			||||||
                 """),
 | 
					 | 
				
			||||||
    "Minecraft": ("Minecraft",
 | 
					 | 
				
			||||||
                  """
 | 
					 | 
				
			||||||
                  Minecraft is a game about creativity. In a world made entirely of cubes, you explore, discover, mine,
 | 
					 | 
				
			||||||
                  craft, and try not to explode. Delve deep into the earth and discover abandoned mines, ancient
 | 
					 | 
				
			||||||
                  structures, and materials to create a portal to another world. Defeat the Ender Dragon, and claim
 | 
					 | 
				
			||||||
                  victory!"""),
 | 
					 | 
				
			||||||
    "Subnautica": ("Subnautica",
 | 
					 | 
				
			||||||
                   """
 | 
					 | 
				
			||||||
                   Subnautica is an undersea exploration game. Stranded on an alien world, you become infected by
 | 
					 | 
				
			||||||
                   an unknown bacteria. The planet's automatic quarantine will shoot you down if you try to leave.
 | 
					 | 
				
			||||||
                   You must find a cure for yourself, build an escape rocket, and leave the planet.
 | 
					 | 
				
			||||||
                   """),
 | 
					 | 
				
			||||||
    "Ocarina of Time": ("The Legend of Zelda: Ocarina of Time",
 | 
					 | 
				
			||||||
                        """
 | 
					 | 
				
			||||||
                        The Legend of Zelda: Ocarina of Time was the first three dimensional Zelda game. Journey as
 | 
					 | 
				
			||||||
                        Link as he quests to fulfil his destiny. Journey across Hyrule and defeat the evil masters of
 | 
					 | 
				
			||||||
                        corrupted temples or seek out the pieces of the Triforce. Defeat the evil Ganondorf to become
 | 
					 | 
				
			||||||
                        the Hero of Time and save Hyrule!
 | 
					 | 
				
			||||||
                        """),
 | 
					 | 
				
			||||||
    "Super Metroid": ("Super Metroid",
 | 
					 | 
				
			||||||
                      """
 | 
					 | 
				
			||||||
                      Samus is back in her first 16 bit adventure! Space pirates have attacked Ceres station and stolen
 | 
					 | 
				
			||||||
                      the last living Metroid. Go to planet Zebes and search out the abilities you will need to power
 | 
					 | 
				
			||||||
                      up your suit and defeat the villainous leader of the space pirates, Mother Brain.
 | 
					 | 
				
			||||||
                      """),
 | 
					 | 
				
			||||||
    "Risk of Rain 2": ("Risk of Rain 2",
 | 
					 | 
				
			||||||
                       """
 | 
					 | 
				
			||||||
                       Escape a chaotic alien planet by fighting through hordes of frenzied monsters – with your friends
 | 
					 | 
				
			||||||
                       , or on your own. Combine loot in surprising ways and master each character until you become the 
 | 
					 | 
				
			||||||
                       havoc you feared upon your first crash landing.
 | 
					 | 
				
			||||||
                       """)
 | 
					 | 
				
			||||||
    # "Ori and the Blind Forest": ("Ori and the Blind Forest", "Coming Soon™"),
 | 
					 | 
				
			||||||
    # "Hollow Knight": ("Hollow Knight", "Coming Soon™"),
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Player settings pages
 | 
					# Player settings pages
 | 
				
			||||||
@app.route('/games/<string:game>/player-settings')
 | 
					@app.route('/games/<string:game>/player-settings')
 | 
				
			||||||
| 
						 | 
					@ -151,7 +104,11 @@ def game_page(game):
 | 
				
			||||||
# List of supported games
 | 
					# List of supported games
 | 
				
			||||||
@app.route('/games')
 | 
					@app.route('/games')
 | 
				
			||||||
def games():
 | 
					def games():
 | 
				
			||||||
    return render_template("games/games.html", games_list=games_list)
 | 
					    worlds = {}
 | 
				
			||||||
 | 
					    for game, world in AutoWorldRegister.world_types.items():
 | 
				
			||||||
 | 
					        if not world.hidden:
 | 
				
			||||||
 | 
					            worlds[game] = world.__doc__ if world.__doc__ else "No description provided."
 | 
				
			||||||
 | 
					    return render_template("games/games.html", worlds=worlds)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@app.route('/tutorial/<string:game>/<string:file>/<string:lang>')
 | 
					@app.route('/tutorial/<string:game>/<string:file>/<string:lang>')
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,8 +1,8 @@
 | 
				
			||||||
from flask import send_file, Response
 | 
					from flask import send_file, Response, render_template
 | 
				
			||||||
from pony.orm import select
 | 
					from pony.orm import select
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from Patch import update_patch_data
 | 
					from Patch import update_patch_data
 | 
				
			||||||
from WebHostLib import app, Slot, Room, Seed
 | 
					from WebHostLib import app, Slot, Room, Seed, cache
 | 
				
			||||||
import zipfile
 | 
					import zipfile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@app.route("/dl_patch/<suuid:room_id>/<int:patch_id>")
 | 
					@app.route("/dl_patch/<suuid:room_id>/<int:patch_id>")
 | 
				
			||||||
| 
						 | 
					@ -68,4 +68,14 @@ def download_slot_file(room_id, player_id: int):
 | 
				
			||||||
                        fname = name.rsplit("/", 1)[0]+".zip"
 | 
					                        fname = name.rsplit("/", 1)[0]+".zip"
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            return "Game download not supported."
 | 
					            return "Game download not supported."
 | 
				
			||||||
        return send_file(io.BytesIO(slot_data.data), as_attachment=True, attachment_filename=fname)
 | 
					        return send_file(io.BytesIO(slot_data.data), as_attachment=True, attachment_filename=fname)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@app.route("/templates")
 | 
				
			||||||
 | 
					@cache.cached()
 | 
				
			||||||
 | 
					def list_yaml_templates():
 | 
				
			||||||
 | 
					    files = []
 | 
				
			||||||
 | 
					    from worlds.AutoWorld import AutoWorldRegister
 | 
				
			||||||
 | 
					    for world_name, world in AutoWorldRegister.world_types.items():
 | 
				
			||||||
 | 
					        if not world.hidden:
 | 
				
			||||||
 | 
					            files.append(world_name)
 | 
				
			||||||
 | 
					    return render_template("templates.html", files=files)
 | 
				
			||||||
| 
						 | 
					@ -10,9 +10,18 @@ target_folder = os.path.join("WebHostLib", "static", "generated")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def create():
 | 
					def create():
 | 
				
			||||||
 | 
					    def dictify_range(option):
 | 
				
			||||||
 | 
					        data = {option.range_start: 0, option.range_end: 0, "random": 0, "random-low": 0, "random-high": 0,
 | 
				
			||||||
 | 
					                option.default: 50}
 | 
				
			||||||
 | 
					        notes = {
 | 
				
			||||||
 | 
					            option.range_start: "minimum value",
 | 
				
			||||||
 | 
					            option.range_end: "maximum value"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return data, notes
 | 
				
			||||||
    for game_name, world in AutoWorldRegister.world_types.items():
 | 
					    for game_name, world in AutoWorldRegister.world_types.items():
 | 
				
			||||||
        res = Template(open(os.path.join("WebHostLib", "templates", "options.yaml")).read()).render(
 | 
					        res = Template(open(os.path.join("WebHostLib", "templates", "options.yaml")).read()).render(
 | 
				
			||||||
            options=world.options, __version__=__version__, game=game_name, yaml_dump=yaml.dump
 | 
					            options=world.options, __version__=__version__, game=game_name, yaml_dump=yaml.dump,
 | 
				
			||||||
 | 
					            dictify_range=dictify_range
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        with open(os.path.join(target_folder, game_name + ".yaml"), "w") as f:
 | 
					        with open(os.path.join(target_folder, game_name + ".yaml"), "w") as f:
 | 
				
			||||||
| 
						 | 
					@ -39,7 +48,7 @@ def create():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                for sub_option_name, sub_option_id in option.options.items():
 | 
					                for sub_option_name, sub_option_id in option.options.items():
 | 
				
			||||||
                    this_option["options"].append({
 | 
					                    this_option["options"].append({
 | 
				
			||||||
                        "name": sub_option_name,
 | 
					                        "name": option.get_option_name(sub_option_id),
 | 
				
			||||||
                        "value": sub_option_name,
 | 
					                        "value": sub_option_name,
 | 
				
			||||||
                    })
 | 
					                    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,9 +9,9 @@
 | 
				
			||||||
    {% include 'header/grassHeader.html' %}
 | 
					    {% include 'header/grassHeader.html' %}
 | 
				
			||||||
    <div id="games">
 | 
					    <div id="games">
 | 
				
			||||||
        <h1>Currently Supported Games</h1>
 | 
					        <h1>Currently Supported Games</h1>
 | 
				
			||||||
        {% for game, (display_name, description) in games_list.items() %}
 | 
					        {% for game, description in worlds.items() %}
 | 
				
			||||||
        <h3><a href="{{ url_for("game_page", game=game) }}">{{ display_name}}</a></h3>
 | 
					        <h3><a href="{{ url_for("game_page", game=game) }}">{{ game }}</a></h3>
 | 
				
			||||||
        <p>{{ description}}</p>
 | 
					        <p>{{ description }}</p>
 | 
				
			||||||
        {% endfor %}
 | 
					        {% endfor %}
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
{% endblock %}
 | 
					{% endblock %}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,7 +18,8 @@
 | 
				
			||||||
# http://www.yamllint.com/
 | 
					# http://www.yamllint.com/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
description: Default {{ game }} Template # Used to describe your yaml. Useful if you have multiple files
 | 
					description: Default {{ game }} Template # Used to describe your yaml. Useful if you have multiple files
 | 
				
			||||||
name: YourName{number} # Your name in-game. Spaces will be replaced with underscores and there is a 16 character limit
 | 
					# Your name in-game. Spaces will be replaced with underscores and there is a 16 character limit
 | 
				
			||||||
 | 
					name: YourName{number}
 | 
				
			||||||
#{player} will be replaced with the player's slot number.
 | 
					#{player} will be replaced with the player's slot number.
 | 
				
			||||||
#{PLAYER} will be replaced with the player's slot number if that slot number is greater than 1.
 | 
					#{PLAYER} will be replaced with the player's slot number if that slot number is greater than 1.
 | 
				
			||||||
#{number} will be replaced with the counter value of the name.
 | 
					#{number} will be replaced with the counter value of the name.
 | 
				
			||||||
| 
						 | 
					@ -51,16 +52,18 @@ progression_balancing:
 | 
				
			||||||
#  - "Progressive Weapons"
 | 
					#  - "Progressive Weapons"
 | 
				
			||||||
# exclude_locations: # Force certain locations to never contain progression items, and always be filled with junk.
 | 
					# exclude_locations: # Force certain locations to never contain progression items, and always be filled with junk.
 | 
				
			||||||
#  - "Master Sword Pedestal"
 | 
					#  - "Master Sword Pedestal"
 | 
				
			||||||
 | 
					{%- macro range_option(option) %}
 | 
				
			||||||
 | 
					    # you can add additional values between minimum and maximum
 | 
				
			||||||
 | 
					    {%- set data, notes = dictify_range(option) %}
 | 
				
			||||||
 | 
					    {%- for entry, default in data.items() %}
 | 
				
			||||||
 | 
					    {{ entry }}: {{ default }}{% if notes[entry] %} # {{ notes[entry] }}{% endif %}
 | 
				
			||||||
 | 
					    {%- endfor -%}
 | 
				
			||||||
 | 
					{% endmacro %}
 | 
				
			||||||
{{ game }}:
 | 
					{{ game }}:
 | 
				
			||||||
  {%- for option_key, option in options.items() %}
 | 
					  {%- for option_key, option in options.items() %}
 | 
				
			||||||
  {{ option_key }}:{% if option.__doc__ %} # {{ option.__doc__ | replace('\n', '\n#') | indent(4, first=False) }}{% endif %}
 | 
					  {{ option_key }}:{% if option.__doc__ %} # {{ option.__doc__ | replace('\n', '\n#') | indent(4, first=False) }}{% endif %}
 | 
				
			||||||
    {%- if option.range_start is defined  %}
 | 
					    {%- if option.range_start is defined  %}
 | 
				
			||||||
    # you can add additional values between minimum and maximum
 | 
					    {{- range_option(option) -}}
 | 
				
			||||||
    {{ option.range_start }}: 0 # minimum value
 | 
					 | 
				
			||||||
    {{ option.range_end }}: 0 # maximum value
 | 
					 | 
				
			||||||
    random: 50
 | 
					 | 
				
			||||||
    random-low: 0
 | 
					 | 
				
			||||||
    random-high: 0
 | 
					 | 
				
			||||||
    {%- elif option.options -%}
 | 
					    {%- elif option.options -%}
 | 
				
			||||||
    {%- for suboption_option_id, sub_option_name in option.name_lookup.items() %}
 | 
					    {%- for suboption_option_id, sub_option_name in option.name_lookup.items() %}
 | 
				
			||||||
    {{ sub_option_name }}: {% if suboption_option_id == option.default %}50{% else %}0{% endif %}
 | 
					    {{ sub_option_name }}: {% if suboption_option_id == option.default %}50{% else %}0{% endif %}
 | 
				
			||||||
| 
						 | 
					@ -68,4 +71,5 @@ progression_balancing:
 | 
				
			||||||
    {%- else %}
 | 
					    {%- else %}
 | 
				
			||||||
    {{ yaml_dump(option.default) | indent(4, first=False) }}
 | 
					    {{ yaml_dump(option.default) | indent(4, first=False) }}
 | 
				
			||||||
  {%- endif -%}
 | 
					  {%- endif -%}
 | 
				
			||||||
  {%- endfor -%}
 | 
					  {%- endfor %}
 | 
				
			||||||
 | 
					  {% if not options %}{}{% endif %}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,21 @@
 | 
				
			||||||
 | 
					{% extends 'pageWrapper.html' %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block head %}
 | 
				
			||||||
 | 
					    {% include 'header/grassHeader.html' %}
 | 
				
			||||||
 | 
					    <title>Option Templates (YAML)</title>
 | 
				
			||||||
 | 
					    <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename="styles/markdown.css") }}" />
 | 
				
			||||||
 | 
					    <script src="https://cdnjs.cloudflare.com/ajax/libs/showdown/1.9.1/showdown.min.js"
 | 
				
			||||||
 | 
					            integrity="sha512-L03kznCrNOfVxOUovR6ESfCz9Gfny7gihUX/huVbQB9zjODtYpxaVtIaAkpetoiyV2eqWbvxMH9fiSv5enX7bw=="
 | 
				
			||||||
 | 
					            crossorigin="anonymous"></script>
 | 
				
			||||||
 | 
					{% endblock %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block body %}
 | 
				
			||||||
 | 
					    <div>
 | 
				
			||||||
 | 
					    <h1>Option Templates (YAML)</h1>
 | 
				
			||||||
 | 
					    <ul>
 | 
				
			||||||
 | 
					        {% for file in files %}
 | 
				
			||||||
 | 
					        <li><a href="{{ url_for('static', filename="generated/"+file+".yaml") }}">{{ file }}</a></li>
 | 
				
			||||||
 | 
					        {% endfor %}
 | 
				
			||||||
 | 
					    </ul>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					{%  endblock %}
 | 
				
			||||||
| 
						 | 
					@ -157,6 +157,8 @@ def fill_dungeons_restrictive(autoworld, world):
 | 
				
			||||||
            in_dungeon_items.sort(
 | 
					            in_dungeon_items.sort(
 | 
				
			||||||
                key=lambda item: sort_order.get(item.type, 1) +
 | 
					                key=lambda item: sort_order.get(item.type, 1) +
 | 
				
			||||||
                                 (5 if (item.player, item.name) in dungeon_specific else 0))
 | 
					                                 (5 if (item.player, item.name) in dungeon_specific else 0))
 | 
				
			||||||
 | 
					            for item in in_dungeon_items:
 | 
				
			||||||
 | 
					                all_state_base.remove(item)
 | 
				
			||||||
            fill_restrictive(world, all_state_base, locations, in_dungeon_items, True, True)
 | 
					            fill_restrictive(world, all_state_base, locations, in_dungeon_items, True, True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,6 @@
 | 
				
			||||||
# ToDo: With shuffle_ganon option, prevent gtower from linking to an exit only location through a 2 entrance cave.
 | 
					# ToDo: With shuffle_ganon option, prevent gtower from linking to an exit only location through a 2 entrance cave.
 | 
				
			||||||
from collections import defaultdict
 | 
					from collections import defaultdict
 | 
				
			||||||
 | 
					from worlds.alttp.OverworldGlitchRules import overworld_glitch_connections
 | 
				
			||||||
from worlds.alttp.UnderworldGlitchRules import underworld_glitch_connections
 | 
					from worlds.alttp.UnderworldGlitchRules import underworld_glitch_connections
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def link_entrances(world, player):
 | 
					def link_entrances(world, player):
 | 
				
			||||||
| 
						 | 
					@ -1066,9 +1067,11 @@ def link_entrances(world, player):
 | 
				
			||||||
        raise NotImplementedError(
 | 
					        raise NotImplementedError(
 | 
				
			||||||
            f'{world.shuffle[player]} Shuffling not supported yet. Player {world.get_player_name(player)}')
 | 
					            f'{world.shuffle[player]} Shuffling not supported yet. Player {world.get_player_name(player)}')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # mandatory hybrid major glitches connections
 | 
					    if world.logic[player] in ['owglitches', 'hybridglitches', 'nologic']:
 | 
				
			||||||
    if world.logic[player] in ['hybridglitches', 'nologic']:
 | 
					        overworld_glitch_connections(world, player)
 | 
				
			||||||
        underworld_glitch_connections(world, player)
 | 
					        # mandatory hybrid major glitches connections
 | 
				
			||||||
 | 
					        if world.logic[player] in ['hybridglitches', 'nologic']:
 | 
				
			||||||
 | 
					            underworld_glitch_connections(world, player)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # check for swamp palace fix
 | 
					    # check for swamp palace fix
 | 
				
			||||||
    if world.get_entrance('Dam', player).connected_region.name != 'Dam' or world.get_entrance('Swamp Palace', player).connected_region.name != 'Swamp Palace (Entrance)':
 | 
					    if world.get_entrance('Dam', player).connected_region.name != 'Dam' or world.get_entrance('Swamp Palace', player).connected_region.name != 'Swamp Palace (Entrance)':
 | 
				
			||||||
| 
						 | 
					@ -1771,9 +1774,11 @@ def link_inverted_entrances(world, player):
 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
        raise NotImplementedError('Shuffling not supported yet')
 | 
					        raise NotImplementedError('Shuffling not supported yet')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # mandatory hybrid major glitches connections
 | 
					    if world.logic[player] in ['owglitches', 'hybridglitches', 'nologic']:
 | 
				
			||||||
    if world.logic[player] in ['hybridglitches', 'nologic']:
 | 
					        overworld_glitch_connections(world, player)
 | 
				
			||||||
        underworld_glitch_connections(world, player)
 | 
					        # mandatory hybrid major glitches connections
 | 
				
			||||||
 | 
					        if world.logic[player] in ['hybridglitches', 'nologic']:
 | 
				
			||||||
 | 
					            underworld_glitch_connections(world, player)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # patch swamp drain
 | 
					    # patch swamp drain
 | 
				
			||||||
    if world.get_entrance('Dam', player).connected_region.name != 'Dam' or world.get_entrance('Swamp Palace', player).connected_region.name != 'Swamp Palace (Entrance)':
 | 
					    if world.get_entrance('Dam', player).connected_region.name != 'Dam' or world.get_entrance('Swamp Palace', player).connected_region.name != 'Swamp Palace (Entrance)':
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -235,24 +235,41 @@ def no_logic_rules(world, player):
 | 
				
			||||||
        create_no_logic_connections(player, world, get_mirror_offset_spots_lw(player))
 | 
					        create_no_logic_connections(player, world, get_mirror_offset_spots_lw(player))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def overworld_glitch_connections(world, player):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Boots-accessible locations.
 | 
				
			||||||
 | 
					    create_owg_connections(player, world, get_boots_clip_exits_lw(world.mode[player] == 'inverted'))
 | 
				
			||||||
 | 
					    create_owg_connections(player, world, get_boots_clip_exits_dw(world.mode[player] == 'inverted', player))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Glitched speed drops.
 | 
				
			||||||
 | 
					    create_owg_connections(player, world, get_glitched_speed_drops_dw(world.mode[player] == 'inverted'))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Mirror clip spots.
 | 
				
			||||||
 | 
					    if world.mode[player] != 'inverted':
 | 
				
			||||||
 | 
					        create_owg_connections(player, world, get_mirror_clip_spots_dw())
 | 
				
			||||||
 | 
					        create_owg_connections(player, world, get_mirror_offset_spots_dw())
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        create_owg_connections(player, world, get_mirror_offset_spots_lw(player))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def overworld_glitches_rules(world, player):
 | 
					def overworld_glitches_rules(world, player):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Boots-accessible locations.
 | 
					    # Boots-accessible locations.
 | 
				
			||||||
    create_owg_connections(player, world, get_boots_clip_exits_lw(world.mode[player] == 'inverted'), lambda state: state.can_boots_clip_lw(player))
 | 
					    set_owg_connection_rules(player, world, get_boots_clip_exits_lw(world.mode[player] == 'inverted'), lambda state: state.can_boots_clip_lw(player))
 | 
				
			||||||
    create_owg_connections(player, world, get_boots_clip_exits_dw(world.mode[player] == 'inverted', player), lambda state: state.can_boots_clip_dw(player))
 | 
					    set_owg_connection_rules(player, world, get_boots_clip_exits_dw(world.mode[player] == 'inverted', player), lambda state: state.can_boots_clip_dw(player))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Glitched speed drops.
 | 
					    # Glitched speed drops.
 | 
				
			||||||
    create_owg_connections(player, world, get_glitched_speed_drops_dw(world.mode[player] == 'inverted'), lambda state: state.can_get_glitched_speed_dw(player))
 | 
					    set_owg_connection_rules(player, world, get_glitched_speed_drops_dw(world.mode[player] == 'inverted'), lambda state: state.can_get_glitched_speed_dw(player))
 | 
				
			||||||
    # Dark Death Mountain Ledge Clip Spot also accessible with mirror.
 | 
					    # Dark Death Mountain Ledge Clip Spot also accessible with mirror.
 | 
				
			||||||
    if world.mode[player] != 'inverted':
 | 
					    if world.mode[player] != 'inverted':
 | 
				
			||||||
        add_alternate_rule(world.get_entrance('Dark Death Mountain Ledge Clip Spot', player), lambda state: state.has('Magic Mirror', player))
 | 
					        add_alternate_rule(world.get_entrance('Dark Death Mountain Ledge Clip Spot', player), lambda state: state.has('Magic Mirror', player))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Mirror clip spots.
 | 
					    # Mirror clip spots.
 | 
				
			||||||
    if world.mode[player] != 'inverted':
 | 
					    if world.mode[player] != 'inverted':
 | 
				
			||||||
        create_owg_connections(player, world, get_mirror_clip_spots_dw(), lambda state: state.has('Magic Mirror', player))
 | 
					        set_owg_connection_rules(player, world, get_mirror_clip_spots_dw(), lambda state: state.has('Magic Mirror', player))
 | 
				
			||||||
        create_owg_connections(player, world, get_mirror_offset_spots_dw(), lambda state: state.has('Magic Mirror', player) and state.can_boots_clip_lw(player))
 | 
					        set_owg_connection_rules(player, world, get_mirror_offset_spots_dw(), lambda state: state.has('Magic Mirror', player) and state.can_boots_clip_lw(player))
 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
        create_owg_connections(player, world, get_mirror_offset_spots_lw(player), lambda state: state.has('Magic Mirror', player) and state.can_boots_clip_dw(player))
 | 
					        set_owg_connection_rules(player, world, get_mirror_offset_spots_lw(player), lambda state: state.has('Magic Mirror', player) and state.can_boots_clip_dw(player))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Regions that require the boots and some other stuff.
 | 
					    # Regions that require the boots and some other stuff.
 | 
				
			||||||
    if world.mode[player] != 'inverted':
 | 
					    if world.mode[player] != 'inverted':
 | 
				
			||||||
| 
						 | 
					@ -282,12 +299,16 @@ def create_no_logic_connections(player, world, connections):
 | 
				
			||||||
        parent.exits.append(connection)
 | 
					        parent.exits.append(connection)
 | 
				
			||||||
        connection.connect(target)
 | 
					        connection.connect(target)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def create_owg_connections(player, world, connections, default_rule):
 | 
					def create_owg_connections(player, world, connections):
 | 
				
			||||||
    for entrance, parent_region, target_region, *rule_override in connections:
 | 
					    for entrance, parent_region, target_region, *rule_override in connections:
 | 
				
			||||||
        parent = world.get_region(parent_region, player)
 | 
					        parent = world.get_region(parent_region, player)
 | 
				
			||||||
        target = world.get_region(target_region, player)
 | 
					        target = world.get_region(target_region, player)
 | 
				
			||||||
        connection = Entrance(player, entrance, parent)
 | 
					        connection = Entrance(player, entrance, parent)
 | 
				
			||||||
        parent.exits.append(connection)
 | 
					        parent.exits.append(connection)
 | 
				
			||||||
        connection.connect(target)
 | 
					        connection.connect(target)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def set_owg_connection_rules(player, world, connections, default_rule):
 | 
				
			||||||
 | 
					    for entrance, _, _, *rule_override in connections:
 | 
				
			||||||
 | 
					        connection = world.get_entrance(entrance, player)
 | 
				
			||||||
        rule = rule_override[0] if len(rule_override) > 0 else default_rule
 | 
					        rule = rule_override[0] if len(rule_override) > 0 else default_rule
 | 
				
			||||||
        connection.access_rule = rule
 | 
					        connection.access_rule = rule
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -853,7 +853,9 @@ def set_trock_key_rules(world, player):
 | 
				
			||||||
    for entrance in ['Turtle Rock Dark Room Staircase', 'Turtle Rock (Chain Chomp Room) (North)', 'Turtle Rock (Chain Chomp Room) (South)', 'Turtle Rock Pokey Room', 'Turtle Rock Big Key Door']:
 | 
					    for entrance in ['Turtle Rock Dark Room Staircase', 'Turtle Rock (Chain Chomp Room) (North)', 'Turtle Rock (Chain Chomp Room) (South)', 'Turtle Rock Pokey Room', 'Turtle Rock Big Key Door']:
 | 
				
			||||||
        set_rule(world.get_entrance(entrance, player), lambda state: False)
 | 
					        set_rule(world.get_entrance(entrance, player), lambda state: False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    all_state = world.get_all_state(True)
 | 
					    all_state = world.get_all_state()
 | 
				
			||||||
 | 
					    all_state.reachable_regions[player] = set()  # wipe reachable regions so that the locked doors actually work
 | 
				
			||||||
 | 
					    all_state.stale[player] = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Check if each of the four main regions of the dungoen can be reached. The previous code section prevents key-costing moves within the dungeon.
 | 
					    # Check if each of the four main regions of the dungoen can be reached. The previous code section prevents key-costing moves within the dungeon.
 | 
				
			||||||
    can_reach_back = all_state.can_reach(world.get_region('Turtle Rock (Eye Bridge)', player)) if world.can_access_trock_eyebridge[player] is None else world.can_access_trock_eyebridge[player]
 | 
					    can_reach_back = all_state.can_reach(world.get_region('Turtle Rock (Eye Bridge)', player)) if world.can_access_trock_eyebridge[player] is None else world.can_access_trock_eyebridge[player]
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -24,6 +24,12 @@ lttp_logger = logging.getLogger("A Link to the Past")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ALTTPWorld(World):
 | 
					class ALTTPWorld(World):
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    The Legend of Zelda: A Link to the Past is an action/adventure game. Take on the role of
 | 
				
			||||||
 | 
					    Link, a boy who is destined to save the land of Hyrule. Delve through three palaces and nine
 | 
				
			||||||
 | 
					    dungeons on your quest to rescue the descendents of the seven wise men and defeat the evil
 | 
				
			||||||
 | 
					    Ganon!
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
    game: str = "A Link to the Past"
 | 
					    game: str = "A Link to the Past"
 | 
				
			||||||
    options = alttp_options
 | 
					    options = alttp_options
 | 
				
			||||||
    topology_present = True
 | 
					    topology_present = True
 | 
				
			||||||
| 
						 | 
					@ -192,8 +198,8 @@ class ALTTPWorld(World):
 | 
				
			||||||
                elif 'Bow' in item_name:
 | 
					                elif 'Bow' in item_name:
 | 
				
			||||||
                    if state.has('Silver Bow', item.player):
 | 
					                    if state.has('Silver Bow', item.player):
 | 
				
			||||||
                        return
 | 
					                        return
 | 
				
			||||||
                    elif state.has('Bow', item.player) and (self.world.difficulty_requirements[item.player].progressive_bow_limit >= 2 
 | 
					                    elif state.has('Bow', item.player) and (self.world.difficulty_requirements[item.player].progressive_bow_limit >= 2
 | 
				
			||||||
                        or self.world.logic[item.player] == 'noglitches' 
 | 
					                        or self.world.logic[item.player] == 'noglitches'
 | 
				
			||||||
                        or self.world.swordless[item.player]): # modes where silver bow is always required for ganon
 | 
					                        or self.world.swordless[item.player]): # modes where silver bow is always required for ganon
 | 
				
			||||||
                        return 'Silver Bow'
 | 
					                        return 'Silver Bow'
 | 
				
			||||||
                    elif self.world.difficulty_requirements[item.player].progressive_bow_limit >= 1:
 | 
					                    elif self.world.difficulty_requirements[item.player].progressive_bow_limit >= 1:
 | 
				
			||||||
| 
						 | 
					@ -206,7 +212,7 @@ class ALTTPWorld(World):
 | 
				
			||||||
        attempts = 5
 | 
					        attempts = 5
 | 
				
			||||||
        world = self.world
 | 
					        world = self.world
 | 
				
			||||||
        player = self.player
 | 
					        player = self.player
 | 
				
			||||||
        all_state = world.get_all_state(keys=True)
 | 
					        all_state = world.get_all_state()
 | 
				
			||||||
        crystals = [self.create_item(name) for name in ['Red Pendant', 'Blue Pendant', 'Green Pendant', 'Crystal 1', 'Crystal 2', 'Crystal 3', 'Crystal 4', 'Crystal 7', 'Crystal 5', 'Crystal 6']]
 | 
					        crystals = [self.create_item(name) for name in ['Red Pendant', 'Blue Pendant', 'Green Pendant', 'Crystal 1', 'Crystal 2', 'Crystal 3', 'Crystal 4', 'Crystal 7', 'Crystal 5', 'Crystal 6']]
 | 
				
			||||||
        crystal_locations = [world.get_location('Turtle Rock - Prize', player),
 | 
					        crystal_locations = [world.get_location('Turtle Rock - Prize', player),
 | 
				
			||||||
                             world.get_location('Eastern Palace - Prize', player),
 | 
					                             world.get_location('Eastern Palace - Prize', player),
 | 
				
			||||||
| 
						 | 
					@ -401,4 +407,4 @@ class ALttPLogic(LogicMixin):
 | 
				
			||||||
            return True
 | 
					            return True
 | 
				
			||||||
        if self.world.smallkey_shuffle[player] == smallkey_shuffle.option_universal:
 | 
					        if self.world.smallkey_shuffle[player] == smallkey_shuffle.option_universal:
 | 
				
			||||||
            return self.can_buy_unlimited('Small Key (Universal)', player)
 | 
					            return self.can_buy_unlimited('Small Key (Universal)', player)
 | 
				
			||||||
        return self.prog_items[item, player] >= count
 | 
					        return self.prog_items[item, player] >= count
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -24,6 +24,11 @@ all_items["Evolution Trap"] = factorio_base_id - 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Factorio(World):
 | 
					class Factorio(World):
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    Factorio is a game about automation. You play as an engineer who has crash landed on the planet
 | 
				
			||||||
 | 
					    Nauvis, an inhospitable world filled with dangerous creatures called biters. Build a factory,
 | 
				
			||||||
 | 
					    research new technologies, and become more efficient in your quest to build a rocket and return home.
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
    game: str = "Factorio"
 | 
					    game: str = "Factorio"
 | 
				
			||||||
    static_nodes = {"automation", "logistics", "rocket-silo"}
 | 
					    static_nodes = {"automation", "logistics", "rocket-silo"}
 | 
				
			||||||
    custom_recipes = {}
 | 
					    custom_recipes = {}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,6 +16,12 @@ from ..AutoWorld import World
 | 
				
			||||||
client_version = 6
 | 
					client_version = 6
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class MinecraftWorld(World):
 | 
					class MinecraftWorld(World):
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    Minecraft is a game about creativity. In a world made entirely of cubes, you explore, discover, mine,
 | 
				
			||||||
 | 
					    craft, and try not to explode. Delve deep into the earth and discover abandoned mines, ancient
 | 
				
			||||||
 | 
					    structures, and materials to create a portal to another world. Defeat the Ender Dragon, and claim
 | 
				
			||||||
 | 
					    victory!
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
    game: str = "Minecraft"
 | 
					    game: str = "Minecraft"
 | 
				
			||||||
    options = minecraft_options
 | 
					    options = minecraft_options
 | 
				
			||||||
    topology_present = True
 | 
					    topology_present = True
 | 
				
			||||||
| 
						 | 
					@ -47,7 +53,7 @@ class MinecraftWorld(World):
 | 
				
			||||||
        itempool = []
 | 
					        itempool = []
 | 
				
			||||||
        junk_pool = junk_weights.copy()
 | 
					        junk_pool = junk_weights.copy()
 | 
				
			||||||
        # Add all required progression items
 | 
					        # Add all required progression items
 | 
				
			||||||
        for (name, num) in required_items.items(): 
 | 
					        for (name, num) in required_items.items():
 | 
				
			||||||
            itempool += [name] * num
 | 
					            itempool += [name] * num
 | 
				
			||||||
        # Add structure compasses if desired
 | 
					        # Add structure compasses if desired
 | 
				
			||||||
        if self.world.structure_compasses[self.player]:
 | 
					        if self.world.structure_compasses[self.player]:
 | 
				
			||||||
| 
						 | 
					@ -85,9 +91,9 @@ class MinecraftWorld(World):
 | 
				
			||||||
        def MCRegion(region_name: str, exits=[]):
 | 
					        def MCRegion(region_name: str, exits=[]):
 | 
				
			||||||
            ret = Region(region_name, None, region_name, self.player, self.world)
 | 
					            ret = Region(region_name, None, region_name, self.player, self.world)
 | 
				
			||||||
            ret.locations = [MinecraftAdvancement(self.player, loc_name, loc_data.id, ret)
 | 
					            ret.locations = [MinecraftAdvancement(self.player, loc_name, loc_data.id, ret)
 | 
				
			||||||
                for loc_name, loc_data in advancement_table.items() 
 | 
					                for loc_name, loc_data in advancement_table.items()
 | 
				
			||||||
                if loc_data.region == region_name]
 | 
					                if loc_data.region == region_name]
 | 
				
			||||||
            for exit in exits: 
 | 
					            for exit in exits:
 | 
				
			||||||
                ret.exits.append(Entrance(self.player, exit, ret))
 | 
					                ret.exits.append(Entrance(self.player, exit, ret))
 | 
				
			||||||
            return ret
 | 
					            return ret
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -100,7 +106,7 @@ class MinecraftWorld(World):
 | 
				
			||||||
        with open(os.path.join(output_directory, filename), 'wb') as f:
 | 
					        with open(os.path.join(output_directory, filename), 'wb') as f:
 | 
				
			||||||
            f.write(b64encode(bytes(json.dumps(data), 'utf-8')))
 | 
					            f.write(b64encode(bytes(json.dumps(data), 'utf-8')))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def fill_slot_data(self): 
 | 
					    def fill_slot_data(self):
 | 
				
			||||||
        slot_data = self._get_mc_data()
 | 
					        slot_data = self._get_mc_data()
 | 
				
			||||||
        for option_name in minecraft_options:
 | 
					        for option_name in minecraft_options:
 | 
				
			||||||
            option = getattr(self.world, option_name)[self.player]
 | 
					            option = getattr(self.world, option_name)[self.player]
 | 
				
			||||||
| 
						 | 
					@ -115,7 +121,7 @@ class MinecraftWorld(World):
 | 
				
			||||||
            item.never_exclude = True
 | 
					            item.never_exclude = True
 | 
				
			||||||
        return item
 | 
					        return item
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def mc_update_output(raw_data, server, port): 
 | 
					def mc_update_output(raw_data, server, port):
 | 
				
			||||||
    data = json.loads(b64decode(raw_data))
 | 
					    data = json.loads(b64decode(raw_data))
 | 
				
			||||||
    data['server'] = server
 | 
					    data['server'] = server
 | 
				
			||||||
    data['port'] = port
 | 
					    data['port'] = port
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,6 +15,11 @@ from ..AutoWorld import World
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class SubnauticaWorld(World):
 | 
					class SubnauticaWorld(World):
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    Subnautica is an undersea exploration game. Stranded on an alien world, you become infected by
 | 
				
			||||||
 | 
					    an unknown bacteria. The planet's automatic quarantine will shoot you down if you try to leave.
 | 
				
			||||||
 | 
					    You must find a cure for yourself, build an escape rocket, and leave the planet.
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
    game: str = "Subnautica"
 | 
					    game: str = "Subnautica"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    item_name_to_id = items_lookup_name_to_id
 | 
					    item_name_to_id = items_lookup_name_to_id
 | 
				
			||||||
| 
						 | 
					@ -53,7 +58,7 @@ class SubnauticaWorld(World):
 | 
				
			||||||
        pass
 | 
					        pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def fill_slot_data(self): 
 | 
					    def fill_slot_data(self):
 | 
				
			||||||
        slot_data = {}
 | 
					        slot_data = {}
 | 
				
			||||||
        return slot_data
 | 
					        return slot_data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue