Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ Original (Forge) Implementation by KonoTyran.

## Configuring your YAML file

### Unlockable Hearts

This fork adds an `unlockable_hearts` option to the Minecraft APWorld. When enabled, players start with one heart, and nine progression `Heart` items are added to the item pool. Each received `Heart` restores one additional max heart up to the vanilla ten hearts.

Use the packaged `minecraft.apworld` from this repository together with the matching NeoForgeAP mod jar built from this branch.

### What is a YAML file and why do I need one?

See the guide on setting up a basic YAML at the Archipelago setup
Expand Down
20 changes: 20 additions & 0 deletions apworld_src/minecraft/Constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import json
import pkgutil


def load_data_file(*args) -> dict:
fname = "/".join(["data", *args])
return json.loads(pkgutil.get_data(__name__, fname).decode())


item_info = load_data_file("items.json")
item_name_to_id = {name: index \
for index, name in enumerate(item_info["all_items"], start=1)}

location_info = load_data_file("locations.json")
location_name_to_id = {name: index \
for index, name in enumerate(location_info["all_locations"], start=1)}

exclusion_info = load_data_file("excluded_locations.json")

region_info = load_data_file("regions.json")
31 changes: 31 additions & 0 deletions apworld_src/minecraft/Container.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import json
import zipfile
from base64 import b64encode
from typing import Any, Optional

from worlds.Files import APPlayerContainer


class MinecraftContainer(APPlayerContainer):
"""
Generates the apmc file
"""
game = "Minecraft"
patch_file_ending = ".apmc"

def __init__(self,
patch_data: dict[str, Any],
patch_name: str,
path: Optional[str] = None,
player: Optional[int] = None,
player_name: str = "",
server: str = ""):
super().__init__(path, player, player_name, server)
self.patch_data = patch_data
self.patch_name = patch_name

def write_contents(self, opened_zipfile: zipfile.ZipFile) -> None:
super().write_contents(opened_zipfile)
filename = f"{self.patch_name}_json.apmcmeta"
opened_zipfile.writestr(filename,json.dumps(self.patch_data))

59 changes: 59 additions & 0 deletions apworld_src/minecraft/ItemPool.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
from math import ceil
from typing import List

from BaseClasses import Item

from . import Constants
from typing import TYPE_CHECKING

if TYPE_CHECKING:
from . import MinecraftWorld


def get_junk_item_names(rand, k: int) -> str:
junk_weights = Constants.item_info["junk_weights"]
junk = rand.choices(
list(junk_weights.keys()),
weights=list(junk_weights.values()),
k=k)
return junk

def build_item_pool(world: "MinecraftWorld") -> List[Item]:
multiworld = world.multiworld
player = world.player

itempool = []
total_location_count = len(multiworld.get_unfilled_locations(player))

required_pool = Constants.item_info["required_pool"]

# Add required progression items
for item_name, num in required_pool.items():
itempool += [world.create_item(item_name) for _ in range(num)]

# Add structure compasses
if world.options.structure_compasses:
compasses = [name for name in world.item_name_to_id if "Structure Compass" in name]
for item_name in compasses:
itempool.append(world.create_item(item_name))

# Dragon egg shards
if world.options.egg_shards_required > 0:
num = world.options.egg_shards_available
itempool += [world.create_item("Dragon Egg Shard") for _ in range(num)]

# Unlockable hearts
if world.options.unlockable_hearts:
itempool += [world.create_item(f"Heart {heart}") for heart in range(1, 10)]

# Bee traps
bee_trap_percentage = world.options.bee_traps * 0.01
if bee_trap_percentage > 0:
bee_trap_qty = ceil(bee_trap_percentage * (total_location_count - len(itempool)))
itempool += [world.create_item("Bee Trap") for _ in range(bee_trap_qty)]

# Fill remaining itempool with randomly generated junk
junk = get_junk_item_names(world.random, total_location_count - len(itempool))
itempool += [world.create_item(name) for name in junk]

return itempool
Loading