mirror of
https://github.com/Steffo99/lihzahrd.git
synced 2024-11-21 23:54:23 +00:00
First pass at 1.4.0.4 world header parsing.
This commit is contained in:
parent
4fbc952d4e
commit
304b279c6a
12 changed files with 213 additions and 39 deletions
|
@ -1,5 +1,5 @@
|
|||
import lihzahrd
|
||||
|
||||
world = lihzahrd.World.create_from_file("Casarao.wld")
|
||||
world = lihzahrd.World.create_from_file("test-1404.wld")
|
||||
|
||||
breakpoint()
|
||||
|
|
|
@ -10,18 +10,22 @@ from .generatorinfo import GeneratorInfo
|
|||
from .hardmodeore import HardmodeTier1Ore, HardmodeTier2Ore, HardmodeTier3Ore
|
||||
from .invasion import Invasion
|
||||
from .invasiontype import InvasionType
|
||||
from .lanternevent import LanternEvent
|
||||
from .lunarevents import LunarEvents
|
||||
from .moonphase import MoonPhase
|
||||
from .moonstyle import MoonStyle
|
||||
from .oldonesarmytiers import OldOnesArmyTiers
|
||||
from .party import Party
|
||||
from .pets import Pets
|
||||
from .pillarsinfo import PillarsInfo
|
||||
from .rain import Rain
|
||||
from .sandstorm import Sandstorm
|
||||
from .savednpcs import SavedNPCs
|
||||
from .savedoretiers import SavedOreTiers
|
||||
from .shadoworbs import ShadowOrbs
|
||||
from .styles import Styles
|
||||
from .time import Time
|
||||
from .treetopvariants import TreetopVariants
|
||||
from .version import Version
|
||||
from .worldeviltype import WorldEvilType
|
||||
|
||||
|
@ -40,18 +44,22 @@ __all__ = [
|
|||
"HardmodeTier3Ore",
|
||||
"Invasion",
|
||||
"InvasionType",
|
||||
"LanternEvent",
|
||||
"LunarEvents",
|
||||
"MoonPhase",
|
||||
"MoonStyle",
|
||||
"OldOnesArmyTiers",
|
||||
"Party",
|
||||
"Pets",
|
||||
"PillarsInfo",
|
||||
"Rain",
|
||||
"Sandstorm",
|
||||
"SavedNPCs",
|
||||
"SavedOreTiers",
|
||||
"ShadowOrbs",
|
||||
"Styles",
|
||||
"Time",
|
||||
"TreetopVariants",
|
||||
"Version",
|
||||
"WorldEvilType"
|
||||
]
|
||||
|
|
|
@ -11,7 +11,12 @@ class Backgrounds:
|
|||
bg_hallow: int,
|
||||
bg_crimson: int,
|
||||
bg_desert: int,
|
||||
bg_ocean: int):
|
||||
bg_ocean: int,
|
||||
new_bg_1: int,
|
||||
new_bg_2: int,
|
||||
new_bg_3: int,
|
||||
new_bg_4: int,
|
||||
new_bg_5: int,):
|
||||
self.bg_underground_snow: int = bg_underground_snow
|
||||
self.bg_underground_jungle: int = bg_underground_jungle
|
||||
self.bg_hell: int = bg_hell
|
||||
|
@ -23,8 +28,14 @@ class Backgrounds:
|
|||
self.bg_crimson: int = bg_crimson
|
||||
self.bg_desert: int = bg_desert
|
||||
self.bg_ocean: int = bg_ocean
|
||||
self.new_bg_1: int = new_bg_1
|
||||
self.new_bg_2: int = new_bg_2
|
||||
self.new_bg_3: int = new_bg_3
|
||||
self.new_bg_4: int = new_bg_4
|
||||
self.new_bg_5: int = new_bg_5
|
||||
|
||||
def __repr__(self):
|
||||
return f"WorldBackgrounds({self.bg_underground_snow}, {self.bg_underground_jungle}, {self.bg_hell}," \
|
||||
f" {self.bg_forest}, {self.bg_corruption}, {self.bg_jungle}, {self.bg_snow}, {self.bg_hallow}," \
|
||||
f" {self.bg_crimson}, {self.bg_desert}, {self.bg_ocean})"
|
||||
f" {self.bg_crimson}, {self.bg_desert}, {self.bg_ocean}," \
|
||||
f" {self.new_bg_1}, {self.new_bg_2}, {self.new_bg_3}, {self.new_bg_4}, {self.new_bg_5})"
|
||||
|
|
|
@ -29,7 +29,9 @@ class BossesDefeated:
|
|||
martian_madness: bool,
|
||||
lunatic_cultist: bool,
|
||||
lunar_pillars: PillarsInfo,
|
||||
old_ones_army: OldOnesArmyTiers):
|
||||
old_ones_army: OldOnesArmyTiers,
|
||||
empress_of_light: bool,
|
||||
queen_slime: bool):
|
||||
self.eye_of_cthulhu: bool = eye_of_cthulhu
|
||||
self.eater_of_worlds: bool = eater_of_worlds
|
||||
self.skeletron: bool = skeletron
|
||||
|
@ -59,6 +61,8 @@ class BossesDefeated:
|
|||
self.lunatic_cultist: bool = lunatic_cultist
|
||||
self.lunar_pillars: PillarsInfo = lunar_pillars
|
||||
self.old_ones_army: OldOnesArmyTiers = old_ones_army
|
||||
self.empress_of_light: bool = empress_of_light
|
||||
self.queen_slime: bool = queen_slime
|
||||
|
||||
def __repr__(self):
|
||||
return f"<BossesDefeated>"
|
||||
|
|
|
@ -3,7 +3,7 @@ from .rain import Rain
|
|||
from .party import Party
|
||||
from .sandstorm import Sandstorm
|
||||
from .lunarevents import LunarEvents
|
||||
|
||||
from .lanternevent import LanternEvent
|
||||
|
||||
class Events:
|
||||
"""Information about the ongoing world events."""
|
||||
|
@ -15,7 +15,8 @@ class Events:
|
|||
rain: Rain,
|
||||
party: Party,
|
||||
sandstorm: Sandstorm,
|
||||
lunar_events: LunarEvents):
|
||||
lunar_events: LunarEvents,
|
||||
lantern_night: LanternEvent):
|
||||
self.blood_moon: bool = blood_moon
|
||||
"""If the current moon is a Blood Moon."""
|
||||
|
||||
|
@ -40,5 +41,8 @@ class Events:
|
|||
self.lunar_events: LunarEvents = lunar_events
|
||||
"""Information about the currently ongoing Lunar Events."""
|
||||
|
||||
self.lantern_night: LanternEvent = lantern_night
|
||||
"""Information about the currently ongoing lantern night."""
|
||||
|
||||
def __repr__(self):
|
||||
return f"<WorldEvents>"
|
||||
|
|
29
lihzahrd/header/lanternevent.py
Executable file
29
lihzahrd/header/lanternevent.py
Executable file
|
@ -0,0 +1,29 @@
|
|||
import typing
|
||||
|
||||
|
||||
class LanternEvent:
|
||||
"""Lantern Night event related information."""
|
||||
def __init__(self,
|
||||
nights_on_cooldown: int,
|
||||
genuine: bool,
|
||||
manual: bool,
|
||||
next_night_is_lantern_night: bool):
|
||||
self.nights_on_cooldown: int = nights_on_cooldown
|
||||
"""How many nights before the next lantern night can happen."""
|
||||
|
||||
self.genuine: bool = genuine
|
||||
"""Was this night started by the game spontaneously?"""
|
||||
|
||||
self.manual: bool = manual
|
||||
"""Was this night started by the player?"""
|
||||
|
||||
self.next_night_is_lantern_night:bool = next_night_is_lantern_night
|
||||
"""Is the next night a lantern night?"""
|
||||
|
||||
def __repr__(self):
|
||||
return f"WorldLanternNight(nights_on_cooldown={self.nights_on_cooldown}," \
|
||||
f" genuine={self.genuine}, manual={self.manual}, nights_on_cooldown={self.nights_on_cooldown})"
|
||||
|
||||
@property
|
||||
def is_active(self):
|
||||
return self.genuine or self.manual # ToDo: Test this!
|
|
@ -6,6 +6,13 @@ class MoonStyle(enum.IntEnum):
|
|||
WHITE = 0
|
||||
ORANGE = 1
|
||||
RINGED_GREEN = 2
|
||||
BLUE = 3
|
||||
ICE = 4
|
||||
GREEN = 5
|
||||
PINK = 6
|
||||
PINK_ORANGE = 7
|
||||
TRIPLE_PURPLE = 8
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
return f"{self.__class__.__name__}.{self.name}"
|
||||
|
|
19
lihzahrd/header/pets.py
Executable file
19
lihzahrd/header/pets.py
Executable file
|
@ -0,0 +1,19 @@
|
|||
import typing
|
||||
|
||||
class Pets:
|
||||
"""Pet related information"""
|
||||
def __init__(self,
|
||||
cat: bool,
|
||||
dog: bool,
|
||||
bunny: bool):
|
||||
self.cat: bool = cat
|
||||
"""Has the cat been bought."""
|
||||
|
||||
self.dog: int = dog
|
||||
"""Has the cat been bought."""
|
||||
|
||||
self.bunny: float = bunny
|
||||
"""Has the bunny been bought."""
|
||||
|
||||
def __repr__(self):
|
||||
return f"WorldPets(cat={self.cat}, dog={self.dog}, bunny={self.bunny})"
|
|
@ -6,7 +6,9 @@ class SavedNPCs:
|
|||
angler: bool,
|
||||
stylist: bool,
|
||||
tax_collector: bool,
|
||||
bartender: bool):
|
||||
bartender: bool,
|
||||
golfer: bool,
|
||||
advanced_combat: bool):
|
||||
self.goblin_tinkerer: bool = goblin_tinkerer
|
||||
self.wizard: bool = wizard
|
||||
self.mechanic: bool = mechanic
|
||||
|
@ -14,8 +16,11 @@ class SavedNPCs:
|
|||
self.stylist: bool = stylist
|
||||
self.tax_collector: bool = tax_collector
|
||||
self.bartender: bool = bartender
|
||||
self.golfer: bool = golfer
|
||||
self.advanced_combat: bool = advanced_combat
|
||||
"""Was the Advanced Combat Technique Book used."""
|
||||
|
||||
def __repr__(self):
|
||||
return f"SavedNPCs(goblin_tinkerer={self.goblin_tinkerer}, wizard={self.wizard}, mechanic={self.mechanic}," \
|
||||
f" angler={self.angler}, stylist={self.stylist}, tax_collector={self.tax_collector}," \
|
||||
f" bartender={self.bartender})"
|
||||
f" bartender={self.bartender}, golfer={self.golfer}, advanced_combat={self.advanced_combat}"
|
||||
|
|
17
lihzahrd/header/savedoretiers.py
Executable file
17
lihzahrd/header/savedoretiers.py
Executable file
|
@ -0,0 +1,17 @@
|
|||
import typing
|
||||
|
||||
class SavedOreTiers:
|
||||
"""Information about the treetop variants in the worls"""
|
||||
def __init__(self,
|
||||
saved_ore_tier_copper: int,
|
||||
saved_ore_tier_iron: int,
|
||||
saved_ore_tier_silver: int,
|
||||
saved_ore_tier_gold: int,
|
||||
):
|
||||
self.copper: int = saved_ore_tier_copper
|
||||
self.iron: int = saved_ore_tier_iron
|
||||
self.silver: int = saved_ore_tier_copper
|
||||
self.gold: int = saved_ore_tier_gold
|
||||
|
||||
def __repr__(self):
|
||||
return f"WorldSavedOreTier(copper={self.copper}, iron={self.iron}, silver={self.silver}, gold={self.gold})"
|
10
lihzahrd/header/treetopvariants.py
Executable file
10
lihzahrd/header/treetopvariants.py
Executable file
|
@ -0,0 +1,10 @@
|
|||
import typing
|
||||
|
||||
class TreetopVariants:
|
||||
"""Information about the treetop variants in the worls"""
|
||||
def __init__(self,
|
||||
treetop_variants: typing.List[str]):
|
||||
self.treetop_variants: typing.List[str] = treetop_variants
|
||||
|
||||
def __repr__(self):
|
||||
return f"WorldTreetopVariants({self.treetop_variants})"
|
|
@ -27,7 +27,9 @@ class World:
|
|||
id_: int,
|
||||
bounds: Rect,
|
||||
size: Coordinates,
|
||||
is_expert: bool,
|
||||
game_mode: int,
|
||||
drunk_world: bool,
|
||||
get_good_world: bool,
|
||||
created_on,
|
||||
styles: Styles,
|
||||
backgrounds: Backgrounds,
|
||||
|
@ -54,6 +56,9 @@ class World:
|
|||
tile_entities: typing.List[TileEntity],
|
||||
weighed_pressure_plates: typing.List[WeighedPressurePlate],
|
||||
rooms: typing.List[Room],
|
||||
pets: Pets,
|
||||
treetop_variants: TreetopVariants,
|
||||
saved_ore_tiers: SavedNPCs,
|
||||
unknown_file_format_data: bytes = b"",
|
||||
unknown_world_header_data: bytes = b"",
|
||||
unknown_world_tiles_data: bytes = b"",
|
||||
|
@ -94,8 +99,17 @@ class World:
|
|||
self.size: Coordinates = size
|
||||
"""The world size in tiles."""
|
||||
|
||||
self.is_expert: bool = is_expert
|
||||
"""If the world is in expert mode or not."""
|
||||
self.game_mode: int = game_mode
|
||||
"""Which mode the game is in. 0=classic, 1=expert, 2=master, 3=journey"""
|
||||
|
||||
self.is_expert: bool = True if self.game_mode==1 else False
|
||||
"""If the world is in expert mode or not, no longer stored in worldfile."""
|
||||
|
||||
self.drunk_world: bool = drunk_world
|
||||
"""Was this world created with the drunk worldgen seed."""
|
||||
|
||||
self.get_good_world: bool = get_good_world
|
||||
"""Was this world created with the get good worldgen seed."""
|
||||
|
||||
self.created_on = created_on
|
||||
"""The date and time this world was created in."""
|
||||
|
@ -166,6 +180,15 @@ class World:
|
|||
self.weighed_pressure_plates: typing.List[WeighedPressurePlate] = weighed_pressure_plates
|
||||
"""A list of all Weighed Pressure Plates in the world."""
|
||||
|
||||
self.pets: Pets = pets
|
||||
"""Which pets have bene purchased."""
|
||||
|
||||
self.treetop_variants: TreetopVariants = treetop_variants
|
||||
"""Treetops variants that can exist in the world."""
|
||||
|
||||
self.saved_ore_tiers: SavedOreTiers = saved_ore_tiers
|
||||
"""Probably related to drunk wordgen having both types of ores."""
|
||||
|
||||
self.rooms: typing.List[Room] = rooms
|
||||
self.clouds: Clouds = clouds
|
||||
self.cultist_delay: int = cultist_delay
|
||||
|
@ -292,8 +315,8 @@ class World:
|
|||
version = Version(f.int4())
|
||||
relogic = f.string(7)
|
||||
savefile_type = f.uint1()
|
||||
if version != Version("1.3.5.3") or relogic != "relogic" or savefile_type != 2:
|
||||
raise NotImplementedError("This parser can only read Terraria 1.3.5.3 save files.")
|
||||
if version != Version("1.4.0.4") or relogic != "relogic" or savefile_type != 2:
|
||||
raise NotImplementedError("This parser can only read Terraria 1.4.0.4 save files.")
|
||||
|
||||
revision = f.uint4()
|
||||
is_favorite = f.uint8() != 0
|
||||
|
@ -309,14 +332,15 @@ class World:
|
|||
unknown_file_format_data = f.read_until(pointers.world_header)
|
||||
|
||||
name = f.string()
|
||||
|
||||
generator = GeneratorInfo(f.string(), f.uint8())
|
||||
|
||||
uuid_ = f.uuid()
|
||||
id_ = f.int4()
|
||||
bounds = f.rect()
|
||||
world_size = Coordinates(y=f.int4(), x=f.int4())
|
||||
is_expert = f.bool()
|
||||
game_mode = f.int4()
|
||||
drunk_world = f.bool()
|
||||
get_good_world = f.bool()
|
||||
created_on = f.datetime()
|
||||
|
||||
world_styles = Styles(moon=MoonStyle(f.uint1()),
|
||||
|
@ -415,18 +439,6 @@ class World:
|
|||
bg_desert = f.int1()
|
||||
bg_ocean = f.int1()
|
||||
|
||||
backgrounds = Backgrounds(bg_underground_snow=bg_underground_snow,
|
||||
bg_underground_jungle=bg_underground_jungle,
|
||||
bg_hell=bg_hell,
|
||||
bg_forest=bg_forest,
|
||||
bg_corruption=bg_corruption,
|
||||
bg_jungle=bg_jungle,
|
||||
bg_snow=bg_snow,
|
||||
bg_hallow=bg_hallow,
|
||||
bg_crimson=bg_crimson,
|
||||
bg_desert=bg_desert,
|
||||
bg_ocean=bg_ocean)
|
||||
|
||||
clouds = Clouds(bg_cloud=f.int4(), cloud_number=f.int2(), wind_speed=f.single())
|
||||
|
||||
angler_today_quest_completed_by_count = f.uint1()
|
||||
|
@ -442,6 +454,7 @@ class World:
|
|||
|
||||
saved_stylist = f.bool()
|
||||
saved_tax_collector = f.bool()
|
||||
saved_golfer = f.bool()
|
||||
|
||||
invasion_size_start = f.int4() # ???
|
||||
invasion = Invasion(delay=invasion_delay,
|
||||
|
@ -497,6 +510,49 @@ class World:
|
|||
severity=f.single(),
|
||||
intended_severity=f.single())
|
||||
|
||||
saved_bartender = f.bool()
|
||||
|
||||
old_ones_army = OldOnesArmyTiers(f.bool(), f.bool(), f.bool())
|
||||
|
||||
# ToDo: Figure out which biomes got new BGs.
|
||||
# Oasis and Graveyard probably got new backgrounds.
|
||||
new_bg_1 = f.int1()
|
||||
new_bg_2 = f.int1()
|
||||
new_bg_3 = f.int1() # Maybe oasis.
|
||||
new_bg_4 = f.int1()
|
||||
new_bg_5 = f.int1()
|
||||
|
||||
backgrounds = Backgrounds(bg_underground_snow=bg_underground_snow,
|
||||
bg_underground_jungle=bg_underground_jungle,
|
||||
bg_hell=bg_hell,
|
||||
bg_forest=bg_forest,
|
||||
bg_corruption=bg_corruption,
|
||||
bg_jungle=bg_jungle,
|
||||
bg_snow=bg_snow,
|
||||
bg_hallow=bg_hallow,
|
||||
bg_crimson=bg_crimson,
|
||||
bg_desert=bg_desert,
|
||||
bg_ocean=bg_ocean,
|
||||
new_bg_1=new_bg_1,
|
||||
new_bg_2=new_bg_2,
|
||||
new_bg_3=new_bg_3,
|
||||
new_bg_4=new_bg_4,
|
||||
new_bg_5=new_bg_5,)
|
||||
|
||||
combat_book_used = f.bool()
|
||||
|
||||
saved_npcs = SavedNPCs(goblin_tinkerer=saved_goblin_tinkerer,
|
||||
wizard=saved_wizard,
|
||||
mechanic=saved_mechanic,
|
||||
angler=saved_angler,
|
||||
stylist=saved_stylist,
|
||||
tax_collector=saved_tax_collector,
|
||||
bartender=saved_bartender,
|
||||
golfer=saved_golfer,
|
||||
advanced_combat=combat_book_used)
|
||||
|
||||
lantern_night = LanternEvent(f.int4(), f.bool(), f.bool(), f.bool())
|
||||
|
||||
events = Events(blood_moon=blood_moon,
|
||||
solar_eclipse=eclipse,
|
||||
invasion=invasion,
|
||||
|
@ -504,18 +560,18 @@ class World:
|
|||
rain=rain,
|
||||
party=party,
|
||||
sandstorm=sandstorm,
|
||||
lunar_events=lunar_events)
|
||||
lunar_events=lunar_events,
|
||||
lantern_night=lantern_night)
|
||||
|
||||
saved_bartender = f.bool()
|
||||
saved_npcs = SavedNPCs(goblin_tinkerer=saved_goblin_tinkerer,
|
||||
wizard=saved_wizard,
|
||||
mechanic=saved_mechanic,
|
||||
angler=saved_angler,
|
||||
stylist=saved_stylist,
|
||||
tax_collector=saved_tax_collector,
|
||||
bartender=saved_bartender)
|
||||
treetop_variant_count = f.int4()
|
||||
treetop_variants = TreetopVariants([f.int4() for _ in range(treetop_variant_count)])
|
||||
|
||||
old_ones_army = OldOnesArmyTiers(f.bool(), f.bool(), f.bool())
|
||||
saved_ore_tiers = SavedOreTiers(f.int4(), f.int4(), f.int4(), f.int4())
|
||||
|
||||
pets = Pets(f.bool(), f.bool(), f.bool())
|
||||
|
||||
defeated_empress_of_light = f.bool()
|
||||
defeated_queen_slime = f.bool()
|
||||
|
||||
bosses_defeated = BossesDefeated(eye_of_cthulhu=defeated_eye_of_cthulhu,
|
||||
eater_of_worlds=defeated_eater_of_worlds,
|
||||
|
@ -542,7 +598,9 @@ class World:
|
|||
lunar_pillars=defeated_pillars,
|
||||
old_ones_army=old_ones_army,
|
||||
martian_madness=defeated_martian_madness,
|
||||
lunatic_cultist=defeated_lunatic_cultist)
|
||||
lunatic_cultist=defeated_lunatic_cultist,
|
||||
empress_of_light=defeated_empress_of_light,
|
||||
queen_slime=defeated_queen_slime)
|
||||
|
||||
unknown_world_header_data = f.read_until(pointers.world_tiles)
|
||||
|
||||
|
@ -671,7 +729,8 @@ class World:
|
|||
# Object creation
|
||||
world = cls(version=version, savefile_type=savefile_type, revision=revision, is_favorite=is_favorite,
|
||||
name=name, generator=generator, uuid_=uuid_, id_=id_, bounds=bounds, size=world_size,
|
||||
is_expert=is_expert, created_on=created_on, styles=world_styles, backgrounds=backgrounds,
|
||||
game_mode=game_mode, drunk_world=drunk_world, get_good_world=get_good_world,
|
||||
created_on=created_on, styles=world_styles, backgrounds=backgrounds,
|
||||
spawn_point=spawn_point, underground_level=underground_level, cavern_level=cavern_level,
|
||||
time=time, events=events, dungeon_point=dungeon_point, world_evil=world_evil,
|
||||
saved_npcs=saved_npcs, altars_smashed=altars_smashed, is_hardmode=is_hardmode,
|
||||
|
@ -679,6 +738,7 @@ class World:
|
|||
clouds=clouds, cultist_delay=cultist_delay, tiles=tm, chests=chests, signs=signs,
|
||||
npcs=npcs, mobs=mobs, tile_entities=tile_entities,
|
||||
weighed_pressure_plates=weighed_pressure_plates, rooms=rooms,
|
||||
treetop_variants=treetop_variants, saved_ore_tiers=saved_ore_tiers, pets=pets,
|
||||
unknown_file_format_data=unknown_file_format_data,
|
||||
unknown_world_header_data=unknown_world_header_data,
|
||||
unknown_world_tiles_data=unknown_world_tiles_data,
|
||||
|
|
Loading…
Reference in a new issue