diff --git a/ConsoleInteractive b/ConsoleInteractive index a5ed69ef..b4fd7da2 160000 --- a/ConsoleInteractive +++ b/ConsoleInteractive @@ -1 +1 @@ -Subproject commit a5ed69efcf6a8803a8f5c3c10501266cd21947c7 +Subproject commit b4fd7da2595ad54479880fc1c9c6e14975412d92 diff --git a/MinecraftClient/Commands/Chunk.cs b/MinecraftClient/Commands/Chunk.cs new file mode 100644 index 00000000..855e5658 --- /dev/null +++ b/MinecraftClient/Commands/Chunk.cs @@ -0,0 +1,261 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using MinecraftClient.Mapping; + +namespace MinecraftClient.Commands +{ + public class Chunk : Command + { + public override string CmdName { get { return "chunk"; } } + public override string CmdUsage { get { return "chunk status [chunkX chunkZ|locationX locationY locationZ]"; } } + public override string CmdDesc { get { return "cmd.chunk.desc"; } } + + public override string Run(McClient handler, string command, Dictionary? localVars) + { + if (hasArg(command)) + { + string[] args = getArgs(command); + if (args.Length > 0) + { + if (args[0] == "status") + { + World world = handler.GetWorld(); + Location current = handler.GetCurrentLocation(); + + Tuple? markedChunkPos = ParseChunkPos(args); + (int markChunkX, int markChunkZ) = markedChunkPos ?? (new(current.ChunkX, current.ChunkZ)); + + StringBuilder sb = new(); + + sb.Append(getChunkLoadingStatus(handler.GetWorld())); + sb.Append('\n'); + + sb.Append(String.Format("Current location:{0}, chunk: ({1}, {2}).\n", current, current.ChunkX, current.ChunkZ)); + if (markedChunkPos != null) + { + sb.Append("Marked location: "); + if (args.Length == 1 + 3) + sb.Append(String.Format("X:{0:0.00} Y:{1:0.00} Z:{2:0.00}, ", double.Parse(args[1]), double.Parse(args[2]), double.Parse(args[3]))); + sb.Append(String.Format("chunk: ({0}, {1}).\n", markChunkX, markChunkZ)); + } + + int consoleHeight = Math.Max(Console.BufferHeight - 2, 25); + if (consoleHeight % 2 == 0) + --consoleHeight; + + int consoleWidth = Math.Max(Console.BufferWidth / 2, 17); + if (consoleWidth % 2 == 0) + --consoleWidth; + + int startZ = current.ChunkZ - consoleHeight, endZ = current.ChunkZ + consoleHeight; + int startX = current.ChunkX - consoleWidth, endX = current.ChunkX + consoleWidth; + + int leftMost = endX, rightMost = startX, topMost = endZ, bottomMost = startZ; + for (int z = startZ; z <= endZ; z++) + { + for (int x = startX; x <= endX; ++x) + { + if (world[x, z] != null) + { + leftMost = Math.Min(leftMost, x); + rightMost = Math.Max(rightMost, x); + topMost = Math.Min(topMost, z); + bottomMost = Math.Max(bottomMost, z); + } + } + } + + // Include the player's location + topMost = Math.Min(topMost, current.ChunkZ); + bottomMost = Math.Max(bottomMost, current.ChunkZ); + leftMost = Math.Min(leftMost, current.ChunkX); + rightMost = Math.Max(rightMost, current.ChunkX); + + // Empty one row and one column each + --leftMost; ++rightMost; --topMost; ++bottomMost; + + // Resize according to limitations + if ((bottomMost - topMost + 1) > consoleHeight) + { + int delta = (bottomMost - topMost + 1) - consoleHeight; + if (bottomMost - (delta + 1) / 2 < current.ChunkZ + 1) + { + int bottomReduce = bottomMost - (current.ChunkZ + 1); + bottomMost -= bottomReduce; + topMost += delta - bottomReduce; + } + else if (topMost + delta / 2 > current.ChunkZ - 1) + { + int topAdd = topMost - (current.ChunkZ - 1); + topMost += topAdd; + bottomMost -= delta - topAdd; + } + else + { + topMost += delta / 2; + bottomMost -= (delta + 1) / 2; + } + } + if ((rightMost - leftMost + 1) > consoleWidth) + { + int delta = (rightMost - leftMost + 1) - consoleWidth; + if (rightMost - (delta + 1) / 2 < current.ChunkX + 1) + { + int rightReduce = rightMost - (current.ChunkX + 1); + rightMost -= rightReduce; + leftMost += delta - rightReduce; + } + else if (leftMost + delta / 2 > current.ChunkX - 1) + { + int leftAdd = leftMost - (current.ChunkX - 1); + leftMost += leftAdd; + rightMost -= delta - leftAdd; + } + else + { + leftMost += delta / 2; + rightMost -= (delta + 1) / 2; + } + } + + // Try to include the marker chunk + if (markedChunkPos != null && + (((Math.Max(bottomMost, markChunkZ) - Math.Min(topMost, markChunkZ) + 1) > consoleHeight) || + ((Math.Max(rightMost, markChunkX) - Math.Min(leftMost, markChunkX) + 1) > consoleWidth))) + sb.Append("§x§0Since the marked chunk is outside the graph, it will not be displayed!§r\n"); + else + { + topMost = Math.Min(topMost, markChunkZ); + bottomMost = Math.Max(bottomMost, markChunkZ); + leftMost = Math.Min(leftMost, markChunkX); + rightMost = Math.Max(rightMost, markChunkX); + } + + // Output + for (int z = topMost; z <= bottomMost; ++z) + { + for (int x = leftMost; x <= rightMost; ++x) + { + if (z == current.ChunkZ && x == current.ChunkX) + sb.Append("§z"); // Player Location: background gray + else if (z == markChunkZ && x == markChunkX) + sb.Append("§w"); // Marked chunk: background red + + ChunkColumn? chunkColumn = world[x, z]; + if (chunkColumn == null) + sb.Append("\ud83d\udd33"); // "🔳" white hollow square + else if (chunkColumn.FullyLoaded) + sb.Append("\ud83d\udfe9"); // "🟩" green + else + sb.Append("\ud83d\udfe8"); // "🟨" yellow + + if ((z == current.ChunkZ && x == current.ChunkX) || (z == markChunkZ && x == markChunkX)) + sb.Append("§r"); // Reset background color + } + sb.Append('\n'); + } + + sb.Append("Player:§z §r, MarkedChunk:§w §r, NotReceived:\ud83d\udd33, Loading:\ud83d\udfe8, Loaded:\ud83d\udfe9"); + return sb.ToString(); + } + else if (args[0] == "setloading") // For debugging + { + Tuple? chunkPos = ParseChunkPos(args); + if (chunkPos != null) + { + handler.Log.Info("§x§0This command is used for debugging, make sure you know what you are doing.§r"); + World world = handler.GetWorld(); + (int chunkX, int chunkZ) = chunkPos; + ChunkColumn? chunkColumn = world[chunkX, chunkZ]; + if (chunkColumn != null) + chunkColumn.FullyLoaded = false; + return (chunkColumn == null) ? "Fail: chunk dosen't exist!" : + String.Format("Successfully marked chunk ({0}, {1}) as loading.", chunkX, chunkZ); + } + else + return GetCmdDescTranslated(); + } + else if (args[0] == "setloaded") // For debugging + { + Tuple? chunkPos = ParseChunkPos(args); + if (chunkPos != null) + { + handler.Log.Info("§x§0This command is used for debugging, make sure you know what you are doing.§r"); + World world = handler.GetWorld(); + (int chunkX, int chunkZ) = chunkPos; + ChunkColumn? chunkColumn = world[chunkX, chunkZ]; + if (chunkColumn != null) + chunkColumn.FullyLoaded = true; + return (chunkColumn == null) ? "Fail: chunk dosen't exist!" : + String.Format("Successfully marked chunk ({0}, {1}) as loaded.", chunkX, chunkZ); + } + else + return GetCmdDescTranslated(); + } + else if (args[0] == "delete") // For debugging + { + Tuple? chunkPos = ParseChunkPos(args); + if (chunkPos != null) + { + handler.Log.Info("§x§0This command is used for debugging, make sure you know what you are doing.§r"); + World world = handler.GetWorld(); + (int chunkX, int chunkZ) = chunkPos; + world[chunkX, chunkZ] = null; + return String.Format("Successfully deleted chunk ({0}, {1}).", chunkX, chunkZ); + } + else + return GetCmdDescTranslated(); + } + else + return GetCmdDescTranslated(); + } + else + return GetCmdDescTranslated(); + } + else + return GetCmdDescTranslated(); + } + + private Tuple? ParseChunkPos(string[] args) + { + try + { + int chunkX, chunkZ; + if (args.Length == 1 + 3) + { + Location pos = new(double.Parse(args[1]), double.Parse(args[2]), double.Parse(args[3])); + chunkX = pos.ChunkX; + chunkZ = pos.ChunkZ; + } + else if (args.Length == 1 + 2) + { + chunkX = int.Parse(args[1]); + chunkZ = int.Parse(args[2]); + } + else + return null; + return new(chunkX, chunkZ); + } + catch (FormatException) + { + return null; + } + } + + private string getChunkLoadingStatus(World world) + { + double chunkLoadedRatio; + if (world.chunkCnt == 0) + chunkLoadedRatio = 0; + else + chunkLoadedRatio = (world.chunkCnt - world.chunkLoadNotCompleted) / (double)world.chunkCnt; + + string status = Translations.Get("cmd.move.chunk_loading_status", + chunkLoadedRatio, world.chunkCnt - world.chunkLoadNotCompleted, world.chunkCnt); + + return status; + } + } +} diff --git a/MinecraftClient/Commands/Move.cs b/MinecraftClient/Commands/Move.cs index 7fa718b0..8922b88e 100644 --- a/MinecraftClient/Commands/Move.cs +++ b/MinecraftClient/Commands/Move.cs @@ -76,7 +76,7 @@ namespace MinecraftClient.Commands ChunkColumn? chunkColumn = handler.GetWorld().GetChunkColumn(goal); if (chunkColumn == null || chunkColumn.FullyLoaded == false) - return Translations.Get("cmd.move.chunk_not_loaded"); + return Translations.Get("cmd.move.chunk_not_loaded", goal.X, goal.Y, goal.Z); if (Movement.CanMove(handler.GetWorld(), handler.GetCurrentLocation(), direction)) { @@ -99,7 +99,7 @@ namespace MinecraftClient.Commands ChunkColumn? chunkColumn = handler.GetWorld().GetChunkColumn(goal); if (chunkColumn == null || chunkColumn.FullyLoaded == false) - return Translations.Get("cmd.move.chunk_not_loaded"); + return Translations.Get("cmd.move.chunk_not_loaded", x, y, z); if (takeRisk || Movement.PlayerFitsHere(handler.GetWorld(), goal)) { diff --git a/MinecraftClient/Mapping/Dimension.cs b/MinecraftClient/Mapping/Dimension.cs index 72cdf844..d260ce71 100644 --- a/MinecraftClient/Mapping/Dimension.cs +++ b/MinecraftClient/Mapping/Dimension.cs @@ -182,7 +182,7 @@ namespace MinecraftClient.Mapping this.height = (int)nbt["height"]; if (nbt.ContainsKey("min_y") && nbt.ContainsKey("height")) this.maxY = this.minY + this.height; - if (nbt.ContainsKey("logical_height")) + if (nbt.ContainsKey("logical_height") && nbt["logical_height"].GetType() != typeof(byte)) this.logicalHeight = (int)nbt["logical_height"]; if (nbt.ContainsKey("coordinate_scale")) { diff --git a/MinecraftClient/Mapping/MaterialExtensions.cs b/MinecraftClient/Mapping/MaterialExtensions.cs index d10913c2..cf29dd71 100644 --- a/MinecraftClient/Mapping/MaterialExtensions.cs +++ b/MinecraftClient/Mapping/MaterialExtensions.cs @@ -19,32 +19,40 @@ namespace MinecraftClient.Mapping { switch (m) { + case Material.AcaciaDoor: case Material.AcaciaFence: case Material.AcaciaFenceGate: case Material.AcaciaLeaves: case Material.AcaciaLog: case Material.AcaciaPlanks: + case Material.AcaciaPressurePlate: + case Material.AcaciaSign: case Material.AcaciaSlab: case Material.AcaciaStairs: case Material.AcaciaTrapdoor: + case Material.AcaciaWallSign: case Material.AcaciaWood: case Material.AmethystBlock: case Material.AmethystCluster: + case Material.AncientDebris: case Material.Andesite: case Material.AndesiteSlab: case Material.AndesiteStairs: case Material.AndesiteWall: case Material.Anvil: + case Material.AttachedMelonStem: + case Material.AttachedPumpkinStem: case Material.Azalea: case Material.AzaleaLeaves: case Material.Bamboo: + case Material.BambooSapling: case Material.Barrel: case Material.Barrier: case Material.Basalt: case Material.Beacon: case Material.Bedrock: - case Material.BeeNest: case Material.Beehive: + case Material.BeeNest: case Material.Bell: case Material.BirchDoor: case Material.BirchFence: @@ -52,10 +60,14 @@ namespace MinecraftClient.Mapping case Material.BirchLeaves: case Material.BirchLog: case Material.BirchPlanks: + case Material.BirchPressurePlate: + case Material.BirchSign: case Material.BirchSlab: case Material.BirchStairs: case Material.BirchTrapdoor: + case Material.BirchWallSign: case Material.BirchWood: + case Material.BlackBanner: case Material.BlackBed: case Material.BlackCandle: case Material.BlackCandleCake: @@ -68,9 +80,12 @@ namespace MinecraftClient.Mapping case Material.Blackstone: case Material.BlackstoneSlab: case Material.BlackstoneStairs: + case Material.BlackstoneWall: case Material.BlackTerracotta: + case Material.BlackWallBanner: case Material.BlackWool: case Material.BlastFurnace: + case Material.BlueBanner: case Material.BlueBed: case Material.BlueCandle: case Material.BlueCandleCake: @@ -82,15 +97,17 @@ namespace MinecraftClient.Mapping case Material.BlueStainedGlass: case Material.BlueStainedGlassPane: case Material.BlueTerracotta: + case Material.BlueWallBanner: case Material.BlueWool: case Material.BoneBlock: case Material.Bookshelf: case Material.BrainCoralBlock: case Material.BrewingStand: + case Material.Bricks: case Material.BrickSlab: case Material.BrickStairs: case Material.BrickWall: - case Material.Bricks: + case Material.BrownBanner: case Material.BrownBed: case Material.BrownCandle: case Material.BrownCandleCake: @@ -102,6 +119,7 @@ namespace MinecraftClient.Mapping case Material.BrownStainedGlass: case Material.BrownStainedGlassPane: case Material.BrownTerracotta: + case Material.BrownWallBanner: case Material.BrownWool: case Material.BubbleColumn: case Material.BubbleCoralBlock: @@ -115,10 +133,13 @@ namespace MinecraftClient.Mapping case Material.CartographyTable: case Material.CarvedPumpkin: case Material.Cauldron: + case Material.Chain: case Material.ChainCommandBlock: case Material.Chest: case Material.ChippedAnvil: case Material.ChiseledDeepslate: + case Material.ChiseledNetherBricks: + case Material.ChiseledPolishedBlackstone: case Material.ChiseledQuartzBlock: case Material.ChiseledRedSandstone: case Material.ChiseledSandstone: @@ -137,6 +158,7 @@ namespace MinecraftClient.Mapping case Material.CobblestoneSlab: case Material.CobblestoneStairs: case Material.CobblestoneWall: + case Material.Cobweb: case Material.CommandBlock: case Material.Composter: case Material.Conduit: @@ -144,10 +166,26 @@ namespace MinecraftClient.Mapping case Material.CopperOre: case Material.CrackedDeepslateBricks: case Material.CrackedDeepslateTiles: + case Material.CrackedNetherBricks: + case Material.CrackedPolishedBlackstoneBricks: case Material.CrackedStoneBricks: case Material.CraftingTable: case Material.CreeperHead: case Material.CreeperWallHead: + case Material.CrimsonDoor: + case Material.CrimsonFence: + case Material.CrimsonFenceGate: + case Material.CrimsonHyphae: + case Material.CrimsonNylium: + case Material.CrimsonPlanks: + case Material.CrimsonPressurePlate: + case Material.CrimsonSign: + case Material.CrimsonSlab: + case Material.CrimsonStairs: + case Material.CrimsonStem: + case Material.CrimsonTrapdoor: + case Material.CrimsonWallSign: + case Material.CryingObsidian: case Material.CutCopper: case Material.CutCopperSlab: case Material.CutCopperStairs: @@ -155,6 +193,7 @@ namespace MinecraftClient.Mapping case Material.CutRedSandstoneSlab: case Material.CutSandstone: case Material.CutSandstoneSlab: + case Material.CyanBanner: case Material.CyanBed: case Material.CyanCandle: case Material.CyanCandleCake: @@ -165,6 +204,7 @@ namespace MinecraftClient.Mapping case Material.CyanStainedGlass: case Material.CyanStainedGlassPane: case Material.CyanTerracotta: + case Material.CyanWallBanner: case Material.CyanWool: case Material.DamagedAnvil: case Material.DarkOakDoor: @@ -173,29 +213,54 @@ namespace MinecraftClient.Mapping case Material.DarkOakLeaves: case Material.DarkOakLog: case Material.DarkOakPlanks: + case Material.DarkOakPressurePlate: + case Material.DarkOakSign: case Material.DarkOakSlab: case Material.DarkOakStairs: case Material.DarkOakTrapdoor: + case Material.DarkOakWallSign: case Material.DarkOakWood: case Material.DarkPrismarine: case Material.DarkPrismarineSlab: case Material.DarkPrismarineStairs: case Material.DaylightDetector: + case Material.DeadBrainCoral: case Material.DeadBrainCoralBlock: + case Material.DeadBrainCoralFan: + case Material.DeadBrainCoralWallFan: + case Material.DeadBubbleCoral: case Material.DeadBubbleCoralBlock: + case Material.DeadBubbleCoralFan: + case Material.DeadBubbleCoralWallFan: + case Material.DeadFireCoral: case Material.DeadFireCoralBlock: + case Material.DeadFireCoralFan: + case Material.DeadFireCoralWallFan: + case Material.DeadHornCoral: case Material.DeadHornCoralBlock: + case Material.DeadHornCoralFan: + case Material.DeadHornCoralWallFan: + case Material.DeadTubeCoral: case Material.DeadTubeCoralBlock: + case Material.DeadTubeCoralFan: + case Material.DeadTubeCoralWallFan: case Material.Deepslate: + case Material.DeepslateBricks: case Material.DeepslateBrickSlab: case Material.DeepslateBrickStairs: case Material.DeepslateBrickWall: - case Material.DeepslateBricks: + case Material.DeepslateCoalOre: case Material.DeepslateCopperOre: + case Material.DeepslateDiamondOre: + case Material.DeepslateEmeraldOre: + case Material.DeepslateGoldOre: + case Material.DeepslateIronOre: + case Material.DeepslateLapisOre: + case Material.DeepslateRedstoneOre: + case Material.DeepslateTiles: case Material.DeepslateTileSlab: case Material.DeepslateTileStairs: case Material.DeepslateTileWall: - case Material.DeepslateTiles: case Material.DiamondBlock: case Material.DiamondOre: case Material.Diorite: @@ -214,14 +279,14 @@ namespace MinecraftClient.Mapping case Material.EmeraldBlock: case Material.EmeraldOre: case Material.EnchantingTable: + case Material.EnderChest: case Material.EndPortalFrame: case Material.EndRod: case Material.EndStone: + case Material.EndStoneBricks: case Material.EndStoneBrickSlab: case Material.EndStoneBrickStairs: case Material.EndStoneBrickWall: - case Material.EndStoneBricks: - case Material.EnderChest: case Material.ExposedCopper: case Material.ExposedCutCopper: case Material.ExposedCutCopperSlab: @@ -229,11 +294,12 @@ namespace MinecraftClient.Mapping case Material.Farmland: case Material.FireCoralBlock: case Material.FletchingTable: - case Material.FlowerPot: case Material.FloweringAzalea: case Material.FloweringAzaleaLeaves: + case Material.FlowerPot: case Material.FrostedIce: case Material.Furnace: + case Material.GildedBlackstone: case Material.Glass: case Material.GlassPane: case Material.Glowstone: @@ -245,6 +311,7 @@ namespace MinecraftClient.Mapping case Material.GraniteWall: case Material.GrassBlock: case Material.Gravel: + case Material.GrayBanner: case Material.GrayBed: case Material.GrayCandle: case Material.GrayCandleCake: @@ -255,7 +322,9 @@ namespace MinecraftClient.Mapping case Material.GrayStainedGlass: case Material.GrayStainedGlassPane: case Material.GrayTerracotta: + case Material.GrayWallBanner: case Material.GrayWool: + case Material.GreenBanner: case Material.GreenBed: case Material.GreenCandle: case Material.GreenCandleCake: @@ -266,9 +335,11 @@ namespace MinecraftClient.Mapping case Material.GreenStainedGlass: case Material.GreenStainedGlassPane: case Material.GreenTerracotta: + case Material.GreenWallBanner: case Material.GreenWool: case Material.Grindstone: case Material.HayBlock: + case Material.HeavyWeightedPressurePlate: case Material.HoneyBlock: case Material.HoneycombBlock: case Material.Hopper: @@ -295,9 +366,12 @@ namespace MinecraftClient.Mapping case Material.JungleLeaves: case Material.JungleLog: case Material.JunglePlanks: + case Material.JunglePressurePlate: + case Material.JungleSign: case Material.JungleSlab: case Material.JungleStairs: case Material.JungleTrapdoor: + case Material.JungleWallSign: case Material.JungleWood: case Material.Ladder: case Material.Lantern: @@ -306,6 +380,7 @@ namespace MinecraftClient.Mapping case Material.LargeAmethystBud: case Material.LavaCauldron: case Material.Lectern: + case Material.LightBlueBanner: case Material.LightBlueBed: case Material.LightBlueCandle: case Material.LightBlueCandleCake: @@ -316,7 +391,9 @@ namespace MinecraftClient.Mapping case Material.LightBlueStainedGlass: case Material.LightBlueStainedGlassPane: case Material.LightBlueTerracotta: + case Material.LightBlueWallBanner: case Material.LightBlueWool: + case Material.LightGrayBanner: case Material.LightGrayBed: case Material.LightGrayCandle: case Material.LightGrayCandleCake: @@ -327,9 +404,12 @@ namespace MinecraftClient.Mapping case Material.LightGrayStainedGlass: case Material.LightGrayStainedGlassPane: case Material.LightGrayTerracotta: + case Material.LightGrayWallBanner: case Material.LightGrayWool: case Material.LightningRod: + case Material.LightWeightedPressurePlate: case Material.LilyPad: + case Material.LimeBanner: case Material.LimeBed: case Material.LimeCandle: case Material.LimeCandleCake: @@ -340,8 +420,11 @@ namespace MinecraftClient.Mapping case Material.LimeStainedGlass: case Material.LimeStainedGlassPane: case Material.LimeTerracotta: + case Material.LimeWallBanner: case Material.LimeWool: + case Material.Lodestone: case Material.Loom: + case Material.MagentaBanner: case Material.MagentaBed: case Material.MagentaCandle: case Material.MagentaCandleCake: @@ -352,39 +435,55 @@ namespace MinecraftClient.Mapping case Material.MagentaStainedGlass: case Material.MagentaStainedGlassPane: case Material.MagentaTerracotta: + case Material.MagentaWallBanner: case Material.MagentaWool: case Material.MagmaBlock: + case Material.MangroveDoor: + case Material.MangroveFence: + case Material.MangroveFenceGate: case Material.MangroveLeaves: case Material.MangroveLog: case Material.MangrovePlanks: case Material.MangrovePressurePlate: case Material.MangroveRoots: + case Material.MangroveSign: case Material.MangroveSlab: case Material.MangroveStairs: + case Material.MangroveTrapdoor: + case Material.MangroveWallSign: case Material.MangroveWood: case Material.MediumAmethystBud: case Material.Melon: + case Material.MelonStem: case Material.MossBlock: case Material.MossCarpet: case Material.MossyCobblestone: case Material.MossyCobblestoneSlab: case Material.MossyCobblestoneStairs: case Material.MossyCobblestoneWall: + case Material.MossyStoneBricks: case Material.MossyStoneBrickSlab: case Material.MossyStoneBrickStairs: case Material.MossyStoneBrickWall: - case Material.MossyStoneBricks: case Material.MovingPiston: + case Material.Mud: + case Material.MudBricks: + case Material.MudBrickSlab: + case Material.MudBrickStairs: + case Material.MudBrickWall: + case Material.MuddyMangroveRoots: case Material.MushroomStem: case Material.Mycelium: case Material.NetherBrickFence: + case Material.NetherBricks: case Material.NetherBrickSlab: case Material.NetherBrickStairs: case Material.NetherBrickWall: - case Material.NetherBricks: + case Material.NetherGoldOre: + case Material.NetheriteBlock: case Material.NetherQuartzOre: - case Material.NetherWartBlock: case Material.Netherrack: + case Material.NetherWartBlock: case Material.NoteBlock: case Material.OakDoor: case Material.OakFence: @@ -392,12 +491,17 @@ namespace MinecraftClient.Mapping case Material.OakLeaves: case Material.OakLog: case Material.OakPlanks: + case Material.OakPressurePlate: + case Material.OakSign: case Material.OakSlab: case Material.OakStairs: case Material.OakTrapdoor: + case Material.OakWallSign: case Material.OakWood: case Material.Observer: case Material.Obsidian: + case Material.OchreFroglight: + case Material.OrangeBanner: case Material.OrangeBed: case Material.OrangeCandle: case Material.OrangeCandleCake: @@ -408,13 +512,17 @@ namespace MinecraftClient.Mapping case Material.OrangeStainedGlass: case Material.OrangeStainedGlassPane: case Material.OrangeTerracotta: + case Material.OrangeWallBanner: case Material.OrangeWool: case Material.OxidizedCopper: case Material.OxidizedCutCopper: case Material.OxidizedCutCopperSlab: case Material.OxidizedCutCopperStairs: case Material.PackedIce: + case Material.PackedMud: + case Material.PearlescentFroglight: case Material.PetrifiedOakSlab: + case Material.PinkBanner: case Material.PinkBed: case Material.PinkCandle: case Material.PinkCandleCake: @@ -425,6 +533,7 @@ namespace MinecraftClient.Mapping case Material.PinkStainedGlass: case Material.PinkStainedGlassPane: case Material.PinkTerracotta: + case Material.PinkWallBanner: case Material.PinkWool: case Material.Piston: case Material.PistonHead: @@ -436,6 +545,15 @@ namespace MinecraftClient.Mapping case Material.PolishedAndesiteSlab: case Material.PolishedAndesiteStairs: case Material.PolishedBasalt: + case Material.PolishedBlackstone: + case Material.PolishedBlackstoneBricks: + case Material.PolishedBlackstoneBrickSlab: + case Material.PolishedBlackstoneBrickStairs: + case Material.PolishedBlackstoneBrickWall: + case Material.PolishedBlackstonePressurePlate: + case Material.PolishedBlackstoneSlab: + case Material.PolishedBlackstoneStairs: + case Material.PolishedBlackstoneWall: case Material.PolishedDeepslate: case Material.PolishedDeepslateSlab: case Material.PolishedDeepslateStairs: @@ -475,13 +593,15 @@ namespace MinecraftClient.Mapping case Material.PottedWitherRose: case Material.PowderSnowCauldron: case Material.Prismarine: + case Material.PrismarineBricks: case Material.PrismarineBrickSlab: case Material.PrismarineBrickStairs: - case Material.PrismarineBricks: case Material.PrismarineSlab: case Material.PrismarineStairs: case Material.PrismarineWall: case Material.Pumpkin: + case Material.PumpkinStem: + case Material.PurpleBanner: case Material.PurpleBed: case Material.PurpleCandle: case Material.PurpleCandleCake: @@ -492,18 +612,21 @@ namespace MinecraftClient.Mapping case Material.PurpleStainedGlass: case Material.PurpleStainedGlassPane: case Material.PurpleTerracotta: + case Material.PurpleWallBanner: case Material.PurpleWool: case Material.PurpurBlock: case Material.PurpurPillar: case Material.PurpurSlab: case Material.PurpurStairs: case Material.QuartzBlock: + case Material.QuartzBricks: case Material.QuartzPillar: case Material.QuartzSlab: case Material.QuartzStairs: case Material.RawCopperBlock: case Material.RawGoldBlock: case Material.RawIronBlock: + case Material.RedBanner: case Material.RedBed: case Material.RedCandle: case Material.RedCandleCake: @@ -511,10 +634,10 @@ namespace MinecraftClient.Mapping case Material.RedConcretePowder: case Material.RedGlazedTerracotta: case Material.RedMushroomBlock: + case Material.RedNetherBricks: case Material.RedNetherBrickSlab: case Material.RedNetherBrickStairs: case Material.RedNetherBrickWall: - case Material.RedNetherBricks: case Material.RedSand: case Material.RedSandstone: case Material.RedSandstoneSlab: @@ -523,21 +646,29 @@ namespace MinecraftClient.Mapping case Material.RedShulkerBox: case Material.RedStainedGlass: case Material.RedStainedGlassPane: - case Material.RedTerracotta: - case Material.RedWool: case Material.RedstoneBlock: case Material.RedstoneLamp: case Material.RedstoneOre: + case Material.RedTerracotta: + case Material.RedWallBanner: + case Material.RedWool: + case Material.ReinforcedDeepslate: case Material.RepeatingCommandBlock: + case Material.RespawnAnchor: case Material.RootedDirt: case Material.Sand: case Material.Sandstone: case Material.SandstoneSlab: case Material.SandstoneStairs: case Material.SandstoneWall: + case Material.Sculk: + case Material.SculkCatalyst: case Material.SculkSensor: + case Material.SculkShrieker: + case Material.SculkVein: case Material.SeaLantern: case Material.SeaPickle: + case Material.Shroomlight: case Material.ShulkerBox: case Material.SkeletonSkull: case Material.SkeletonWallSkull: @@ -558,6 +689,8 @@ namespace MinecraftClient.Mapping case Material.SmoothStone: case Material.SmoothStoneSlab: case Material.SnowBlock: + case Material.SoulCampfire: + case Material.SoulLantern: case Material.SoulSand: case Material.SoulSoil: case Material.Spawner: @@ -568,32 +701,43 @@ namespace MinecraftClient.Mapping case Material.SpruceLeaves: case Material.SpruceLog: case Material.SprucePlanks: + case Material.SprucePressurePlate: + case Material.SpruceSign: case Material.SpruceSlab: case Material.SpruceStairs: case Material.SpruceTrapdoor: + case Material.SpruceWallSign: case Material.SpruceWood: case Material.StickyPiston: case Material.Stone: + case Material.StoneBricks: case Material.StoneBrickSlab: case Material.StoneBrickStairs: case Material.StoneBrickWall: - case Material.StoneBricks: + case Material.Stonecutter: + case Material.StonePressurePlate: case Material.StoneSlab: case Material.StoneStairs: - case Material.Stonecutter: case Material.StrippedAcaciaLog: case Material.StrippedAcaciaWood: case Material.StrippedBirchLog: case Material.StrippedBirchWood: + case Material.StrippedCrimsonHyphae: + case Material.StrippedCrimsonStem: case Material.StrippedDarkOakLog: case Material.StrippedDarkOakWood: case Material.StrippedJungleLog: case Material.StrippedJungleWood: + case Material.StrippedMangroveLog: + case Material.StrippedMangroveWood: case Material.StrippedOakLog: case Material.StrippedOakWood: case Material.StrippedSpruceLog: case Material.StrippedSpruceWood: + case Material.StrippedWarpedHyphae: + case Material.StrippedWarpedStem: case Material.StructureBlock: + case Material.Target: case Material.Terracotta: case Material.TintedGlass: case Material.Tnt: @@ -601,6 +745,21 @@ namespace MinecraftClient.Mapping case Material.TubeCoralBlock: case Material.Tuff: case Material.TurtleEgg: + case Material.VerdantFroglight: + case Material.WarpedDoor: + case Material.WarpedFence: + case Material.WarpedFenceGate: + case Material.WarpedHyphae: + case Material.WarpedNylium: + case Material.WarpedPlanks: + case Material.WarpedPressurePlate: + case Material.WarpedSign: + case Material.WarpedSlab: + case Material.WarpedStairs: + case Material.WarpedStem: + case Material.WarpedTrapdoor: + case Material.WarpedWallSign: + case Material.WarpedWartBlock: case Material.WaterCauldron: case Material.WaxedCopperBlock: case Material.WaxedCutCopper: @@ -623,6 +782,7 @@ namespace MinecraftClient.Mapping case Material.WeatheredCutCopperSlab: case Material.WeatheredCutCopperStairs: case Material.WetSponge: + case Material.WhiteBanner: case Material.WhiteBed: case Material.WhiteCandle: case Material.WhiteCandleCake: @@ -633,9 +793,11 @@ namespace MinecraftClient.Mapping case Material.WhiteStainedGlass: case Material.WhiteStainedGlassPane: case Material.WhiteTerracotta: + case Material.WhiteWallBanner: case Material.WhiteWool: case Material.WitherSkeletonSkull: case Material.WitherSkeletonWallSkull: + case Material.YellowBanner: case Material.YellowBed: case Material.YellowCandle: case Material.YellowCandleCake: @@ -646,10 +808,10 @@ namespace MinecraftClient.Mapping case Material.YellowStainedGlass: case Material.YellowStainedGlassPane: case Material.YellowTerracotta: + case Material.YellowWallBanner: case Material.YellowWool: case Material.ZombieHead: case Material.ZombieWallHead: - case Material.AcaciaDoor: return true; default: return false; diff --git a/MinecraftClient/Mapping/Movement.cs b/MinecraftClient/Mapping/Movement.cs index 97af6359..5cde8624 100644 --- a/MinecraftClient/Mapping/Movement.cs +++ b/MinecraftClient/Mapping/Movement.cs @@ -462,11 +462,37 @@ namespace MinecraftClient.Mapping /// True if the specified location is on the ground public static bool IsOnGround(World world, Location location) { - if (world.GetChunkColumn(location) == null || world.GetChunkColumn(location).FullyLoaded == false) + ChunkColumn? chunkColumn = world.GetChunkColumn(location); + if (chunkColumn == null || chunkColumn.FullyLoaded == false) return true; // avoid moving downward in a not loaded chunk - return world.GetBlock(Move(location, Direction.Down)).Type.IsSolid() - && (location.Y <= Math.Truncate(location.Y) + 0.0001); + Location down = Move(location, Direction.Down); + + bool result = world.GetBlock(down).Type.IsSolid(); + + bool northCheck = 1 + Math.Floor(down.Z) - down.Z > 0.7; + bool eastCheck = down.X - Math.Floor(down.X) > 0.7; + bool southCheck = down.Z - Math.Floor(down.Z) > 0.7; + bool westCheck = 1 + Math.Floor(down.X) - down.X > 0.7; + + if (!result && northCheck) + result |= world.GetBlock(Move(down, Direction.North)).Type.IsSolid(); + if (!result && northCheck && eastCheck) + result |= world.GetBlock(Move(down, Direction.NorthEast)).Type.IsSolid(); + if (!result && eastCheck) + result |= world.GetBlock(Move(down, Direction.East)).Type.IsSolid(); + if (!result && eastCheck && southCheck) + result |= world.GetBlock(Move(down, Direction.SouthEast)).Type.IsSolid(); + if (!result && southCheck) + result |= world.GetBlock(Move(down, Direction.South)).Type.IsSolid(); + if (!result && southCheck && westCheck) + result |= world.GetBlock(Move(down, Direction.SouthWest)).Type.IsSolid(); + if (!result && westCheck) + result |= world.GetBlock(Move(down, Direction.West)).Type.IsSolid(); + if (!result && westCheck && northCheck) + result |= world.GetBlock(Move(down, Direction.NorthWest)).Type.IsSolid(); + + return result && (location.Y <= Math.Truncate(location.Y) + 0.0001); } /// diff --git a/MinecraftClient/Mapping/World.cs b/MinecraftClient/Mapping/World.cs index 63ecb0c4..47a768ad 100644 --- a/MinecraftClient/Mapping/World.cs +++ b/MinecraftClient/Mapping/World.cs @@ -21,9 +21,9 @@ namespace MinecraftClient.Mapping /// /// The dimension info of the world /// - private static Dimension curDimension = new Dimension(); + private static Dimension curDimension = new(); - private static Dictionary? dimensionList = null; + private static Dictionary dimensionList = new(); /// /// Chunk data parsing progress @@ -61,16 +61,27 @@ namespace MinecraftClient.Mapping /// Registry Codec nbt data public static void StoreDimensionList(Dictionary registryCodec) { - dimensionList = new(); var dimensionListNbt = (object[])(((Dictionary)registryCodec["minecraft:dimension_type"])["value"]); foreach (Dictionary dimensionNbt in dimensionListNbt) { string dimensionName = (string)dimensionNbt["name"]; - Dictionary element = (Dictionary)dimensionNbt["element"]; - dimensionList.Add(dimensionName, new Dimension(dimensionName, element)); + Dictionary dimensionType = (Dictionary)dimensionNbt["element"]; + StoreOneDimension(dimensionName, dimensionType); } } + /// + /// Store one dimension - Directly used in 1.16.2 to 1.18.2 + /// + /// Dimension name + /// Dimension Type nbt data + public static void StoreOneDimension(string dimensionName, Dictionary dimensionType) + { + if (dimensionList.ContainsKey(dimensionName)) + dimensionList.Remove(dimensionName); + dimensionList.Add(dimensionName, new Dimension(dimensionName, dimensionType)); + } + /// /// Set current dimension - 1.16 and above @@ -79,7 +90,7 @@ namespace MinecraftClient.Mapping /// The dimension type (NBT Tag Compound) public static void SetDimension(string name) { - curDimension = dimensionList![name]; // Should not fail + curDimension = dimensionList[name]; // Should not fail } diff --git a/MinecraftClient/Protocol/Handlers/Protocol18.cs b/MinecraftClient/Protocol/Handlers/Protocol18.cs index d05cf455..a00011ce 100644 --- a/MinecraftClient/Protocol/Handlers/Protocol18.cs +++ b/MinecraftClient/Protocol/Handlers/Protocol18.cs @@ -371,7 +371,8 @@ namespace MinecraftClient.Protocol.Handlers for (int i = 0; i < worldCount; i++) dataTypes.ReadNextString(packetData); // Dimension Names (World Names) - 1.16 and above var registryCodec = dataTypes.ReadNextNbt(packetData); // Registry Codec (Dimension Codec) - 1.16 and above - World.StoreDimensionList(registryCodec); + if (handler.GetTerrainEnabled()) + World.StoreDimensionList(registryCodec); } // Current dimension @@ -380,12 +381,13 @@ namespace MinecraftClient.Protocol.Handlers // String identifier: 1.16 and 1.16.1 // varInt: [1.9.1 to 1.15.2] // byte: below 1.9.1 + Dictionary? dimensionType = null; if (protocolVersion >= MC_1_16_Version) { if (protocolVersion >= MC_1_19_Version) dataTypes.ReadNextString(packetData); // Dimension Type: Identifier else if (protocolVersion >= MC_1_16_2_Version) - dataTypes.ReadNextNbt(packetData); // Dimension Type: NBT Tag Compound + dimensionType = dataTypes.ReadNextNbt(packetData); // Dimension Type: NBT Tag Compound else dataTypes.ReadNextString(packetData); this.currentDimension = 0; @@ -401,7 +403,12 @@ namespace MinecraftClient.Protocol.Handlers if (protocolVersion >= MC_1_16_Version) { string dimensionName = dataTypes.ReadNextString(packetData); // Dimension Name (World Name) - 1.16 and above - World.SetDimension(dimensionName); + if (handler.GetTerrainEnabled()) + { + if (protocolVersion >= MC_1_16_2_Version && protocolVersion < MC_1_19_Version) + World.StoreOneDimension(dimensionName, dimensionType!); + World.SetDimension(dimensionName); + } } if (protocolVersion >= MC_1_15_Version) @@ -594,12 +601,13 @@ namespace MinecraftClient.Protocol.Handlers } break; case PacketTypesIn.Respawn: + Dictionary? dimensionTypeRespawn = null; if (protocolVersion >= MC_1_16_Version) { if (protocolVersion >= MC_1_19_Version) dataTypes.ReadNextString(packetData); // Dimension Type: Identifier else if (protocolVersion >= MC_1_16_2_Version) - dataTypes.ReadNextNbt(packetData); // Dimension Type: NBT Tag Compound + dimensionTypeRespawn = dataTypes.ReadNextNbt(packetData); // Dimension Type: NBT Tag Compound else dataTypes.ReadNextString(packetData); this.currentDimension = 0; @@ -612,7 +620,12 @@ namespace MinecraftClient.Protocol.Handlers if (protocolVersion >= MC_1_16_Version) { string dimensionName = dataTypes.ReadNextString(packetData); // Dimension Name (World Name) - 1.16 and above - World.SetDimension(dimensionName); + if (handler.GetTerrainEnabled()) + { + if (protocolVersion >= MC_1_16_2_Version && protocolVersion < MC_1_19_Version) + World.StoreOneDimension(dimensionName, dimensionTypeRespawn!); + World.SetDimension(dimensionName); + } } if (protocolVersion < MC_1_14_Version) diff --git a/MinecraftClient/Resources/lang/en.ini b/MinecraftClient/Resources/lang/en.ini index 49bbfd8f..ba86f955 100644 --- a/MinecraftClient/Resources/lang/en.ini +++ b/MinecraftClient/Resources/lang/en.ini @@ -227,6 +227,9 @@ cmd.changeSlot.nan=Could not change slot: Not a Number cmd.changeSlot.changed=Changed to slot {0} cmd.changeSlot.fail=Could not change slot +# Chunk +cmd.chunk.desc=Displays the chunk loading status. + # Connect cmd.connect.desc=connect to the specified server. cmd.connect.unknown=Unknown account '{0}'. @@ -334,7 +337,7 @@ cmd.move.suggestforce=Failed to compute a safe path to {0}. Try -f parameter to cmd.move.gravity.enabled=Gravity is enabled. cmd.move.gravity.disabled=Gravity is disabled. cmd.move.chunk_loading_status=Chunk loading status: {0:P} - {1} out of {2} load completed. -cmd.move.chunk_not_loaded=The chunk where the target location resides has not yet been loaded. +cmd.move.chunk_not_loaded=The chunk where the target location resides has not yet been loaded.\nYou can use "/chunk status {0:0.0} {1:0.0} {2:0.0}" to check the chunk loading status. # Reco cmd.reco.desc=restart and reconnect to the server.