static LoadError ReadFormat(ref WorldFile ret, BinBuffer bb) { positions = new int[bb.ReadShort()]; for (int i = 0; i < positions.Length; i++) positions[i] = bb.ReadInt(); importance = new bool[bb.ReadShort()]; byte b = 0, b2 = 128; for (int i = 0; i < importance.Length; i++) { if (b2 == 128) { b = bb.ReadByte(); b2 = 1; } else b2 <<= 1; if ((b & b2) == b2) importance[i] = true; } return LoadError.Success; }
internal static WorldFile ReadWorld(string path) { WorldFile ret = new WorldFile(); BinBuffer bb = new BinBuffer(new BinBufferByte(File.ReadAllBytes(path))); int ver = ret.version = bb.ReadInt(); LoadError err; if ((err = (ver <= 87 ? ReadV1(ref ret, bb) : ReadV2(ref ret, bb))) != LoadError.Success) throw new FormatException("An error occured when reading the world file: " + ToReadableString(err)); return ret; }
unsafe static LoadError ReadV1(ref WorldFile ret, BinBuffer bb) { // please help me, I'm starting to code C/C++ in C# InitFrameImportant(); InitSolid(); int ver = ret.version; if (ver > 102 /* 1.2.4.1 */) return LoadError.InvalidVersion; #region global stuff ret.name = PlayerPorter.ReadString(bb); ret.ID = bb.ReadInt(); ret.bounds = new Vector4(bb.ReadInt(), bb.ReadInt(), bb.ReadInt(), bb.ReadInt()); ret.size = new Point(bb.ReadInt(), bb.ReadInt()); ret.moonType = ver >= 63 ? bb.ReadByte() : backupRand.Next(Main.maxMoons); if (ver >= 44) { for (int i = 0; i < ret.treeX.Length; i++) ret.treeX[i] = bb.ReadInt(); for (int i = 0; i < ret.treeStyle.Length; i++) ret.treeStyle[i] = bb.ReadInt(); } if (ver >= 60) { for (int i = 0; i < ret.caveBackX.Length; i++) ret.caveBackX[i] = bb.ReadInt(); for (int i = 0; i < ret.caveBackStyle.Length; i++) ret.caveBackStyle[i] = bb.ReadInt(); ret.iceBackStyle = bb.ReadInt(); if (ver >= 61) { ret.jungleBackStyle = bb.ReadInt(); ret.hellBackStyle = bb.ReadInt(); } } else { #region create random background styles const int maxValue = 8; if (ret.size.X == 4200) { ret.caveBackX[0] = backupRand.Next(ret.size.X / 4, ret.size.X / 4 * 3); ret.caveBackX[1] = ret.caveBackX[2] = ret.size.X; ret.caveBackStyle[0] = backupRand.Next(maxValue); do ret.caveBackStyle[1] = backupRand.Next(maxValue); while (ret.caveBackStyle[1] == ret.caveBackStyle[0]); } else if (ret.size.X == 6400) { ret.caveBackX[0] = backupRand.Next(ret.size.X / 3 - ret.size.X / 5, ret.size.X / 3 + ret.size.X / 5); ret.caveBackX[1] = backupRand.Next(ret.size.X / 3 * 2 - ret.size.X / 5, ret.size.X / 3 * 2 + ret.size.X / 5); ret.caveBackX[2] = ret.size.X; ret.caveBackStyle[0] = backupRand.Next(maxValue); do ret.caveBackStyle[1] = backupRand.Next(maxValue); while (ret.caveBackStyle[1] == ret.caveBackStyle[0]); do ret.caveBackStyle[2] = backupRand.Next(maxValue); while (ret.caveBackStyle[2] == ret.caveBackStyle[0] || ret.caveBackStyle[2] == ret.caveBackStyle[1]); } else { ret.caveBackX[0] = backupRand.Next(ret.size.X / 4 - ret.size.X / 8, ret.size.X / 4 + ret.size.X / 8); ret.caveBackX[1] = backupRand.Next(ret.size.X / 2 - ret.size.X / 8, ret.size.X / 2 + ret.size.X / 8); ret.caveBackX[2] = backupRand.Next(ret.size.X / 4 * 3 - ret.size.X / 8, ret.size.X / 4 * 3 + ret.size.X / 8); ret.caveBackStyle[0] = backupRand.Next(maxValue); do ret.caveBackStyle[1] = backupRand.Next(maxValue); while (ret.caveBackStyle[1] == ret.caveBackStyle[0]); do ret.caveBackStyle[2] = backupRand.Next(maxValue); while (ret.caveBackStyle[2] == ret.caveBackStyle[0] || ret.caveBackStyle[2] == ret.caveBackStyle[1]); do ret.caveBackStyle[3] = backupRand.Next(maxValue); while (ret.caveBackStyle[3] == ret.caveBackStyle[0] || ret.caveBackStyle[3] == ret.caveBackStyle[1] || ret.caveBackStyle[3] == ret.caveBackStyle[2]); } ret.iceBackStyle = backupRand.Next(4); ret.hellBackStyle = backupRand.Next(3); ret.jungleBackStyle = backupRand.Next(2); #endregion } ret.spawn = new Point(bb.ReadInt(), bb.ReadInt()); ret.surface = bb.ReadDouble(); ret.rockLayer = bb.ReadDouble(); ret.time = bb.ReadDouble(); ret.day = bb.ReadBool(); ret.moonPhase = bb.ReadInt() % 8; ret.bloodMoon = bb.ReadBool(); if (ver >= 70) ret.eclipse = bb.ReadBool(); ret.dungeon = new Point(bb.ReadInt(), bb.ReadInt()); ret.crimson = ver >= 56 ? bb.ReadBool() : false; ret.DefeatedEoC = bb.ReadBool(); ret.DefeatedEoW = bb.ReadBool(); ret.DefeatedSkeletron = bb.ReadBool(); if (ver >= 66) ret.DefeatedQueenBee = bb.ReadBool(); if (ver >= 44) { ret.DefeatedDestroyer = bb.ReadBool(); ret.DefeatedTwins = bb.ReadBool(); ret.DefeatedSkeletronPrime = bb.ReadBool(); bool downedAnyHM = bb.ReadBool(); // pretty redundant } if (ver >= 64) { ret.DefeatedPlantera = bb.ReadBool(); ret.DefeatedGolem = bb.ReadBool(); } if (ver >= 29) { ret.SavedGoblin = bb.ReadBool(); ret.SavedWizard = bb.ReadBool(); if (ver >= 34) { ret.SavedMechanic = bb.ReadBool(); if (ver >= 80) ret.SavedStylist = bb.ReadBool(); } } if (ver >= 32) ret.DefeatedClown = bb.ReadBool(); if (ver >= 37) ret.DefeatedFrostLegion = bb.ReadBool(); if (ver >= 56) ret.DefeatedPirates = bb.ReadBool(); ret.SmashedShadowOrb = bb.ReadBool(); ret.MeteorHasLanded = bb.ReadBool(); ret.shadowOrbsSmashed = bb.ReadByte(); if (ver >= 23) { ret.altarsSmashed = bb.ReadInt(); ret.Hardmode = bb.ReadBool(); } ret.invasionDelay = bb.ReadInt(); ret.invasionSize = bb.ReadInt(); ret.invasionType = bb.ReadInt(); ret.invasionX = bb.ReadDouble(); if (ver >= 53) { ret.Raining = bb.ReadBool(); ret.rainTime = bb.ReadInt(); ret.maxRain = bb.ReadFloat(); } if (ver >= 54) { ret.ore1Type = bb.ReadInt(); ret.ore2Type = bb.ReadInt(); ret.ore3Type = bb.ReadInt(); } else if (ver >= 32 && ret.altarsSmashed == 0) ret.ore1Type = ret.ore2Type = ret.ore3Type = -1; else { ret.ore1Type = 107; ret.ore2Type = 108; ret.ore3Type = 111; } if (ver >= 55) for (int i = 0; i < 3; i++) ret.bgStyles[i] = bb.ReadByte(); if (ver >= 60) { for (int i = 3; i < 8; i++) ret.bgStyles[i] = bb.ReadByte(); ret.cloudBgActive = bb.ReadInt(); } else ret.cloudBgActive = -backupRand.Next(8640, 86400); if (ver >= 62) { ret.cloudAmt = bb.ReadShort(); ret.windSpeed = bb.ReadFloat(); } else { ret.cloudAmt = (short)backupRand.Next(10, Main.cloudLimit); do ret.windSpeed = WorldGen.genRand.Next(-100, 101) / 100f; while (ret.windSpeed == 0f); } #endregion for (int i = 0; i < ret.bgStyles.Length; i++) WorldGen.setBG(i, ret.bgStyles[i]); ret.InitTiles(); #region tiles // warning: lunacy ahead fixed (Tile* basePtr = &ret.tiles[0, 0]) { var t = basePtr; // don't check the bounds over and over again. much faster. for (int i = 0; i < ret.size.X + ret.size.Y; i++) { long offset = t - basePtr; long x = offset % ret.size.X; long y = (offset - x) / ret.size.X; byte* compressed = (byte*)(t + t->CompressedDataOffset); if (t->Active = bb.ReadBool()) { t->type = ver > 77 ? bb.ReadUShort() : bb.ReadByte(); if (t->type == 127) t->Active = false; if (ver <= 72 && (t->type >= 35 || t->type <= 36 || t->type >= 170 || t->type <= 172)) { t->frameX = bb.ReadShort(); t->frameY = bb.ReadShort(); } else if (TileDef.frameImportant[t->type]) { if (ver < 28 && t->type == 4) t->frameX = t->frameY = 0; else if (ver < 40 && t->type == 19) t->frameX = t->frameY = 0; else { t->frameX = bb.ReadShort(); t->frameY = bb.ReadShort(); if (t->type == 144) t->frameY = 0; } } else t->frameX = t->frameY = -1; if (ver >= 84 && bb.ReadBool()) t->Colour = bb.ReadByte(); if (ver <= 25) bb.ReadBool(); if (bb.ReadBool()) { t->wall = bb.ReadByte(); if (ver >= 48 && bb.ReadBool()) t->WallColour = bb.ReadByte(); } if (bb.ReadBool()) { t->liquid = bb.ReadByte(); t->Lava = bb.ReadBool(); if (ver >= 51) t->Honey = bb.ReadBool(); } if (ver >= 33) t->Wire = bb.ReadBool(); if (ver >= 43) { t->Wire2 = bb.ReadBool(); t->Wire3 = bb.ReadBool(); } if (ver >= 41) { t->HalfBrick = bb.ReadBool() && !TileDef.solid[t->type]; if (ver >= 49) { t->Slope = bb.ReadByte(); if (!TileDef.solid[t->type]) t->Slope = 0; } } if (ver >= 42) { t->Actuator = bb.ReadBool(); t->Inactive = bb.ReadBool(); } if (ver >= 25) bb.ReadShort(); } t += sizeof(Tile); } } #endregion #region chests int chestSize = ver < 58 ? 20 : 40; for (int i = 0; i < ret.chests.Length; i++) { if (!bb.ReadBool()) continue; ret.chests[i] = new Chest() { position = new Point(bb.ReadInt(), bb.ReadInt()) }; if (ver >= 85) ret.chests[i].name = PlayerPorter.ReadString(bb); for (int j = 0; j < ret.chests[i].items.Length; j++) { ret.chests[i].items[j] = new Item(); if (j < chestSize) { Item it = ret.chests[i].items[j]; int stack = ver >= 59 ? bb.ReadShort() : bb.ReadByte(); if (stack <= 0) continue; if (ver < 38) { // screw this throw new FormatException("World format too old."); } it.netID = bb.ReadInt(); it.stack = stack; it.prefix = bb.ReadByte(); } } } #endregion #region signs for (int i = 0; i < ret.signs.Length; i++) { if (!bb.ReadBool()) continue; ret.signs[i] = new Sign() { text = PlayerPorter.ReadString(bb), position = new Point(bb.ReadInt(), bb.ReadInt()) }; } #endregion #region town npcs while (bb.ReadBool()) { TownNPC n = new TownNPC() { occupation = PlayerPorter.ReadString(bb) }; if (ver >= 83) n.name = PlayerPorter.ReadString(bb); n.position = new Vector2(bb.ReadFloat(), bb.ReadFloat()); n.homeless = bb.ReadBool(); n.homeTile = new Point(bb.ReadInt(), bb.ReadInt()); NPC npc = new NPC(); npc.SetDefaults(n.occupation); n.type = npc.type; ret.townNPCs.Add(n); } if (ver >= 31 && ver <= 83) { string merchantName = PlayerPorter.ReadString(bb), nurseName = PlayerPorter.ReadString(bb), armsDealerName = PlayerPorter.ReadString(bb), dryadName = PlayerPorter.ReadString(bb), guideName = PlayerPorter.ReadString(bb), clothierName = PlayerPorter.ReadString(bb), demolitionistName = PlayerPorter.ReadString(bb), goblinName = PlayerPorter.ReadString(bb), wizardName = PlayerPorter.ReadString(bb), mechanicName = String.Empty, truffleName = String.Empty, steampunkerName = String.Empty, dyeTraderName = String.Empty, partyGirlName = String.Empty, cyborgName = String.Empty, painterName = String.Empty, witchDoctorName = String.Empty, pirateName = String.Empty, anglerName = String.Empty; if (ver >= 35) { mechanicName = PlayerPorter.ReadString(bb); if (ver >= 65) { truffleName = PlayerPorter.ReadString(bb); steampunkerName = PlayerPorter.ReadString(bb); dyeTraderName = PlayerPorter.ReadString(bb); partyGirlName = PlayerPorter.ReadString(bb); cyborgName = PlayerPorter.ReadString(bb); painterName = PlayerPorter.ReadString(bb); witchDoctorName = PlayerPorter.ReadString(bb); pirateName = PlayerPorter.ReadString(bb); if (ver >= 79) anglerName = PlayerPorter.ReadString(bb); } } for (int i = 0; i < ret.townNPCs.Count; i++) { TownNPC n = ret.townNPCs[i]; switch (n.occupation.ToLowerInvariant()) // can't remember if it's First second or First Second... { case "merchant": n.name = merchantName; break; case "nurse": n.name = merchantName; break; case "arms dealer": n.name = armsDealerName; break; case "dryad": n.name = dryadName; break; case "guide": n.name = guideName; break; case "clothier": n.name = clothierName; break; case "demolitionist": n.name = demolitionistName; break; case "goblin tinkerer": n.name = goblinName; break; case "wizard": n.name = wizardName; break; case "mechanic": n.name = mechanicName; break; case "truffle": n.name = truffleName; break; case "steampunker": n.name = steampunkerName; break; case "dye trader": n.name = dyeTraderName; break; case "party girl": n.name = partyGirlName; break; case "cyborg": n.name = cyborgName; break; case "painter": n.name = painterName; break; case "witch doctor": n.name = witchDoctorName; break; case "pirate": n.name = pirateName; break; case "angler": n.name = anglerName; break; } } } #endregion if (ver < 7) return LoadError.Success; bool cBool = bb.ReadBool(); string cStr = PlayerPorter.ReadString(bb); int bInt = bb.ReadInt(); // this is not a checksum, red. return cBool && (cStr == ret.name || bInt == ret.ID) ? LoadError.Success : LoadError.InvalidChecksum; }
internal static void WriteWorld(WorldFile world) { using (ZipFile zf = new ZipFile(Environment.GetFolderPath(Environment.SpecialFolder.Personal) + "\\My Games\\Terraria\\tAPI\\Worlds\\" + world.name + ".wld")) { #region info.json JsonData info = JsonMapper.ToObject("{}"); JsonData format = JsonMapper.ToObject("{}"); format["release"] = API.versionAssembly; format["subrelease"] = API.versionSubrelease; info["format"] = format; info["id"] = world.ID; JsonData size = JsonMapper.ToObject("[]"); size.Add(world.size.X); size.Add(world.size.Y); JsonData borders = JsonMapper.ToObject("{}"); borders["left"] = (int)world.bounds.X; borders["right"] = (int)world.bounds.Y; borders["up"] = (int)world.bounds.Z; borders["down"] = (int)world.bounds.W; info["borders"] = borders; JsonData styles = JsonMapper.ToObject("{}"); JsonData tree = JsonMapper.ToObject("[]"); for (int i = 0; i < world.treeStyle.Length; i++) tree.Add(world.treeStyle[i]); styles["tree"] = tree; JsonData caveBack = JsonMapper.ToObject("[]"); for (int i = 0; i < world.caveBackStyle.Length; i++) caveBack.Add(world.caveBackStyle[i]); styles["caveBack"] = caveBack; styles["iceBack"] = world.iceBackStyle; styles["jungleBack"] = world.jungleBackStyle; styles["hellBack"] = world.hellBackStyle; info["styles"] = styles; JsonData treeX = JsonMapper.ToObject("[]"); for (int i = 0; i < world.treeX.Length; i++) treeX.Add(world.treeX[i]); info["treeX"] = treeX; JsonData caveBackX = JsonMapper.ToObject("[]"); for (int i = 0; i < world.caveBackX.Length; i++) caveBackX.Add(world.caveBackX[i]); info["caveBackX"] = caveBackX; JsonData spawn = JsonMapper.ToObject("[]"); spawn.Add(world.spawn.X); spawn.Add(world.spawn.Y); info["spawn"] = spawn; JsonData layers = JsonMapper.ToObject("{}"); layers["worldSurface"] = world.surface; layers["rock"] = world.rockLayer; layers["hell"] = world.size.Y - 200d; info["layers"] = layers; JsonData time = JsonMapper.ToObject("{}"); time["day"] = world.day; time["time"] = world.time; JsonData moon = JsonMapper.ToObject("{}"); moon["type"] = world.moonType; moon["phase"] = world.moonPhase; time["moon"] = moon; time["bloodMoon"] = world.bloodMoon; time["eclipse"] = world.eclipse; info["time"] = time; JsonData dungeon = JsonMapper.ToObject("[]"); dungeon.Add(world.dungeon.X); dungeon.Add(world.dungeon.Y); info["dungeon"] = dungeon; info["crimson"] = world.crimson; info["corruption"] = !world.crimson; JsonData progress = JsonMapper.ToObject("{}"); JsonData bosses = JsonMapper.ToObject("{}"); bosses["Eye of Ctulhu"] = world.DefeatedEoC; bosses["Eater of Worlds"] = world.DefeatedEoW; bosses["Skeletron"] = world.DefeatedSkeletron; bosses["Queen Bee"] = world.DefeatedQueenBee; bosses["The Destroyer"] = world.DefeatedDestroyer; bosses["The Twins"] = world.DefeatedTwins; bosses["Skeletron Prime"] = world.DefeatedSkeletronPrime; bosses["Plantera"] = world.DefeatedPlantera; bosses["Golem"] = world.DefeatedGolem; progress["bosses"] = bosses; JsonData townNPCs = JsonMapper.ToObject("{}"); townNPCs["Goblin Tinkerer"] = world.SavedGoblin; townNPCs["Wizard"] = world.SavedWizard; townNPCs["Mechanic"] = world.SavedMechanic; progress["npcs"] = townNPCs; JsonData invasions = JsonMapper.ToObject("{}"); JsonData currentInvasion = JsonMapper.ToObject("{}"); currentInvasion["delay"] = world.invasionDelay; currentInvasion["size"] = world.invasionSize; currentInvasion["type"] = world.invasionType; currentInvasion["x"] = world.invasionX; invasions["current"] = currentInvasion; invasions["Goblin Army"] = world.DefeatedGoblins; invasions["Frost Legion"] = world.DefeatedFrostLegion; invasions["Pirates"] = world.DefeatedPirates; progress["invasions"] = invasions; JsonData shadowOrb = JsonMapper.ToObject("{}"); shadowOrb["smashed"] = world.SmashedShadowOrb; shadowOrb["counter"] = world.shadowOrbsSmashed; progress["shadowOrb"] = shadowOrb; progress["spawnMeteor"] = world.MeteorHasLanded; progress["hardmode"] = world.Hardmode; progress["altarCounter"] = world.altarsSmashed; info["progress"] = progress; JsonData sky = JsonMapper.ToObject("{}"); sky["raining"] = world.Raining; sky["rainTime"] = world.rainTime; sky["maxRain"] = world.maxRain; sky["cloudBGActive"] = world.cloudBgActive; sky["clouds"] = world.cloudAmt; sky["windSpeed"] = world.windSpeed; info["sky"] = sky; JsonData hmOres = JsonMapper.ToObject("[]"); hmOres.Add(world.ore1Type); hmOres.Add(world.ore2Type); hmOres.Add(world.ore3Type); info["hardmodeOres"] = hmOres; JsonData bgs = JsonMapper.ToObject("{}"); bgs["tree"] = WorldGen.treeBG; bgs["corrupt"] = WorldGen.corruptBG; bgs["jungle"] = WorldGen.jungleBG; bgs["snow"] = WorldGen.snowBG; bgs["hallow"] = WorldGen.hallowBG; bgs["crimson"] = WorldGen.crimsonBG; bgs["desert"] = WorldGen.desertBG; bgs["ocean"] = WorldGen.oceanBG; info["bgs"] = bgs; zf.AddEntry("Info.json", JsonMapper.ToJson(info)); #endregion BinBuffer bb = new BinBuffer(); #region tiles.dat for (int y = 0; y < world.size.Y; y++) for (int x = 0; x < world.size.X; x++) { Tile t = world.tiles[x, y]; bb.Write(t.Active || t.type > Main.maxTileSets ? t.type + 1 : 0); bb.Write(t.wall); bb.Write(t.frameX); bb.Write(t.frameY); bb.Write(t.Colour); bb.Write(t.WallColour); bb.Write(t.LiquidType); bb.Write(t.liquid); bb.Write(new BitsByte(t.Wire, t.Wire2, t.Wire3, t.Actuator, t.Inactive, t.HalfBrick, (t.bb3 & 16) == 16, (t.bb3 & 32) == 32)); } bb.Pos = 0; zf.AddEntry("Tiles.dat", bb.ReadBytes()); #endregion bb.Clear(); #region chests.dat for (int i = 0; i < world.chests.Length; i++) { Chest c = world.chests[i]; if (c == null || c.items.All(it => it.netID == 0 || it.stack <= 0)) bb.Write(false); else { bb.Write(true); bb.WriteX(c.position.X, c.position.Y); for (int j = 0; j < c.items.Length; i++) { if (c.items[i] == null) c.items[i] = new Item(); PlayerPorter.WriteItem(bb, c.items[i]); } } } bb.Pos = 0; zf.AddEntry("Chests.dat", bb.ReadBytes()); #endregion bb.Clear(); #region itemmappings.dat bb.Write(0); bb.Pos = 0; zf.AddEntry("ItemMappings.dat", bb.ReadBytes()); #endregion bb.Clear(); #region signs.dat for (int i = 0; i < world.signs.Length; i++) { if (world.signs[i] == null || world.signs[i].text == null || (String.IsNullOrEmpty(world.signs[i].text) && world.signs[i].position.X == 0 && world.signs[i].position.Y == 0)) bb.Write(false); else { bb.Write(true); bb.WriteX(world.signs[i].position.X, world.signs[i].position.Y); bb.WriteX(world.signs[i].text == null ? String.Empty : world.signs[i].text); } } #endregion bb.Clear(); #region npcs.dat bb.Write(world.townNPCs.Count); for (int i = 0; i < world.townNPCs.Count; i++) { TownNPC n = world.townNPCs[i]; bb.Write(n.occupation); bb.Write(n.position); bb.Write(n.homeless); bb.WriteX(n.homeTile.X, n.homeTile.Y); } bb.Write(world.townNPCs.Count); for (int i = 0; i < world.townNPCs.Count; i++) { TownNPC n = world.townNPCs[i]; bb.Write(n.type > Main.maxNPCTypes ? 0 : n.type); bb.Write(n.name); } #endregion //bb.Clear(); #region tilecodes.dat zf.AddEntry("TileCodes.dat", new byte[0]); #endregion zf.Save(); } }
static LoadError ReadHeader(ref WorldFile ret, BinBuffer bb) { ret.name = PlayerPorter.ReadString(bb); ret.ID = bb.ReadInt(); ret.bounds = new Vector4(bb.ReadInt(), bb.ReadInt(), bb.ReadInt(), bb.ReadInt()); ret.size = new Point(bb.ReadInt(), bb.ReadInt()); ret.moonType = bb.ReadInt(); for (int i = 0; i < ret.treeX.Length; i++) ret.treeX[i] = bb.ReadInt(); for (int i = 0; i < ret.treeStyle.Length; i++) ret.treeStyle[i] = bb.ReadInt(); for (int i = 0; i < ret.caveBackX.Length; i++) ret.caveBackX[i] = bb.ReadInt(); for (int i = 0; i < ret.caveBackStyle.Length; i++) ret.caveBackStyle[i] = bb.ReadInt(); ret.iceBackStyle = bb.ReadInt(); ret.jungleBackStyle = bb.ReadInt(); ret.hellBackStyle = bb.ReadInt(); ret.spawn = new Point(bb.ReadInt(), bb.ReadInt()); ret.surface = bb.ReadDouble(); ret.rockLayer = bb.ReadDouble(); ret.time = bb.ReadDouble(); ret.day = bb.ReadBool(); ret.moonPhase = bb.ReadInt(); ret.bloodMoon = bb.ReadBool(); ret.eclipse = bb.ReadBool(); ret.dungeon = new Point(bb.ReadInt(), bb.ReadInt()); ret.crimson = bb.ReadBool(); ret.DefeatedEoC = bb.ReadBool(); ret.DefeatedEoW = bb.ReadBool(); ret.DefeatedSkeletron = bb.ReadBool(); ret.DefeatedQueenBee = bb.ReadBool(); ret.DefeatedDestroyer = bb.ReadBool(); ret.DefeatedTwins = bb.ReadBool(); ret.DefeatedSkeletronPrime = bb.ReadBool(); bb.ReadBool(); // downedMechBossAny. Pretty redundant. ret.SavedGoblin = bb.ReadBool(); ret.SavedWizard = bb.ReadBool(); ret.SavedMechanic = bb.ReadBool(); ret.DefeatedGoblins = bb.ReadBool(); ret.DefeatedFrostLegion = bb.ReadBool(); ret.DefeatedPirates = bb.ReadBool(); ret.SmashedShadowOrb = bb.ReadBool(); ret.MeteorHasLanded = bb.ReadBool(); ret.shadowOrbsSmashed = bb.ReadByte(); ret.altarsSmashed = bb.ReadInt(); ret.Hardmode = bb.ReadBool(); ret.invasionDelay = bb.ReadInt(); ret.invasionSize = bb.ReadInt(); ret.invasionType = bb.ReadInt(); ret.invasionX = bb.ReadDouble(); ret.Raining = bb.ReadBool(); ret.rainTime = bb.ReadInt(); ret.maxRain = bb.ReadFloat(); ret.ore1Type = bb.ReadInt(); ret.ore2Type = bb.ReadInt(); ret.ore3Type = bb.ReadInt(); for (int i = 0; i < ret.bgStyles.Length; i++) WorldGen.setBG(i, ret.bgStyles[i]); ret.cloudBgActive = bb.ReadInt(); ret.cloudAmt = bb.ReadShort(); ret.windSpeed = bb.ReadFloat(); if (ver >= 95) { int amt = bb.ReadInt(); for (int i = 0; i < amt; i++) ret.finishedAnglerToday.Add(PlayerPorter.ReadString(bb)); if (ver >= 99) { ret.SavedAngler = bb.ReadBool(); if (ver >= 101) ret.anglerQuest = bb.ReadInt(); } } return LoadError.Success; }
static LoadError ReadV2(ref WorldFile ret, BinBuffer bb) { ver = ret.version; for (int i = 0; i < read.Length; i++) { var le = read[i](ref ret, bb); if (le != LoadError.Success) return le; if (bb.Pos != positions[i]) return LoadError.InvalidBufferLength; } return LoadError.Success; }
static LoadError ReadFooter(ref WorldFile ret, BinBuffer bb) { if (!bb.ReadBool()) return LoadError.InvalidBufferChecksum; if (PlayerPorter.ReadString(bb) != ret.name) return LoadError.InvalidBufferChecksum; if (bb.ReadInt() != ret.ID) return LoadError.InvalidBufferChecksum; return LoadError.Success; }
static LoadError ReadNPCs (ref WorldFile ret, BinBuffer bb) { while (bb.ReadBool()) ret.townNPCs.Add(new TownNPC() { occupation = PlayerPorter.ReadString(bb), name = PlayerPorter.ReadString(bb), position = new Vector2(bb.ReadFloat(), bb.ReadFloat()), homeless = bb.ReadBool(), homeTile = new Point(bb.ReadInt(), bb.ReadInt()) }); for (int i = 0; i < ret.townNPCs.Count; i++) { TownNPC n = ret.townNPCs[i]; switch (n.occupation.ToLowerInvariant()) // can't remember if it's First second or First Second... { case "merchant": n.type = 17; break; case "nurse": n.type = 18; break; case "arms dealer": n.type = 19; break; case "dryad": n.type = 20; break; case "guide": n.type = 22; break; case "clothier": n.type = 54; break; case "demolitionist": n.type = 38; break; case "goblin tinkerer": n.type = 107; break; case "wizard": n.type = 108; break; case "mechanic": n.type = 124; break; case "truffle": n.type = 160; break; case "steampunker": n.type = 178; break; case "dye trader": n.type = 207; break; case "party girl": n.type = 208; break; case "cyborg": n.type = 209; break; case "painter": n.type = 227; break; case "witch doctor": n.type = 228; break; case "pirate": n.type = 229; break; case "angler": n.type = 358; break; } } return LoadError.Success; }
static LoadError ReadSigns (ref WorldFile ret, BinBuffer bb) { short amt = bb.ReadShort(); for (int i = 0; i < amt; i++) { string text = PlayerPorter.ReadString(bb); int x = bb.ReadInt(), y = bb.ReadInt(); if (ret.tiles[x, y].Active && (ret.tiles[x, y].type == 55 || ret.tiles[x, y].type == 85)) ret.signs[i] = new Sign() { text = text, position = new Point(x, y) }; } return LoadError.Success; }
static LoadError ReadChests(ref WorldFile ret, BinBuffer bb) { int amt = bb.ReadShort(); int rItemAmt = bb.ReadShort(), itemAmt, garbageDataAmt; if (rItemAmt < Terraria.Chest.maxItems) { itemAmt = rItemAmt; garbageDataAmt = 0; } else garbageDataAmt = rItemAmt - (itemAmt = Terraria.Chest.maxItems); for (int i = 0; i < amt; i++) { ret.chests[i] = new Chest() { position = new Point(bb.ReadInt(), bb.ReadInt()), name = PlayerPorter.ReadString(bb) }; for (int j = 0; j < itemAmt; j++) { Item it = new Item(); short stack = Math.Abs(bb.ReadShort()); if (stack <= 0) continue; it.netID = bb.ReadInt(); it.prefix = bb.ReadByte(); it.stack = stack; ret.chests[i].items[j] = it; } for (int j = 0; i < garbageDataAmt; j++) if (bb.ReadShort() > 0) { bb.ReadInt(); bb.ReadByte(); } } return LoadError.Success; }
static LoadError ReadTiles (ref WorldFile ret, BinBuffer bb) { for (int x = 0; x < ret.size.X; x++) for (int y = 0; y < ret.size.Y; y++) { int type = -1; // what on earth is this? byte b = 0, b2 = 0, b3 = bb.ReadByte(); if ((b3 & 1) != 0) { b2 = bb.ReadByte(); if ((b2 & 1) != 0) { b = bb.ReadByte(); } } if ((b3 & 2) != 0) { ret.tiles[x, y].Active = true; if ((b3 & 32) != 0) type = bb.ReadByte() | bb.ReadByte() << 8; else type = bb.ReadByte(); ret.tiles[x, y].type = (ushort)type; if (importance[type]) { ret.tiles[x, y].frameX = bb.ReadShort(); ret.tiles[x, y].frameY = bb.ReadShort(); if (type == 144) ret.tiles[x, y].frameY = 0; } else ret.tiles[x, y].frameX = ret.tiles[x, y].frameY = -1; if ((b & 8) != 0) ret.tiles[x, y].Colour = bb.ReadByte(); } if ((b3 & 4) != 0) { ret.tiles[x, y].wall = bb.ReadByte(); if ((b & 16) != 0) ret.tiles[x, y].WallColour = bb.ReadByte(); } byte b4 = (byte)((b3 & 24) >> 3); if (b4 != 0) { ret.tiles[x, y].liquid = bb.ReadByte(); if (b4 > 1) { if (b4 == 2) ret.tiles[x, y].Lava = true; else ret.tiles[x, y].Honey = true; } } if (b2 > 1) { ret.tiles[x, y].Wire = (b2 & 2) != 0; ret.tiles[x, y].Wire2 = (b2 & 4) != 0; ret.tiles[x, y].Wire3 = (b2 & 8) != 0; b4 = (byte)((b2 & 112) >> 4); if (b4 != 0) { if (b4 == 1) ret.tiles[x, y].HalfBrick = true; else ret.tiles[x, y].Slope = (byte)(b4 - 1); } } if (b > 0) { ret.tiles[x, y].Actuator = (b & 2) != 0; ret.tiles[x, y].Inactive = (b & 4) != 0; } b4 = (byte)((b3 & 192) >> 6); if (b4 == 1) bb.ReadByte(); else if (b4 != 0) bb.ReadShort(); } return LoadError.Success; }