예제 #1
0
    /// <summary>
    /// Default RunToCombat causes the entity to look at its target
    /// If it has line of sight, it runs directly towards
    /// </summary>
    protected virtual void RunToCombat()
    {
        Entity.LookAt(CurrentTarget.Position2);
        Entity.GetLoadedEntity().SetRunning(true);

        if (LineOfSight(CurrentTarget))
        {
            DebugGUI.Instance.SetData(Entity.Name, "line of sight");
            Vector2 movement = CurrentTarget.Position2 - Entity.Position2;
            Entity.GetLoadedEntity().MoveInDirection(movement);
        }
        else if (Entity.EntityAI.GeneratePath(Vec2i.FromVector3(CurrentTarget.Position)))
        {
            DebugGUI.Instance.SetData(Entity.Name, "path found");
            //If a valid path can/has been generated
            Entity.EntityAI.FollowPath();
        }
        else
        {
            DebugGUI.Instance.SetData(Entity.Name, "no line of sight");

            Vector2 movement = CurrentTarget.Position2 - Entity.Position2;
            Entity.GetLoadedEntity().MoveInDirection(movement);
        }
    }
    /// <summary>
    /// Called when the Marching cube wall is first created.
    /// Initiates the positions and arrays needed for the function to work.
    /// </summary>
    /// <param name="midpoint"></param>
    public void Initiate(Vector3 midpoint)
    {
        WallPoints = new bool[SIZE_XZ, SIZE_XZ];
        Timer      = new Stopwatch();
        Timer.Start();
        Marching = new MarchingCubes(surface: 0);

        this.transform.position = midpoint - new Vector3(SIZE_XZ / 2, 0, SIZE_XZ / 2);
        MidPos2 = Vec2i.FromVector3(midpoint);
    }
예제 #3
0
 public void Kill()
 {
     KillInternal();
     GameManager.EntityManager.UnloadEntity(GetLoadedEntity());
     if (!Inventory.IsEmpty)
     {
         LootSack loot = new LootSack(Vec2i.FromVector3(GetLoadedEntity().transform.position));
         loot.GetInventory().AddAll(Inventory);
         GameManager.WorldManager.AddNewObject(loot);
     }
     GameManager.EventManager.InvokeNewEvent(new EntityDeath(this));
 }
    private LoadedChunk2 CreateChunk(PreLoadedChunk pChunk)
    {
        GameObject cObj = Instantiate(ChunkPrefab);
        cObj.transform.parent = transform;

        cObj.name = "chunk_" + pChunk.Position;
        LoadedChunk2 loaded = cObj.GetComponent<LoadedChunk2>();

        MeshFilter mf = loaded.GetComponent<MeshFilter>();
        //Create the terrain mesh
        mf.mesh = PreLoadedChunk.CreateMesh(pChunk.TerrainMesh);
        mf.mesh.RecalculateNormals();
        MeshCollider mc = loaded.GetComponent<MeshCollider>();
        mc.sharedMesh = mf.mesh;
        //Iterate all voxels
        foreach (Voxel v in MiscUtils.GetValues<Voxel>())
        {
            if (v == Voxel.none)
                continue;
            if (pChunk.VoxelMesh.TryGetValue(v, out PreMesh pmesh))
            {
                GameObject voxelObj = Instantiate(ChunkVoxelPrefab);
                MeshFilter voxelMf = voxelObj.GetComponent<MeshFilter>();
                MeshRenderer voxelMr = voxelObj.GetComponent<MeshRenderer>();
                voxelMr.material = ResourceManager.GetVoxelMaterial(v);
                voxelMf.mesh = PreLoadedChunk.CreateMesh(pmesh);
                MeshCollider voxelMc = voxelObj.GetComponent<MeshCollider>();
                voxelMc.sharedMesh = voxelMf.mesh;
                voxelObj.transform.parent = cObj.transform;
                voxelObj.transform.localPosition = Vector3.up * (pChunk.ChunkData.BaseHeight + 0.7f);

                voxelMf.mesh.RecalculateNormals();
            }
        }

        cObj.transform.position = pChunk.Position.AsVector3() * World.ChunkSize;
        loaded.SetChunk(pChunk.ChunkData);

        if (pChunk.ChunkData.WorldObjects != null)
        {
            foreach (WorldObjectData objData in pChunk.ChunkData.WorldObjects)
            {
                Vec2i localPos = Vec2i.FromVector3(objData.Position.Mod(World.ChunkSize));
                float off = loaded.Chunk.GetHeight(localPos);
                WorldObject obj = WorldObject.CreateWorldObject(objData, loaded.transform, off + 0.7f);
                obj.AdjustHeight();
            }


        }

        return loaded;
    }
