create options files on WebHost startup

This commit is contained in:
Fabian Dill 2021-07-22 18:21:31 +02:00
parent df9bad75ea
commit 34ff5d9662
5 changed files with 120 additions and 21 deletions

View File

@ -12,6 +12,7 @@ from waitress import serve
from WebHostLib.models import db
from WebHostLib.autolauncher import autohost
from WebHostLib.lttpsprites import update_sprites_lttp
from WebHostLib.options import create as create_options_files
configpath = os.path.abspath("config.yaml")
@ -33,6 +34,7 @@ if __name__ == "__main__":
logging.basicConfig(format='[%(asctime)s] %(message)s', level=logging.INFO)
update_sprites_lttp()
app = get_app()
create_options_files()
if app.config["SELFLAUNCH"]:
autohost(app.config)
if app.config["SELFHOST"]: # using WSGI, you just want to run get_app()

17
WebHostLib/options.py Normal file
View File

@ -0,0 +1,17 @@
import os
from Utils import __version__
from jinja2 import Template
import yaml
from worlds.AutoWorld import AutoWorldRegister
target_folder = os.path.join("WebHostLib", "static", "generated")
def create():
for game_name, world in AutoWorldRegister.world_types.items():
res = Template(open(os.path.join("WebHostLib", "templates", "options.yaml")).read()).render(
options=world.options, __version__ = __version__, game=game_name, yaml_dump = yaml.dump
)
with open(os.path.join(target_folder, game_name+".yaml"), "w") as f:
f.write(res)

View File

@ -0,0 +1,71 @@
# What is this file?
# This file contains options which allow you to configure your multiworld experience while allowing others
# to play how they want as well.
# How do I use it?
# The options in this file are weighted. This means the higher number you assign to a value, the more
# chances you have for that option to be chosen. For example, an option like this:
#
# map_shuffle:
# on: 5
# off: 15
#
# Means you have 5 chances for map shuffle to occur, and 15 chances for map shuffle to be turned off
# I've never seen a file like this before. What characters am I allowed to use?
# This is a .yaml file. You are allowed to use most characters.
# To test if your yaml is valid or not, you can use this website:
# http://www.yamllint.com/
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
#{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.
#{number} will be replaced with the counter value of the name.
#{NUMBER} will be replaced with the counter value of the name if the counter value is greater than 1.
game:
{{ game }}: 1
requires:
version: {{ __version__ }} # Version of Archipelago required for this yaml to work as expected.
# Shared Options supported by all games:
accessibility:
items: 0 # Guarantees you will be able to acquire all items, but you may not be able to access all locations
locations: 50 # Guarantees you will be able to access all locations, and therefore all items
none: 0 # Guarantees only that the game is beatable. You may not be able to access all locations or acquire all items
progression_balancing:
on: 50 # A system to reduce BK, as in times during which you can't do anything by moving your items into an earlier access sphere to make it likely you have stuff to do
off: 0 # Turn this off if you don't mind a longer multiworld, or can glitch/sequence break around missing items.
# The following 4 options can be uncommented and moved into a game's section they should affect
# start_inventory: # Begin the file with the listed items/upgrades
# Please only use items for the correct game, use triggers if need to be have seperated lists.
# Pegasus Boots: on
# Bomb Upgrade (+10): 4
# Arrow Upgrade (+10): 4
# start_hints: # Begin the game with these items' locations revealed to you at the start of the game. Get the info via !hint in your client.
# - Moon Pearl
# local_items: # Force certain items to appear in your world only, not across the multiworld. Recognizes some group names, like "Swords"
# - "Moon Pearl"
# - "Small Keys"
# - "Big Keys"
# non_local_items: # Force certain items to appear outside your world only, unless in single-player. Recognizes some group names, like "Swords"
# - "Progressive Weapons"
# exclude_locations: # Force certain locations to never contain progression items, and always be filled with junk.
# - "Master Sword Pedestal"
{{ game }}:
{%- for option_name, option in options.items() %}
{{ option_name }}:{% if option.__doc__ %} # {{ option.__doc__ }}{% endif %}
{%- if option.range_start is defined %}
# you can add additional values between minimum and maximum
{{ option.range_start }}: 0 # minimum value
{{ option.range_end }}: 0 # maximum value
random: 50
random-low: 0
random-high: 0
{%- elif option.options -%}
{%- for sub_option_name, suboption_option_id in option.options.items() %}
{{ sub_option_name }}: {% if suboption_option_id == option.default %}50{% else %}0{% endif %}
{%- endfor -%}
{%- else %}
{{ yaml_dump(option.default) | indent(4, first=False) }}
{%- endif -%}
{%- endfor -%}

View File

