/// <summary> /// Creates a setBlock like from the given arguments /// </summary> /// <param name="s">The schematic to pull from</param> /// <param name="imports">The imports list to modify as needed</param> /// <param name="x">X</param> /// <param name="y">Y</param> /// <param name="z">Z</param> /// <param name="chunkX">Chunk X</param> /// <param name="chunkZ">Chunk Z</param> /// <returns>The generated setBlock line</returns> public static string MakeSetBlockLine(Schematic s, ref List <string> imports, int x, int y, int z, int chunkX, int chunkZ) { var b = s.GetBlockAt(x, y, z); var sb = new StringBuilder(); sb.AppendFormat("{4}b(w,i+{0},j+{1},k+{2},{3},0);\r\n", x - chunkX, y, z - chunkZ, b.GetName(), "\t\t"); if (s.GetBlockMetadataAt(x, y, z) != 0) { sb.AppendFormat("{4}m(w,i+{0},j+{1},k+{2},{3});\r\n", x - chunkX, y, z - chunkZ, s.GetBlockMetadataAt(x, y, z), "\t\t"); } return(sb.ToString().Replace("+0", "")); }
/// <summary> /// Exports the given schematic following the given export options /// </summary> /// <param name="options">The export options</param> /// <param name="schematic">The schematic to export</param> /// <returns>The number of chunks exported</returns> public static int Export(ExportOptions options, Schematic schematic) { var gen = new StringBuilder(); var first = true; gen.AppendLine(HeaderComment()); gen.AppendLine("if (this.locY == 0)"); gen.AppendLine("\tthis.locY = (int)MathUtils.map(this.rootHeight, -2, 2, 0, 128);\n"); var chunks = 0; if (!Directory.Exists("output/" + options.Path)) { Directory.CreateDirectory("output/" + options.Path); } for (var x = 0; x < schematic.Width; x += 16) { for (var z = 0; z < schematic.Length; z += 16) { var classTitle = Utils.UpperFirst(string.Format(options.ClassName, string.Format("_x{0}_z{1}", x, z))); Console.Title = string.Format("SchematicExporter - Exporting {0}...", classTitle); ChunkExport.Export(options, schematic, x, z); chunks++; gen.AppendLine(string.Format("{0}if (chunkX == {1} && chunkZ == {2})", first ? "" : "else ", x, z)); gen.AppendLine( string.Format("\t{0}.generate(world, chunkX, this.locY, chunkZ);", classTitle)); first = false; } } using (var w = new StreamWriter("output/" + options.Path + "/" + string.Format(options.FileName, "Generator"))) w.WriteLine(gen); return(chunks); }
/// <summary> /// Creates a chest from a NbtCompound'ed TileEntity /// </summary> /// <param name="s">The schematic to pull from</param> /// <param name="imports">The imports list to modify as needed</param> /// <param name="chestId">The ID of the chest (variable suffix)</param> /// <param name="x">X</param> /// <param name="y">Y</param> /// <param name="z">Z</param> /// <param name="linePrefix">The line prefix</param> /// <returns>The generated line</returns> public static string MakeChest(ref Schematic s, ref List <string> imports, int chestId, int x, int y, int z, string linePrefix) { var sb = new StringBuilder(); var c = s.GetTileEntityAt(x, y, z); if (c == null) { return(sb.ToString()); } if (((NbtList)c["Items"]).Count == 0 && Arguments.EmptyChestRandom) { sb.Clear(); sb.AppendLine( string.Format( "{0}LootGenUtils.fillLootChest(w.provider.dimensionId, w.rand, (TileEntityChest)w.getTileEntity(i + {1}, j + {2}, k + {3}));", linePrefix, x, y, z)); imports.Require("com.parzivail.pswm.utils.LootGenUtils"); return(sb.ToString()); } sb.AppendLine( string.Format( "{0}TileEntityChest chest{4} = (TileEntityChest)w.getTileEntity(i + {1}, j + {2}, k + {3});", linePrefix, x, y, z, chestId)); imports.Require("net.minecraft.tileentity.TileEntityChest"); foreach (var nbtTag in (NbtList)c["Items"]) { var itemstack = (NbtCompound)nbtTag; int slot = itemstack["Slot"].ByteValue; int id = itemstack["id"].ShortValue; int count = itemstack["Count"].ByteValue; int damage = itemstack["Damage"].ShortValue; if (slot == 0) { if (id == IdMapper.Instance.GetIdFromItem("blaze_rod")) // blaze rod in top left = randomize loot { sb.Clear(); sb.Append( string.Format( "{0}LootGenUtils.fillLootChest(w.provider.dimensionId, w.rand, (TileEntityChest)w.getTileEntity(i + {1}, j + {2}, k + {3});", linePrefix, x, y, z)); imports.Require("com.parzivail.pswm.utils.LootGenUtils"); break; } if (id == IdMapper.Instance.GetIdFromItem("lever") && !Arguments.IgnoreChestToEntity) // lever in top left = spawn entity { sb.Clear(); var item = (NbtCompound)c["Items"][1]; // slot 2 var n = IdMapper.Instance.GetItemFromId(item["id"].ShortValue); var e = IdMapper.Instance.GetEntityFromAssociation(n); if (e != null) { s.SetFlagAt(x, y, z, true); imports.Require(e.GetQualifiedName()); return(MakeEntitySpawn(e, chestId, x, y, z, "\t\t")); } break; } } //new ItemStack(item, size, meta) sb.AppendLine(string.Format("{0}chest{5}.setInventorySlotContents({1}, new ItemStack({2}, {3}, {4}));", linePrefix, slot, IdMapper.Instance.GetItemFromId(id).CreateJavaVariable(), count, damage, chestId)); var nsp = IdMapper.Instance.GetItemFromId(id).GetNamespacePrefix(); switch (nsp) { case IdMapper.ClassBlocks: imports.Require("net.minecraft.init.Blocks"); break; case IdMapper.ClassItems: imports.Require("net.minecraft.init.Items"); break; case IdMapper.ClassPswm: imports.Require("com.parzivail.pswm.StarWarsMod"); break; } } return(sb.ToString()); }
private static void Main(string[] args) { Arguments.EmptyChestRandom = false; Arguments.IgnoreAirBlocks = false; Arguments.IgnoreChestToEntity = false; Arguments.UseTemplate = "default.java"; Arguments.UsePackage = "your.mod.pkg"; Arguments.UseBlocks = "blocks.txt"; Arguments.UseItems = "items.txt"; Console.ForegroundColor = ConsoleColor.White; Console.Title = "SchematicExporter - Ready"; if (!Directory.Exists("logs/")) { Directory.CreateDirectory("logs/"); } _logWriter = new StreamWriter(string.Format("logs/log-{0}.log", DateTime.Now.Ticks)); _logWriter.WriteLine("Running with args: {0}\n\n", string.Join(", ", args)); if (args.Length > 0) { foreach (var s in args) { switch (s) { case "-emptyloot": Arguments.EmptyChestRandom = true; Console.WriteLine("Custom Setting: empty chests will be filled with random loot"); break; case "-ignoreair": Arguments.IgnoreAirBlocks = true; Console.WriteLine("Custom Setting: air blocks will not be exported"); break; case "-r": Arguments.SearchRecursive = true; Console.WriteLine("Custom Setting: input directory searched recursively"); break; case "-nochestentity": Arguments.IgnoreChestToEntity = true; Console.WriteLine( "Custom Setting: chests with entity selectors inside will not export as entities"); break; case "-help": Console.WriteLine("Available arguments:"); Console.WriteLine( "-emptyloot\n\tEmpty chests (instead of blaze rod in top left corner) will be filled with random loot"); Console.WriteLine( "-template:<template file>\n\tOutout will be generated based off of template/<template file>" + "\n\tPlaceholders:" + "\n\t\t{{CLASS_COMMENT}}" + "\n\t\t{{PACKAGE}}" + "\n\t\t{{CLASS}}" + "\n\t\t{{GEN_METHODS}}" + "\n\t\t{{IMPORTS}}"); Console.WriteLine("-package:<package>\n\tThe package for the file to be exported for"); Console.WriteLine("-blocks:<blocks>\n\tThe dictionary file to pull blocks from"); Console.WriteLine("-items:<items>\n\tThe dictionary file to pull items from"); Console.WriteLine("-ignoreair\n\tAir blocks will not be exported"); Console.WriteLine("-r\n\tInput directory will be searched recursively"); Console.WriteLine( "-nochestentity\n\tChests with entity selectors inside will not export as entities"); Console.WriteLine("Press any key to exit..."); Console.ReadKey(); Environment.Exit(0); break; default: if (new Regex("-template:(\\S+)").IsMatch(s)) { Arguments.UseTemplate = s.Split(':')[1]; Console.WriteLine("Custom Setting: using template/{0}", Arguments.UseTemplate); } else if (new Regex("-package:(\\S+)").IsMatch(s)) { Arguments.UsePackage = s.Split(':')[1]; Console.WriteLine("Custom Setting: using package {0}", Arguments.UsePackage); } else if (new Regex("-blocks:(\\S+)").IsMatch(s)) { Arguments.UseBlocks = s.Split(':')[1]; Console.WriteLine("Custom Setting: using block dictionary data/{0}", Arguments.UseBlocks); } else if (new Regex("-items:(\\S+)").IsMatch(s)) { Arguments.UseItems = s.Split(':')[1]; Console.WriteLine("Custom Setting: using item dictionary data/{0}", Arguments.UseItems); } else { Console.WriteLine("Invalid argument: \"{0}\"", s); Console.WriteLine("Use \"-help\" for a list of available arguments"); } break; } } Console.WriteLine(); } // Check I/O directories if (!Directory.Exists("input/")) { Directory.CreateDirectory("input/"); Console.WriteLine("Created input directory"); _logWriter.WriteLine("Input directory not found, created one."); } if (!Directory.Exists("output/")) { Directory.CreateDirectory("output/"); Console.WriteLine("Created output directory"); _logWriter.WriteLine("Output directory not found, created one."); } // Draw the header Console.WriteLine("{0}{1}{2}{3}{4}{5}{6}{7}", "File".PadRight(40), "Iterate".PadRight(10), "Blocks".PadRight(10), "Tiles".PadRight(10), "Methods".PadRight(10), "Write".PadRight(10), "Total".PadRight(10), "Filesize".PadRight(10)); Console.WriteLine("".PadRight(110, '=')); // Start a stopwatch to time the exports var totalElapse = new Stopwatch(); totalElapse.Start(); // File counter var files = 0; foreach (var rFile in Utils.GetFiles("input", "*.schematic", Arguments.SearchRecursive)) { //load the schematic var s = new Schematic(rFile); _logWriter.WriteLine("Loaded schematic {0}, found {1} blocks", rFile, s.Size()); var upperFirstName = Utils.UpperFirst(Path.GetFileNameWithoutExtension(rFile)); // Set how you want to export var options = new ExportOptions("WorldGen" + upperFirstName + "{0}.java", Arguments.UsePackage, "WorldGen" + upperFirstName + "{0}", Path.GetDirectoryName(rFile).Substring(5)); _logWriter.WriteLine("Exporting with options: className={0}, package={1}", string.Format(options.ClassName, ""), options.Package); // Actually export the schematic var oldChunks = Metrics.TotalChunks; _logWriter.Write("Exporting chunks... "); try { Metrics.TotalChunks += Exporter.Export(options, s); _logWriter.WriteLine("Exported {0} chunks", Metrics.TotalChunks - oldChunks); } catch (Exception exception) { Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine("\nError while exporting, check log for details!\n"); _logWriter.WriteLine("Error while exporting {0}: {1}\n{2}", rFile, exception.Message, exception.StackTrace); } _logWriter.WriteLine(); Console.ForegroundColor = ConsoleColor.DarkCyan; files++; } totalElapse.Stop(); Console.Title = "SchematicExporter - Done"; Console.ForegroundColor = ConsoleColor.White; Console.WriteLine(); Console.WriteLine("Done exporting {0:n0} file{3} ({2:n0} chunk{4}) in {1}", files, Utils.MillisToHrd(totalElapse.ElapsedMilliseconds), Metrics.TotalChunks, files == 1 ? "" : "s", Metrics.TotalChunks == 1 ? "" : "s"); if (Metrics.TotalChunks > 0) { Console.WriteLine("\tAverage Time\t\t{0}", Utils.MillisToHrd(totalElapse.ElapsedMilliseconds / Metrics.TotalChunks)); Console.WriteLine("\tAverage Files/Second\t{0:n0}", 1000 / ((float)totalElapse.ElapsedMilliseconds / Metrics.TotalChunks)); Console.WriteLine("\tBlocks (incl. air)\t{0:n0}", Metrics.TotalBlocks); Console.WriteLine("\tTiles\t\t\t{0:n0}", Metrics.TotalTiles); Console.WriteLine("\tAverage Filesize\t{0}", Utils.SizeSuffix(Metrics.TotalFilesize / Metrics.TotalChunks)); Console.WriteLine("\tTotal Filesize\t\t{0}", Utils.SizeSuffix(Metrics.TotalFilesize)); Console.WriteLine("\tChunks over 1 MB\t{0:n0} ({1}%)", Metrics.FilesOverOneMeg, 100 * Metrics.FilesOverOneMeg / Metrics.TotalChunks); } _logWriter.Close(); Console.Read(); }
/// <summary> /// Exports a single chunk /// </summary> /// <param name="options">The export options</param> /// <param name="schematic">The schematic to export</param> /// <param name="chunkX">The chunk X to export</param> /// <param name="chunkZ">The chunk Y to export</param> public static void Export(ExportOptions options, Schematic schematic, int chunkX, int chunkZ) { if (!Directory.Exists("template/")) { Directory.CreateDirectory("template/"); } Console.ForegroundColor = ConsoleColor.White; string clazz = string.Format(options.ClassName, string.Format("_x{0}_z{1}", chunkX, chunkZ)); Console.Write((clazz.Length <= 38 ? clazz : "..." + clazz.Substring(clazz.Length - 35, 35)).PadRight(40)); // Load the java template var template = Utils.RequireFile(string.Format("template/{0}", Arguments.UseTemplate)).ReadToEnd(); Console.ForegroundColor = ConsoleColor.Green; var gen = new StringBuilder(); var tiles = new StringBuilder(); var imports = new StringBuilder(); var lImports = new List <string>(); // Load primary imports lImports.Require("net.minecraft.world.World"); lImports.Require("static com.parzivail.util.world.WorldUtils.b"); lImports.Require("static com.parzivail.util.world.WorldUtils.m"); var numStatements = 0; var currentGen = 0; // Start an overall timer var swOverall = new Stopwatch(); swOverall.Start(); // Start an iterate timer var swIterate = new Stopwatch(); swIterate.Start(); // Iterate over tile entities var totalTiles = 0; var l = schematic.GetTileEntities(); for (var i = 0; i < l.Count; i++) { var t = (NbtCompound)l[i]; var x = t["x"].IntValue; var y = t["y"].IntValue; var z = t["z"].IntValue; if (t["id"].StringValue != "Chest" || !(x >= chunkX && x < chunkX + 16 && z >= chunkZ && z < chunkZ + 16)) { continue; } tiles.Append(JavaBuilder.MakeChest(ref schematic, ref lImports, totalTiles, x, y, z, "\t\t")); totalTiles++; } // Iterate over blocks gen.AppendLine(JavaBuilder.MakeGen(currentGen)); gen.AppendLine("\t{"); for (var x = chunkX; x < chunkX + 16; x++) { for (var y = 0; y < schematic.Height; y++) { for (var z = chunkZ; z < chunkZ + 16; z++) { if (x >= schematic.Width || z >= schematic.Length) { continue; } var b = schematic.GetBlockAt(x, y, z); if (schematic.GetFlagAt(x, y, z) || (b.GetName() == "air" && Arguments.IgnoreAirBlocks)) { continue; } lImports.Require("static " + b.CreateJavaVariable()); gen.Append(JavaBuilder.MakeSetBlockLine(schematic, ref lImports, x, y, z, chunkX, chunkZ)); numStatements++; //Console.WriteLine(schematic.getBlockIdAt(x, y, z)); if (numStatements <= Exporter.MaxBlocksPerGen) { continue; } numStatements = 0; currentGen++; gen.AppendLine(JavaBuilder.MakeCallGen(currentGen)); gen.AppendLine("\t}"); gen.AppendLine(JavaBuilder.MakeGen(currentGen)); gen.AppendLine("\t{"); } } } // Sort imports lImports.Sort(); for (var i = 0; i < lImports.Count; i++) { imports.AppendFormat("import {0};\r\n", lImports[i]); } swIterate.Stop(); var iterateElapsed = swIterate.ElapsedMilliseconds; gen.Append(tiles); gen.AppendLine("\t}"); // Replace template placeholders with true data template = template.Replace("{{CLASS_COMMENT}}", Exporter.HeaderComment()); template = template.Replace("{{PACKAGE}}", options.Package); template = template.Replace("{{CLASS}}", new StringBuilder().AppendFormat(options.ClassName, new StringBuilder().AppendFormat("_x{0}_z{1}", chunkX, chunkZ)).ToString()); template = template.Replace("{{GEN_METHODS}}", gen.ToString()); template = template.Replace("{{IMPORTS}}", imports.ToString()); var blocks = currentGen * Exporter.MaxBlocksPerGen + numStatements; swIterate.Restart(); Metrics.TotalBlocks += blocks; Metrics.TotalTiles += totalTiles; // Write data to file using ( var w = new StreamWriter("output/" + options.Path + "/" + new StringBuilder().AppendFormat(options.FileName, new StringBuilder().AppendFormat("_x{0}_z{1}", chunkX, chunkZ)))) w.WriteLine(template); swIterate.Stop(); swOverall.Stop(); Console.ForegroundColor = ConsoleColor.Blue; Console.Write(Utils.MillisToHrd(iterateElapsed).PadRight(10)); Console.ForegroundColor = ConsoleColor.DarkGreen; Console.Write("{0}{1}{2}", new StringBuilder().AppendFormat("{0:n0}", blocks).ToString().PadRight(10), new StringBuilder().AppendFormat("{0:n0}", totalTiles).ToString().PadRight(10), new StringBuilder().AppendFormat("{0:n0}", currentGen + 1).ToString().PadRight(10)); Console.ForegroundColor = ConsoleColor.Blue; Console.Write("{0}{1}", Utils.MillisToHrd(swIterate.ElapsedMilliseconds).PadRight(10), Utils.MillisToHrd(swOverall.ElapsedMilliseconds).PadRight(10)); var isize = File.ReadAllBytes("output/" + options.Path + "/" + new StringBuilder().AppendFormat(options.FileName, new StringBuilder().AppendFormat("_x{0}_z{1}", chunkX, chunkZ))) .Length; Metrics.TotalFilesize += isize; var size = Utils.SizeSuffix( isize); if (size.Contains("MB")) { Console.ForegroundColor = ConsoleColor.Yellow; Metrics.FilesOverOneMeg++; } else { Console.ForegroundColor = ConsoleColor.DarkGreen; } Console.Write(size.PadRight(10)); Console.WriteLine(); }