diff --git a/Minecraft Client/Assets/Content/Player.prefab b/Minecraft Client/Assets/Content/Player.prefab index 3391926..8b2908b 100644 --- a/Minecraft Client/Assets/Content/Player.prefab +++ b/Minecraft Client/Assets/Content/Player.prefab @@ -57,7 +57,7 @@ Transform: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 6443714940181712877} m_LocalRotation: {x: -0.7071068, y: 0, z: 0, w: 0.7071068} - m_LocalPosition: {x: 0, y: -0.132, z: 0.024} + m_LocalPosition: {x: 0, y: -0.092, z: 0.024} m_LocalScale: {x: 0.24999988, y: 0.24999988, z: 0.25} m_Children: [] m_Father: {fileID: 4093383343133656141} diff --git a/Minecraft Client/Assets/Scripts/Game/Chunk.cs b/Minecraft Client/Assets/Scripts/Game/Chunk.cs index fdec88d..1d41f77 100644 --- a/Minecraft Client/Assets/Scripts/Game/Chunk.cs +++ b/Minecraft Client/Assets/Scripts/Game/Chunk.cs @@ -9,6 +9,7 @@ public class Chunk private Material material; private ChunkCoord chunkPosition; private World world; + public bool active = false; //rendering public GameObject gameObject; @@ -136,6 +137,17 @@ public class Chunk meshFilter.mesh = mesh; meshRenderer.material = material; collider.sharedMesh = mesh; + active = true; + } + + public void DestroyMesh() + { + meshFilter.mesh = null; + vertices.Clear(); + triangles.Clear(); + uv.Clear(); + collider.sharedMesh = null; + active = false; } public void Edit(byte x, byte y, byte z, byte blockID) diff --git a/Minecraft Client/Assets/Scripts/Game/Data.cs b/Minecraft Client/Assets/Scripts/Game/Data.cs index 5ffe058..63d2535 100644 --- a/Minecraft Client/Assets/Scripts/Game/Data.cs +++ b/Minecraft Client/Assets/Scripts/Game/Data.cs @@ -6,6 +6,7 @@ public class Data { public static int chunkWidth = 15, chunkHeight = 250; public static int textureAtlasSize = 16; + public static int viewDistance = 9; public static readonly Vector3[] vertices = { diff --git a/Minecraft Client/Assets/Scripts/Game/Player.cs b/Minecraft Client/Assets/Scripts/Game/Player.cs index 8a093ba..8c94e08 100644 --- a/Minecraft Client/Assets/Scripts/Game/Player.cs +++ b/Minecraft Client/Assets/Scripts/Game/Player.cs @@ -277,10 +277,10 @@ public class Player : MonoBehaviour private float CheckUpSpeed(float upSpeed) { if ( - world.CheckBlock(new Vector3(transform.position.x - playerWidth, transform.position.y + upSpeed + 2f, transform.position.z - playerWidth)) || - world.CheckBlock(new Vector3(transform.position.x + playerWidth, transform.position.y + upSpeed + 2f, transform.position.z - playerWidth)) || - world.CheckBlock(new Vector3(transform.position.x + playerWidth, transform.position.y + upSpeed + 2f, transform.position.z + playerWidth)) || - world.CheckBlock(new Vector3(transform.position.x - playerWidth, transform.position.y + upSpeed + 2f, transform.position.z + playerWidth)) + world.CheckBlock(new Vector3(transform.position.x - playerWidth, transform.position.y + upSpeed + 1.9f, transform.position.z - playerWidth)) || + world.CheckBlock(new Vector3(transform.position.x + playerWidth, transform.position.y + upSpeed + 1.9f, transform.position.z - playerWidth)) || + world.CheckBlock(new Vector3(transform.position.x + playerWidth, transform.position.y + upSpeed + 1.9f, transform.position.z + playerWidth)) || + world.CheckBlock(new Vector3(transform.position.x - playerWidth, transform.position.y + upSpeed + 1.9f, transform.position.z + playerWidth)) ) { return 0; diff --git a/Minecraft Client/Assets/Scripts/Game/World.cs b/Minecraft Client/Assets/Scripts/Game/World.cs index 791badb..8f3a897 100644 --- a/Minecraft Client/Assets/Scripts/Game/World.cs +++ b/Minecraft Client/Assets/Scripts/Game/World.cs @@ -24,10 +24,12 @@ public class World : MonoBehaviour [SerializeField] private Player player; [SerializeField] private GameObject deadScreen; [SerializeField] private GameObject pauseScreen; + private ChunkCoord lastPlayerChunkCoord = new ChunkCoord(0, 0); //chunks private Chunk[,] chunks; private Queue chunksToUpdate = new Queue(); + private List lastActiveChunks = new List(); //blocks [SerializeField] public BlockData[] blockData; @@ -54,6 +56,17 @@ public class World : MonoBehaviour private void Update() { + ChunkCoord playerChunkCoord = new ChunkCoord((int)(player.transform.position.x / Data.chunkWidth), + (int)(player.transform.position.z / Data.chunkWidth)); + + if (lastPlayerChunkCoord.x != playerChunkCoord.x || lastPlayerChunkCoord.z != playerChunkCoord.z) + { + LoadChunks(playerChunkCoord); + } + + lastPlayerChunkCoord = new ChunkCoord((int)(player.transform.position.x / Data.chunkWidth), + (int)(player.transform.position.z / Data.chunkWidth)); + //update 1 chunk in list if (chunksToUpdate.Count > 0) { @@ -107,6 +120,41 @@ public class World : MonoBehaviour } } + private void LoadChunks(ChunkCoord playerChunk) + { + List checkList = new List(); + + for (int x = playerChunk.x - Data.viewDistance; x < playerChunk.x + Data.viewDistance; x++) + { + for (int z = playerChunk.z - Data.viewDistance; z < playerChunk.z + Data.viewDistance; z++) + { + if(chunks[x, z].gameObject == null) + { + chunks[x, z].Initialize(); + chunks[x, z].gameObject.transform.SetParent(gameObject.transform); + } + if(!chunks[x, z].active) + { + chunksToUpdate.Enqueue(new ChunkCoord(x, z)); + } + checkList.Add(chunks[x, z]); + } + } + + foreach (Chunk c in lastActiveChunks) + { + if (!checkList.Contains(c)) + { + c.DestroyMesh(); + } + } + + lastActiveChunks.Clear(); + + lastActiveChunks = new List(checkList); + } + + //enqueue player position update to list public void UpdatePlayerPosition(Vector3 position, byte id) { @@ -149,14 +197,14 @@ public class World : MonoBehaviour //initialized the chunk objects public void CreateChunks() { - for (int x = 0; x < worldSize; x++) + for (int x = worldSize / 2 - Data.viewDistance; x < worldSize / 2 + Data.viewDistance; x++) { - for (int z = 0; z < worldSize; z++) + for (int z = worldSize / 2 - Data.viewDistance; z < worldSize / 2 + Data.viewDistance; z++) { chunks[x, z].Initialize(); chunks[x, z].gameObject.transform.SetParent(gameObject.transform); - chunks[x, z].AddBlocks(); - chunks[x, z].CreateMesh(); + chunksToUpdate.Enqueue(new ChunkCoord(x, z)); + lastActiveChunks.Add(chunks[x, z]); } } } @@ -213,11 +261,11 @@ public class World : MonoBehaviour int zInChunk = z - (zChunk * Data.chunkWidth); Chunk c = chunks[xChunk, zChunk]; - for (int y = 0; y < Data.chunkHeight; y++) + for (int y = Data.chunkHeight - 1; y > 0; y--) { - if (c.blocks[xInChunk, y, zInChunk] == 0) + if (c.blocks[xInChunk, y, zInChunk] != 0) { - return (byte)(y - 1); + return (byte)(y + 1); } } @@ -309,6 +357,8 @@ public class World : MonoBehaviour Time.timeScale = 1; player.transform.position = player.GetDefaultPlayerPosition(); deadScreen.SetActive(false); + LoadChunks(new ChunkCoord((int)(player.transform.position.x / Data.chunkWidth), + (int)(player.transform.position.z / Data.chunkWidth))); } public void ResumeButton() diff --git a/Minecraft Server/Assets/Game/Noise.cs b/Minecraft Server/Assets/Game/Noise.cs new file mode 100644 index 0000000..2049108 --- /dev/null +++ b/Minecraft Server/Assets/Game/Noise.cs @@ -0,0 +1,51 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class Noise +{ + public byte GetHeight(int x, int z, int randomOffsetX, int randomOffsetZ) + { + float scale = 0.025f; + byte perlinHeight = 10; + byte groundHeight = 50; + + byte height = (byte)(Mathf.PerlinNoise((x + randomOffsetX) * scale + 0.1f, (z + randomOffsetZ) * scale + 0.1f) * perlinHeight + groundHeight); + return height; + } + + public bool CheckTree(int x, int z) + { + float scale = .99f; + float threshold = .96f; + + if (Mathf.PerlinNoise((x) * scale + 0.1f, (z) * scale + 0.1f) >= threshold) + { + return true; + } + + return false; + } + + public bool Get3DPerlin(Vector3 position, float offset, float scale, float threshold) + { + float x = (position.x + offset + .1f) * scale; + float y = (position.y + offset + .1f) * scale; + float z = (position.z + offset + .1f) * scale; + + float AB = Mathf.PerlinNoise(x, y); + float BC = Mathf.PerlinNoise(y, z); + float AC = Mathf.PerlinNoise(x, z); + + float BA = Mathf.PerlinNoise(y, x); + float CB = Mathf.PerlinNoise(z, y); + float CA = Mathf.PerlinNoise(z, x); + + if ((AB + BC + AC + BA + CB + CA) / 6f > threshold) + { + return true; + } + + return false; + } +} diff --git a/Minecraft Server/Assets/Game/Noise.cs.meta b/Minecraft Server/Assets/Game/Noise.cs.meta new file mode 100644 index 0000000..1024a5a --- /dev/null +++ b/Minecraft Server/Assets/Game/Noise.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: dedaa2ec7a8b12443a08f16cad880f84 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Minecraft Server/Assets/Game/World.cs b/Minecraft Server/Assets/Game/World.cs index 3371c84..05e500c 100644 --- a/Minecraft Server/Assets/Game/World.cs +++ b/Minecraft Server/Assets/Game/World.cs @@ -13,6 +13,7 @@ public class World : MonoBehaviour private int randomOffsetX, randomOffsetZ; private int seed = 0; private string dataPath; + private Noise noise = new Noise(); //chunks public Chunk[,] chunks; @@ -29,6 +30,8 @@ public class World : MonoBehaviour if (File.Exists(Application.dataPath + "\\save.world")) { + Console.WriteLine("loading world... \n"); + chunks = new Chunk[worldSize, worldSize]; for (int x = 0; x < worldSize; x++) { @@ -65,6 +68,8 @@ public class World : MonoBehaviour } else { + Console.WriteLine("generate world... \n"); + CreateChunks(); CreateTrees(); } @@ -102,12 +107,12 @@ public class World : MonoBehaviour { for (int z = 4; z < worldSize * Data.chunkWidth - 4; z++) { - if (CheckTree(x, z)) + if (noise.CheckTree(x, z)) { ChunkCoord chunk = new ChunkCoord((int)(x / Data.chunkWidth), (int)(z / Data.chunkWidth)); int xInChunk = (int)(x - chunk.x * Data.chunkWidth); - int yInChunk = (int)(GetHeight(x, z)); + int yInChunk = (int)(noise.GetHeight(x, z, randomOffsetX, randomOffsetZ)); int zInChunk = (int)(z - chunk.z * Data.chunkWidth); int height = Random.Range(5, 9); @@ -157,11 +162,6 @@ public class World : MonoBehaviour } } } - - - - - } } } @@ -170,7 +170,7 @@ public class World : MonoBehaviour //return the ID of a block public byte GetBlockID(Vector3 positionInWorld) { - byte height = GetHeight((int)positionInWorld.x, (int)positionInWorld.z); + byte height = noise.GetHeight((int)positionInWorld.x, (int)positionInWorld.z, randomOffsetX, randomOffsetZ); //world pass if (positionInWorld.x < 0 || positionInWorld.y < 0 || positionInWorld.z < 0 || @@ -180,24 +180,37 @@ public class World : MonoBehaviour return 0; } - //chunk pass + //surface pass if ((int)positionInWorld.y == height) { return 3; } + //bedrock pass if ((int)positionInWorld.y == 0) { + return 1; } + //dirt pass if ((int)positionInWorld.y > height - 3) { return 2; } + //underground pass if ((int)positionInWorld.y < height) { + //caves + if((int)positionInWorld.y > 6 && (int)positionInWorld.y < height - 8) + { + if (noise.Get3DPerlin(positionInWorld, 0, 0.18f, 0.5f)) + { + return 0; + } + } + return 4; } @@ -240,30 +253,6 @@ public class World : MonoBehaviour return true; } - private byte GetHeight(int x, int z) - { - float scale = 0.025f; - byte perlinHeight = 10; - byte groundHeight = 10; - - byte height = (byte)(Mathf.PerlinNoise((x + randomOffsetX) * scale + 0.1f, (z + randomOffsetZ) * scale + 0.1f) * perlinHeight + groundHeight); - return height; - } - - private bool CheckTree(int x, int z) - { - float scale = .99f; - float threshold = .96f; - - if (Mathf.PerlinNoise((x) * scale + 0.1f, (z) * scale + 0.1f) >= threshold) - { - return true; - } - - return false; - - } - public void EditBlock(ChunkCoord chunk, Vector3 positionInChunk, byte blockID) { byte xInChunk = (byte)(positionInChunk.x); @@ -311,6 +300,6 @@ public class World : MonoBehaviour } } writer.Close(); - Console.WriteLine("world saved! \n"); + Console.WriteLine("world saved! (world.save) \n"); } } diff --git a/Minecraft Server/Assets/Scenes/Server.unity b/Minecraft Server/Assets/Scenes/Server.unity index ce1753d..74bc46c 100644 --- a/Minecraft Server/Assets/Scenes/Server.unity +++ b/Minecraft Server/Assets/Scenes/Server.unity @@ -166,5 +166,5 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 5457f26f725053d46bffb9885acfd7d8, type: 3} m_Name: m_EditorClassIdentifier: - worldSize: 20 + worldSize: 60 transferDelay: 5 diff --git a/Minecraft Server/Assets/save.world b/Minecraft Server/Assets/save.world new file mode 100644 index 0000000..e69de29 diff --git a/Minecraft Server/Assets/save.world.meta b/Minecraft Server/Assets/save.world.meta new file mode 100644 index 0000000..69f851e --- /dev/null +++ b/Minecraft Server/Assets/save.world.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 940041af630d8d944ac3b74467aa4ae7 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: