From 561651a0b61c1d6564fe7e45e58d5cb1e43a45d4 Mon Sep 17 00:00:00 2001 From: Christen Lofland Date: Sun, 19 Dec 2021 21:33:15 -0600 Subject: [PATCH 1/9] Update required .NET Core version to align with current code requirements. --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index c0c4aa8..160406e 100644 --- a/readme.md +++ b/readme.md @@ -169,7 +169,7 @@ Copyright (C) 2020 Markus Jungnickel ## Building Papyrus runs on .NET Core 3.0+. -First, make sure you have [.NET Core 3.0](https://dotnet.microsoft.com/download/dotnet-core/3.0) on your development machine. +First, make sure you have [.NET Core 3.1](https://dotnet.microsoft.com/download/dotnet-core/3.1) on your development machine. To compile for Windows, either use a recent Visual Studio or run: ```dotnet publish PapyrusCs -c Release --self-contained --runtime win-x64``` From dd2efbcd14e5997d2fa418a7cbebc88af2fec32b Mon Sep 17 00:00:00 2001 From: Christen Lofland Date: Tue, 21 Dec 2021 17:15:09 -0600 Subject: [PATCH 2/9] Catch and log errors by chunk. By catching and logging out errors here in the loop, I am able to log exactly which chunk failed, aiding in fixing maps or debugging code. --- .../Strategies/Dataflow/CreateChunkAndRenderBlock.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/PapyrusAlgorithms/Strategies/Dataflow/CreateChunkAndRenderBlock.cs b/PapyrusAlgorithms/Strategies/Dataflow/CreateChunkAndRenderBlock.cs index 5fd442a..e561b91 100644 --- a/PapyrusAlgorithms/Strategies/Dataflow/CreateChunkAndRenderBlock.cs +++ b/PapyrusAlgorithms/Strategies/Dataflow/CreateChunkAndRenderBlock.cs @@ -58,7 +58,14 @@ public CreateChunkAndRenderBlock( var z = chunk.Z % chunksPerDimension; if (x < 0) x += chunksPerDimension; if (z < 0) z += chunksPerDimension; - chunkRenderer.ChunkRenderer.RenderChunk(b, chunk, x * chunkSize, z * chunkSize); + try + { + chunkRenderer.ChunkRenderer.RenderChunk(b, chunk, x * chunkSize, z * chunkSize); + } + catch (Exception ex) + { + Console.WriteLine("RenderChunk Error at " + chunkData.X + " " + chunkData.Z + " : " + ex.Message); + } world.ChunkPool?.Return(chunk); count++; From b2f20e52631228f666144ed98155b9b3f8687a25 Mon Sep 17 00:00:00 2001 From: Christen Lofland Date: Tue, 21 Dec 2021 17:17:34 -0600 Subject: [PATCH 3/9] Catch errors in Texture data Either texture issues or map corruption often causes failures in getting textures. Previously this would result in entire chunks being unrendered and it was difficult to figure out why. By catching the failures here, it is easy to see exactly which block is causing issues. It also allows the chunk to continue to render with one missing block, instead of the entire chunk being blank. --- Maploader/Renderer/Texture/TextureFinder.cs | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/Maploader/Renderer/Texture/TextureFinder.cs b/Maploader/Renderer/Texture/TextureFinder.cs index e11c083..23f78c5 100644 --- a/Maploader/Renderer/Texture/TextureFinder.cs +++ b/Maploader/Renderer/Texture/TextureFinder.cs @@ -255,15 +255,24 @@ public TextureStack FindTexturePath(string name, Dictionary data { name = name.Replace("minecraft:", ""); - var newTexture = GetSubstitution(name, data, x, z, y); - - if (newTexture != null) + try { - return newTexture; + var newTexture = GetSubstitution(name, data, x, z, y); + if (newTexture != null) + { + return newTexture; + } + if (texturesJson.ContainsKey(name)) + { + return GetTexture(name, data); + } } - if (texturesJson.ContainsKey(name)) + catch (Exception ex) { - return GetTexture(name, data); + Console.WriteLine("Error getting texture for:"); + String datastring = string.Join(", ", data.Select(kvp => kvp.Key + ": " + kvp.Value.ToString())); + Console.WriteLine($"{x} {z} {y}: {name}, {datastring}"); + Console.WriteLine("Error: " + ex); } return null; From 402d7f861a87a6515f96e2f2573208ac4dac06aa Mon Sep 17 00:00:00 2001 From: Christen Lofland Date: Tue, 21 Dec 2021 17:18:17 -0600 Subject: [PATCH 4/9] Log chunk location of missing textures Often a missing texture is actually a bad block in a map. This makes it easier to find those blocks and remove them. --- Maploader/Renderer/ChunkRenderer.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Maploader/Renderer/ChunkRenderer.cs b/Maploader/Renderer/ChunkRenderer.cs index e5d7545..479d67a 100644 --- a/Maploader/Renderer/ChunkRenderer.cs +++ b/Maploader/Renderer/ChunkRenderer.cs @@ -259,7 +259,8 @@ public void RenderChunk(TImage dest, Chunk c, int xOffset, int zOffset) textureFinder.FindTexturePath(block.Block.Id, block.Block.Data, block.X, block.Z, block.Y); if (textures == null) { - Console.WriteLine($"Missing Texture(2): {block.ToString().PadRight(30)}"); + Console.WriteLine($"\r\nMissing Texture(2): {block.ToString().PadRight(30)}"); + Console.WriteLine("\tin " + c); MissingTextures.Add($"ID: {block.Block.Id}"); continue; } From 49c1848f70517bdf68234189bc1ad6c8ed67399e Mon Sep 17 00:00:00 2001 From: Christen Lofland Date: Tue, 21 Dec 2021 17:20:39 -0600 Subject: [PATCH 5/9] Stone Slab type 2 Apparently, at least in my map, stone_slab_type 2 is labeled "wood". --- Maploader/Renderer/Texture/TextureFinder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Maploader/Renderer/Texture/TextureFinder.cs b/Maploader/Renderer/Texture/TextureFinder.cs index 23f78c5..9a510ba 100644 --- a/Maploader/Renderer/Texture/TextureFinder.cs +++ b/Maploader/Renderer/Texture/TextureFinder.cs @@ -2224,7 +2224,7 @@ private TextureStack CreateTexture(string texturePath) {1, new Dictionary() { {"smooth_stone", 0}, {"sandstone", 1}, - // {"planks"?, 2}, + {"wood", 2}, {"cobblestone", 3}, {"brick", 4}, {"stone_brick", 5}, From 77a184108698aff768bc3fe09f7472ff571da63a Mon Sep 17 00:00:00 2001 From: Christen Lofland Date: Tue, 21 Dec 2021 20:45:17 -0600 Subject: [PATCH 6/9] Properly Render invisible blocks I found two block in my world: invisibleBedrock and movingBlock that were failing to render and causing "black holes". invisibleBedrock is something one can get via a command stick into the world. It is essentially what it says. I'm not sure what movingBlocks are. Possibly the result of a bug in old versions. I have marked both with a structure_void block that gives a red block around the spot, and also set them to transparent so you an see the terrain under them. --- Maploader/Renderer/Texture/TextureFinder.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Maploader/Renderer/Texture/TextureFinder.cs b/Maploader/Renderer/Texture/TextureFinder.cs index 9a510ba..3854029 100644 --- a/Maploader/Renderer/Texture/TextureFinder.cs +++ b/Maploader/Renderer/Texture/TextureFinder.cs @@ -238,6 +238,10 @@ public class TextureFinder where TImage : class {"minecraft:red_candle", true}, {"minecraft:black_candle", true}, {"minecraft:spore_blossom", true}, + + // Special cases + {"minecraft:invisibleBedrock", true}, + {"minecraft:movingBlock", true}, }; private readonly Dictionary texturesJson; @@ -1303,6 +1307,15 @@ private TextureStack GetSubstitution(string name, Dictionary dat case "red_candle": case "black_candle": return RenderCandle(name, data); + + // Special cases + // These blocks either don't strictly "exist" and are not visible, + // but they can be in the world either via commands or old Bedrock worlds + // I am using a structure_void block because it is in he default tile set + // and seems to indicate "look, something is here" + case "invisibleBedrock": + case "movingBlock": + return "textures/blocks/structure_void"; } return null; From 996c9f596c783eb3746dd45dcf15b47283a40746 Mon Sep 17 00:00:00 2001 From: Christen Lofland Date: Tue, 21 Dec 2021 20:47:08 -0600 Subject: [PATCH 7/9] Handle missing data fields in blocks For whatever reason, my map was missing the required data fields on many blocks. I have updated the code to handle this missing data gracefully and render a "default" variety of the given block in each instance without crashing or complaining. --- Maploader/Renderer/Texture/TextureFinder.cs | 59 ++++++++++++--------- 1 file changed, 33 insertions(+), 26 deletions(-) diff --git a/Maploader/Renderer/Texture/TextureFinder.cs b/Maploader/Renderer/Texture/TextureFinder.cs index 3854029..21f1049 100644 --- a/Maploader/Renderer/Texture/TextureFinder.cs +++ b/Maploader/Renderer/Texture/TextureFinder.cs @@ -323,7 +323,7 @@ private TextureStack GetSubstitution(string name, Dictionary dat { // TODO: fix bed colours int headBit = (int)data.GetValueOrDefault("head_piece_bit", 0); - RotateFlip rot = RotateFromDirection(((int)data["direction"] + 3) % 4); + RotateFlip rot = data.ContainsKey("direction") ? RotateFromDirection(((int)data["direction"] + 3) % 4) : 0; return CreateTexture(headBit != 0 ? "textures/blocks/bed_head_top" : "textures/blocks/bed_feet_top") @@ -334,7 +334,7 @@ private TextureStack GetSubstitution(string name, Dictionary dat case "wooden_slab": case "double_wooden_slab": { - int plankIndex = WoodIndexes[(string)data.GetValueOrDefault("wood_type")]; + int plankIndex = data.ContainsKey("wood_type") ? WoodIndexes[(string)data.GetValueOrDefault("wood_type")] : 0; return GetTexture("planks", plankIndex); } @@ -440,9 +440,9 @@ private TextureStack GetSubstitution(string name, Dictionary dat return RenderRail("rail_detector", "rail_detector_powered", data); case "stonebrick": - return GetTexture("stonebrick", StoneBrickIndexes[(string)data["stone_brick_type"]]); + return GetTexture("stonebrick", data.ContainsKey("stone_brick_type") ? StoneBrickIndexes[(string)data["stone_brick_type"]] : 0); case "monster_egg": - return GetTexture("monster_egg", MonsterEggIndexes[(string)data["monster_egg_stone_type"]]); + return GetTexture("monster_egg", data.ContainsKey("monster_egg_stone_type") ? MonsterEggIndexes[(string)data["monster_egg_stone_type"]] : 0); case "red_mushroom_block": return GetTexture("mushroom_red_top", data); @@ -481,7 +481,8 @@ private TextureStack GetSubstitution(string name, Dictionary dat return GetTexture("daylight_detector_top", 1); case "dispenser": { - switch ((BlockFace) data["facing_direction"]) + var facingDirection = data.ContainsKey("facing_direction") ? data["facing_direction"] : BlockFace.Down; + switch ((BlockFace) facingDirection) { case BlockFace.Up: return GetTexture("dispenser_front_vertical"); @@ -492,7 +493,8 @@ private TextureStack GetSubstitution(string name, Dictionary dat case "observer": { int powered = (int)data.GetValueOrDefault("powered_bit", 0); - switch ((BlockFace) data["facing_direction"]) + var facingDirection = data.ContainsKey("facing_direction") ? data["facing_direction"] : BlockFace.South; + switch ((BlockFace) facingDirection) { case BlockFace.Down: return GetTexture("observer_south", powered); @@ -511,7 +513,8 @@ private TextureStack GetSubstitution(string name, Dictionary dat } case "dropper": { - switch ((BlockFace) data["facing_direction"]) + var facingDirection = data.ContainsKey("facing_direction") ? data["facing_direction"] : BlockFace.Down; + switch ((BlockFace) facingDirection) { case BlockFace.Up: return GetTexture("dropper_front_vertical"); @@ -546,12 +549,17 @@ private TextureStack GetSubstitution(string name, Dictionary dat case "anvil": { int damage = 0; - switch ((string)data["damage"]) + if (data.ContainsKey("damage")) { - case "slightly_damaged": - damage = 1; break; - case "very_damaged": - damage = 2; break; + switch ((string)data["damage"]) + { + case "slightly_damaged": + damage = 1; + break; + case "very_damaged": + damage = 2; + break; + } } return GetTexture("anvil_top_damaged_x", damage, null, RotateFromDirection(data)); } @@ -609,7 +617,7 @@ private TextureStack GetSubstitution(string name, Dictionary dat case "nether_brick_fence": return RenderFence("nether_brick", data); case "fence": - data["val"] = WoodIndexes[(string)data.GetValueOrDefault("wood_type")]; + data["val"] = data.ContainsKey("wood_type") ? WoodIndexes[(string)data.GetValueOrDefault("wood_type")] : 0; return RenderFence("planks", data); case "podzol": return GetTexture("dirt_podzol_top", data); @@ -808,16 +816,16 @@ private TextureStack GetSubstitution(string name, Dictionary dat case "stone_slab": case "double_stone_slab": - return GetTexture("stone_slab_top", StoneSlabIndexes[1][(string)data["stone_slab_type"]]); + return GetTexture("stone_slab_top", data.ContainsKey("stone_slab_type") ? StoneSlabIndexes[1][(string)data["stone_slab_type"]] : 0); case "stone_slab2": case "double_stone_slab2": - return GetTexture("stone_slab_top_2", StoneSlabIndexes[2][(string)data["stone_slab_type_2"]]); + return GetTexture("stone_slab_top_2", data.ContainsKey("stone_slab_type_2") ? StoneSlabIndexes[2][(string)data["stone_slab_type_2"]] : 0); case "stone_slab3": case "double_stone_slab3": - return GetTexture("stone_slab_top_3", StoneSlabIndexes[3][(string)data["stone_slab_type_3"]]); + return GetTexture("stone_slab_top_3", data.ContainsKey("stone_slab_type_3") ? StoneSlabIndexes[3][(string)data["stone_slab_type_3"]] : 0); case "stone_slab4": case "double_stone_slab4": - return GetTexture("stone_slab_top_4", StoneSlabIndexes[4][(string)data["stone_slab_type_4"]]); + return GetTexture("stone_slab_top_4", data.ContainsKey("stone_slab_type_4") ? StoneSlabIndexes[4][(string)data["stone_slab_type_4"]] : 0); case "bone_block": return RenderPillar("bone_block_top", "bone_block_side", data); @@ -903,8 +911,7 @@ private TextureStack GetSubstitution(string name, Dictionary dat case "sapling": { - int val = WoodIndexes[(string)data.GetValueOrDefault("sapling_type")]; - return GetTexture("sapling", val); + return GetTexture("sapling", data.ContainsKey("sapling_type") ? WoodIndexes[(string)data.GetValueOrDefault("sapling_type")] : 0); } case "enchanting_table": @@ -1151,7 +1158,7 @@ private TextureStack GetSubstitution(string name, Dictionary dat new Rect(0, 0, 4, 11), // 11 might not be the right number new Rect(6, 5, 4, 11)); case "sponge": - return GetTexture("sponge", (string)data["sponge_type"] == "wet" ? 1 : 0); + return GetTexture("sponge", data.ContainsKey("sponge_type") && (string)data["sponge_type"] == "wet" ? 1 : 0); case "stone": { int index = StoneIndexes[(string)data.GetValueOrDefault("stone_type", "stone")]; @@ -1451,7 +1458,7 @@ private TextureStack RenderButton (Dictionary data, string textu } private TextureStack RenderButton(string texture, Dictionary data) { - int direction = (int)data["facing_direction"]; + int direction = data.ContainsKey("facing_direction") ? (int)data["facing_direction"] : 0; var t = GetTexture(texture, 0); int thickness = (int)data.GetValueOrDefault("button_pressed_bit", 0) == 0 ? 2 : 1; switch (direction) @@ -1489,8 +1496,8 @@ private TextureStack RenderFenceGate (Dictionary data, string te } private TextureStack RenderFenceGate (string texture, Dictionary data) { - int direction = (int)data["direction"]; - int open_bit = (int)data["open_bit"]; + int direction = data.ContainsKey("direction") ? (int)data["direction"] : 0; + int open_bit = data.ContainsKey("open_bit") ? (int)data["open_bit"] : 0; if (open_bit != 0) { @@ -2088,11 +2095,11 @@ private TextureStack RenderBamboo(Dictionary data) private RotateFlip RotateFromDirection(Dictionary data, int offset) { - return RotateFromDirection((int)data["direction"] + offset); + return RotateFromDirection(data.ContainsKey("direction") ? (int)data["direction"] + offset : offset); } private RotateFlip RotateFromDirection(Dictionary data) { - return RotateFromDirection((int)data["direction"]); + return RotateFromDirection(data.ContainsKey("direction") ? (int)data["direction"] : 0); } private RotateFlip RotateFromDirection(int direction) { @@ -2411,7 +2418,7 @@ private TextureStack GetTexture(string name, Dictionary data, Te } if(blockProperties.Key == "facing_direction") { - int direction = (int)data["facing_direction"]; + int direction = data.ContainsKey("facing_direction") ? (int)data["facing_direction"] : 0; switch (direction) { case 2: From 8d9b330a12438178a115c83ea9fc66b29cf88cb2 Mon Sep 17 00:00:00 2001 From: Christen Lofland Date: Mon, 17 Oct 2022 17:24:59 -0500 Subject: [PATCH 8/9] Fix my terrible merge attempt. --- Maploader/Renderer/Texture/TextureFinder.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Maploader/Renderer/Texture/TextureFinder.cs b/Maploader/Renderer/Texture/TextureFinder.cs index 456a9d7..fc7d82f 100644 --- a/Maploader/Renderer/Texture/TextureFinder.cs +++ b/Maploader/Renderer/Texture/TextureFinder.cs @@ -842,7 +842,6 @@ private TextureStack GetSubstitution(string name, Dictionary dat case "stone_slab": case "double_stone_slab": -<<<<<<< HEAD return GetTexture("stone_slab_top", data.ContainsKey("stone_slab_type") ? StoneSlabIndexes[1][(string)data["stone_slab_type"]] : 0); case "stone_slab2": case "double_stone_slab2": @@ -853,7 +852,6 @@ private TextureStack GetSubstitution(string name, Dictionary dat case "stone_slab4": case "double_stone_slab4": return GetTexture("stone_slab_top_4", data.ContainsKey("stone_slab_type_4") ? StoneSlabIndexes[4][(string)data["stone_slab_type_4"]] : 0); -======= case "stone_block_slab": case "double_stone_block_slab": return GetTexture("stone_slab_top", StoneSlabIndexes[1][(string)data["stone_slab_type"]]); @@ -872,7 +870,6 @@ private TextureStack GetSubstitution(string name, Dictionary dat case "stone_block_slab4": case "double_stone_block_slab4": return GetTexture("stone_slab_top_4", StoneSlabIndexes[4][(string)data["stone_slab_type_4"]]); ->>>>>>> upstream/master case "bone_block": return RenderPillar("bone_block_top", "bone_block_side", data); @@ -1358,7 +1355,6 @@ private TextureStack GetSubstitution(string name, Dictionary dat case "red_candle": case "black_candle": return RenderCandle(name, data); -<<<<<<< HEAD // Special cases // These blocks either don't strictly "exist" and are not visible, @@ -1368,7 +1364,6 @@ private TextureStack GetSubstitution(string name, Dictionary dat case "invisibleBedrock": case "movingBlock": return "textures/blocks/structure_void"; -======= // 1.19 case "mangrove_wood": @@ -1514,7 +1509,6 @@ private TextureStack GetSubstitution(string name, Dictionary dat return new TextureStack(); // transparent case "structure_block": return GetTexture("structure_block", data); ->>>>>>> upstream/master } return null; From 4cc8125942d9824ff1613e78e3786f7400f3002e Mon Sep 17 00:00:00 2001 From: Christen Lofland Date: Tue, 18 Oct 2022 09:00:10 -0500 Subject: [PATCH 9/9] More merge cleanup. --- Maploader/Renderer/Texture/TextureFinder.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Maploader/Renderer/Texture/TextureFinder.cs b/Maploader/Renderer/Texture/TextureFinder.cs index fc7d82f..4cb0a08 100644 --- a/Maploader/Renderer/Texture/TextureFinder.cs +++ b/Maploader/Renderer/Texture/TextureFinder.cs @@ -855,18 +855,12 @@ private TextureStack GetSubstitution(string name, Dictionary dat case "stone_block_slab": case "double_stone_block_slab": return GetTexture("stone_slab_top", StoneSlabIndexes[1][(string)data["stone_slab_type"]]); - case "stone_slab2": - case "double_stone_slab2": case "stone_block_slab2": case "double_stone_block_slab2": return GetTexture("stone_slab_top_2", StoneSlabIndexes[2][(string)data["stone_slab_type_2"]]); - case "stone_slab3": - case "double_stone_slab3": case "stone_block_slab3": case "double_stone_block_slab3": return GetTexture("stone_slab_top_3", StoneSlabIndexes[3][(string)data["stone_slab_type_3"]]); - case "stone_slab4": - case "double_stone_slab4": case "stone_block_slab4": case "double_stone_block_slab4": return GetTexture("stone_slab_top_4", StoneSlabIndexes[4][(string)data["stone_slab_type_4"]]);