1
Fork 0
mirror of https://github.com/Steffo99/lihzahrd.git synced 2024-11-21 23:54:23 +00:00

Process unknown data

This commit is contained in:
Steffo 2023-03-06 02:21:06 +01:00
parent 66d0e221e1
commit d451fd3731
4 changed files with 231 additions and 16 deletions

View file

@ -22,6 +22,12 @@ It _will_ take a while to process: a small Terraria world contains more than 5 m
Once you have a `World` object, you can use all data present in the save file by accessing [its attributes](http://gh.steffo.eu/lihzahrd/html/world.html). Once you have a `World` object, you can use all data present in the save file by accessing [its attributes](http://gh.steffo.eu/lihzahrd/html/world.html).
> **Warning**
>
> Maliciously designed Terraria worlds can drain system resources, crash the interpreter, or possibly do more evil things!
>
> **Make sure you trust the worlds you are parsing!**
## Documentation ## Documentation
The documentation is available [here](https://gh.steffo.eu/lihzahrd/html/). The documentation is available [here](https://gh.steffo.eu/lihzahrd/html/).

View file

@ -5143,6 +5143,181 @@ class ItemType(enum.IntEnum):
PRINCESS_64 = 5085 PRINCESS_64 = 5085
PAINTING_OF_A_LASS = 5086 PAINTING_OF_A_LASS = 5086
DARK_SIDE_OF_THE_HOLLOW = 5087 DARK_SIDE_OF_THE_HOLLOW = 5087
BERNIES_BUTTON = 5088
GLOMMERS_FLOWER = 5089
DEERCLOPS_EYEBALL = 5090
MONSTER_MEAT = 5091
MONSTER_LASAGNA = 5092
FROGGLE_BUNWICH = 5093
TENTACLE_SPIKE = 5094
LUCY_THE_AXE = 5095
HAM_BAT = 5096
BAT_BAT = 5097
EYE_BONE = 5098
GARLAND = 5099
BONE_HELM = 5100
EYEBRELLA = 5101
GENTLEMANS_VEST = 5102
GENTLEMANS_TROUSERS = 5103
GENTLEMANS_BEARD = 5104
GENTLEMANS_LONG_BEARD = 5105
GENTLEMANS_MAGNIFICENT_BEARD = 5106
MAGILUMINESCENCE = 5107
DEERCLOPS_TROPHY = 5108
DEERCLOPS_MASK = 5109
DEERCLOPS_RELIC = 5110
TREASURE_BAG_DEERCLOPS = 5111
MUSIC_BOX_DEERCLOPS = 5112
RADIO_THING = 5113
ABIGAILS_FLOWER = 5114
FIRESTARTERS_SWEATER = 5115
FIRESTARTERS_SKIRT = 5116
PEW_MATIC_HORN = 5117
WEATHER_PAIN = 5118
HOUNDIUS_SHOOTIUS = 5119
DEER_THING = 5120
THE_GENTLEMAN_SCIENTIST = 5121
THE_FIRESTARTER = 5122
THE_BEREAVED = 5123
THE_STRONGMAN = 5124
FART_MINECART = 5125
HAND_OF_CREATION = 5126
VIOLET_MOSS = 5127
RAINBOW_MOSS = 5128
FLYMEAL = 5129
WOLF_MOUNT_ITEM = 5130
RESPLENDENT_DESSERT = 5131
STINKBUG = 5132
STINKBUG_CAGE = 5133
CLENTAMINATOR_2 = 5134
VENOM_DART_TRAP = 5135
VULKELF_EAR = 5136
STINKBUG_HOUSING_BLOCKER = 5137
STINKBUG_HOUSING_BLOCKER_ECHO = 5138
FISHING_BOBBER = 5139
FISHING_BOBBER_GLOWING_STAR = 5140
FISHING_BOBBER_GLOWING_LAVA = 5141
FISHING_BOBBER_GLOWING_KRYPTON = 5142
FISHING_BOBBER_GLOWING_XENON = 5143
FISHING_BOBBER_GLOWING_ARGON = 5144
FISHING_BOBBER_GLOWING_VIOLET = 5145
FISHING_BOBBER_GLOWING_RAINBOW = 5146
WANDOF_FROSTING = 5147
CORAL_BATHTUB = 5148
CORAL_BED = 5149
CORAL_BOOKCASE = 5150
CORAL_DRESSER = 5151
CORAL_CANDELABRA = 5152
CORAL_CANDLE = 5153
CORAL_CHAIR = 5154
CORAL_CHANDELIER = 5155
CORAL_CHEST = 5156
CORAL_CLOCK = 5157
CORAL_DOOR = 5158
CORAL_LAMP = 5159
CORAL_LANTERN = 5160
CORAL_PIANO = 5161
CORAL_PLATFORM = 5162
CORAL_SINK = 5163
CORAL_SOFA = 5164
CORAL_TABLE = 5165
CORAL_WORKBENCH = 5166
FAKE_CORAL_CHEST = 5167
CORAL_TOILET = 5168
BALLOON_BATHTUB = 5169
BALLOON_BED = 5170
BALLOON_BOOKCASE = 5171
BALLOON_DRESSER = 5172
BALLOON_CANDELABRA = 5173
BALLOON_CANDLE = 5174
BALLOON_CHAIR = 5175
BALLOON_CHANDELIER = 5176
BALLOON_CHEST = 5177
BALLOON_CLOCK = 5178
BALLOON_DOOR = 5179
BALLOON_LAMP = 5180
BALLOON_LANTERN = 5181
BALLOON_PIANO = 5182
BALLOON_PLATFORM = 5183
BALLOON_SINK = 5184
BALLOON_SOFA = 5185
BALLOON_TABLE = 5186
BALLOON_WORKBENCH = 5187
FAKE_BALLOON_CHEST = 5188
BALLOON_TOILET = 5189
ASH_WOOD_BATHTUB = 5190
ASH_WOOD_BED = 5191
ASH_WOOD_BOOKCASE = 5192
ASH_WOOD_DRESSER = 5193
ASH_WOOD_CANDELABRA = 5194
ASH_WOOD_CANDLE = 5195
ASH_WOOD_CHAIR = 5196
ASH_WOOD_CHANDELIER = 5197
ASH_WOOD_CHEST = 5198
ASH_WOOD_CLOCK = 5199
ASH_WOOD_DOOR = 5200
ASH_WOOD_LAMP = 5201
ASH_WOOD_LANTERN = 5202
ASH_WOOD_PIANO = 5203
ASH_WOOD_PLATFORM = 5204
ASH_WOOD_SINK = 5205
ASH_WOOD_SOFA = 5206
ASH_WOOD_TABLE = 5207
ASH_WOOD_WORKBENCH = 5208
FAKE_ASH_WOOD_CHEST = 5209
ASH_WOOD_TOILET = 5210
BIOME_SIGHT_POTION = 5211
SCARLET_MACAW = 5212
SCARLET_MACAW_CAGE = 5213
ASH_GRASS_SEEDS = 5214
ASH_WOOD = 5215
ASH_WOOD_WALL = 5216
ASH_WOOD_FENCE = 5217
OUTCAST = 5218
FAIRY_GUIDES = 5219
AHORRIBLE_NIGHTFOR_ALCHEMY = 5220
MORNING_HUNT = 5221
SUSPICIOUSLY_SPARKLY = 5222
REQUIEM = 5223
CAT_SWORD = 5224
KARGOHS_SUMMON = 5225
HIGH_PITCH = 5226
AMACHINEFOR_TERRARIANS = 5227
TERRA_BLADE_CHRONICLES = 5228
BENNY_WARHOL = 5229
LIZARD_KING = 5230
MY_SON = 5231
DUALITY = 5232
PARSEC_PALS = 5233
REMNANTSOF_DEVOTION = 5234
NOT_SO_LOST_IN_PARADISE = 5235
OCULAR_RESONANCE = 5236
WINGSOF_EVIL = 5237
CONSTELLATION = 5238
EYEZORHEAD = 5239
DREADOFTHE_RED_SEA = 5240
DO_NOT_EATTHE_VILE_MUSHROOM = 5241
YUUMA_THE_BLUE_TIGER = 5242
MOONMANAND_COMPANY = 5243
SUNSHINEOF_ISRAPONY = 5244
PURITY = 5245
SUFFICIENTLY_ADVANCED = 5246
STRANGE_GROWTH = 5247
HAPPY_LITTLE_TREE = 5248
STRANGE_DEAD_FELLOWS = 5249
SECRETS = 5250
THUNDERBOLT = 5251
CRUSTOGRAPHY = 5252
THE_WEREWOLF = 5253
BLESSINGFROM_THE_HEAVENS = 5254
LOVEISINTHE_TRASH_SLOT = 5255
FANGS = 5256
HAILTOTHE_KING = 5257
SEE_THE_WORLD_FOR_WHAT_IT_IS = 5258
WHAT_LURKS_BELOW = 5259
THIS_IS_GETTING_OUT_OF_HAND = 5260
BUDDIES = 5261
MIDNIGHT_SUN = 5262
COUCH_GAG = 5263 COUCH_GAG = 5263
SILENT_FISH = 5264 SILENT_FISH = 5264
THE_DUKE = 5265 THE_DUKE = 5265

View file

@ -2,7 +2,7 @@ class Time:
"""Game time related information.""" """Game time related information."""
def __init__( def __init__(
self, current: float, is_daytime: bool, moon_phase: int, sundial_cooldown: int, fast_forward_time: bool self, current: float, is_daytime: bool, moon_phase: int, sundial_cooldown: int, sundial_is_running: bool, moondial_cooldown: int, moondial_is_running: bool
): ):
self.current: float = current self.current: float = current
"""The current game time.""" """The current game time."""
@ -16,10 +16,17 @@ class Time:
self.sundial_cooldown: int = sundial_cooldown self.sundial_cooldown: int = sundial_cooldown
"""The number of days the Enchanted Sundial can't be used for.""" """The number of days the Enchanted Sundial can't be used for."""
self.fast_forward_time: bool = fast_forward_time self.sundial_is_running: bool = sundial_is_running
"""Whether the Enchanted Sundial is currently fast-forwarding time."""
self.moondial_cooldown: int = sundial_cooldown
"""The number of days the Enchanted Moondial can't be used for."""
self.moondial_is_running: bool = sundial_is_running
"""Whether the Enchanted Moondial is currently fast-forwarding time."""
def __repr__(self): def __repr__(self):
return ( return (
f"WorldTime(current={self.current}, is_daytime={self.is_daytime}, moon_phase={self.moon_phase}," f"WorldTime(current={self.current}, is_daytime={self.is_daytime}, moon_phase={self.moon_phase},"
f" sundial_cooldown={self.sundial_cooldown}, fast_forward_time={self.fast_forward_time})" f" sundial_cooldown={self.sundial_cooldown}, fast_forward_time={self.sundial_is_running})"
) )

View file

@ -1,5 +1,6 @@
import uuid import uuid
import math import math
import sys
from typing import * from typing import *
from .fileutils import * from .fileutils import *
from .enums import * from .enums import *
@ -64,6 +65,7 @@ class World:
journey_powers: JourneyPowers, journey_powers: JourneyPowers,
chests: List[Chest], chests: List[Chest],
signs: List[Sign], signs: List[Sign],
shimmered_npcs: List[int],
npcs: List[NPC], npcs: List[NPC],
mobs: List[Mob], mobs: List[Mob],
tile_entities: List[TileEntity], tile_entities: List[TileEntity],
@ -201,6 +203,9 @@ class World:
self.signs: List[Sign] = signs self.signs: List[Sign] = signs
"""A list of all non-empty signs in the world.""" """A list of all non-empty signs in the world."""
self.shimmered_npcs: List[int] = shimmered_npcs
"""A list of the ids of the NPCs that have been shimmered."""
self.npcs: List[NPC] = npcs self.npcs: List[NPC] = npcs
"""A list of all the NPCs currently living in the world, including the Old Man.""" """A list of all the NPCs currently living in the world, including the Old Man."""
@ -410,11 +415,18 @@ class World:
# File header # File header
version = Version(f.int4()) version = Version(f.int4())
relogic = f.string(7) # TODO: this can appearently be "xindong"? relogic = f.string(7) # TODO: this can appearently be "xindong"?
if relogic != "relogic":
raise ValueError("World file is missing the 'relogic' magic string", relogic)
savefile_type = f.uint1() savefile_type = f.uint1()
supported_versions = (Version("1.4.4.9"), Version("1.4.4.9")) if savefile_type != 2:
if version not in supported_versions or relogic != "relogic" or savefile_type != 2: raise NotImplementedError("World file uses an unknown savefile type", savefile_type)
raise NotImplementedError("This parser can only read Terraria 1.4.4.9 save files.")
supported_versions = (Version("1.4.4.9"),)
if version not in supported_versions:
raise NotImplementedError("World file has been created with a unsupported version of Terraria", version)
revision = f.uint4() revision = f.uint4()
is_favorite = f.uint8() != 0 is_favorite = f.uint8() != 0
@ -573,14 +585,7 @@ class World:
for mob_id in range(mob_types_count): for mob_id in range(mob_types_count):
mob_kills[mob_id] = f.int4() mob_kills[mob_id] = f.int4()
fast_forward_time = f.bool() sundial_is_running = f.bool()
time = Time(
current=current_time,
is_daytime=is_daytime,
moon_phase=moon_phase,
sundial_cooldown=sundial_cooldown,
fast_forward_time=fast_forward_time,
)
defeated_duke_fishron = f.bool() defeated_duke_fishron = f.bool()
defeated_martian_madness = f.bool() defeated_martian_madness = f.bool()
@ -714,8 +719,6 @@ class World:
deerclops=defeated_deerclops, deerclops=defeated_deerclops,
) )
defeated_deerclops = f.bool()
saved_slime_nerdy = f.bool() saved_slime_nerdy = f.bool()
saved_merchant = f.bool() saved_merchant = f.bool()
saved_demolitionist = f.bool() saved_demolitionist = f.bool()
@ -765,6 +768,19 @@ class World:
slime_squire=saved_slime_squire, slime_squire=saved_slime_squire,
) )
moondial_is_running = f.bool()
moondial_cooldown = f.uint1()
time = Time(
current=current_time,
is_daytime=is_daytime,
moon_phase=moon_phase,
sundial_cooldown=sundial_cooldown,
sundial_is_running=sundial_is_running,
moondial_cooldown=moondial_cooldown,
moondial_is_running=moondial_is_running,
)
unknown_world_header_data = f.read_until(pointers.world_tiles) unknown_world_header_data = f.read_until(pointers.world_tiles)
# Tiles # Tiles
@ -814,6 +830,11 @@ class World:
npcs = [] npcs = []
mobs = [] mobs = []
shimmered_npcs_count = f.int4()
shimmered_npcs = []
for _ in range(shimmered_npcs_count):
shimmered_npcs.append(f.int4())
while f.bool(): while f.bool():
npc_type = EntityType(f.int4()) npc_type = EntityType(f.int4())
npc_name = f.string() npc_name = f.string()
@ -1013,6 +1034,7 @@ class World:
tiles=tm, tiles=tm,
chests=chests, chests=chests,
signs=signs, signs=signs,
shimmered_npcs=shimmered_npcs,
npcs=npcs, npcs=npcs,
mobs=mobs, mobs=mobs,
tile_entities=tile_entities, tile_entities=tile_entities,
@ -1049,3 +1071,8 @@ class World:
f.file.close() f.file.close()
return world return world
if __name__ == "__main__":
world = World.create_from_file(sys.argv[1])
breakpoint()