예제 #5
0
    public void Kill()
    {
        KillInternal();
        IsAlive = false;
        EntityManager.Instance.UnloadEntity(GetLoadedEntity(), killEntity: true);
        if (!Inventory.IsEmpty)
        {
            LootSack loot = new LootSack(Vec2i.FromVector3(GetLoadedEntity().transform.position).AsVector3());
            loot.GetInventory().AddAll(Inventory);
            GameManager.WorldManager?.AddNewObject(loot);
        }

        EventManager.Instance.InvokeNewEvent(new EntityDeath(this));
        Debug.Log("Entity  " + this + " is killed");
    }
예제 #6
0
    /// <summary>
    /// Enters the player into the subworld of the given ID.
    /// If the given subworld is the one the player is already in, leave the subworld <see cref="WorldManager.LeaveSubworld"/>
    /// Unloads world chunks
    /// </summary>
    /// <param name="id"></param>
    public void EnterSubworld(int id)
    {
        //Collect subworld based on its ID
        Subworld sub = World.GetSubworld(id);

        //Check for null
        if (sub == null)
        {
            Debug.Error("Subworld of ID '" + id + "' could not be found");
            return;
        }
        if (sub == CurrentSubworld)
        {
            LeaveSubworld();
            return;
        }
        //If the subworld doesn't have an entrance, set its entrance as the current player position.
        if (sub.InternalEntrancePos == null)
        {
            Debug.Error("Subworld " + sub.ToString() + " has no WorldEntrance, Player position " + Player.Position + " has been set");
            sub.SetWorldEntrance(Vec2i.FromVector3(Player.Position));
        }

        if (CurrentSubworld != null)
        {
            Debug.Error("Cannot enter a subworld while already in one.");
            return;
        }
        if (sub != null)
        {
            Debug.Log("Player entering subworld " + sub.ToString(), Debug.NORMAL);
            //First unload all world chunks and set the current subworld
            CurrentSubworld = sub;
            //EntityManager.Instance?.UnloadAllChunks();
            //Load all subworld chunks and add them to the the relevent list
            CRManager.LoadSubworldChunks(sub);

            //GameManager.PathFinder.LoadSubworld(sub);
            //Inform entity manager we are entering the sub world, then teleport player to correct position.

            Player.SetPosition(sub.InternalEntrancePos.AsVector3());
            WaitAndPathScanCoroutine();

            EntityManager.Instance?.EnterSubworld(sub);

            //PlayerManager.Instance.ProceduralGridMover.UpdateGraph();
        }
    }
예제 #7
0
    public bool AddObject(WorldObjectData data, bool force = false, bool debug = false)
    {
        //Find local chunk position of object
        Vec2i cPos = World.GetChunkPosition(Vec2i.FromVector3(data.Position));
        //The global position of this object
        Vector3 finalPos = (BaseChunk * World.ChunkSize).AsVector3() + data.Position;

        //If force, we do not check for collision with other objects.
        if (force)
        {
            if (ObjectMaps[cPos.x, cPos.z] == null)
            {
                ObjectMaps[cPos.x, cPos.z] = new List <WorldObjectData>();
            }

            ObjectMaps[cPos.x, cPos.z].Add(data);

            if (debug)
            {
                Debug.Log("Object " + data + " added at local chunk " + cPos + " -> global chunk " + (cPos + BaseChunk) + " total objects now:" + ObjectMaps[cPos.x, cPos.z].Count);
            }
            return(true);
        }

        if (ObjectMaps[cPos.x, cPos.z] != null)
        {
            //iterate all obejcts in chunk, check for intersection
            foreach (WorldObjectData objDat in ObjectMaps[cPos.x, cPos.z])
            {
                //If we intersect, return false and don't place the object
                if (data.Intersects(objDat))
                {
                    return(false);
                }
            }



            ObjectMaps[cPos.x, cPos.z].Add(data);
            return(true);
        }
        else
        {
            ObjectMaps[cPos.x, cPos.z] = new List <WorldObjectData>();
            ObjectMaps[cPos.x, cPos.z].Add(data);
            return(true);
        }
    }
