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

Correctly parse WorldTiles data

This commit is contained in:
Steffo 2019-08-10 19:59:37 +02:00
parent 6f8b9b75b3
commit 740577f578
24 changed files with 1151 additions and 269 deletions

View file

@ -0,0 +1,5 @@
from .filereader import FileReader
from .rect import Rect
from .pointers import Pointers
__all__ = ["FileReader", "Rect", "Pointers"]

View file

@ -44,14 +44,14 @@ class FileReader:
def bits(self) -> typing.Tuple[bool, bool, bool, bool, bool, bool, bool, bool]:
data = struct.unpack("B", self.file.read(1))[0]
return (bool(data & 0b1000_0000),
bool(data & 0b0100_0000),
bool(data & 0b0010_0000),
bool(data & 0b0001_0000),
bool(data & 0b0000_1000),
bool(data & 0b0000_0100),
return (bool(data & 0b0000_0001),
bool(data & 0b0000_0010),
bool(data & 0b0000_0001))
bool(data & 0b0000_0100),
bool(data & 0b0000_1000),
bool(data & 0b0001_0000),
bool(data & 0b0010_0000),
bool(data & 0b0100_0000),
bool(data & 0b1000_0000))
def rect(self) -> Rect:
left, right, top, bottom = struct.unpack("iiii", self.file.read(16))
@ -73,3 +73,12 @@ class FileReader:
# https://docs.microsoft.com/it-it/dotnet/api/system.datetime.kind?view=netframework-4.8#System_DateTime_Kind
datetime_bytes = self.file.read(8)
return datetime_bytes
def read_until(self, address: int) -> bytearray:
data = bytearray()
while self.file.tell() < address:
data += self.file.read(1)
return data
def __repr__(self):
return f"<FileReader at {hex(self.file.tell())}>"

View file

@ -0,0 +1,22 @@
import typing
class Pointers:
def __init__(self,
world_header: int,
world_tiles: int,
chests: int,
signs: int,
npcs: int,
entities: int,
footer: int,
*unknown):
self.file_format: int = 0
self.world_header: int = world_header
self.world_tiles: int = world_tiles
self.chests: int = chests
self.signs: int = signs
self.npcs: int = npcs
self.entities: int = entities
self.footer: int = footer
self.unknown: typing.List[int] = list(unknown)

View file

@ -35,7 +35,6 @@ __all__ = [
"Clouds",
"Coordinates",
"Events",
"FileReader",
"FourPartSplit",
"GeneratorInfo",
"HardmodeTier1Ore",
@ -50,7 +49,6 @@ __all__ = [
"Party",
"PillarsInfo",
"Rain",
"Rect",
"Sandstorm",
"SavedNPCs",
"ShadowOrbs",

View file

@ -43,4 +43,4 @@ class AnglerQuestFish(enum.IntEnum):
TROPICAL_BARRACUDA = 38
def __repr__(self):
return f"AnglerQuestFish('{self.name}')"
return f"{self.__class__.__name__}.{self.name}"

View file

@ -25,4 +25,6 @@ class Backgrounds:
self.bg_ocean: int = bg_ocean
def __repr__(self):
return f"WorldBackgrounds({self.bg_underground_snow}, {self.bg_underground_jungle}, {self.bg_hell}, {self.bg_forest}, {self.bg_corruption}, {self.bg_jungle}, {self.bg_snow}, {self.bg_hallow}, {self.bg_crimson}, {self.bg_desert}, {self.bg_ocean})"
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})"

View file

@ -7,7 +7,7 @@ class HardmodeTier1Ore(enum.IntEnum):
PALLADIUM = 221
def __repr__(self):
return f"HardmodeTier1Ore('{self.name}')"
return f"{self.__class__.__name__}.{self.name}"
class HardmodeTier2Ore(enum.IntEnum):
@ -16,7 +16,7 @@ class HardmodeTier2Ore(enum.IntEnum):
ORICHALCUM = 222
def __repr__(self):
return f"HardmodeTier2Ore('{self.name}')"
return f"{self.__class__.__name__}.{self.name}"
class HardmodeTier3Ore(enum.IntEnum):
@ -26,4 +26,4 @@ class HardmodeTier3Ore(enum.IntEnum):
TITANIUM = 223
def __repr__(self):
return f"HardmodeTier3Ore('{self.name}')"
return f"{self.__class__.__name__}.{self.name}"

View file

@ -8,4 +8,4 @@ class MoonStyle(enum.IntEnum):
RINGED_GREEN = 2
def __repr__(self):
return f"MoonStyle('{self.name}')"
return f"{self.__class__.__name__}.{self.name}"

View file

@ -15,4 +15,5 @@ class Sandstorm:
self.intended_severity: float = intended_severity
def __repr__(self):
return f"WorldSandstorm(is_active={self.is_active}, time_left={self.time_left}, severity={self.severity}, intended_severity={self.intended_severity})"
return f"WorldSandstorm(is_active={self.is_active}, time_left={self.time_left}," \
f" severity={self.severity}, intended_severity={self.intended_severity})"

View file

@ -6,4 +6,4 @@ class WorldEvilType(enum.Enum):
CRIMSON = True
def __repr__(self):
return f"CorruptionType('{self.name}')"
return f"{self.__class__.__name__}.{self.name}"

View file

@ -1,6 +1,14 @@
from .liquid import Liquid
from .liquidtype import LiquidType
from .rleencoding import RLEEncoding
from .shape import Shape
from .wires import Wires
from .blocktype import BlockType
from .frameimportantdata import FrameImportantData
from .walltype import WallType
from .block import Block
from .wall import Wall
from .liquid import Liquid
from .tile import Tile
__all__ = ["Liquid", "RLEEncoding", "Shape", "Wires"]
__all__ = ["LiquidType", "RLEEncoding", "Shape", "Wires", "BlockType", "FrameImportantData", "WallType", "Block",
"Wall", "Liquid", "Tile"]

18
lihzahrd/tiles/block.py Normal file
View file

@ -0,0 +1,18 @@
import typing
from .blocktype import BlockType
from .frameimportantdata import FrameImportantData
class Block:
def __init__(self,
type_: BlockType,
frame: typing.Optional[FrameImportantData],
paint: typing.Optional[int],
is_active: bool = True):
self.type: BlockType = type_
self.frame: typing.Optional[FrameImportantData] = frame
self.paint: typing.Optional[int] = paint
self.is_active: bool = is_active
def __repr__(self):
return f"Block(type_={repr(self.type)}, frame={self.frame}, paint={self.paint}, is_active={self.is_active})"

478
lihzahrd/tiles/blocktype.py Normal file
View file

