diff --git a/ClassicalSharp/ClassicalSharp.csproj b/ClassicalSharp/ClassicalSharp.csproj index ffb5aae35..30b93ed52 100644 --- a/ClassicalSharp/ClassicalSharp.csproj +++ b/ClassicalSharp/ClassicalSharp.csproj @@ -4,7 +4,7 @@ {BEB1C785-5CAD-48FF-A886-876BF0A318D4} Debug AnyCPU - Exe + WinExe ClassicalSharp ClassicalSharp v2.0 diff --git a/ClassicalSharp/Map/Lighting/BasicLighting.Updater.cs b/ClassicalSharp/Map/Lighting/BasicLighting.Updater.cs index 1c521fa40..bd6df1bb1 100644 --- a/ClassicalSharp/Map/Lighting/BasicLighting.Updater.cs +++ b/ClassicalSharp/Map/Lighting/BasicLighting.Updater.cs @@ -1,6 +1,7 @@ // Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3 using System; using ClassicalSharp.Renderers; +using BlockRaw = System.Byte; using BlockID = System.UInt16; namespace ClassicalSharp.Map { @@ -20,8 +21,8 @@ namespace ClassicalSharp.Map { RefreshAffected(x, y, z, newBlock, lightH + 1, newHeight); } - MapRenderer renderer; - void UpdateLighting(int x, int y, int z, BlockID oldBlock, + MapRenderer renderer; + void UpdateLighting(int x, int y, int z, BlockID oldBlock, BlockID newBlock, int index, int lightH) { bool didBlock = BlockInfo.BlocksLight[oldBlock]; bool nowBlocks = BlockInfo.BlocksLight[newBlock]; @@ -93,29 +94,43 @@ namespace ClassicalSharp.Map { int cx, int cy, int cz, int minCy, int maxCy) { World world = game.World; if (minCy == maxCy) { - int index = x + world.Width * (z + y * world.Length); - ResetNeighourChunk(cx, cy, cz, block, y, index, y); + int minY = cy << 4; + int i = x + world.Width * (z + y * world.Length); + + if (NeedsNeighbour(block, i, minY, y, y)) { + renderer.RefreshChunk(cx, cy, cz); + } } else { for (cy = maxCy; cy >= minCy; cy--) { - int maxY = Math.Min(world.MaxY, (cy << 4) + 15); - int index = x + world.Width * (z + maxY * world.Length); - ResetNeighourChunk(cx, cy, cz, block, maxY, index, y); + int minY = cy << 4, maxY = Math.Min(world.MaxY, (cy << 4) + 15); + int i = x + world.Width * (z + maxY * world.Length); + + if (NeedsNeighbour(block, i, minY, maxY, y)) { + renderer.RefreshChunk(cx, cy, cz); + } } } } - void ResetNeighourChunk(int cx, int cy, int cz, BlockID block, - int y, int index, int nY) { + bool NeedsNeighbour(BlockID block, int i, int minY, int y, int nY) { World world = game.World; - int minY = cy << 4; + BlockRaw[] blocks = world.blocks; // Update if any blocks in the chunk are affected by light change - for (; y >= minY; y--) { - BlockID other = world.blocks[index]; - bool affected = y == nY ? Needs(block, other) : BlockInfo.Draw[other] != DrawType.Gas; - if (affected) { renderer.RefreshChunk(cx, cy, cz); return; } - index -= world.Width * world.Length; + if (BlockInfo.MaxDefined < 256) { + for (; y >= minY; y--, i -= world.OneY) { + BlockID other = blocks[i]; + bool affected = y == nY ? Needs(block, other) : BlockInfo.Draw[other] != DrawType.Gas; + if (affected) return true; + } + } else { + for (; y >= minY; y--, i -= world.OneY) { + BlockID other = (BlockID)(blocks[i] | (world.blocks2[i] << 8)); + bool affected = y == nY ? Needs(block, other) : BlockInfo.Draw[other] != DrawType.Gas; + if (affected) return true; + } } + return false; } void ResetColumn(int cx, int cy, int cz, int minCy, int maxCy) { diff --git a/ClassicalSharp/Map/World.cs b/ClassicalSharp/Map/World.cs index 058a04afa..45f76ec9d 100644 --- a/ClassicalSharp/Map/World.cs +++ b/ClassicalSharp/Map/World.cs @@ -13,7 +13,7 @@ namespace ClassicalSharp.Map { public sealed class World { public BlockRaw[] blocks, blocks2; - public int Width, Height, Length, MaxX, MaxY, MaxZ; + public int Width, Height, Length, MaxX, MaxY, MaxZ, OneY; public bool HasBlocks; /// Contains the environment metadata for this world. @@ -34,6 +34,8 @@ namespace ClassicalSharp.Map { Env.Reset(); Width = 0; Height = 0; Length = 0; MaxX = 0; MaxY = 0; MaxZ = 0; + OneY = 0; + blocks = null; blocks2 = null; Uuid = Guid.NewGuid(); @@ -45,6 +47,7 @@ namespace ClassicalSharp.Map { Width = width; MaxX = width - 1; Height = height; MaxY = height - 1; Length = length; MaxZ = length - 1; + OneY = width * length; blocks = blocksRaw; if (blocks.Length == 0) blocks = null; diff --git a/ClassicalSharp/Network/Protocols/Classic.cs b/ClassicalSharp/Network/Protocols/Classic.cs index 72a608b2f..19cefe725 100644 --- a/ClassicalSharp/Network/Protocols/Classic.cs +++ b/ClassicalSharp/Network/Protocols/Classic.cs @@ -47,6 +47,9 @@ namespace ClassicalSharp.Network.Protocols { GZipHeaderReader gzipHeader; int mapSizeIndex, mapIndex; byte[] mapSize = new byte[4], map; + #if USE16_BIT + byte[] map2; + #endif FixedBufferStream gzippedMap; Screen prevScreen; bool prevCursorVisible; @@ -74,10 +77,10 @@ namespace ClassicalSharp.Network.Protocols { int size = reader.ReadInt32(); gzipHeader.done = true; mapSizeIndex = 4; - #if USE16_BIT - if (reader.ExtendedBlocks) size *= 2; - #endif map = new byte[size]; + #if USE16_BIT + if (reader.ExtendedBlocks) map2 = new byte[size]; + #endif } } @@ -130,10 +133,10 @@ namespace ClassicalSharp.Network.Protocols { if (mapSizeIndex == 4) { if (map == null) { int size = mapSize[0] << 24 | mapSize[1] << 16 | mapSize[2] << 8 | mapSize[3]; - #if USE16_BIT - if (reader.ExtendedBlocks) size *= 2; - #endif map = new byte[size]; + #if USE16_BIT + if (reader.ExtendedBlocks) map2 = new byte[size]; + #endif } mapIndex += gzipStream.Read(map, mapIndex, map.Length - mapIndex); } @@ -144,17 +147,6 @@ namespace ClassicalSharp.Network.Protocols { game.WorldEvents.RaiseMapLoading(progress); } - #if USE16_BIT - static void DecomposeArray(byte[] src, out byte[] b1, out byte[] b2) { - b1 = new byte[src.Length / 2]; - b2 = new byte[src.Length / 2]; - - for (int i = 0, j = 0; i < src.Length; j++) { - b1[j] = src[i++]; b2[j] = src[i++]; - } - } - #endif - void HandleLevelFinalise() { game.Gui.SetNewScreen(null); game.Gui.activeScreen = prevScreen; @@ -170,17 +162,9 @@ namespace ClassicalSharp.Network.Protocols { double loadingMs = (DateTime.UtcNow - mapReceiveStart).TotalMilliseconds; Utils.LogDebug("map loading took: " + loadingMs); - #if USE16_BIT - if (reader.ExtendedBlocks) { - byte[] b1, b2; - DecomposeArray(map, out b1, out b2); - game.World.SetNewMap(b1, mapWidth, mapHeight, mapLength); - game.World.blocks2 = b2; - } else{ - game.World.SetNewMap(map, mapWidth, mapHeight, mapLength); - } - #else game.World.SetNewMap(map, mapWidth, mapHeight, mapLength); + #if USE16_BIT + if (reader.ExtendedBlocks) game.World.blocks2 = map2; #endif game.WorldEvents.RaiseOnNewMapLoaded(); diff --git a/ClassicalSharp/Singleplayer/FoliagePhysics.cs b/ClassicalSharp/Singleplayer/FoliagePhysics.cs index dabf947f0..ee66647f6 100644 --- a/ClassicalSharp/Singleplayer/FoliagePhysics.cs +++ b/ClassicalSharp/Singleplayer/FoliagePhysics.cs @@ -87,7 +87,7 @@ namespace ClassicalSharp.Singleplayer { } BlockRaw below = Block.Stone; - if (y > 0) below = map.blocks[index - map.Width * map.Length]; + if (y > 0) below = map.blocks[index - map.OneY]; if (!(below == Block.Stone || below == Block.Cobblestone)) { game.UpdateBlock(x, y, z, Block.Air); physics.ActivateNeighbours(x, y, z, index); diff --git a/ClassicalSharp/Singleplayer/OtherPhysics.cs b/ClassicalSharp/Singleplayer/OtherPhysics.cs index 57c848703..a2be1b18b 100644 --- a/ClassicalSharp/Singleplayer/OtherPhysics.cs +++ b/ClassicalSharp/Singleplayer/OtherPhysics.cs @@ -17,8 +17,8 @@ namespace ClassicalSharp.Singleplayer { } void HandleSlab(int index, BlockRaw block) { - if (index < map.Width * map.Length) return; // y < 1 - if (map.blocks[index - map.Width * map.Length] != Block.Slab) return; + if (index < map.OneY) return; + if (map.blocks[index - map.OneY] != Block.Slab) return; int x = index % map.Width; int z = (index / map.Width) % map.Length; @@ -28,8 +28,8 @@ namespace ClassicalSharp.Singleplayer { } void HandleCobblestoneSlab(int index, BlockRaw block) { - if (index < map.Width * map.Length) return; // y < 1 - if (map.blocks[index - map.Width * map.Length] != Block.CobblestoneSlab) return; + if (index < map.OneY) return; + if (map.blocks[index - map.OneY] != Block.CobblestoneSlab) return; int x = index % map.Width; int z = (index / map.Width) % map.Length; diff --git a/ClassicalSharp/Singleplayer/Physics.cs b/ClassicalSharp/Singleplayer/Physics.cs index 96bd4ae45..0542867ff 100644 --- a/ClassicalSharp/Singleplayer/Physics.cs +++ b/ClassicalSharp/Singleplayer/Physics.cs @@ -103,7 +103,7 @@ namespace ClassicalSharp.Singleplayer { return false; return y >= env.SidesHeight && y < env.EdgeHeight - && (x == 0 || z == 0 || x == (map.Width - 1) || z == (map.Length - 1)); + && (x == 0 || z == 0 || x == map.MaxX || z == map.MaxZ); } void ResetMap(object sender, EventArgs e) { diff --git a/src/Client/Lighting.c b/src/Client/Lighting.c index ff84bc729..ff3970950 100644 --- a/src/Client/Lighting.c +++ b/src/Client/Lighting.c @@ -132,27 +132,32 @@ bool Lighting_Needs(BlockID block, BlockID other) { return Block_Draw[block] != DRAW_OPAQUE || Block_Draw[other] != DRAW_GAS; } -void Lighting_ResetNeighourChunk(Int32 cx, Int32 cy, Int32 cz, BlockID block, Int32 y, Int32 index, Int32 nY) { - Int32 minY = cy << 4; - +bool Lighting_NeedsNeighour(BlockID block, Int32 index, Int32 minY, Int32 y, Int32 nY) { /* Update if any blocks in the chunk are affected by light change. */ - for (; y >= minY; y--) { + for (; y >= minY; y--, index -= World_OneY) { BlockID other = World_Blocks[index]; bool affected = y == nY ? Lighting_Needs(block, other) : Block_Draw[other] != DRAW_GAS; - if (affected) { MapRenderer_RefreshChunk(cx, cy, cz); return; } - index -= World_OneY; + if (affected) return true; } + return false; } void Lighting_ResetNeighbour(Int32 x, Int32 y, Int32 z, BlockID block, Int32 cx, Int32 cy, Int32 cz, Int32 minCy, Int32 maxCy) { if (minCy == maxCy) { - Lighting_ResetNeighourChunk(cx, cy, cz, block, y, World_Pack(x, y, z), y); + Int32 minY = cy << 4; + + if (Lighting_NeedsNeighour(block, World_Pack(x, y, z), minY, y, y)) { + MapRenderer_RefreshChunk(cx, cy, cz); + } } else { for (cy = maxCy; cy >= minCy; cy--) { - Int32 maxY = (cy << 4) + 15; + Int32 minY = cy << 4, maxY = (cy << 4) + 15; if (maxY > World_MaxY) maxY = World_MaxY; - Lighting_ResetNeighourChunk(cx, cy, cz, block, maxY, World_Pack(x, maxY, z), y); + + if (Lighting_NeedsNeighour(block, World_Pack(x, maxY, z), minY, maxY, y)) { + MapRenderer_RefreshChunk(cx, cy, cz); + } } } }