예제 #8
0
    public override string ToString()
    {
        string total = "";

        switch (InitType)
        {
        case InitiationType.TALK_TO_NPC:
            total = "Talk to " + GetNPC().Name + " at " + Vec2i.FromVector3(GetNPC().Position);
            break;

        case InitiationType.PICK_UP_ITEM:
            total = "Pick up item " + GetItem().Name + " at " + GetLocation(1);
            break;
        }

        return(total);
    }
예제 #9
0
    /// <summary>
    /// Generartes the subworld for this building, and then sets it
    /// </summary>
    public void CreateSubworld()
    {
        for (int x = 0; x < Size.x; x++)
        {
            for (int z = 0; z < Size.z; z++)
            {
                int cx = WorldToChunk(x);
                int cz = WorldToChunk(z);
                int tx = x % World.ChunkSize;
                int tz = z % World.ChunkSize;

                Tiles[cx, cz][tx, tz] = Building.BuildingTiles[x, z] == null?0: Building.BuildingTiles[x, z].ID;
                for (int y = 0; y < BuildVox.Height; y++)
                {
                    Voxels[cx, cz].SetVoxelNode(tx, y, tz, BuildVox.GetVoxelNode(x, y, z));
                }
            }
        }
        foreach (WorldObjectData obj in Building.GetBuildingInternalObjects())
        {
            Vec2i v  = Vec2i.FromVector3(obj.Position);
            int   cx = WorldToChunk(v.x);
            int   cz = WorldToChunk(v.z);
            if (Objects[cx, cz] == null)
            {
                Objects[cx, cz] = new List <WorldObjectData>();
            }
            //obj.SetPosition(obj.Position.Mod(World.ChunkSize));
            //Debug.Log(obj.Position);
            Objects[cx, cz].Add(obj);
        }
        ChunkData[,] chunks = new ChunkData[ChunkSize.x, ChunkSize.z];
        for (int x = 0; x < ChunkSize.x; x++)
        {
            for (int z = 0; z < ChunkSize.z; z++)
            {
                chunks[x, z] = new ChunkData(x, z, Tiles[x, z], true, 0, null, Objects[x, z]);
                chunks[x, z].SetVoxelData(Voxels[x, z]);
            }
        }
        Debug.Log("ENTRANCE SIDE: " + Plan.EntranceSide);
        Subworld sw = new Subworld(chunks, Building.Entrance - (Plan.EntranceSide * 2), (Building.Entrance + Plan.EntranceSide * 2));

        Building.BuildingSubworld = sw;
    }
예제 #10
0
    protected override void KillInternal()
    {
        //If no items, we do nothing
        if (Inventory.GetItems().Count == 0)
        {
            return;
        }

        LootSack lootSack = new LootSack(Vec2i.FromVector3(Position));

        foreach (ItemStack it in Inventory.GetItems())
        {
            lootSack.GetInventory().AddItemStack(it);
        }

        Vec2i pos = Vec2i.FromVector3(Position);

        GameManager.WorldManager.AddNewObject(lootSack);
    }