@ -0,0 +1,478 @@
import enum
class BlockType(enum.IntEnum):
DIRT = 0
STONE = 1
GRASS = 2
PLANTS = 3
TORCHES = 4
TREES = 5
IRON = 6
COPPER = 7
GOLD = 8
SILVER = 9
CLOSED_DOOR = 10
OPEN_DOOR = 11
HEART = 12
BOTTLES = 13
TABLES = 14
CHAIRS = 15
ANVILS = 16
FURNACES = 17
WORK_BENCHES = 18
PLATFORMS = 19
SAPLINGS = 20
CONTAINERS = 21
DEMONITE = 22
CORRUPT_GRASS = 23
CORRUPT_PLANTS = 24
EBONSTONE = 25
DEMON_ALTAR = 26
SUNFLOWER = 27
POTS = 28
PIGGY_BANK = 29
WOOD_BLOCK = 30
SHADOW_ORBS = 31
CORRUPT_THORNS = 32
CANDLES = 33
CHANDELIERS = 34
JACKOLANTERNS = 35
PRESENTS = 36
METEORITE = 37
GRAY_BRICK = 38
RED_BRICK = 39
CLAY_BLOCK = 40
BLUE_DUNGEON_BRICK = 41
HANGING_LANTERNS = 42
GREEN_DUNGEON_BRICK = 43
PINK_DUNGEON_BRICK = 44
GOLD_BRICK = 45
SILVER_BRICK = 46
COPPER_BRICK = 47
SPIKES = 48
WATER_CANDLE = 49
BOOKS = 50
COBWEB = 51
VINES = 52
SAND = 53
GLASS = 54
SIGNS = 55
OBSIDIAN = 56
ASH = 57
HELLSTONE = 58
MUD = 59
JUNGLE_GRASS = 60
JUNGLE_PLANTS = 61
JUNGLE_VINES = 62
SAPPHIRE = 63
RUBY = 64
EMERALD = 65
TOPAZ = 66
AMETHYST = 67
DIAMOND = 68
JUNGLE_THORNS = 69
MUSHROOM_GRASS = 70
MUSHROOM_PLANTS = 71
MUSHROOM_TREES = 72
PLANTS2 = 73
JUNGLE_PLANTS2 = 74
OBSIDIAN_BRICK = 75
HELLSTONE_BRICK = 76
HELLFORGE = 77
CLAY_POT = 78
BEDS = 79
CACTUS = 80
CORAL = 81
IMMATURE_HERBS = 82
MATURE_HERBS = 83
BLOOMING_HERBS = 84
TOMBSTONES = 85
LOOM = 86
PIANOS = 87
DRESSERS = 88
BENCHES = 89
BATHTUBS = 90
BANNERS = 91
LAMPPOSTS = 92
LAMPS = 93
KEGS = 94
CHINESE_LANTERNS = 95
COOKING_POTS = 96
SAFES = 97
SKULL_LANTERNS = 98
TRASH_CAN = 99
CANDELABRAS = 100
BOOKCASES = 101
THRONES = 102
BOWLS = 103
GRANDFATHER_CLOCKS = 104
STATUES = 105
SAWMILL = 106
COBALT = 107
MYTHRIL = 108
HALLOWED_GRASS = 109
HALLOWED_PLANTS = 110
ADAMANTITE = 111
EBONSAND = 112
HALLOWED_PLANTS2 = 113
TINKERERS_WORKBENCH = 114
HALLOWED_VINES = 115
PEARLSAND = 116
PEARLSTONE = 117
PEARLSTONE_BRICK = 118
IRIDESCENT_BRICK = 119
MUDSTONE = 120
COBALT_BRICK = 121
MYTHRIL_BRICK = 122
SILT = 123
WOODEN_BEAM = 124
CRYSTAL_BALL = 125
DISCO_BALL = 126
MAGICAL_ICE_BLOCK = 127
MANNEQUIN = 128
CRYSTALS = 129
ACTIVE_STONE_BLOCK = 130
INACTIVE_STONE_BLOCK = 131
LEVER = 132
ADAMANTITE_FORGE = 133
MYTHRIL_ANVIL = 134
PRESSURE_PLATES = 135
SWITCHES = 136
TRAPS = 137
BOULDER = 138
MUSIC_BOXES = 139
DEMONITE_BRICK = 140
EXPLOSIVES = 141
INLET_PUMP = 142
OUTLET_PUMP = 143
TIMERS = 144
CANDY_CANE_BLOCK = 145
GREEN_CANDY_CANE_BLOCK = 146
SNOW_BLOCK = 147
SNOW_BRICK = 148
HOLIDAY_LIGHTS = 149
ADAMANTITE_BEAM = 150
SANDSTONE_BRICK = 151
EBONSTONE_BRICK = 152
RED_STUCCO = 153
YELLOW_STUCCO = 154
GREEN_STUCCO = 155
GRAY_STUCCO = 156
EBONWOOD = 157
RICH_MAHOGANY = 158
PEARLWOOD = 159
RAINBOW_BRICK = 160
ICE_BLOCK = 161
BREAKABLE_ICE = 162
CORRUPT_ICE = 163
HALLOWED_ICE = 164
STALACTITE = 165
TIN = 166
LEAD = 167
TUNGSTEN = 168
PLATINUM = 169
PINE_TREE = 170
CHRISTMAS_TREE = 171
SINKS = 172
PLATINUM_CANDELABRA = 173
PLATINUM_CANDLE = 174
TIN_BRICK = 175
TUNGSTEN_BRICK = 176
PLATINUM_BRICK = 177
EXPOSED_GEMS = 178
GREEN_MOSS = 179
BROWN_MOSS = 180
RED_MOSS = 181
BLUE_MOSS = 182
PURPLE_MOSS = 183
LONG_MOSS = 184
SMALL_PILES = 185
LARGE_PILES = 186
LARGE_PILES2 = 187
CACTUS_BLOCK = 188
CLOUD = 189
MUSHROOM_BLOCK = 190
LIVING_WOOD = 191
LEAF_BLOCK = 192
SLIME_BLOCK = 193
BONE_BLOCK = 194
FLESH_BLOCK = 195
RAIN_CLOUD = 196
FROZEN_SLIME_BLOCK = 197
ASPHALT = 198
FLESH_GRASS = 199
FLESH_ICE = 200
FLESH_WEEDS = 201
SUNPLATE = 202
CRIMSTONE = 203
CRIMTANE = 204
CRIMSON_VINES = 205
ICE_BRICK = 206
WATER_FOUNTAIN = 207
SHADEWOOD = 208
CANNON = 209
LAND_MINE = 210
CHLOROPHYTE = 211
SNOWBALL_LAUNCHER = 212
ROPE = 213
CHAIN = 214
CAMPFIRE = 215
FIREWORK = 216
BLENDOMATIC = 217
MEAT_GRINDER = 218
EXTRACTINATOR = 219
SOLIDIFIER = 220
PALLADIUM = 221
ORICHALCUM = 222
TITANIUM = 223
SLUSH = 224
HIVE = 225
LIHZAHRD_BRICK = 226
DYE_PLANTS = 227
DYE_VAT = 228
HONEY_BLOCK = 229
CRISPY_HONEY_BLOCK = 230
LARVA = 231
WOODEN_SPIKES = 232
PLANT_DETRITUS = 233
CRIMSAND = 234
TELEPORTER = 235
LIFE_FRUIT = 236
LIHZAHRD_ALTAR = 237
PLANTERA_BULB = 238
METAL_BARS = 239
PAINTING3X3 = 240
PAINTING4X3 = 241
PAINTING6X4 = 242
IMBUING_STATION = 243
BUBBLE_MACHINE = 244
PAINTING2X3 = 245
PAINTING3X2 = 246
AUTOHAMMER = 247
PALLADIUM_COLUMN = 248
BUBBLEGUM_BLOCK = 249
TITANSTONE = 250
PUMPKIN_BLOCK = 251
HAY_BLOCK = 252
SPOOKY_WOOD = 253
PUMPKINS = 254
AMETHYST_GEMSPARK_OFF = 255
TOPAZ_GEMSPARK_OFF = 256
SAPPHIRE_GEMSPARK_OFF = 257
EMERALD_GEMSPARK_OFF = 258
RUBY_GEMSPARK_OFF = 259
DIAMOND_GEMSPARK_OFF = 260
AMBER_GEMSPARK_OFF = 261
AMETHYST_GEMSPARK = 262
TOPAZ_GEMSPARK = 263
SAPPHIRE_GEMSPARK = 264
EMERALD_GEMSPARK = 265
RUBY_GEMSPARK = 266
DIAMOND_GEMSPARK = 267
AMBER_GEMSPARK = 268
WOMANNEQUIN = 269
FIREFLYINA_BOTTLE = 270
LIGHTNING_BUGINA_BOTTLE = 271
COG = 272
STONE_SLAB = 273
SAND_STONE_SLAB = 274
BUNNY_CAGE = 275
SQUIRREL_CAGE = 276
MALLARD_DUCK_CAGE = 277
DUCK_CAGE = 278
BIRD_CAGE = 279
BLUE_JAY = 280
CARDINAL_CAGE = 281
FISH_BOWL = 282
HEAVY_WORK_BENCH = 283
COPPER_PLATING = 284
SNAIL_CAGE = 285
GLOWING_SNAIL_CAGE = 286
AMMO_BOX = 287
MONARCH_BUTTERFLY_JAR = 288
PURPLE_EMPEROR_BUTTERFLY_JAR = 289
RED_ADMIRAL_BUTTERFLY_JAR = 290
ULYSSES_BUTTERFLY_JAR = 291
SULPHUR_BUTTERFLY_JAR = 292
TREE_NYMPH_BUTTERFLY_JAR = 293
ZEBRA_SWALLOWTAIL_BUTTERFLY_JAR = 294
JULIA_BUTTERFLY_JAR = 295
SCORPION_CAGE = 296
BLACK_SCORPION_CAGE = 297
FROG_CAGE = 298
MOUSE_CAGE = 299
BONE_WELDER = 300
FLESH_CLONING_VAT = 301
GLASS_KILN = 302
LIHZAHRD_FURNACE = 303
LIVING_LOOM = 304
SKY_MILL = 305
ICE_MACHINE = 306
STEAMPUNK_BOILER = 307
HONEY_DISPENSER = 308
PENGUIN_CAGE = 309
WORM_CAGE = 310
DYNASTY_WOOD = 311
RED_DYNASTY_SHINGLES = 312
BLUE_DYNASTY_SHINGLES = 313
MINECART_TRACK = 314
CORALSTONE = 315
BLUE_JELLYFISH_BOWL = 316
GREEN_JELLYFISH_BOWL = 317
PINK_JELLYFISH_BOWL = 318
SHIP_IN_ABOTTLE = 319
SEAWEED_PLANTER = 320
BOREAL_WOOD = 321
PALM_WOOD = 322
PALM_TREE = 323
BEACH_PILES = 324
TIN_PLATING = 325
WATERFALL = 326
LAVAFALL = 327
CONFETTI = 328
CONFETTI_BLACK = 329
COPPER_COIN_PILE = 330
SILVER_COIN_PILE = 331
GOLD_COIN_PILE = 332
PLATINUM_COIN_PILE = 333
WEAPONS_RACK = 334
FIREWORKS_BOX = 335
LIVING_FIRE = 336
ALPHABET_STATUES = 337
FIREWORK_FOUNTAIN = 338
GRASSHOPPER_CAGE = 339
LIVING_CURSED_FIRE = 340
LIVING_DEMON_FIRE = 341
LIVING_FROST_FIRE = 342
LIVING_ICHOR = 343
LIVING_ULTRABRIGHT_FIRE = 344
HONEYFALL = 345
CHLOROPHYTE_BRICK = 346
CRIMTANE_BRICK = 347
SHROOMITE_PLATING = 348
MUSHROOM_STATUE = 349
MARTIAN_CONDUIT_PLATING = 350
CHIMNEY_SMOKE = 351
CRIMTANE_THORNS = 352
VINE_ROPE = 353
BEWITCHING_TABLE = 354
ALCHEMY_TABLE = 355
SUNDIAL = 356
MARBLE_BLOCK = 357
GOLD_BIRD_CAGE = 358
GOLD_BUNNY_CAGE = 359
GOLD_BUTTERFLY_CAGE = 360
GOLD_FROG_CAGE = 361
GOLD_GRASSHOPPER_CAGE = 362
GOLD_MOUSE_CAGE = 363
GOLD_WORM_CAGE = 364
SILK_ROPE = 365
WEB_ROPE = 366
MARBLE = 367
GRANITE = 368
GRANITE_BLOCK = 369
METEORITE_BRICK = 370
PINK_SLIME_BLOCK = 371
PEACE_CANDLE = 372
WATER_DRIP = 373
LAVA_DRIP = 374
HONEY_DRIP = 375
FISHING_CRATE = 376
SHARPENING_STATION = 377
TARGET_DUMMY = 378
BUBBLE = 379
PLANTER_BOX = 380
LAVA_MOSS = 381
VINE_FLOWERS = 382
LIVING_MAHOGANY = 383
LIVING_MAHOGANY_LEAVES = 384
CRYSTAL_BLOCK = 385
TRAPDOOR_OPEN = 386
TRAPDOOR_CLOSED = 387
TALL_GATE_CLOSED = 388
TALL_GATE_OPEN = 389
LAVA_LAMP = 390
CAGE_ENCHANTED_NIGHTCRAWLER = 391
CAGE_BUGGY = 392
CAGE_GRUBBY = 393
CAGE_SLUGGY = 394
ITEM_FRAME = 395
SANDSTONE = 396
HARDENED_SAND = 397
CORRUPT_HARDENED_SAND = 398
CRIMSON_HARDENED_SAND = 399
CORRUPT_SANDSTONE = 400
CRIMSON_SANDSTONE = 401
HALLOW_HARDENED_SAND = 402
HALLOW_SANDSTONE = 403
DESERT_FOSSIL = 404
FIREPLACE = 405
CHIMNEY = 406
FOSSIL_ORE = 407
LUNAR_ORE = 408
LUNAR_BRICK = 409
LUNAR_MONOLITH = 410
DETONATOR = 411
LUNAR_CRAFTING_STATION = 412
SQUIRREL_ORANGE_CAGE = 413
SQUIRREL_GOLD_CAGE = 414
LUNAR_BLOCK_SOLAR = 415
LUNAR_BLOCK_VORTEX = 416
LUNAR_BLOCK_NEBULA = 417
LUNAR_BLOCK_STARDUST = 418
LOGIC_GATE_LAMP = 419
LOGIC_GATE = 420
CONVEYOR_BELT_LEFT = 421
CONVEYOR_BELT_RIGHT = 422
LOGIC_SENSOR = 423
WIRE_PIPE = 424
ANNOUNCEMENT_BOX = 425
TEAM_BLOCK_RED = 426
TEAM_BLOCK_RED_PLATFORM = 427
WEIGHTED_PRESSURE_PLATE = 428
WIRE_BULB = 429
TEAM_BLOCK_GREEN = 430
TEAM_BLOCK_BLUE = 431
TEAM_BLOCK_YELLOW = 432
TEAM_BLOCK_PINK = 433
TEAM_BLOCK_WHITE = 434
TEAM_BLOCK_GREEN_PLATFORM = 435
TEAM_BLOCK_BLUE_PLATFORM = 436
TEAM_BLOCK_YELLOW_PLATFORM = 437
TEAM_BLOCK_PINK_PLATFORM = 438
TEAM_BLOCK_WHITE_PLATFORM = 439
GEM_LOCKS = 440
FAKE_CONTAINERS = 441
PROJECTILE_PRESSURE_PAD = 442
GEYSER_TRAP = 443
BEE_HIVE = 444
PIXEL_BOX = 445
SILLY_BALLOON_PINK = 446
SILLY_BALLOON_PURPLE = 447
SILLY_BALLOON_GREEN = 448
SILLY_STREAMER_BLUE = 449
SILLY_STREAMER_GREEN = 450
SILLY_STREAMER_PINK = 451
SILLY_BALLOON_MACHINE = 452
SILLY_BALLOON_TILE = 453
PIGRONATA = 454
PARTY_MONOLITH = 455
PARTY_BUNDLE_OF_BALLOON_TILE = 456
PARTY_PRESENT = 457
SAND_FALL_BLOCK = 458
SNOW_FALL_BLOCK = 459
SNOW_CLOUD = 460
SAND_DRIP = 461
DJINN_LAMP = 462
DEFENDERS_FORGE = 463
WAR_TABLE = 464
WAR_TABLE_BANNER = 465
ELDER_CRYSTAL_STAND = 466
CONTAINERS2 = 467
FAKE_CONTAINERS2 = 468
TABLES2 = 469
COUNT = 470
def __repr__(self):
return f"{self.__class__.__name__}.{self.name}"

