mirror of
https://github.com/Steffo99/lihzahrd.git
synced 2024-11-25 01:24:21 +00:00
Added parsing for bestiary and journey mode powers.
Journey mode powers could use some convenience functions to map and from the values shown in the game.
This commit is contained in:
parent
dc091f37b8
commit
e4d06c2e55
9 changed files with 162 additions and 12 deletions
|
@ -1,5 +1,5 @@
|
||||||
import lihzahrd
|
import lihzahrd
|
||||||
|
|
||||||
world = lihzahrd.World.create_from_file("test-1404.wld")
|
world = lihzahrd.World.create_from_file("test-1404j.wld")
|
||||||
|
|
||||||
breakpoint()
|
breakpoint()
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
from .world import World
|
from .world import World
|
||||||
from . import chests, fileutils, header, npcs, pressureplates, signs, tileentities, tiles, townmanager
|
from . import bestiary, chests, fileutils, header, journeypowers, npcs, pressureplates, signs, tileentities, tiles, townmanager
|
||||||
|
|
||||||
__all__ = ["World", "chests", "fileutils", "header", "npcs", "pressureplates", "signs", "tileentities", "tiles",
|
__all__ = ["World", "bestiary", "chests", "fileutils", "header", "journeypowers", "npcs", "pressureplates", "signs", "tileentities", "tiles",
|
||||||
"townmanager"]
|
"townmanager"]
|
||||||
|
|
3
lihzahrd/bestiary/__init__.py
Executable file
3
lihzahrd/bestiary/__init__.py
Executable file
|
@ -0,0 +1,3 @@
|
||||||
|
from .bestiary import Bestiary
|
||||||
|
|
||||||
|
__all__ = ["Bestiary"]
|
23
lihzahrd/bestiary/bestiary.py
Executable file
23
lihzahrd/bestiary/bestiary.py
Executable file
|
@ -0,0 +1,23 @@
|
||||||
|
import typing
|
||||||
|
|
||||||
|
class Bestiary:
|
||||||
|
"""A bestiary entry."""
|
||||||
|
|
||||||
|
__slots__ = "npc_chats_count", "npc_chats_data", "npc_kill_count","npc_kill_data", "npc_sighting_count", "npc_sighting_data"
|
||||||
|
|
||||||
|
def __init__(self,
|
||||||
|
npc_chats_count: int,
|
||||||
|
npc_chats_data: typing.Dict[str, int],
|
||||||
|
npc_kill_count: int,
|
||||||
|
npc_kill_data: typing.List[str],
|
||||||
|
npc_sighting_count: int,
|
||||||
|
npc_sighting_data: typing.List[str],):
|
||||||
|
self.npc_chats_count: int = npc_chats_count
|
||||||
|
self.npc_chats_data: typing.Dict[str, int] = npc_chats_data
|
||||||
|
self.npc_kill_count: int = npc_kill_count
|
||||||
|
self.npc_kill_data: typing.List[str] = npc_kill_data
|
||||||
|
self.npc_sighting_count: int = npc_sighting_count
|
||||||
|
self.npc_sighting_data: typing.List[str] = npc_sighting_data
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"<Bestiary entry: chats={self.npc_chats_count}: {self.npc_chats_data}, kills={self.npc_kill_count}: {self.npc_kill_data}, sightings={self.npc_sighting_count}: {self.npc_sighting_data}>"
|
|
@ -11,6 +11,8 @@ class Pointers:
|
||||||
tile_entities: int,
|
tile_entities: int,
|
||||||
pressure_plates: int,
|
pressure_plates: int,
|
||||||
town_manager: int,
|
town_manager: int,
|
||||||
|
bestiary: int,
|
||||||
|
journey_powers: int,
|
||||||
footer: int,
|
footer: int,
|
||||||
*unknown):
|
*unknown):
|
||||||
self.file_format: int = 0
|
self.file_format: int = 0
|
||||||
|
@ -22,5 +24,7 @@ class Pointers:
|
||||||
self.tile_entities: int = tile_entities
|
self.tile_entities: int = tile_entities
|
||||||
self.pressure_plates: int = pressure_plates
|
self.pressure_plates: int = pressure_plates
|
||||||
self.town_manager: int = town_manager
|
self.town_manager: int = town_manager
|
||||||
|
self.bestiary: int = bestiary
|
||||||
|
self.journey_powers: int = journey_powers
|
||||||
self.footer: int = footer
|
self.footer: int = footer
|
||||||
self.unknown: typing.List[int] = list(unknown)
|
self.unknown: typing.List[int] = list(unknown)
|
||||||
|
|
3
lihzahrd/journeypowers/__init__.py
Executable file
3
lihzahrd/journeypowers/__init__.py
Executable file
|
@ -0,0 +1,3 @@
|
||||||
|
from .journeypowers import JourneyPowers
|
||||||
|
|
||||||
|
__all__ = ["JourneyPowers"]
|
45
lihzahrd/journeypowers/journeypowers.py
Executable file
45
lihzahrd/journeypowers/journeypowers.py
Executable file
|
@ -0,0 +1,45 @@
|
||||||
|
import typing
|
||||||
|
|
||||||
|
class JourneyPowers:
|
||||||
|
"""Journey mode powers settings. Spawn rate does not appear to be stored in the world."""
|
||||||
|
|
||||||
|
__slots__ = "freeze_time", "god_mode", "time_rate", "freeze_rain", "freeze_wind", "far_placement_range", "difficulty", "freeze_biome_spread", "spawn_rate"
|
||||||
|
|
||||||
|
def __init__(self,
|
||||||
|
freeze_time: typing.Optional[bool] = None,
|
||||||
|
god_mode: typing.Optional[bool] = None,
|
||||||
|
time_rate: typing.Optional[float] = None,
|
||||||
|
freeze_rain: typing.Optional[bool] = None,
|
||||||
|
freeze_wind: typing.Optional[bool] = None,
|
||||||
|
far_placement_range: typing.Optional[bool] = None,
|
||||||
|
difficulty: typing.Optional[float] = None,
|
||||||
|
freeze_biome_spread: typing.Optional[bool] = None,):
|
||||||
|
|
||||||
|
self.freeze_time: bool = freeze_time
|
||||||
|
"""Can time be frozen."""
|
||||||
|
|
||||||
|
self.god_mode: bool = god_mode
|
||||||
|
"""Can god mode be enabled."""
|
||||||
|
|
||||||
|
self.time_rate: float = time_rate
|
||||||
|
"""How fast does time go, 1x to 24x. Value ranges from 0.0 to 1.0."""
|
||||||
|
|
||||||
|
self.freeze_rain: bool = freeze_rain
|
||||||
|
"""Can the rain change."""
|
||||||
|
|
||||||
|
self.freeze_wind: bool = freeze_wind
|
||||||
|
"""Can the wind speed and direction change."""
|
||||||
|
|
||||||
|
self.far_placement_range: bool = far_placement_range
|
||||||
|
"""Can players place blocks further than normal."""
|
||||||
|
|
||||||
|
self.difficulty: float = difficulty
|
||||||
|
"""Enemy difficulty scaling, 0.5x to 3x. Value ranges from 0.0 to 1.0."""
|
||||||
|
|
||||||
|
self.freeze_biome_spread: bool = freeze_biome_spread
|
||||||
|
"""Can evil biomes & the hallow spread."""
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"<JourneyPowers: freeze_time={self.freeze_time}, god_mode={self.god_mode}, freeze_rain={self.freeze_rain}," \
|
||||||
|
f"freeze_wind={self.freeze_wind}, far_placement={self.far_placement_range}, biome_spread={self.freeze_biome_spread}," \
|
||||||
|
f"time_rate={self.time_rate}, difficulty={self.difficulty}>"
|
|
@ -6,13 +6,14 @@ from ..fileutils import Coordinates
|
||||||
class NPC:
|
class NPC:
|
||||||
"""A NPC somewhere in the world."""
|
"""A NPC somewhere in the world."""
|
||||||
|
|
||||||
__slots__ = "type", "name", "position", "home"
|
__slots__ = "type", "name", "position", "home", "variation_index"
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
type_: EntityType,
|
type_: EntityType,
|
||||||
name: str,
|
name: str,
|
||||||
position: Coordinates,
|
position: Coordinates,
|
||||||
home: typing.Optional[Coordinates] = None):
|
variation_index: int,
|
||||||
|
home: typing.Optional[Coordinates] = None,):
|
||||||
self.type: EntityType = type_
|
self.type: EntityType = type_
|
||||||
"""The NPC this object represents."""
|
"""The NPC this object represents."""
|
||||||
|
|
||||||
|
@ -25,5 +26,8 @@ class NPC:
|
||||||
self.home: typing.Optional[Coordinates] = home
|
self.home: typing.Optional[Coordinates] = home
|
||||||
"""The coordinates of the home of this NPC, or None if the NPC is homeless."""
|
"""The coordinates of the home of this NPC, or None if the NPC is homeless."""
|
||||||
|
|
||||||
|
self.variation_index: int = variation_index
|
||||||
|
"""Unsure, but seems to be an index to different possible NPC variations."""
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f"<NPC {repr(self.type)} at {self.position}>"
|
return f"<NPC {repr(self.type)} at {self.position}>"
|
||||||
|
|
|
@ -4,6 +4,8 @@ import typing
|
||||||
from .fileutils import *
|
from .fileutils import *
|
||||||
from .header import *
|
from .header import *
|
||||||
from .tiles import *
|
from .tiles import *
|
||||||
|
from .bestiary import *
|
||||||
|
from .journeypowers import *
|
||||||
from .chests import *
|
from .chests import *
|
||||||
from .signs import *
|
from .signs import *
|
||||||
from .npcs import *
|
from .npcs import *
|
||||||
|
@ -49,6 +51,8 @@ class World:
|
||||||
clouds: Clouds,
|
clouds: Clouds,
|
||||||
cultist_delay: int,
|
cultist_delay: int,
|
||||||
tiles: TileMatrix,
|
tiles: TileMatrix,
|
||||||
|
bestiary: Bestiary,
|
||||||
|
journey_powers: JourneyPowers,
|
||||||
chests: typing.List[Chest],
|
chests: typing.List[Chest],
|
||||||
signs: typing.List[Sign],
|
signs: typing.List[Sign],
|
||||||
npcs: typing.List[NPC],
|
npcs: typing.List[NPC],
|
||||||
|
@ -69,7 +73,9 @@ class World:
|
||||||
unknown_npcs_data: bytes = b"",
|
unknown_npcs_data: bytes = b"",
|
||||||
unknown_tile_entities_data: bytes = b"",
|
unknown_tile_entities_data: bytes = b"",
|
||||||
unknown_pressure_plates_data: bytes = b"",
|
unknown_pressure_plates_data: bytes = b"",
|
||||||
unknown_town_manager_data: bytes = b""):
|
unknown_town_manager_data: bytes = b"",
|
||||||
|
unknown_bestiary_data: bytes = b"",
|
||||||
|
unknown_journey_powers_data: bytes = b""):
|
||||||
|
|
||||||
self.version: Version = version
|
self.version: Version = version
|
||||||
"""The game version when this savefile was last saved."""
|
"""The game version when this savefile was last saved."""
|
||||||
|
@ -210,6 +216,12 @@ class World:
|
||||||
self.unknown_pressure_plates_data: bytes = unknown_pressure_plates_data
|
self.unknown_pressure_plates_data: bytes = unknown_pressure_plates_data
|
||||||
self.unknown_town_manager_data: bytes = unknown_town_manager_data
|
self.unknown_town_manager_data: bytes = unknown_town_manager_data
|
||||||
|
|
||||||
|
self.bestiary: Bestiary = bestiary
|
||||||
|
"""Information about the bestiary, including sightings, kills and takling to NPCs."""
|
||||||
|
|
||||||
|
self.journey_powers: JourneyPowers= journey_powers
|
||||||
|
"""Status of powers available in Journey mode."""
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f'<World "{self.name}">'
|
return f'<World "{self.name}">'
|
||||||
|
|
||||||
|
@ -676,10 +688,14 @@ class World:
|
||||||
if is_homeless:
|
if is_homeless:
|
||||||
npc_home = None
|
npc_home = None
|
||||||
|
|
||||||
|
npc_flags = f.bits()
|
||||||
|
npc_variation_index = 0 if npc_flags[0] else f.int4()
|
||||||
|
|
||||||
npc = NPC(type_=npc_type,
|
npc = NPC(type_=npc_type,
|
||||||
name=npc_name,
|
name=npc_name,
|
||||||
position=npc_position,
|
position=npc_position,
|
||||||
home=npc_home)
|
home=npc_home,
|
||||||
|
variation_index=npc_variation_index)
|
||||||
npcs.append(npc)
|
npcs.append(npc)
|
||||||
|
|
||||||
while f.bool():
|
while f.bool():
|
||||||
|
@ -735,7 +751,56 @@ class World:
|
||||||
room = Room(npc=EntityType(f.int4()), position=Coordinates(f.int4(), f.int4()))
|
room = Room(npc=EntityType(f.int4()), position=Coordinates(f.int4(), f.int4()))
|
||||||
rooms.append(room)
|
rooms.append(room)
|
||||||
|
|
||||||
unknown_town_manager_data = f.read_until(pointers.footer)
|
unknown_town_manager_data = f.read_until(pointers.bestiary)
|
||||||
|
|
||||||
|
bestiary_kill_count = f.int4()
|
||||||
|
bestiary_kill_data = {f.string(): f.int4() for _ in range(bestiary_kill_count)}
|
||||||
|
bestiary_sighting_count = f.int4()
|
||||||
|
bestiary_sighting_data = [f.string() for _ in range(bestiary_sighting_count)]
|
||||||
|
bestiary_chat_count = f.int4()
|
||||||
|
bestiary_chat_data = [f.string() for _ in range(bestiary_chat_count)]
|
||||||
|
bestiary = Bestiary(bestiary_chat_count,
|
||||||
|
bestiary_chat_data,
|
||||||
|
bestiary_kill_count,
|
||||||
|
bestiary_kill_data,
|
||||||
|
bestiary_sighting_count,
|
||||||
|
bestiary_sighting_data)
|
||||||
|
unknown_bestiary_data = f.read_until(pointers.journey_powers)
|
||||||
|
|
||||||
|
while f.bool():
|
||||||
|
journey_powers = JourneyPowers()
|
||||||
|
power_id = f.int2()
|
||||||
|
if power_id == 0:
|
||||||
|
freeze_time = f.bool()
|
||||||
|
journey_powers.freeze_time = freeze_time
|
||||||
|
elif power_id == 5:
|
||||||
|
god_mode = f.bool()
|
||||||
|
journey_powers.god_mode = god_mode
|
||||||
|
elif power_id == 8:
|
||||||
|
time_rate = f.single()
|
||||||
|
journey_powers.time_rate = time_rate
|
||||||
|
elif power_id == 9:
|
||||||
|
freeze_rain = f.bool()
|
||||||
|
journey_powers.freeze_rain = freeze_rain
|
||||||
|
elif power_id == 10:
|
||||||
|
freeze_wind = f.bool()
|
||||||
|
journey_powers.freeze_wind = freeze_wind
|
||||||
|
elif power_id == 11:
|
||||||
|
far_placement_range = f.bool()
|
||||||
|
journey_powers.far_placement_range = far_placement_range
|
||||||
|
elif power_id == 12:
|
||||||
|
difficulty = f.single()
|
||||||
|
journey_powers.difficulty = difficulty
|
||||||
|
elif power_id == 13:
|
||||||
|
freeze_biome_spread = f.bool()
|
||||||
|
journey_powers.freeze_biome_spread = freeze_biome_spread
|
||||||
|
elif power_id == -1:
|
||||||
|
spawn_rate: f.single()
|
||||||
|
journey_powers.spawn_rate = spawn_rate
|
||||||
|
else:
|
||||||
|
print(f"Unknown id: {power_id}")
|
||||||
|
|
||||||
|
unknown_journey_powers_data = f.read_until(pointers.footer)
|
||||||
|
|
||||||
# Object creation
|
# Object creation
|
||||||
world = cls(version=version, savefile_type=savefile_type, revision=revision, is_favorite=is_favorite,
|
world = cls(version=version, savefile_type=savefile_type, revision=revision, is_favorite=is_favorite,
|
||||||
|
@ -751,6 +816,7 @@ class World:
|
||||||
weighed_pressure_plates=weighed_pressure_plates, rooms=rooms,
|
weighed_pressure_plates=weighed_pressure_plates, rooms=rooms,
|
||||||
halloween_today=halloween_today, xmas_today=xmas_today,
|
halloween_today=halloween_today, xmas_today=xmas_today,
|
||||||
treetop_variants=treetop_variants, saved_ore_tiers=saved_ore_tiers, pets=pets,
|
treetop_variants=treetop_variants, saved_ore_tiers=saved_ore_tiers, pets=pets,
|
||||||
|
bestiary=bestiary, journey_powers=journey_powers,
|
||||||
unknown_file_format_data=unknown_file_format_data,
|
unknown_file_format_data=unknown_file_format_data,
|
||||||
unknown_world_header_data=unknown_world_header_data,
|
unknown_world_header_data=unknown_world_header_data,
|
||||||
unknown_world_tiles_data=unknown_world_tiles_data,
|
unknown_world_tiles_data=unknown_world_tiles_data,
|
||||||
|
@ -759,7 +825,9 @@ class World:
|
||||||
unknown_npcs_data=unknown_npcs_data,
|
unknown_npcs_data=unknown_npcs_data,
|
||||||
unknown_tile_entities_data=unknown_tile_entities_data,
|
unknown_tile_entities_data=unknown_tile_entities_data,
|
||||||
unknown_pressure_plates_data=unknown_pressure_plates_data,
|
unknown_pressure_plates_data=unknown_pressure_plates_data,
|
||||||
unknown_town_manager_data=unknown_town_manager_data)
|
unknown_town_manager_data=unknown_town_manager_data,
|
||||||
|
unknown_bestiary_data=unknown_bestiary_data,
|
||||||
|
unknown_journey_powers_data=unknown_journey_powers_data)
|
||||||
|
|
||||||
# Footer
|
# Footer
|
||||||
if not f.bool():
|
if not f.bool():
|
||||||
|
|
Loading…
Reference in a new issue