예제 #11
0
    /// <summary>
    /// Finds all empty points around a given world object.
    /// Object must be an instance
    /// </summary>
    /// <param name="obj"></param>
    /// <returns></returns>
    public Vec2i[] EmptyTilesAroundWorldObject(WorldObjectData obj)
    {
        Vec2i instPos = Vec2i.FromVector3(obj.Position);

        if (instPos == null)
        {
            Debug.Error("Provided world object has no instance: " + obj.ToString());
            return(null);
        }
        return(EmptyTilesAroundPoint(instPos));

        /*
         * //Check if this object is part of a multicell object.
         * if(obj.HasMetaData && (obj.MetaData.IsParent || obj.MetaData.Parent!=null))
         * {
         *  WorldObject parent = obj.MetaData.IsParent ? obj : obj.MetaData.Parent; //Get the valid parent
         *  List<Vec2i> toTry = new List<Vec2i>(parent.MetaData.MultiCellWidth*2 + parent.MetaData.MultiCellHeight*3);
         *  //Iterate all boundary tiles
         *  for(int x=-1; x<parent.MetaData.MultiCellWidth+1; x++)
         *  {
         *      toTry.Add(instPos + new Vec2i(x, -1));
         *      toTry.Add(instPos + new Vec2i(x, parent.MetaData.MultiCellHeight+1));
         *  }
         *  for (int z = 0; z < parent.MetaData.MultiCellHeight; z++)
         *  {
         *      toTry.Add(instPos + new Vec2i(-1, z));
         *      toTry.Add(instPos + new Vec2i(parent.MetaData.MultiCellWidth+1, z));
         *
         *  }
         *  List<Vec2i> freeTiles = new List<Vec2i>(parent.MetaData.MultiCellWidth * 2 + parent.MetaData.MultiCellHeight * 3);
         *  foreach (Vec2i v_ in toTry)
         *  {
         *      if (GetWorldObject(v_) == null)
         *          freeTiles.Add(v_);
         *  }
         *  return freeTiles.ToArray();
         * }
         * else
         * {
         *  //If no meta data, this must be a single tile object, so return free points around the isntance pos
         *  return EmptyTilesAroundPoint(instPos);
         * }*/
    }
예제 #12
0
    private void LoadSingleObject(int count = 0)
    {
        if (count > 10)
        {
            return;
        }

        WorldObjectData objData = null;


        lock (ObjectsToLoadLock) {
            objData = ObjectsToLoad[0];
            ObjectsToLoad.RemoveAt(0);
        }
        //Find the chunk for the first object to generate
        Vec2i chunk = World.GetChunkPosition(objData.Position);



        LoadedChunk2 lc2 = ChunkRegionManager.GetLoadedChunk(chunk);

        if (lc2 == null)
        {
            //Debug.Log(chunk);
            Debug.Log("[ChunkLoader] Chunk ( " + chunk + " ) for object ( " + objData + " ) is not loaded, attempting another object");
            //if the chunk is null, we throw this object to the end of the que and try again.
            lock (ObjectsToLoadLock)
            {
                ObjectsToLoad.Add(objData);
            }
            LoadSingleObject(count + 1);
            return;
        }
        Vec2i       localPos = Vec2i.FromVector3(objData.Position.Mod(World.ChunkSize));
        float       off      = lc2.Chunk.GetHeight(localPos);
        WorldObject obj      = WorldObject.CreateWorldObject(objData, lc2.transform, off + 0.7f);
        //Debug.Log("Created object " + obj);
        //obj.AdjustHeight();
    }
    //Attempts to build the wall
    public void BuildWall(Vector3 position)
    {
        //If wall is collapsing, we cannot build on it
        if (IsCollapsing)
        {
            return;
        }
        //If we are adding to the wall or building on an existing point, we restart the destruction timer
        Timer.Restart();
        Vec2i pos2 = Vec2i.FromVector3(position) - MidPos2 + new Vec2i(SIZE_XZ / 2, SIZE_XZ / 2);

        //If the position is out of bounds, return
        if (pos2.x < 1 || pos2.x >= SIZE_XZ - 1 || pos2.z < 1 || pos2.z >= SIZE_XZ - 1)
        {
            return;
        }
        //If the wall point has already been created, return
        if (WallPoints[pos2.x, pos2.z])
        {
            return;
        }
        //Otherwise, add the point
        AddPoint(pos2.x, pos2.z);
    }