View file

@ -0,0 +1,7 @@
class FrameImportantData:
def __init__(self, frame_x, frame_y):
self.frame_x: int = frame_x
self.frame_y: int = frame_y
def __repr__(self):
return f"FrameImportantData(frame_x={self.frame_x}, frame_y={self.frame_y})"

View file

@ -1,18 +1,7 @@
import enum
from .liquidtype import LiquidType
class Liquid(enum.IntEnum):
NO_LIQUID = 0
WATER = 1
LAVA = 2
HONEY = 3
@classmethod
def from_flags(cls, flags1):
if flags1[3] and flags1[4]:
return cls.HONEY
if flags1[4]:
return cls.LAVA
if flags1[3]:
return cls.WATER
return cls.NO_LIQUID
class Liquid:
def __init__(self, type_: LiquidType, volume: int):
self.type: LiquidType = type_
self.volume: int = volume

View file

@ -0,0 +1,21 @@
import enum
class LiquidType(enum.IntEnum):
NO_LIQUID = 0
WATER = 1
LAVA = 2
HONEY = 3
@classmethod
def from_flags(cls, flags1):
if flags1[3] and flags1[4]:
return cls.HONEY
if flags1[4]:
return cls.LAVA
if flags1[3]:
return cls.WATER
return cls.NO_LIQUID
def __repr__(self):
return f"{self.__class__.__name__}.{self.name}"

View file

@ -1,18 +1,15 @@
import enum
import typing
from .block import Block
from .wall import Wall
from .liquid import Liquid
class Liquid(enum.IntEnum):
NO_LIQUID = 0
WATER = 1
LAVA = 2
HONEY = 3
class Tile:
@classmethod
def from_flags(cls, flags13, flags14):
if flags13 and flags14:
return cls.HONEY
if flags14:
return cls.LAVA
if flags13:
return cls.WATER
return cls.NO_LIQUID
def __init__(self, block: typing.Optional[Block], wall: typing.Optional[Wall], liquid: typing.Optional[Liquid]):
self.block: typing.Optional[Block] = block
self.wall: typing.Optional[Wall] = wall
self.liquid: typing.Optional[Liquid] = liquid
def __repr__(self):
return f"<Tile {'B' if self.block else '_'}{'W' if self.wall else '_'}{'L' if self.liquid else '_'}>"

8
lihzahrd/tiles/wall.py Normal file
View file

@ -0,0 +1,8 @@
import typing
from .walltype import WallType
class Wall:
def __init__(self, type_: WallType, paint: typing.Optional[int]):
self.type: WallType = type_
self.paint: typing.Optional[int] = paint

237
lihzahrd/tiles/walltype.py Normal file
View file

@ -0,0 +1,237 @@
import enum
class WallType(enum.IntEnum):
STONE = 1
DIRT_UNSAFE = 2
EBONSTONE_UNSAFE = 3
WOOD = 4
GRAY_BRICK = 5
RED_BRICK = 6
BLUE_DUNGEON_UNSAFE = 7
GREEN_DUNGEON_UNSAFE = 8
PINK_DUNGEON_UNSAFE = 9
GOLD_BRICK = 10
SILVER_BRICK = 11
COPPER_BRICK = 12
HELLSTONE_BRICK_UNSAFE = 13
OBSIDIAN_BRICK_UNSAFE = 14
MUD_UNSAFE = 15
DIRT = 16
BLUE_DUNGEON = 17
GREEN_DUNGEON = 18
PINK_DUNGEON = 19
OBSIDIAN_BRICK = 20
GLASS = 21
PEARLSTONE_BRICK = 22
IRIDESCENT_BRICK = 23
MUDSTONE_BRICK = 24
COBALT_BRICK = 25
MYTHRIL_BRICK = 26
PLANKED = 27
PEARLSTONE_BRICK_UNSAFE = 28
CANDY_CANE = 29
GREEN_CANDY_CANE = 30
SNOW_BRICK = 31
ADAMANTITE_BEAM = 32
DEMONITE_BRICK = 33
SANDSTONE_BRICK = 34
EBONSTONE_BRICK = 35
RED_STUCCO = 36
YELLOW_STUCCO = 37
GREEN_STUCCO = 38
GRAY = 39
SNOW_WALL_UNSAFE = 40
EBONWOOD = 41
RICH_MAOGANY = 42
PEARLWOOD = 43
RAINBOW_BRICK = 44
TIN_BRICK = 45
TUNGSTEN_BRICK = 46
PLATINUM_BRICK = 47
AMETHYST_UNSAFE = 48
TOPAZ_UNSAFE = 49
SAPPHIRE_UNSAFE = 50
EMERALD_UNSAFE = 51
RUBY_UNSAFE = 52
DIAMOND_UNSAFE = 53
CAVE_UNSAFE = 54
CAVE2UNSAFE = 55
CAVE3UNSAFE = 56
CAVE4UNSAFE = 57
CAVE5UNSAFE = 58
CAVE6UNSAFE = 59
LIVING_LEAF = 60
CAVE7UNSAFE = 61
SPIDER_UNSAFE = 62
GRASS_UNSAFE = 63
JUNGLE_UNSAFE = 64
FLOWER_UNSAFE = 65
GRASS = 66
JUNGLE = 67
FLOWER = 68
CORRUPT_GRASS_UNSAFE = 69
HALLOWED_GRASS_UNSAFE = 70
ICE_UNSAFE = 71
CACTUS = 72
CLOUD = 73
MUSHROOM = 74
BONE = 75
SLIME = 76
FLESH = 77
LIVING_WOOD = 78
OBSIDIAN_BACK_UNSAFE = 79
MUSHROOM_UNSAFE = 80
CRIMSON_GRASS_UNSAFE = 81
DISC_WALL = 82
CRIMSTONE_UNSAFE = 83
ICE_BRICK = 84
SHADEWOOD = 85
HIVE_UNSAFE = 86
LIHZAHRD_BRICK_UNSAFE = 87
PURPLE_STAINED_GLASS = 88
YELLOW_STAINED_GLASS = 89
BLUE_STAINED_GLASS = 90
GREEN_STAINED_GLASS = 91
RED_STAINED_GLASS = 92
RAINBOW_STAINED_GLASS = 93
BLUE_DUNGEON_SLAB_UNSAFE = 94
BLUE_DUNGEON_TILE_UNSAFE = 95
PINK_DUNGEON_SLAB_UNSAFE = 96
PINK_DUNGEON_TILE_UNSAFE = 97
GREEN_DUNGEON_SLAB_UNSAFE = 98
GREEN_DUNGEON_TILE_UNSAFE = 99
BLUE_DUNGEON_SLAB = 100
BLUE_DUNGEON_TILE = 101
PINK_DUNGEON_SLAB = 102
PINK_DUNGEON_TILE = 103
GREEN_DUNGEON_SLAB = 104
GREEN_DUNGEON_TILE = 105
WOODEN_FENCE = 106
METAL_FENCE = 107
HIVE = 108
PALLADIUM_COLUMN = 109
BUBBLEGUM_BLOCK = 110
TITANSTONE_BLOCK = 111
LIHZAHRD_BRICK = 112
PUMPKIN = 113
HAY = 114
SPOOKY_WOOD = 115
CHRISTMAS_TREE_WALLPAPER = 116
ORNAMENT_WALLPAPER = 117
CANDY_CANE_WALLPAPER = 118
FESTIVE_WALLPAPER = 119
STARS_WALLPAPER = 120
SQUIGGLES_WALLPAPER = 121
SNOWFLAKE_WALLPAPER = 122
KRAMPUS_HORN_WALLPAPER = 123
BLUEGREEN_WALLPAPER = 124
GRINCH_FINGER_WALLPAPER = 125
FANCY_GRAY_WALLPAPER = 126
ICE_FLOE_WALLPAPER = 127
MUSIC_WALLPAPER = 128
PURPLE_RAIN_WALLPAPER = 129
RAINBOW_WALLPAPER = 130
SPARKLE_STONE_WALLPAPER = 131
STARLIT_HEAVEN_WALLPAPER = 132
BUBBLE_WALLPAPER = 133
COPPER_PIPE_WALLPAPER = 134
DUCKY_WALLPAPER = 135
WATERFALL = 136
LAVAFALL = 137
EBONWOOD_FENCE = 138
RICH_MAHOGANY_FENCE = 139
PEARLWOOD_FENCE = 140
SHADEWOOD_FENCE = 141
WHITE_DYNASTY = 142
BLUE_DYNASTY = 143
ARCANE_RUNES = 144
IRON_FENCE = 145
COPPER_PLATING = 146
STONE_SLAB = 147
SAIL = 148
BOREAL_WOOD = 149
BOREAL_WOOD_FENCE = 150
PALM_WOOD = 151
PALM_WOOD_FENCE = 152
AMBER_GEMSPARK = 153
AMETHYST_GEMSPARK = 154
DIAMOND_GEMSPARK = 155
EMERALD_GEMSPARK = 156
AMBER_GEMSPARK_OFF = 157
AMETHYST_GEMSPARK_OFF = 158
DIAMOND_GEMSPARK_OFF = 159
EMERALD_GEMSPARK_OFF = 160
RUBY_GEMSPARK_OFF = 161
SAPPHIRE_GEMSPARK_OFF = 162
TOPAZ_GEMSPARK_OFF = 163
RUBY_GEMSPARK = 164
SAPPHIRE_GEMSPARK = 165
TOPAZ_GEMSPARK = 166
TIN_PLATING = 167
CONFETTI = 168
CONFETTI_BLACK = 169
CAVE_WALL = 170
CAVE_WALL2 = 171
HONEYFALL = 172
CHLOROPHYTE_BRICK = 173
CRIMTANE_BRICK = 174
SHROOMITE_PLATING = 175
MARTIAN_CONDUIT = 176
HELLSTONE_BRICK = 177
MARBLE_UNSAFE = 178
MARBLE_BLOCK = 179
GRANITE_UNSAFE = 180
GRANITE_BLOCK = 181
METEORITE_BRICK = 182
MARBLE = 183
GRANITE = 184
CAVE8UNSAFE = 185
CRYSTAL = 186
SANDSTONE = 187
CORRUPTION_UNSAFE1 = 188
CORRUPTION_UNSAFE2 = 189
CORRUPTION_UNSAFE3 = 190
CORRUPTION_UNSAFE4 = 191
CRIMSON_UNSAFE1 = 192
CRIMSON_UNSAFE2 = 193
CRIMSON_UNSAFE3 = 194
CRIMSON_UNSAFE4 = 195
DIRT_UNSAFE1 = 196
DIRT_UNSAFE2 = 197
DIRT_UNSAFE3 = 198
DIRT_UNSAFE4 = 199
HALLOW_UNSAFE1 = 200
HALLOW_UNSAFE2 = 201
HALLOW_UNSAFE3 = 202
HALLOW_UNSAFE4 = 203
JUNGLE_UNSAFE1 = 204
JUNGLE_UNSAFE2 = 205
JUNGLE_UNSAFE3 = 206
JUNGLE_UNSAFE4 = 207
LAVA_UNSAFE1 = 208
LAVA_UNSAFE2 = 209
LAVA_UNSAFE3 = 210
LAVA_UNSAFE4 = 211
ROCKS_UNSAFE1 = 212
ROCKS_UNSAFE2 = 213
ROCKS_UNSAFE3 = 214
ROCKS_UNSAFE4 = 215
HARDENED_SAND = 216
CORRUPT_HARDENED_SAND = 217
CRIMSON_HARDENED_SAND = 218
HALLOW_HARDENED_SAND = 219
CORRUPT_SANDSTONE = 220
CRIMSON_SANDSTONE = 221
HALLOW_SANDSTONE = 222
DESERT_FOSSIL = 223
LUNAR_BRICK_WALL = 224
COG_WALL = 225
SAND_FALL = 226
SNOW_FALL = 227
SILLY_BALLOON_PINK_WALL = 228
SILLY_BALLOON_PURPLE_WALL = 229
SILLY_BALLOON_GREEN_WALL = 230
def __repr__(self):
return f"{self.__class__.__name__}.{self.name}"

