AutoWorld: basic Item handling
This commit is contained in:
parent
babd809fa6
commit
31c550d410
|
@ -272,6 +272,8 @@ class MultiWorld():
|
||||||
return next(location for location in self.get_locations() if
|
return next(location for location in self.get_locations() if
|
||||||
location.item and location.item.name == item and location.item.player == player)
|
location.item and location.item.name == item and location.item.player == player)
|
||||||
|
|
||||||
|
def create_item(self, item_name: str, player: int) -> Item:
|
||||||
|
return self.worlds[player].create_item(item_name)
|
||||||
|
|
||||||
def push_precollected(self, item: Item):
|
def push_precollected(self, item: Item):
|
||||||
item.world = self
|
item.world = self
|
||||||
|
@ -859,7 +861,6 @@ class CollectionState(object):
|
||||||
(self.has('Progressive Weapons', player, 1) and self.has('Bed', player)))
|
(self.has('Progressive Weapons', player, 1) and self.has('Bed', player)))
|
||||||
return respawn_dragon and self.has('Progressive Weapons', player, 2) and self.has('Progressive Armor', player) and self.has('Archery', player)
|
return respawn_dragon and self.has('Progressive Weapons', player, 2) and self.has('Progressive Armor', player) and self.has('Archery', player)
|
||||||
|
|
||||||
|
|
||||||
def collect(self, item: Item, event: bool = False, location: Location = None) -> bool:
|
def collect(self, item: Item, event: bool = False, location: Location = None) -> bool:
|
||||||
if location:
|
if location:
|
||||||
self.locations_checked.add(location)
|
self.locations_checked.add(location)
|
||||||
|
|
6
Main.py
6
Main.py
|
@ -9,7 +9,7 @@ import pickle
|
||||||
from typing import Dict, Tuple
|
from typing import Dict, Tuple
|
||||||
|
|
||||||
from BaseClasses import MultiWorld, CollectionState, Region, Item
|
from BaseClasses import MultiWorld, CollectionState, Region, Item
|
||||||
from worlds.alttp.Items import ItemFactory, item_name_groups
|
from worlds.alttp.Items import item_name_groups
|
||||||
from worlds.alttp.Regions import create_regions, mark_light_world_regions, \
|
from worlds.alttp.Regions import create_regions, mark_light_world_regions, \
|
||||||
lookup_vanilla_location_to_entrance
|
lookup_vanilla_location_to_entrance
|
||||||
from worlds.alttp.InvertedRegions import create_inverted_regions, mark_dark_world_regions
|
from worlds.alttp.InvertedRegions import create_inverted_regions, mark_dark_world_regions
|
||||||
|
@ -453,8 +453,8 @@ def main(args, seed=None):
|
||||||
for index, take_any in enumerate(takeanyregions):
|
for index, take_any in enumerate(takeanyregions):
|
||||||
for region in [world.get_region(take_any, player) for player in range(1, world.players + 1) if
|
for region in [world.get_region(take_any, player) for player in range(1, world.players + 1) if
|
||||||
world.retro[player]]:
|
world.retro[player]]:
|
||||||
item = ItemFactory(region.shop.inventory[(0 if take_any == "Old Man Sword Cave" else 1)]['item'],
|
item = world.create_item(region.shop.inventory[(0 if take_any == "Old Man Sword Cave" else 1)]['item'],
|
||||||
region.player)
|
region.player)
|
||||||
player = region.player
|
player = region.player
|
||||||
location_id = SHOP_ID_START + total_shop_slots + index
|
location_id = SHOP_ID_START + total_shop_slots + index
|
||||||
|
|
||||||
|
|
|
@ -516,10 +516,11 @@ def roll_settings(weights: dict, plando_options: typing.Set[str] = frozenset(("b
|
||||||
ret.game = get_choice("game", weights)
|
ret.game = get_choice("game", weights)
|
||||||
if ret.game not in weights:
|
if ret.game not in weights:
|
||||||
raise Exception(f"No game options for selected game \"{ret.game}\" found.")
|
raise Exception(f"No game options for selected game \"{ret.game}\" found.")
|
||||||
|
world_type = AutoWorldRegister.world_types[ret.game]
|
||||||
game_weights = weights[ret.game]
|
game_weights = weights[ret.game]
|
||||||
ret.local_items = set()
|
ret.local_items = set()
|
||||||
for item_name in game_weights.get('local_items', []):
|
for item_name in game_weights.get('local_items', []):
|
||||||
items = item_name_groups.get(item_name, {item_name})
|
items = world_type.item_name_groups.get(item_name, {item_name})
|
||||||
for item in items:
|
for item in items:
|
||||||
if item in lookup_any_item_name_to_id:
|
if item in lookup_any_item_name_to_id:
|
||||||
ret.local_items.add(item)
|
ret.local_items.add(item)
|
||||||
|
@ -528,7 +529,7 @@ def roll_settings(weights: dict, plando_options: typing.Set[str] = frozenset(("b
|
||||||
|
|
||||||
ret.non_local_items = set()
|
ret.non_local_items = set()
|
||||||
for item_name in game_weights.get('non_local_items', []):
|
for item_name in game_weights.get('non_local_items', []):
|
||||||
items = item_name_groups.get(item_name, {item_name})
|
items = world_type.item_name_groups.get(item_name, {item_name})
|
||||||
for item in items:
|
for item in items:
|
||||||
if item in lookup_any_item_name_to_id:
|
if item in lookup_any_item_name_to_id:
|
||||||
ret.non_local_items.add(item)
|
ret.non_local_items.add(item)
|
||||||
|
@ -556,7 +557,7 @@ def roll_settings(weights: dict, plando_options: typing.Set[str] = frozenset(("b
|
||||||
else:
|
else:
|
||||||
setattr(ret, option_name, option.from_any(get_choice(option_name, game_weights)))
|
setattr(ret, option_name, option.from_any(get_choice(option_name, game_weights)))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise Exception(f"Error generating option {option_name} in {ret.game}")
|
raise Exception(f"Error generating option {option_name} in {ret.game}") from e
|
||||||
else:
|
else:
|
||||||
setattr(ret, option_name, option(option.default))
|
setattr(ret, option_name, option(option.default))
|
||||||
if ret.game == "Minecraft":
|
if ret.game == "Minecraft":
|
||||||
|
@ -778,7 +779,6 @@ def roll_alttp_settings(ret: argparse.Namespace, weights, plando_options):
|
||||||
get_choice("direction", placement, "both")
|
get_choice("direction", placement, "both")
|
||||||
))
|
))
|
||||||
|
|
||||||
|
|
||||||
ret.sprite_pool = weights.get('sprite_pool', [])
|
ret.sprite_pool = weights.get('sprite_pool', [])
|
||||||
ret.sprite = get_choice('sprite', weights, "Link")
|
ret.sprite = get_choice('sprite', weights, "Link")
|
||||||
if 'random_sprite_on_event' in weights:
|
if 'random_sprite_on_event' in weights:
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
from BaseClasses import MultiWorld
|
from typing import Dict, Set, Tuple
|
||||||
|
|
||||||
|
from BaseClasses import MultiWorld, Item, CollectionState
|
||||||
|
|
||||||
|
|
||||||
class AutoWorldRegister(type):
|
class AutoWorldRegister(type):
|
||||||
|
@ -29,6 +31,9 @@ class World(metaclass=AutoWorldRegister):
|
||||||
player: int
|
player: int
|
||||||
options: dict = {}
|
options: dict = {}
|
||||||
topology_present: bool = False # indicate if world type has any meaningful layout/pathing
|
topology_present: bool = False # indicate if world type has any meaningful layout/pathing
|
||||||
|
item_names: Set[str] = frozenset()
|
||||||
|
# maps item group names to sets of items. Example: "Weapons" -> {"Sword", "Bow"}
|
||||||
|
item_name_groups: Dict[str, Set[str]] = {}
|
||||||
|
|
||||||
def __init__(self, world: MultiWorld, player: int):
|
def __init__(self, world: MultiWorld, player: int):
|
||||||
self.world = world
|
self.world = world
|
||||||
|
@ -49,15 +54,19 @@ class World(metaclass=AutoWorldRegister):
|
||||||
If you need any last-second randomization, use MultiWorld.slot_seeds[slot] instead."""
|
If you need any last-second randomization, use MultiWorld.slot_seeds[slot] instead."""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def get_required_client_version(self) -> tuple:
|
def get_required_client_version(self) -> Tuple[int, int, int]:
|
||||||
return 0, 0, 3
|
return 0, 0, 3
|
||||||
|
|
||||||
# end of Main.py calls
|
# end of Main.py calls
|
||||||
|
|
||||||
def collect(self, state, item) -> bool:
|
def collect(self, state: CollectionState, item: Item) -> bool:
|
||||||
"""Collect an item into state. For speed reasons items that aren't logically useful get skipped."""
|
"""Collect an item into state. For speed reasons items that aren't logically useful get skipped."""
|
||||||
if item.advancement:
|
if item.advancement:
|
||||||
state.prog_items[item.name, item.player] += 1
|
state.prog_items[item.name, item.player] += 1
|
||||||
return True # indicate that a logical state change has occured
|
return True # indicate that a logical state change has occured
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def create_item(self, name: str) -> Item:
|
||||||
|
"""Create an item for this world type and player.
|
||||||
|
Warning: this may be called with self.world = None, for example by MultiServer"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
|
@ -6,17 +6,19 @@ def GetBeemizerItem(world, player, item):
|
||||||
if world.beemizer[player] and item_name in trap_replaceable:
|
if world.beemizer[player] and item_name in trap_replaceable:
|
||||||
if world.random.random() < world.beemizer[player] * 0.25:
|
if world.random.random() < world.beemizer[player] * 0.25:
|
||||||
if world.random.random() < (0.5 + world.beemizer[player] * 0.1):
|
if world.random.random() < (0.5 + world.beemizer[player] * 0.1):
|
||||||
return "Bee Trap" if isinstance(item, str) else ItemFactory("Bee Trap", player)
|
return "Bee Trap" if isinstance(item, str) else world.create_item("Bee Trap", player)
|
||||||
else:
|
else:
|
||||||
return "Bee" if isinstance(item, str) else ItemFactory("Bee", player)
|
return "Bee" if isinstance(item, str) else world.create_item("Bee", player)
|
||||||
else:
|
else:
|
||||||
return item
|
return item
|
||||||
else:
|
else:
|
||||||
return item
|
return item
|
||||||
|
|
||||||
|
|
||||||
def ItemFactory(items, player):
|
# should be replaced with direct world.create_item(item) call in the future
|
||||||
from worlds.alttp import ALttPItem
|
def ItemFactory(items, player: int):
|
||||||
|
from worlds.alttp import ALTTPWorld
|
||||||
|
world = ALTTPWorld(None, player)
|
||||||
ret = []
|
ret = []
|
||||||
singleton = False
|
singleton = False
|
||||||
if isinstance(items, str):
|
if isinstance(items, str):
|
||||||
|
@ -24,7 +26,7 @@ def ItemFactory(items, player):
|
||||||
singleton = True
|
singleton = True
|
||||||
for item in items:
|
for item in items:
|
||||||
if item in item_table:
|
if item in item_table:
|
||||||
ret.append(ALttPItem(item, *item_table[item], player))
|
ret.append(world.create_item(item))
|
||||||
else:
|
else:
|
||||||
raise Exception(f"Unknown item {item}")
|
raise Exception(f"Unknown item {item}")
|
||||||
|
|
||||||
|
@ -211,6 +213,8 @@ item_table = {'Bow': ItemData(True, None, 0x0B, 'You have\nchosen the\narcher cl
|
||||||
'Open Floodgate': ItemData(True, 'Event', None, None, None, None, None, None, None, None),
|
'Open Floodgate': ItemData(True, 'Event', None, None, None, None, None, None, None, None),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
as_dict_item_table = {name: data._asdict() for name, data in item_table.items()}
|
||||||
|
|
||||||
progression_mapping = {
|
progression_mapping = {
|
||||||
"Golden Sword": ("Progressive Sword", 4),
|
"Golden Sword": ("Progressive Sword", 4),
|
||||||
"Tempered Sword": ("Progressive Sword", 3),
|
"Tempered Sword": ("Progressive Sword", 3),
|
||||||
|
@ -268,8 +272,8 @@ for basename, substring in _simple_groups:
|
||||||
|
|
||||||
del (_simple_groups)
|
del (_simple_groups)
|
||||||
|
|
||||||
progression_items = {name for name, data in item_table.items() if type(data[2]) == int and data[0]}
|
progression_items = {name for name, data in item_table.items() if type(data.item_code) == int and data.advancement}
|
||||||
item_name_groups['Everything'] = {name for name, data in item_table.items() if type(data[2]) == int}
|
item_name_groups['Everything'] = {name for name, data in item_table.items() if type(data.item_code) == int}
|
||||||
item_name_groups['Progression Items'] = progression_items
|
item_name_groups['Progression Items'] = progression_items
|
||||||
item_name_groups['Non Progression Items'] = item_name_groups['Everything'] - progression_items
|
item_name_groups['Non Progression Items'] = item_name_groups['Everything'] - progression_items
|
||||||
|
|
||||||
|
|
|
@ -3,11 +3,15 @@ from typing import Optional
|
||||||
from BaseClasses import Location, Item, CollectionState
|
from BaseClasses import Location, Item, CollectionState
|
||||||
from ..AutoWorld import World
|
from ..AutoWorld import World
|
||||||
from .Options import alttp_options
|
from .Options import alttp_options
|
||||||
|
from .Items import as_dict_item_table, item_name_groups, item_table
|
||||||
|
|
||||||
|
|
||||||
class ALTTPWorld(World):
|
class ALTTPWorld(World):
|
||||||
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
|
||||||
|
item_name_groups = item_name_groups
|
||||||
|
item_names = frozenset(item_table)
|
||||||
|
|
||||||
def collect(self, state: CollectionState, item: Item) -> bool:
|
def collect(self, state: CollectionState, item: Item) -> bool:
|
||||||
if item.name.startswith('Progressive '):
|
if item.name.startswith('Progressive '):
|
||||||
|
@ -66,6 +70,9 @@ class ALTTPWorld(World):
|
||||||
def get_required_client_version(self) -> tuple:
|
def get_required_client_version(self) -> tuple:
|
||||||
return max((0, 1, 4), super(ALTTPWorld, self).get_required_client_version())
|
return max((0, 1, 4), super(ALTTPWorld, self).get_required_client_version())
|
||||||
|
|
||||||
|
def create_item(self, name: str) -> Item:
|
||||||
|
return ALttPItem(name, self.player, **as_dict_item_table[name])
|
||||||
|
|
||||||
|
|
||||||
class ALttPLocation(Location):
|
class ALttPLocation(Location):
|
||||||
game: str = "A Link to the Past"
|
game: str = "A Link to the Past"
|
||||||
|
@ -80,16 +87,16 @@ class ALttPLocation(Location):
|
||||||
|
|
||||||
|
|
||||||
class ALttPItem(Item):
|
class ALttPItem(Item):
|
||||||
|
|
||||||
game: str = "A Link to the Past"
|
game: str = "A Link to the Past"
|
||||||
|
|
||||||
def __init__(self, name='', advancement=False, type=None, code=None, pedestal_hint=None, pedestal_credit=None, sickkid_credit=None, zora_credit=None, witch_credit=None, fluteboy_credit=None, hint_text=None, player=None):
|
def __init__(self, name, player, advancement=False, type=None, item_code=None, pedestal_hint=None, pedestal_credit=None,
|
||||||
super(ALttPItem, self).__init__(name, advancement, code, player)
|
sick_kid_credit=None, zora_credit=None, witch_credit=None, flute_boy_credit=None, hint_text=None):
|
||||||
|
super(ALttPItem, self).__init__(name, advancement, item_code, player)
|
||||||
self.type = type
|
self.type = type
|
||||||
self._pedestal_hint_text = pedestal_hint
|
self._pedestal_hint_text = pedestal_hint
|
||||||
self.pedestal_credit_text = pedestal_credit
|
self.pedestal_credit_text = pedestal_credit
|
||||||
self.sickkid_credit_text = sickkid_credit
|
self.sickkid_credit_text = sick_kid_credit
|
||||||
self.zora_credit_text = zora_credit
|
self.zora_credit_text = zora_credit
|
||||||
self.magicshop_credit_text = witch_credit
|
self.magicshop_credit_text = witch_credit
|
||||||
self.fluteboy_credit_text = fluteboy_credit
|
self.fluteboy_credit_text = flute_boy_credit
|
||||||
self._hint_text = hint_text
|
self._hint_text = hint_text
|
|
@ -4,29 +4,30 @@ from BaseClasses import Region, Entrance, Location, Item
|
||||||
from .Technologies import base_tech_table, recipe_sources, base_technology_table, advancement_technologies, \
|
from .Technologies import base_tech_table, recipe_sources, base_technology_table, advancement_technologies, \
|
||||||
all_ingredient_names, required_technologies, get_rocket_requirements, rocket_recipes, \
|
all_ingredient_names, required_technologies, get_rocket_requirements, rocket_recipes, \
|
||||||
progressive_technology_table, common_tech_table, tech_to_progressive_lookup, progressive_tech_table, \
|
progressive_technology_table, common_tech_table, tech_to_progressive_lookup, progressive_tech_table, \
|
||||||
get_science_pack_pools, Recipe, recipes, technology_table
|
get_science_pack_pools, Recipe, recipes, technology_table, tech_table
|
||||||
from .Shapes import get_shapes
|
from .Shapes import get_shapes
|
||||||
from .Mod import generate_mod
|
from .Mod import generate_mod
|
||||||
from .Options import factorio_options
|
from .Options import factorio_options
|
||||||
|
|
||||||
|
|
||||||
|
class FactorioItem(Item):
|
||||||
|
game = "Factorio"
|
||||||
|
|
||||||
|
|
||||||
class Factorio(World):
|
class Factorio(World):
|
||||||
game: str = "Factorio"
|
game: str = "Factorio"
|
||||||
static_nodes = {"automation", "logistics", "rocket-silo"}
|
static_nodes = {"automation", "logistics", "rocket-silo"}
|
||||||
custom_recipes = {}
|
custom_recipes = {}
|
||||||
additional_advancement_technologies = set()
|
additional_advancement_technologies = set()
|
||||||
|
item_names = frozenset(tech_table)
|
||||||
|
|
||||||
def generate_basic(self):
|
def generate_basic(self):
|
||||||
for tech_name, tech_id in base_tech_table.items():
|
for tech_name in base_tech_table:
|
||||||
if self.world.progressive and tech_name in tech_to_progressive_lookup:
|
if self.world.progressive:
|
||||||
item_name = tech_to_progressive_lookup[tech_name]
|
item_name = tech_to_progressive_lookup.get(tech_name, tech_name)
|
||||||
tech_id = progressive_tech_table[item_name]
|
|
||||||
else:
|
else:
|
||||||
item_name = tech_name
|
item_name = item_name
|
||||||
|
tech_item = self.create_item(item_name)
|
||||||
tech_item = Item(item_name, item_name in advancement_technologies or
|
|
||||||
item_name in self.additional_advancement_technologies,
|
|
||||||
tech_id, self.player)
|
|
||||||
tech_item.game = "Factorio"
|
|
||||||
if tech_name in self.static_nodes:
|
if tech_name in self.static_nodes:
|
||||||
self.world.get_location(tech_name, self.player).place_locked_item(tech_item)
|
self.world.get_location(tech_name, self.player).place_locked_item(tech_item)
|
||||||
else:
|
else:
|
||||||
|
@ -157,3 +158,9 @@ class Factorio(World):
|
||||||
if tech in tech_to_progressive_lookup:
|
if tech in tech_to_progressive_lookup:
|
||||||
prog_add.add(tech_to_progressive_lookup[tech])
|
prog_add.add(tech_to_progressive_lookup[tech])
|
||||||
self.additional_advancement_technologies |= prog_add
|
self.additional_advancement_technologies |= prog_add
|
||||||
|
|
||||||
|
def create_item(self, name: str) -> Item:
|
||||||
|
assert name in tech_table
|
||||||
|
return FactorioItem(name, name in advancement_technologies or
|
||||||
|
name in self.additional_advancement_technologies,
|
||||||
|
tech_table[name], self.player)
|
|
@ -1,6 +1,7 @@
|
||||||
from typing import NamedTuple, Union
|
from typing import NamedTuple, Union
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
|
||||||
class PlandoItem(NamedTuple):
|
class PlandoItem(NamedTuple):
|
||||||
item: str
|
item: str
|
||||||
location: str
|
location: str
|
||||||
|
@ -25,7 +26,3 @@ class PlandoConnection(NamedTuple):
|
||||||
entrance: str
|
entrance: str
|
||||||
exit: str
|
exit: str
|
||||||
direction: str # entrance, exit or both
|
direction: str # entrance, exit or both
|
||||||
|
|
||||||
|
|
||||||
class World():
|
|
||||||
pass
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import logging
|
import logging
|
||||||
|
from typing import Set
|
||||||
|
|
||||||
logger = logging.getLogger("Hollow Knight")
|
logger = logging.getLogger("Hollow Knight")
|
||||||
|
|
||||||
|
@ -14,6 +15,7 @@ from ..AutoWorld import World
|
||||||
class HKWorld(World):
|
class HKWorld(World):
|
||||||
game: str = "Hollow Knight"
|
game: str = "Hollow Knight"
|
||||||
options = hollow_knight_options
|
options = hollow_knight_options
|
||||||
|
item_names: Set[str] = frozenset(item_table)
|
||||||
|
|
||||||
def generate_basic(self):
|
def generate_basic(self):
|
||||||
# Link regions
|
# Link regions
|
||||||
|
@ -22,8 +24,7 @@ class HKWorld(World):
|
||||||
# Generate item pool
|
# Generate item pool
|
||||||
pool = []
|
pool = []
|
||||||
for item_name, item_data in item_table.items():
|
for item_name, item_data in item_table.items():
|
||||||
|
item = self.create_item(item_name)
|
||||||
item = HKItem(item_name, item_data.advancement, item_data.id, item_data.type, player=self.player)
|
|
||||||
|
|
||||||
if item_data.type == "Event":
|
if item_data.type == "Event":
|
||||||
event_location = self.world.get_location(item_name, self.player)
|
event_location = self.world.get_location(item_name, self.player)
|
||||||
|
@ -83,6 +84,9 @@ class HKWorld(World):
|
||||||
slot_data[option_name] = int(option.value)
|
slot_data[option_name] = int(option.value)
|
||||||
return slot_data
|
return slot_data
|
||||||
|
|
||||||
|
def create_item(self, name: str) -> Item:
|
||||||
|
item_data = item_table[name]
|
||||||
|
return HKItem(name, item_data.advancement, item_data.id, item_data.type, self.player)
|
||||||
|
|
||||||
def create_region(world: MultiWorld, player: int, name: str, locations=None, exits=None):
|
def create_region(world: MultiWorld, player: int, name: str, locations=None, exits=None):
|
||||||
ret = Region(name, None, name, player)
|
ret = Region(name, None, name, player)
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
from BaseClasses import Item
|
from BaseClasses import Item
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
|
|
||||||
class ItemData(typing.NamedTuple):
|
class ItemData(typing.NamedTuple):
|
||||||
code: int
|
code: int
|
||||||
progression: bool
|
progression: bool
|
||||||
|
|
||||||
|
|
||||||
class MinecraftItem(Item):
|
class MinecraftItem(Item):
|
||||||
game: str = "Minecraft"
|
game: str = "Minecraft"
|
||||||
def __init__(self, name: str, progression: bool, code: int, player: int):
|
|
||||||
super().__init__(name, progression, code if code else None, player)
|
|
||||||
|
|
||||||
item_table = {
|
item_table = {
|
||||||
"Archery": ItemData(45000, True),
|
"Archery": ItemData(45000, True),
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
|
from typing import Dict, Set
|
||||||
|
|
||||||
|
|
||||||
from .Items import MinecraftItem, item_table, item_frequencies
|
from .Items import MinecraftItem, item_table, item_frequencies
|
||||||
from .Locations import MinecraftAdvancement, advancement_table, exclusion_table, events_table
|
from .Locations import MinecraftAdvancement, advancement_table, exclusion_table, events_table
|
||||||
from .Regions import mc_regions, link_minecraft_structures
|
from .Regions import mc_regions, link_minecraft_structures
|
||||||
from .Rules import set_rules
|
from .Rules import set_rules
|
||||||
|
|
||||||
from BaseClasses import Region, Entrance
|
from BaseClasses import Region, Entrance, Item
|
||||||
from .Options import minecraft_options
|
from .Options import minecraft_options
|
||||||
from ..AutoWorld import World
|
from ..AutoWorld import World
|
||||||
|
|
||||||
|
@ -13,6 +16,7 @@ class MinecraftWorld(World):
|
||||||
game: str = "Minecraft"
|
game: str = "Minecraft"
|
||||||
options = minecraft_options
|
options = minecraft_options
|
||||||
topology_present = True
|
topology_present = True
|
||||||
|
item_names = frozenset(item_table)
|
||||||
|
|
||||||
def _get_mc_data(self):
|
def _get_mc_data(self):
|
||||||
exits = ["Overworld Structure 1", "Overworld Structure 2", "Nether Structure 1", "Nether Structure 2",
|
exits = ["Overworld Structure 1", "Overworld Structure 2", "Nether Structure 1", "Nether Structure 2",
|
||||||
|
@ -27,7 +31,6 @@ class MinecraftWorld(World):
|
||||||
'structures': {exit: self.world.get_entrance(exit, self.player).connected_region.name for exit in exits}
|
'structures': {exit: self.world.get_entrance(exit, self.player).connected_region.name for exit in exits}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def generate_basic(self):
|
def generate_basic(self):
|
||||||
link_minecraft_structures(self.world, self.player)
|
link_minecraft_structures(self.world, self.player)
|
||||||
|
|
||||||
|
@ -35,9 +38,9 @@ class MinecraftWorld(World):
|
||||||
pool_counts = item_frequencies.copy()
|
pool_counts = item_frequencies.copy()
|
||||||
if getattr(self.world, "bee_traps")[self.player]:
|
if getattr(self.world, "bee_traps")[self.player]:
|
||||||
pool_counts.update({"Rotten Flesh": 0, "Bee Trap (Minecraft)": 4})
|
pool_counts.update({"Rotten Flesh": 0, "Bee Trap (Minecraft)": 4})
|
||||||
for item_name, item_data in item_table.items():
|
for item_name in item_table:
|
||||||
for count in range(pool_counts.get(item_name, 1)):
|
for count in range(pool_counts.get(item_name, 1)):
|
||||||
pool.append(MinecraftItem(item_name, item_data.progression, item_data.code, self.player))
|
pool.append(self.create_item(item_name))
|
||||||
|
|
||||||
prefill_pool = {}
|
prefill_pool = {}
|
||||||
prefill_pool.update(events_table)
|
prefill_pool.update(events_table)
|
||||||
|
@ -49,7 +52,7 @@ class MinecraftWorld(World):
|
||||||
for loc_name, item_name in prefill_pool.items():
|
for loc_name, item_name in prefill_pool.items():
|
||||||
item_data = item_table[item_name]
|
item_data = item_table[item_name]
|
||||||
location = self.world.get_location(loc_name, self.player)
|
location = self.world.get_location(loc_name, self.player)
|
||||||
item = MinecraftItem(item_name, item_data.progression, item_data.code, self.player)
|
item = self.create_item(item_name)
|
||||||
self.world.push_item(location, item, collect=False)
|
self.world.push_item(location, item, collect=False)
|
||||||
pool.remove(item)
|
pool.remove(item)
|
||||||
location.event = item_data.progression
|
location.event = item_data.progression
|
||||||
|
@ -57,11 +60,9 @@ class MinecraftWorld(World):
|
||||||
|
|
||||||
self.world.itempool += pool
|
self.world.itempool += pool
|
||||||
|
|
||||||
|
|
||||||
def set_rules(self):
|
def set_rules(self):
|
||||||
set_rules(self.world, self.player)
|
set_rules(self.world, self.player)
|
||||||
|
|
||||||
|
|
||||||
def create_regions(self):
|
def create_regions(self):
|
||||||
def MCRegion(region_name: str, exits=[]):
|
def MCRegion(region_name: str, exits=[]):
|
||||||
ret = Region(region_name, None, region_name, self.player)
|
ret = Region(region_name, None, region_name, self.player)
|
||||||
|
@ -75,7 +76,6 @@ class MinecraftWorld(World):
|
||||||
|
|
||||||
self.world.regions += [MCRegion(*r) for r in mc_regions]
|
self.world.regions += [MCRegion(*r) for r in mc_regions]
|
||||||
|
|
||||||
|
|
||||||
def generate_output(self):
|
def generate_output(self):
|
||||||
import json
|
import json
|
||||||
from base64 import b64encode
|
from base64 import b64encode
|
||||||
|
@ -86,10 +86,13 @@ class MinecraftWorld(World):
|
||||||
with open(output_path(filename), 'wb') as f:
|
with open(output_path(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]
|
||||||
slot_data[option_name] = int(option.value)
|
slot_data[option_name] = int(option.value)
|
||||||
return slot_data
|
return slot_data
|
||||||
|
|
||||||
|
def create_item(self, name: str) -> Item:
|
||||||
|
item_data = item_table[name]
|
||||||
|
return MinecraftItem(name, item_data.progression, item_data.code, self.player)
|
Loading…
Reference in New Issue