@ -5,11 +5,12 @@ from Options import Choice, OptionDict, Option, DefaultOnToggle
from schema import Schema, Optional, And, Or
# schema helpers
FloatRange = lambda low,high: And(Or(int,float), lambda f: low<=f<=high)
LuaBool = Or(bool, And(int, lambda n: n in (0,1)))
FloatRange = lambda low, high: And(Or(int, float), lambda f: low <= f <= high)
LuaBool = Or(bool, And(int, lambda n: n in (0, 1)))
class MaxSciencePack(Choice):
"""Maximum level of science pack required to complete the game."""
option_automation_science_pack = 0
option_logistic_science_pack = 1
option_military_science_pack = 2
@ -30,7 +31,9 @@ class MaxSciencePack(Choice):
def get_max_pack(self):
return self.get_ordered_science_packs()[self.value].replace("_", "-")
class TechCost(Choice):
"""How expensive are the technologies."""
option_very_easy = 0
option_easy = 1
option_kind = 2
@ -42,6 +45,7 @@ class TechCost(Choice):
class FreeSamples(Choice):
"""Get free items with your technologies."""
option_none = 0
option_single_craft = 1
option_half_stack = 2
@ -50,6 +54,7 @@ class FreeSamples(Choice):
class TechTreeLayout(Choice):
"""Selects how the tech tree nodes are interwoven."""
option_single = 0
option_small_diamonds = 1
option_medium_diamonds = 2
@ -64,6 +69,7 @@ class TechTreeLayout(Choice):
class TechTreeInformation(Choice):
"""How much information should be displayed in the tech tree."""
option_none = 0
option_advancement = 1
option_full = 2
@ -71,12 +77,14 @@ class TechTreeInformation(Choice):
class RecipeTime(Choice):
"""randomize the time it takes for any recipe to craft, this includes smelting, chemical lab, hand crafting etc."""
option_vanilla = 0
option_fast = 1
option_normal = 2
option_slow = 4
option_chaos = 5
# TODO: implement random
class Progressive(Choice):
option_off = 0
@ -89,6 +97,7 @@ class Progressive(Choice):
class RecipeIngredients(Choice):
"""Select if rocket, or rocket + science pack ingredients should be random."""
option_rocket = 0
option_science_pack = 1
@ -121,37 +130,37 @@ class FactorioWorldGen(OptionDict):
"pollution_restored_per_tree_damage": 10}}
schema = Schema({
"basic": {
Optional("terrain_segmentation"): FloatRange(0.166,6),
Optional("water"): FloatRange(0.166,6),
Optional("terrain_segmentation"): FloatRange(0.166, 6),
Optional("water"): FloatRange(0.166, 6),
Optional("autoplace_controls"): {
str: {
"frequency": FloatRange(0,6),
"size": FloatRange(0,6),
"richness": FloatRange(0.166,6)}},
Optional("seed"): Or(None,And(int, lambda n: n>=0)),
Optional("starting_area"): FloatRange(0.166,6),
"frequency": FloatRange(0, 6),
"size": FloatRange(0, 6),
"richness": FloatRange(0.166, 6)}},
Optional("seed"): Or(None, And(int, lambda n: n >= 0)),
Optional("starting_area"): FloatRange(0.166, 6),
Optional("peaceful_mode"): LuaBool,
Optional("cliff_settings"): {
"name": str, "cliff_elevation_0": FloatRange(0,99),
"cliff_elevation_interval": FloatRange(0.066,241), # 40/frequency
"richness": FloatRange(0,6)},
"name": str, "cliff_elevation_0": FloatRange(0, 99),
"cliff_elevation_interval": FloatRange(0.066, 241), # 40/frequency
"richness": FloatRange(0, 6)},
},
"advanced": {
Optional("pollution"): {
Optional("enabled"): LuaBool,
Optional("diffusion_ratio"): FloatRange(0,0.25),
Optional("ageing"): FloatRange(0.1,4),
Optional("enemy_attack_pollution_consumption_modifier"): FloatRange(0.1,4),
Optional("min_pollution_to_damage_trees"): FloatRange(0,9999),
Optional("pollution_restored_per_tree_damage"): FloatRange(0,9999)}
Optional("diffusion_ratio"): FloatRange(0, 0.25),
Optional("ageing"): FloatRange(0.1, 4),
Optional("enemy_attack_pollution_consumption_modifier"): FloatRange(0.1, 4),
Optional("min_pollution_to_damage_trees"): FloatRange(0, 9999),
Optional("pollution_restored_per_tree_damage"): FloatRange(0, 9999)}
}
})
def __init__(self, value: typing.Dict[str, typing.Any]):
advanced = {"pollution"}
self.value = {
"basic": { key: value[key] for key in value.keys() - advanced },
"advanced": { key: value[key] for key in value.keys() & advanced }
"basic": {key: value[key] for key in value.keys() - advanced},
"advanced": {key: value[key] for key in value.keys() & advanced}
}
@classmethod
@ -174,4 +183,4 @@ factorio_options: typing.Dict[str, type(Option)] = {
"imported_blueprints": DefaultOnToggle,
"world_gen": FactorioWorldGen,
"progressive": DefaultOnToggle
}
}

View File

@ -25,7 +25,7 @@ class Factorio(World):
item_name_to_id = tech_table
location_name_to_id = base_tech_table
def create_items(self):
def generate_basic(self):
for tech_name in base_tech_table:
if self.world.progressive:
item_name = tech_to_progressive_lookup.get(tech_name, tech_name)