View file

@ -10,3 +10,6 @@ class Wires:
self.blue: bool = blue
self.yellow: bool = yellow
self.actuator: bool = actuator
def __repr__(self):
return f"Wires(red={self.red}, green={self.green}, blue={self.blue}, yellow={self.yellow}, actuator={self.actuator})"

30
lihzahrd/timer.py Normal file
View file

@ -0,0 +1,30 @@
import time
import typing
class Timer:
def __init__(self, name: str, display: bool = False):
self.name: str = name
self.display: bool = display
self._start_time: typing.Optional[float] = None
self._stop_time: typing.Optional[float] = None
@property
def _result(self) -> float:
return self._stop_time - self._start_time
def start(self):
self._start_time = time.time()
if self.display:
print(f"Timer {self.name} started.")
def stop(self):
self._stop_time = time.time()
if self.display:
print(f"Timer {self.name} stopped: {self._result} seconds elapsed.")
def __enter__(self):
self.start()
def __exit__(self, exc_type, exc_val, exc_tb):
self.stop()

View file

@ -1,8 +1,10 @@
import uuid
import math
import typing
from .header import *
from .savedata import filereader
from .fileutils import *
from .tiles import *
from .timer import Timer
class World:
@ -135,12 +137,13 @@ class World:
self.shadow_orbs = value
@staticmethod
def _read_tiles(fr: FileReader, tileframeimportant):
def _read_tiles(fr: FileReader, tileframeimportant) -> typing.List:
# Once again, this code is a mess
flags1 = fr.bits()
has_tile = flags1[1]
has_block = flags1[1]
has_wall = flags1[2]
liquid = Liquid.from_flags(flags1)
extended_block_id = flags1[5]
liquid_type = LiquidType.from_flags(flags1)
has_extended_block_id = flags1[5]
rle_compression = RLEEncoding.from_flags(flags1)
if flags1[0]:
flags2 = fr.bits()
@ -149,278 +152,325 @@ class World:
flags3 = fr.bits()
is_active = not flags3[2]
wires = Wires(red=flags2[1], green=flags2[2], blue=flags2[3], yellow=flags3[5], actuator=flags3[1])
is_tile_painted = flags3[3]
is_block_painted = flags3[3]
is_wall_painted = flags3[4]
else:
is_active = True
wires = Wires(red=flags2[1], green=flags2[2], blue=flags2[3])
is_tile_painted = False
is_block_painted = False
is_wall_painted = False
else:
shape = Shape.NORMAL
is_active = True
wires = Wires()
is_tile_painted = False
is_block_painted = False
is_wall_painted = False
if has_tile:
if extended_block_id:
block_id = fr.uint2()
if has_block:
if has_extended_block_id:
block_id = BlockType(fr.uint2())
else:
block_id = fr.uint1()
block_id = BlockType(fr.uint1())
if tileframeimportant[block_id]:
frame_x = fr.uint2()
frame_y = fr.uint2()
else:
frame_x = None
frame_y = None
if is_block_painted:
block_paint = fr.uint1()
else:
block_paint = None
block = Block(type_=block_id, frame=FrameImportantData(frame_x, frame_y), paint=block_paint)
else:
block_id = None
if tileframeimportant:
...
breakpoint()
block = None
if has_wall:
wall_id = WallType(fr.uint1())
if is_wall_painted:
wall_paint = fr.uint1()
else:
wall_paint = None
wall = Wall(type_=wall_id, paint=wall_paint)
else:
wall = None
if liquid_type != LiquidType.NO_LIQUID:
liquid = Liquid(type_=liquid_type, volume=fr.uint1())
else:
liquid = None
if rle_compression == RLEEncoding.DOUBLE_BYTE:
multiply_by = fr.uint2() + 1
elif rle_compression == RLEEncoding.SINGLE_BYTE:
multiply_by = fr.uint1() + 1
else:
multiply_by = 1
tile = Tile(block=block, wall=wall, liquid=liquid)
return [tile] * multiply_by
@classmethod
def create_from_file(cls, file):
"""Create a World object from a .wld file."""
# This code is a mess.
f = filereader.FileReader(file)
f = FileReader(file)
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.")
with Timer("File Format", display=True):
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.")
revision = f.uint4()
is_favorite = f.uint8() != 0
revision = f.uint4()
is_favorite = f.uint8() != 0
# Pointers and tileframeimportant
_ = [f.int4() for _ in range(f.int2())]
tileframeimportant_size = math.ceil(f.int2() / 8)
tileframeimportant = []
for _ in range(tileframeimportant_size):
current_bit = f.bits()
tileframeimportant = [*tileframeimportant, *current_bit]
# Pointers and tileframeimportant
pointers = Pointers(*[f.int4() for _ in range(f.int2())])
tileframeimportant_size = math.ceil(f.int2() / 8)
tileframeimportant = []
for _ in range(tileframeimportant_size):
current_bit = f.bits()
tileframeimportant = [*tileframeimportant, *current_bit]
name = f.string()
unknown_file_format_data = f.read_until(pointers.world_header)
generator = GeneratorInfo(f.string(), f.int4())
with Timer("World Header", display=True):
name = f.string()
uuid_ = f.uuid()
id_ = f.int8()
bounds = f.rect()
world_size = Coordinates(y=f.int4(), x=f.int4())
is_expert = f.bool()
created_on = f.datetime()
generator = GeneratorInfo(f.string(), f.int4())
world_styles = Styles(moon=MoonStyle(f.uint1()),
trees=FourPartSplit(separators=[f.int4(), f.int4(), f.int4()],
properties=[f.int4(),
f.int4(),
f.int4(),
f.int4()]),
moss=FourPartSplit(separators=[f.int4(), f.int4(), f.int4()],
properties=[f.int4(),
f.int4(),
f.int4(),
f.int4()]))
uuid_ = f.uuid()
id_ = f.int8()
bounds = f.rect()
world_size = Coordinates(y=f.int4(), x=f.int4())
is_expert = f.bool()
created_on = f.datetime()
bg_underground_snow = f.int4()
bg_underground_jungle = f.int4()
bg_hell = f.int4()
world_styles = Styles(moon=MoonStyle(f.uint1()),
trees=FourPartSplit(separators=[f.int4(), f.int4(), f.int4()],
properties=[f.int4(),
f.int4(),
f.int4(),
f.int4()]),
moss=FourPartSplit(separators=[f.int4(), f.int4(), f.int4()],
properties=[f.int4(),
f.int4(),
f.int4(),
f.int4()]))
spawn_point = Coordinates(f.int4(), f.int4())
underground_level = f.double()
cavern_level = f.double()
bg_underground_snow = f.int4()
bg_underground_jungle = f.int4()
bg_hell = f.int4()
current_time = f.double()
is_daytime = f.bool()
moon_phase = MoonPhase(f.uint4())
spawn_point = Coordinates(f.int4(), f.int4())
underground_level = f.double()
cavern_level = f.double()
blood_moon = f.bool()
eclipse = f.bool()
current_time = f.double()
is_daytime = f.bool()
moon_phase = MoonPhase(f.uint4())
dungeon_point = Coordinates(f.int4(), f.int4())
world_evil = WorldEvilType(f.bool())
blood_moon = f.bool()
eclipse = f.bool()
defeated_eye_of_cthulhu = f.bool() # Possibly. I'm not sure.
defeated_eater_of_worlds = f.bool() # Possibly. I'm not sure.
defeated_skeletron = f.bool() # Possibly. I'm not sure.
defeated_queen_bee = f.bool()
defeated_the_twins = f.bool()
defeated_the_destroyer = f.bool()
defeated_skeletron_prime = f.bool()
defeated_any_mechnical_boss = f.bool()
defeated_plantera = f.bool()
defeated_golem = f.bool()
defeated_king_slime = f.bool()
dungeon_point = Coordinates(f.int4(), f.int4())
world_evil = WorldEvilType(f.bool())
saved_goblin_tinkerer = f.bool()
saved_wizard = f.bool()
saved_mechanic = f.bool()
defeated_eye_of_cthulhu = f.bool() # Possibly. I'm not sure.
defeated_eater_of_worlds = f.bool() # Possibly. I'm not sure.
defeated_skeletron = f.bool() # Possibly. I'm not sure.
defeated_queen_bee = f.bool()
defeated_the_twins = f.bool()
defeated_the_destroyer = f.bool()
defeated_skeletron_prime = f.bool()
defeated_any_mechnical_boss = f.bool()
defeated_plantera = f.bool()
defeated_golem = f.bool()
defeated_king_slime = f.bool()
defeated_goblin_army = f.bool()
defeated_clown = f.bool()
defeated_frost_moon = f.bool()
defeated_pirates = f.bool()
saved_goblin_tinkerer = f.bool()
saved_wizard = f.bool()
saved_mechanic = f.bool()
shadow_orbs = ShadowOrbs(smashed_at_least_once=f.bool(),
spawn_meteorite=f.bool(),
evil_boss_counter=f.int4())
defeated_goblin_army = f.bool()
defeated_clown = f.bool()
defeated_frost_moon = f.bool()
defeated_pirates = f.bool()
smashed_altars_count = f.int4()
shadow_orbs = ShadowOrbs(smashed_at_least_once=f.bool(),
spawn_meteorite=f.bool(),
evil_boss_counter=f.int4())
is_hardmode = f.bool()
smashed_altars_count = f.int4()
invasion_delay = f.int4()
invasion_size = f.int4()
invasion_type = InvasionType(f.int4())
invasion_position = f.double()
is_hardmode = f.bool()
time_left_slime_rain = f.double()
invasion_delay = f.int4()
invasion_size = f.int4()
invasion_type = InvasionType(f.int4())
invasion_position = f.double()
sundial_cooldown = f.uint1()
time_left_slime_rain = f.double()
rain = Rain(is_active=f.bool(), time_left=f.int4(), max_rain=f.single())
sundial_cooldown = f.uint1()
hardmode_ore_1 = HardmodeTier1Ore(f.int4())
hardmode_ore_2 = HardmodeTier2Ore(f.int4())
hardmode_ore_3 = HardmodeTier3Ore(f.int4())
altars_smashed = AltarsSmashed(count=smashed_altars_count,
ore_tier1=hardmode_ore_1,
ore_tier2=hardmode_ore_2,
ore_tier3=hardmode_ore_3)
rain = Rain(is_active=f.bool(), time_left=f.int4(), max_rain=f.single())
bg_forest = f.int1()
bg_corruption = f.int1()
bg_jungle = f.int1()
bg_snow = f.int1()
bg_hallow = f.int1()
bg_crimson = f.int1()
bg_desert = f.int1()
bg_ocean = f.int1()
hardmode_ore_1 = HardmodeTier1Ore(f.int4())
hardmode_ore_2 = HardmodeTier2Ore(f.int4())
hardmode_ore_3 = HardmodeTier3Ore(f.int4())
altars_smashed = AltarsSmashed(count=smashed_altars_count,
ore_tier1=hardmode_ore_1,
ore_tier2=hardmode_ore_2,
ore_tier3=hardmode_ore_3)
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)
bg_forest = f.int1()
bg_corruption = f.int1()
bg_jungle = f.int1()
bg_snow = f.int1()
bg_hallow = f.int1()
bg_crimson = f.int1()
bg_desert = f.int1()
bg_ocean = f.int1()
clouds = Clouds(bg_cloud=f.int4(), cloud_number=f.int2(), wind_speed=f.single())
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)
angler_today_quest_completed_by_count = f.uint1()
angler_today_quest_completed_by = []
for _ in range(angler_today_quest_completed_by_count):
angler_today_quest_completed_by.append(f.string())
clouds = Clouds(bg_cloud=f.int4(), cloud_number=f.int2(), wind_speed=f.single())
saved_angler = f.bool()
angler_today_quest_completed_by_count = f.uint1()
angler_today_quest_completed_by = []
for _ in range(angler_today_quest_completed_by_count):
angler_today_quest_completed_by.append(f.string())
angler_today_quest_target = AnglerQuestFish(f.int4())
anglers_quest = AnglerQuest(current_goal=angler_today_quest_target,
completed_by=angler_today_quest_completed_by)
saved_angler = f.bool()
saved_stylist = f.bool()
saved_tax_collector = f.bool()
angler_today_quest_target = AnglerQuestFish(f.int4())
anglers_quest = AnglerQuest(current_goal=angler_today_quest_target,
completed_by=angler_today_quest_completed_by)
invasion_size_start = f.int4() # ???
invasion = Invasion(delay=invasion_delay,
size=invasion_size,
type_=invasion_type,
position=invasion_position,
size_start=invasion_size_start)
saved_stylist = f.bool()
saved_tax_collector = f.bool()
cultist_delay = f.int4() # ???
mob_types_count = f.int2()
mob_kills = {}
for mob_id in range(mob_types_count):
mob_kills[mob_id] = f.int4()
invasion_size_start = f.int4() # ???
invasion = Invasion(delay=invasion_delay,
size=invasion_size,
type_=invasion_type,
position=invasion_position,
size_start=invasion_size_start)
fast_forward_time = 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)
cultist_delay = f.int4() # ???
mob_types_count = f.int2()
mob_kills = {}
for mob_id in range(mob_types_count):
mob_kills[mob_id] = f.int4()
defeated_duke_fishron = f.bool()
defeated_moon_lord = f.bool()
defeated_pumpking = f.bool()
defeated_mourning_wood = f.bool()
defeated_ice_queen = f.bool()
defeated_santa_nk1 = f.bool()
defeated_everscream = f.bool()
defeated_pillars = PillarsInfo(solar=f.bool(), vortex=f.bool(), nebula=f.bool(), stardust=f.bool())
fast_forward_time = 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)
lunar_events = LunarEvents(pillars_present=PillarsInfo(solar=f.bool(),
vortex=f.bool(),
nebula=f.bool(),
stardust=f.bool()),
are_active=f.bool())
defeated_duke_fishron = f.bool()
defeated_moon_lord = f.bool()
defeated_pumpking = f.bool()
defeated_mourning_wood = f.bool()
defeated_ice_queen = f.bool()
defeated_santa_nk1 = f.bool()
defeated_everscream = f.bool()
defeated_pillars = PillarsInfo(solar=f.bool(), vortex=f.bool(), nebula=f.bool(), stardust=f.bool())
party_center_active = f.bool()
party_natural_active = f.bool()
party_cooldown = f.int4()
partying_npcs_count = f.int4()
partying_npcs = []
for _ in range(partying_npcs_count):
partying_npcs.append(f.int4())
party = Party(thrown_by_party_center=party_center_active,
thrown_by_npcs=party_natural_active,
cooldown=party_cooldown,
partying_npcs=partying_npcs)
lunar_events = LunarEvents(pillars_present=PillarsInfo(solar=f.bool(),
vortex=f.bool(),
nebula=f.bool(),
stardust=f.bool()),
are_active=f.bool())
sandstorm = Sandstorm(is_active=f.bool(),
time_left=f.int4(),
severity=f.single(),
intended_severity=f.single())
party_center_active = f.bool()
party_natural_active = f.bool()
party_cooldown = f.int4()
partying_npcs_count = f.int4()
partying_npcs = []
for _ in range(partying_npcs_count):
partying_npcs.append(f.int4())
party = Party(thrown_by_party_center=party_center_active,
thrown_by_npcs=party_natural_active,
cooldown=party_cooldown,
partying_npcs=partying_npcs)
events = Events(blood_moon=blood_moon,
solar_eclipse=eclipse,
invasion=invasion,
slime_rain=time_left_slime_rain,
rain=rain,
party=party,
sandstorm=sandstorm,
lunar_events=lunar_events)
sandstorm = Sandstorm(is_active=f.bool(),
time_left=f.int4(),
severity=f.single(),
intended_severity=f.single())
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)
events = Events(blood_moon=blood_moon,
solar_eclipse=eclipse,
invasion=invasion,
slime_rain=time_left_slime_rain,
rain=rain,
party=party,
sandstorm=sandstorm,
lunar_events=lunar_events)
old_ones_army = OldOnesArmyTiers(f.bool(), f.bool(), f.bool())
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)
bosses_defeated = BossesDefeated(eye_of_cthulhu=defeated_eye_of_cthulhu,
eater_of_worlds=defeated_eater_of_worlds,
skeletron=defeated_skeletron,
queen_bee=defeated_queen_bee,
the_twins=defeated_the_twins,
the_destroyer=defeated_the_destroyer,
skeletron_prime=defeated_skeletron_prime,
any_mechnical_boss=defeated_any_mechnical_boss,
plantera=defeated_plantera,
golem=defeated_golem,
king_slime=defeated_king_slime,
goblin_army=defeated_goblin_army,
clown=defeated_clown,
frost_moon=defeated_frost_moon,
pirates=defeated_pirates,
duke_fishron=defeated_duke_fishron,
moon_lord=defeated_moon_lord,
pumpking=defeated_pumpking,
mourning_wood=defeated_mourning_wood,
ice_queen=defeated_ice_queen,
santa_nk1=defeated_santa_nk1,
everscream=defeated_everscream,
lunar_pillars=defeated_pillars,
old_ones_army=old_ones_army)
# Tile data starts here
first_tile = cls._read_tiles(f)
old_ones_army = OldOnesArmyTiers(f.bool(), f.bool(), f.bool())
bosses_defeated = BossesDefeated(eye_of_cthulhu=defeated_eye_of_cthulhu,
eater_of_worlds=defeated_eater_of_worlds,
skeletron=defeated_skeletron,
queen_bee=defeated_queen_bee,
the_twins=defeated_the_twins,
the_destroyer=defeated_the_destroyer,
skeletron_prime=defeated_skeletron_prime,
any_mechnical_boss=defeated_any_mechnical_boss,
plantera=defeated_plantera,
golem=defeated_golem,
king_slime=defeated_king_slime,
goblin_army=defeated_goblin_army,
clown=defeated_clown,
frost_moon=defeated_frost_moon,
pirates=defeated_pirates,
duke_fishron=defeated_duke_fishron,
moon_lord=defeated_moon_lord,
pumpking=defeated_pumpking,
mourning_wood=defeated_mourning_wood,
ice_queen=defeated_ice_queen,
santa_nk1=defeated_santa_nk1,
everscream=defeated_everscream,
lunar_pillars=defeated_pillars,
old_ones_army=old_ones_army)
unknown_world_header_data = f.read_until(pointers.world_tiles)
with Timer("World Tiles", display=True):
tiledata = []
while len(tiledata) < world_size.x:
# Read a column
column = []
while len(column) < world_size.y:
tiles = cls._read_tiles(f, tileframeimportant)
column = [*column, *tiles]
tiledata.append(column)
unknown_world_tiles_data = f.read_until(pointers.chests)
breakpoint()
world = World(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,
@ -430,5 +480,4 @@ class World:
saved_npcs=saved_npcs, altars_smashed=altars_smashed, is_hardmode=is_hardmode,
shadow_orbs=shadow_orbs, bosses_defeated=bosses_defeated, anglers_quest=anglers_quest,
clouds=clouds, cultist_delay=cultist_delay)
breakpoint()
return world