static void RunOptions(Options opts) { Console.WriteLine($"PlayerMover {Assembly.GetExecutingAssembly().GetName().Version}\n"); // validate position try { var _ = opts.NewPos; } catch (Exception) { Console.WriteLine("Failed to parse position argument"); return; } // validate rotation try { var _ = opts.NewRot; } catch (Exception) { Console.WriteLine("Failed to parse rotation argument"); return; } // log settings Console.WriteLine($"Playerdata dir: {opts.DataDir}"); Console.WriteLine($"Moving players in world: {opts.FromWorldUUID}"); Console.WriteLine($"Moving players to world: DIM: {opts.Dimension} {opts.ToWorldName}/{opts.ToWorldUUID} at ({opts.NewPos}) / ({opts.NewRot})"); // confirm Console.WriteLine("\nPLEASE MAKE A BACKUP OF YOUR WORLD BEFORE RUNNING THIS SOFTWARE - PRESS Y TO CONTINUE, OR ANY OTHER KEY TO QUIT\n"); if (!new char[] { 'y', 'Y' }.Contains(Console.ReadKey(true).KeyChar)) { return; // force user to enter y } // load files string[] files = Directory.GetFiles(opts.DataDir, "*.dat"); if (opts.Verbose) { Console.WriteLine($"\nLoaded {files.Length} player files"); } // open stream to the output file for putting uuids using StreamWriter sw = new StreamWriter(File.OpenWrite("MovedPlayers.txt")); foreach (var fileName in files) { if (opts.Verbose) { Console.WriteLine($"\nLoading file: {fileName}"); } var myFile = new NbtFile(fileName); // read uuid bytes var worldLeast = myFile.RootTag.Get <NbtLong>("WorldUUIDLeast"); var worldMost = myFile.RootTag.Get <NbtLong>("WorldUUIDMost"); // verify uuid bytes if (worldLeast == null || worldMost == null) { throw new Exception($"NBT File {fileName} does not contain a valid world UUID"); } var uuid = UUID.Read(worldMost.Value, worldLeast.Value); if (opts.Verbose) { Console.WriteLine($"Existing world UUID: {uuid}"); } // are we moving the player? if (uuid.Equals(opts.FromWorldUUID)) { //read player's uuid var uuidLeast = myFile.RootTag.Get <NbtLong>("UUIDLeast"); var uuidMost = myFile.RootTag.Get <NbtLong>("UUIDMost"); // verify uuid bytes if (worldLeast == null || worldMost == null) { throw new Exception($"NBT File {fileName} does not contain a valid player UUID"); } var playerUuid = UUID.Read(uuidMost.Value, uuidLeast.Value); Console.WriteLine($"Moving {playerUuid}"); // change world (var newWorldMost, var newWorldLeast) = UUID.GetLongs(opts.ToWorldUUID); worldMost.Value = newWorldMost; worldLeast.Value = newWorldLeast; // set spawn world var spawnWorld = myFile.RootTag.Get <NbtString>("SpawnWorld"); if (spawnWorld != null) { spawnWorld.Value = opts.ToWorldName; } // set position var pos = myFile.RootTag.Get <NbtList>("Pos"); pos[0] = new NbtDouble(opts.NewPos.X); pos[1] = new NbtDouble(opts.NewPos.Y); pos[2] = new NbtDouble(opts.NewPos.Z); // set rotation var rot = myFile.RootTag.Get <NbtList>("Rotation"); rot[0] = new NbtFloat(opts.NewRot.Yaw); rot[1] = new NbtFloat(opts.NewRot.Roll); // set velocity to 0 var motion = myFile.RootTag.Get <NbtList>("Motion"); for (int i = 0; i < motion.Count; i++) { motion[i] = new NbtDouble(0d); } // set fall distance to 0 myFile.RootTag.Get <NbtFloat>("FallDistance").Value = 0f; // set on ground to true myFile.RootTag.Get <NbtByte>("OnGround").Value = 0x01; // write back to file with existing compression myFile.SaveToFile(fileName, myFile.FileCompression); if (opts.Verbose) { Console.WriteLine("Done updating NBT"); } sw.WriteLine(playerUuid.ToString()); } else { if (opts.Verbose) { Console.WriteLine("Move not required"); } } } Console.WriteLine($"\nLog of moved players' UUIDs stored in {Path.Combine(Environment.CurrentDirectory, "MovedPlayers.txt")}"); }