Files
2022-05-18 00:35:16 +02:00

324 lines
11 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEngine;
using Random = UnityEngine.Random;
public class World : MonoBehaviour
{
//basic
[SerializeField] public int worldSize;
private int randomOffsetX, randomOffsetZ;
private int seed = 0;
private string dataPath;
private Noise noise = new Noise();
//chunks
public Chunk[,] chunks;
//network
private Server server;
[SerializeField] private int transferDelay;
private void Start()
{
dataPath = Application.dataPath;
randomOffsetX = Random.Range(0, 10000);
randomOffsetZ = Random.Range(0, 10000);
if (File.Exists(Application.dataPath + "\\save.world"))
{
Console.WriteLine("loading world... \n");
chunks = new Chunk[worldSize, worldSize];
for (int x = 0; x < worldSize; x++)
{
for (int z = 0; z < worldSize; z++)
{
chunks[x, z] = new Chunk(new ChunkCoord(x, z), this);
chunks[x, z].gameObject.transform.SetParent(gameObject.transform);
}
}
StreamReader reader = new StreamReader(Application.dataPath + "\\save.world");
for (int xChunk = 0; xChunk < worldSize; xChunk++)
{
for (int zChunk = 0; zChunk < worldSize; zChunk++)
{
byte[] save = Encoding.ASCII.GetBytes(reader.ReadLine());
int i = 0;
for (int y = 0; y < Data.chunkHeight; y++)
{
for (int x = 0; x < Data.chunkWidth; x++)
{
for (int z = 0; z < Data.chunkWidth; z++)
{
chunks[xChunk, zChunk].blocks[x, y, z] = (byte)(save[i] - 32);
i++;
}
}
}
}
}
reader.Close();
}
else
{
Console.WriteLine("generate world... \n");
CreateChunks();
CreateTrees();
}
Console.WriteLine("world loaded! \n");
server = new Server(this, transferDelay);
}
//creates an array of chunks
private void CreateChunks()
{
chunks = new Chunk[worldSize, worldSize];
for (int x = 0; x < worldSize; x++)
{
for (int z = 0; z < worldSize; z++)
{
chunks[x, z] = new Chunk(new ChunkCoord(x, z), this);
chunks[x, z].gameObject.transform.SetParent(gameObject.transform);
}
}
for (int x = 0; x < worldSize; x++)
{
for (int z = 0; z < worldSize; z++)
{
chunks[x, z].PopulateBlocks();
}
}
}
//Create Trees
private void CreateTrees()
{
for (int x = 4; x < worldSize * Data.chunkWidth - 4; x++)
{
for (int z = 4; z < worldSize * Data.chunkWidth - 4; 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)(noise.GetHeight(x, z, randomOffsetX, randomOffsetZ));
int zInChunk = (int)(z - chunk.z * Data.chunkWidth);
int height = Random.Range(5, 9);
for (int i = 0; i <= height; i++)
{
chunks[chunk.x, chunk.z].blocks[xInChunk, yInChunk + i, zInChunk] = 7;
}
chunks[chunk.x, chunk.z].blocks[xInChunk, yInChunk + height + 2, zInChunk] = 6;
for (int ty = -1; ty <= 0; ty++)
{
for (int tx = -2; tx <= 2; tx++)
{
for (int tz = -2; tz <= 2; tz++)
{
ChunkCoord tempChunk = new ChunkCoord((int)((x - tx) / Data.chunkWidth),
(int)((z - tz) / Data.chunkWidth));
int xTempInChunk = (int)((x - tx) - tempChunk.x * Data.chunkWidth);
int zTempInChunk = (int)((z - tz) - tempChunk.z * Data.chunkWidth);
if (chunks[tempChunk.x, tempChunk.z].blocks[xTempInChunk, yInChunk + height + ty,
zTempInChunk] != 7)
{
chunks[tempChunk.x, tempChunk.z].blocks[xTempInChunk, yInChunk + height + ty,
zTempInChunk] = 6;
}
}
}
}
for (int tx = -1; tx <= 1; tx++)
{
for (int tz = -1; tz <= 1; tz++)
{
ChunkCoord tempChunk = new ChunkCoord((int)((x - tx) / Data.chunkWidth),
(int)((z - tz) / Data.chunkWidth));
int xTempInChunk = (int)((x - tx) - tempChunk.x * Data.chunkWidth);
int zTempInChunk = (int)((z - tz) - tempChunk.z * Data.chunkWidth);
if (chunks[tempChunk.x, tempChunk.z].blocks[xTempInChunk, yInChunk + height + 1,
zTempInChunk] != 7)
{
chunks[tempChunk.x, tempChunk.z].blocks[xTempInChunk, yInChunk + height + 1,
zTempInChunk] = 6;
}
}
}
}
}
}
}
//return the ID of a block
public byte GetBlockID(Vector3 positionInWorld)
{
byte height = noise.GetHeight((int)positionInWorld.x, (int)positionInWorld.z, randomOffsetX, randomOffsetZ);
//world pass
if (positionInWorld.x < 0 || positionInWorld.y < 0 || positionInWorld.z < 0 ||
positionInWorld.x >= worldSize * Data.chunkWidth || positionInWorld.y > height ||
positionInWorld.z >= worldSize * Data.chunkWidth)
{
return 0;
}
//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)
{
//dirt
if((int)positionInWorld.y > 6 && (int)positionInWorld.y < height - 3)
{
if (noise.Get3DPerlin(positionInWorld, 3, 0.28f, 0.65f))
{
return 2;
}
}
//coal
if((int)positionInWorld.y > 6 && (int)positionInWorld.y < height - 8)
{
if (noise.Get3DPerlin(positionInWorld, 5, 0.28f, 0.65f))
{
return 12;
}
}
// //caves
// if((int)positionInWorld.y > 6 && (int)positionInWorld.y < height - 8)
// {
// if (noise.Get3DPerlin(positionInWorld, 0, 0.18f, 0.5f))
// {
// return 0;
// }
// }
return 4;
}
return 0;
}
//returns if a block is on the position
public bool CheckBlock(Vector3 positionInWorld)
{
if (positionInWorld.x < -1 || positionInWorld.z < -1 ||
positionInWorld.x > worldSize * Data.chunkWidth ||
positionInWorld.z > worldSize * Data.chunkWidth)
{
return false;
}
if (positionInWorld.x < 0 || positionInWorld.y < 0 || positionInWorld.z < 0 ||
positionInWorld.x >= worldSize * Data.chunkWidth || positionInWorld.y >= Data.chunkHeight ||
positionInWorld.z >= worldSize * Data.chunkWidth)
{
return true;
}
ChunkCoord chunk = new ChunkCoord((int)(positionInWorld.x / Data.chunkWidth),
(int)(positionInWorld.z / Data.chunkWidth));
int xInChunk = (int)(positionInWorld.x - chunk.x * Data.chunkWidth);
int yInChunk = (int)positionInWorld.y;
int zInChunk = (int)(positionInWorld.z - chunk.z * Data.chunkWidth);
if (chunks[chunk.x, chunk.z] != null)
{
if (chunks[chunk.x, chunk.z].blocks[xInChunk, yInChunk, zInChunk] == 0)
{
return false;
}
}
return true;
}
public void EditBlock(ChunkCoord chunk, Vector3 positionInChunk, byte blockID)
{
byte xInChunk = (byte)(positionInChunk.x);
byte yInChunk = (byte)positionInChunk.y;
byte zInChunk = (byte)(positionInChunk.z);
//edit block in chunk
if(chunks[chunk.x, chunk.z].blocks[xInChunk, yInChunk, zInChunk] != 1)
{
chunks[chunk.x, chunk.z].Update(xInChunk, yInChunk, zInChunk, blockID);
}
}
private void OnApplicationQuit()
{
SaveWorld();
server.Disconnect();
}
public void SaveWorld()
{
StreamWriter writer = new StreamWriter(dataPath + "\\save.world", false);
for (int xChunk = 0; xChunk < worldSize; xChunk++)
{
for (int zChunk = 0; zChunk < worldSize; zChunk++)
{
byte[] save = new byte[Data.chunkWidth * Data.chunkWidth * Data.chunkHeight];
int i = 0;
for (int y = 0; y < Data.chunkHeight; y++)
{
for (int x = 0; x < Data.chunkWidth; x++)
{
for (int z = 0; z < Data.chunkWidth; z++)
{
save[i] = (byte)(chunks[xChunk, zChunk].blocks[x, y, z] + 32);
i++;
}
}
}
writer.WriteLine(Encoding.ASCII.GetString(save));
writer.Flush();
}
}
writer.Close();
Console.WriteLine("world saved! (save.world) \n");
}
}