예제 #14
0
    /// <summary>
    /// Called when the inventory is opened
    /// </summary>
    private void OnEnable()
    {
        Player = GameManager.PlayerManager.Player;
        CurrentInventoryItemTag = ItemTag.WEAPON;

        MainInventory.gameObject.SetActive(true);
        MainInventory.SetInventory(Player.Inventory);
        MainInventory.SetItemTag(CurrentInventoryItemTag);
        MainInventory.SetMain(true);

        //Check if there are any inventories near the player to display
        WorldObjectData invObj = GameManager.WorldManager.World.InventoryObjectNearPoint(Vec2i.FromVector3(Player.Position));

        if (invObj == null || !(invObj is IInventoryObject))
        {
            //If no object is found, turn secondary inventory off
            SecondInventory.gameObject.SetActive(false);
        }
        else
        {
            Inventory inv = (invObj as IInventoryObject).GetInventory();
            SecondInventory.SetInventory(inv);
            SecondInventory.SetItemTag(CurrentInventoryItemTag);
            SecondInventory.SetMain(false);
            SecondInventory.gameObject.SetActive(true);
        }
    }
예제 #15
0
    private PreMesh GenerateMarchingCubesTerrain(ChunkData chunk)
    {
        ChunkData[] neighbors = ChunkRegionManager.GetNeighbors(new Vec2i(chunk.X, chunk.Z));


        float[] cube = new float[(World.ChunkSize + 1) * (World.ChunkSize + 1) * (World.ChunkHeight + 1)];
        Color[,] colourMap = new Color[World.ChunkSize + 1, World.ChunkSize + 1];

        //We iterate through the whole chunk, and create a cub map and colour map based on the
        //height map and tile map
        for (int x = 0; x < World.ChunkSize + 1; x++)
        {
            for (int z = 0; z < World.ChunkSize + 1; z++)
            {
                float height = chunk.BaseHeight;
                if (x == World.ChunkSize && z == World.ChunkSize)
                {
                    if (neighbors != null && neighbors[1] != null)
                    {
                        height = neighbors[1].BaseHeight;
                        if (neighbors[1].Heights != null)
                        {
                            height = neighbors[1].Heights[0, 0];
                        }
                        colourMap[x, z] = neighbors[1].GetTile(0, 0).GetColor();
                    }

                    else
                    {
                        height          = chunk.Heights != null ? chunk.Heights[x - 1, z - 1] : height;
                        colourMap[x, z] = chunk.GetTile(x - 1, z - 1).GetColor();
                    }
                }
                else if (x == World.ChunkSize)
                {
                    if (neighbors != null && neighbors[2] != null)
                    {
                        height = neighbors[2].BaseHeight;
                        if (neighbors[2].Heights != null)
                        {
                            height = neighbors[2].Heights[0, z];
                        }

                        colourMap[x, z] = neighbors[2].GetTile(0, z).GetColor();
                    }
                    else
                    {
                        height          = chunk.Heights != null ? chunk.Heights[x - 1, z] : height;
                        colourMap[x, z] = chunk.GetTile(x - 1, z).GetColor();
                    }
                }
                else if (z == World.ChunkSize)
                {
                    if (neighbors != null && neighbors[0] != null)
                    {
                        height = neighbors[0].BaseHeight;
                        if (neighbors[0].Heights != null)
                        {
                            height = neighbors[0].Heights[x, 0];
                        }

                        colourMap[x, z] = neighbors[0].GetTile(x, 0).GetColor();
                    }
                    else
                    {
                        height          = chunk.Heights != null ? chunk.Heights[x, z - 1] : height;
                        colourMap[x, z] = chunk.GetTile(x, z - 1).GetColor();
                    }
                }
                else
                {
                    if (chunk.Heights != null)
                    {
                        height = chunk.Heights[x, z];
                    }
                    colourMap[x, z] = chunk.GetTile(x, z).GetColor();
                }
                for (int y = 0; y < height + 1; y++)
                {
                    int idx = x + y * (World.ChunkSize + 1) + z * (World.ChunkHeight + 1) * (World.ChunkSize + 1);

                    cube[idx] = -2;
                }
            }
        }

        CurrentVerticies.Clear();
        CurrentTriangles.Clear();
        CurrentColours.Clear();
        //March the terrain map
        MarchingCubes.Generate(cube, World.ChunkSize + 1, World.ChunkHeight + 1, World.ChunkSize + 1, CurrentVerticies, CurrentTriangles);

        //We iterate each triangle
        for (int i = 0; i < CurrentTriangles.Count; i += 3)
        {
            int tri1 = CurrentTriangles[i];
            int tri2 = CurrentTriangles[i + 1];
            int tri3 = CurrentTriangles[i + 2];

            //We find the average/mid point of this triangle
            Vector3 mid  = (CurrentVerticies[tri1] + CurrentVerticies[tri2] + CurrentVerticies[tri3]) / 3;
            Vec2i   tMid = Vec2i.FromVector3(mid);
            Color   c    = colourMap[tMid.x, tMid.z];

            CurrentColours.Add(c);
            CurrentColours.Add(c);
            CurrentColours.Add(c);
        }

        /*
         * for (int i = 0; i < CurrentVerticies.Count; i++)
         * {
         *  int x = (int)CurrentVerticies[i].x;
         *  int z = (int)CurrentVerticies[i].z;
         *  CurrentColours.Add(colourMap[x, z]);
         *
         * }*/

        //We create a thread safe mesh for the terrain
        PreMesh terrainMesh = new PreMesh();

        terrainMesh.Verticies = CurrentVerticies.ToArray();
        terrainMesh.Triangles = CurrentTriangles.ToArray();
        terrainMesh.Colours   = CurrentColours.ToArray();

        return(terrainMesh);
    }
예제 #16
0
 /// <summary>
 /// Used to move the entity. We call <see cref="EntityManager.MoveEntity(Entity, int, Vec2i)"/>.
 /// If <paramref name="newWorldID"/> is 0, then we stay in the same world.
 /// </summary>
 /// <param name="position"></param>
 /// <param name="newWorldID"></param>
 public void MoveEntity(Vector3 position, int newWorldID = 0)
 {
     EntityManager.Instance.MoveEntity(this, newWorldID == 0 ? CurrentSubworldID : newWorldID, Vec2i.FromVector3(position));
 }
예제 #17
0
    public bool GeneratePath(Vec2i target)
    {
        //if no target, null previous paths and return.
        if (target == null)
        {
            Debug.Log("Target is null - no path");
            EntityPathTarget = null;
            EntityPath       = null;
            return(false);
        }

        if (EPF == null)
        {
            //TODO - get free path finder from parent
            EPF = new EntityPathFinder(GameManager.PathFinder);
        }

        Vec2i tilePos = Vec2i.FromVector3(Entity.Position);

        Debug.Log("Attempting path from " + tilePos + " to " + target);

        /*if(GameManager.PathFinder.NodeValue(tilePos) > 100)
         * {
         *  tilePos = Vec2i.FromVector3(Entity.Position + new Vector3(0.5f, 0, 0.5f));
         *  if(GameManager.PathFinder.NodeValue(tilePos) > 100)
         *  {
         *      Debug.Log("hm");
         *  }
         * }*/
        //if we have no path
        if (EntityPath == null)
        {
            //We check if one is being generated
            if (!EPF.IsRunning)
            {
                //If not, we start generating it
                EPF.FindPath(tilePos, target);
                return(false);
            }

            //Check if the path finder has completed its work
            if (EPF.IsComplete())
            {
                //If the path is found, we set it and return true
                if (EPF.FoundPath)
                {
                    EntityPathTarget = target;
                    EntityPath       = new EntityPath(EPF.GetPath());
                    return(true);
                }
                else
                {
                    Debug.Log("Path from " + tilePos + " to " + target + " not found");

                    return(false);
                }
            }
            return(false);

            /*
             * //If there is no path, Attempt to generate it
             * List<Vec2i> path = GameManager.PathFinder.GeneratePath(tilePos, target);
             * if (path==null || path.Count == 0)
             * {
             *  Debug.Log("Path from " + tilePos + " to " + target + " not found");
             *  return false;
             * }
             * EntityPathTarget = target;
             * EntityPath = new EntityPath(path);
             * return true;*/
        }
        else if (EntityPath.Target == target)
        {//If the current path has the same target, return true
            return(true);
        }
        else
        {
            if (Vec2i.QuickDistance(EntityPath.Target, target) < 5)
            {
                //If the path exists but doesn't have the same target, but targets are close, we attempt to re-calculate the path
                return(EntityPath.UpdateTarget(target, EPF));
            }
            else
            {
                EntityPath = null;
                //We check if one is being generated
                if (!EPF.IsRunning)
                {
                    //If not, we start generating it
                    EPF.FindPath(tilePos, target);
                    return(false);
                }/*
                  * List<Vec2i> newPath = GameManager.PathFinder.GeneratePath(tilePos, target);
                  * if(newPath==null || newPath.Count == 0)
                  * {
                  * Debug.Log("No path found from " + tilePos + " to " + target + " for entity " + Entity);
                  * return false;
                  * }
                  * EntityPath = new EntityPath(newPath);
                  * return true;*/
            }
        }
        return(false);
    }
예제 #18
0
    private PreLoadedChunk GeneratePreLoadedChunk(ChunkData chunk)
    {
        //Null till we integrate fully
        //ChunkData2[] neighbors = null;

        ChunkData[] neighbors = GetNeighbors(new Vec2i(chunk.X, chunk.Z));


        float[] cube = new float[(World.ChunkSize + 1) * (World.ChunkSize + 1) * (World.ChunkHeight + 1)];
        Color[,] colourMap = new Color[World.ChunkSize + 1, World.ChunkSize + 1];

        //We iterate through the whole chunk, and create a cub map and colour map based on the
        //height map and tile map
        for (int x = 0; x < World.ChunkSize + 1; x++)
        {
            for (int z = 0; z < World.ChunkSize + 1; z++)
            {
                float height = chunk.BaseHeight;
                if (x == World.ChunkSize && z == World.ChunkSize)
                {
                    if (neighbors != null && neighbors[1] != null)
                    {
                        height = neighbors[1].BaseHeight;
                        if (neighbors[1].Heights != null)
                        {
                            height = neighbors[1].Heights[0, 0];
                        }
                        colourMap[x, z] = neighbors[1].GetTile(0, 0).GetColor();
                    }

                    else
                    {
                        height          = chunk.Heights != null ? chunk.Heights[x - 1, z - 1] : height;
                        colourMap[x, z] = chunk.GetTile(x - 1, z - 1).GetColor();
                    }
                }
                else if (x == World.ChunkSize)
                {
                    if (neighbors != null && neighbors[2] != null)
                    {
                        height = neighbors[2].BaseHeight;
                        if (neighbors[2].Heights != null)
                        {
                            height = neighbors[2].Heights[0, z];
                        }

                        colourMap[x, z] = neighbors[2].GetTile(0, z).GetColor();
                    }
                    else
                    {
                        height          = chunk.Heights != null ? chunk.Heights[x - 1, z] : height;
                        colourMap[x, z] = chunk.GetTile(x - 1, z).GetColor();
                    }
                }
                else if (z == World.ChunkSize)
                {
                    if (neighbors != null && neighbors[0] != null)
                    {
                        height = neighbors[0].BaseHeight;
                        if (neighbors[0].Heights != null)
                        {
                            height = neighbors[0].Heights[x, 0];
                        }

                        colourMap[x, z] = neighbors[0].GetTile(x, 0).GetColor();
                    }
                    else
                    {
                        height          = chunk.Heights != null ? chunk.Heights[x, z - 1] : height;
                        colourMap[x, z] = chunk.GetTile(x, z - 1).GetColor();
                    }
                }
                else
                {
                    if (chunk.Heights != null)
                    {
                        height = chunk.Heights[x, z];
                    }
                    colourMap[x, z] = chunk.GetTile(x, z).GetColor();
                }
                for (int y = 0; y < height + 1; y++)
                {
                    int idx = x + y * (World.ChunkSize + 1) + z * (World.ChunkHeight + 1) * (World.ChunkSize + 1);

                    cube[idx] = -2;
                }
            }
        }

        CurrentVerticies.Clear();
        CurrentTriangles.Clear();
        CurrentColours.Clear();
        //March the terrain map
        MarchingCubes.Generate(cube, World.ChunkSize + 1, World.ChunkHeight + 1, World.ChunkSize + 1, CurrentVerticies, CurrentTriangles);

        for (int i = 0; i < CurrentTriangles.Count; i += 3)
        {
            int tri1 = CurrentTriangles[i];
            int tri2 = CurrentTriangles[i + 1];
            int tri3 = CurrentTriangles[i + 2];

            //We find the average/mid point of this triangle
            Vector3 mid  = (CurrentVerticies[tri1] + CurrentVerticies[tri2] + CurrentVerticies[tri3]) / 3;
            Vec2i   tMid = Vec2i.FromVector3(mid);
            Color   c    = colourMap[tMid.x, tMid.z];

            CurrentColours.Add(c);
            CurrentColours.Add(c);
            CurrentColours.Add(c);
        }

        /*
         * for (int i = 0; i < CurrentVerticies.Count; i++)
         * {
         *  int x = (int)CurrentVerticies[i].x;
         *  int z = (int)CurrentVerticies[i].z;
         *  CurrentColours.Add(colourMap[x, z]);
         *
         * }*/

        //We create a thread safe mesh for the terrain
        PreMesh terrainMesh = new PreMesh();

        terrainMesh.Verticies = CurrentVerticies.ToArray();
        terrainMesh.Triangles = CurrentTriangles.ToArray();
        terrainMesh.Colours   = CurrentColours.ToArray();
        //Debug.Log("[ChunkLoader] Terrain mesh for " + chunk + " created - " + CurrentVerticies.Count + " verticies");
        //Create the base pre-loaded chunk
        PreLoadedChunk preChunk = new PreLoadedChunk(new Vec2i(chunk.X, chunk.Z), terrainMesh, chunk);

        Debug.Log("Pre loaded chunk started, now for voxels");

        //if we have no voxel data, return just the terrain map
        if (chunk.VoxelData == null)
        {
            Debug.Log("Chunk has no voxels");
            return(preChunk);
        }



        foreach (Voxel v in MiscUtils.GetValues <Voxel>())
        {
            if (v == Voxel.none)
            {
                continue;
            }

            if (!chunk.VoxelData.HasVoxel(v))
            {
                // Debug.Log("Chunk " + chunk + " does not have the voxel " + v);
                continue;
            }

            CurrentVerticies.Clear();
            CurrentTriangles.Clear();
            CurrentColours.Clear();
            CurrentUVs.Clear();
            // Debug.Log("starting march");

            //Generate the voxel mesh
            MarchingCubes.Generate(chunk.VoxelData.Voxels, null, v, World.ChunkSize + 1, World.ChunkHeight + 1, World.ChunkSize + 1, CurrentVerticies, CurrentTriangles);
            PreMesh voxelMesh = new PreMesh();
            voxelMesh.Verticies = CurrentVerticies.ToArray();
            voxelMesh.Triangles = CurrentTriangles.ToArray();
            voxelMesh.UV        = CreateUV(voxelMesh);
            //Add it the the pre loaded chunk
            preChunk.VoxelMesh.Add(v, voxelMesh);

            /*
             * //If the chunk has this type of voxel in it
             * if (chunk.VoxelData.VoxelTypeBounds.TryGetValue(v, out VoxelBounds vb))
             * {
             *  //Clear all lists to prepair
             *  CurrentVerticies.Clear();
             *  CurrentTriangles.Clear();
             *  CurrentColours.Clear();
             *  CurrentUVs.Clear();
             *  Debug.Log("starting march");
             *
             *  //Generate the voxel mesh
             *  MarchingCubes.Generate(chunk.VoxelData.Voxels, vb, v, World.ChunkSize+1, World.ChunkHeight+1, World.ChunkSize+1, CurrentVerticies, CurrentTriangles);
             *  PreMesh voxelMesh = new PreMesh();
             *  voxelMesh.Verticies = CurrentVerticies.ToArray();
             *  voxelMesh.Triangles = CurrentTriangles.ToArray();
             *  voxelMesh.UV = CreateUV(voxelMesh);
             *  //Add it the the pre loaded chunk
             *  preChunk.VoxelMesh.Add(v, voxelMesh);
             * }*/
        }



        return(preChunk);
    }