Example #1
0
        public Chunk(World world, ChunkPos chunkPos)
        {
            World = world;
            Pos   = chunkPos;

            _storageKey = StorageKey.Get("ChunkData", chunkPos);

            var saveFile   = world?.Universe?.SaveFile;
            var savedValue = saveFile?.ReadAsync(_storageKey)?.Result;

            if (savedValue != null)
            {
                var chunkData = savedValue.Deserialize <ChunkData>();
                if (chunkData != null)
                {
                    try
                    {
                        PasteChunkData(chunkData);
                    }
                    catch
                    {
                        _data       = null;
                        _isCreated  = false;
                        _chunkData  = null;
                        ContentHash = 0;
                    }
                }
            }

            _saveFile = saveFile;
        }
 //
 override public void SectionDeleted(ChunkPos pos)
 {
     if (basement == null && !TryToRebasement())
     {
         Annihilate(StructureAnnihilationOrder.blockHaveNoSupport);
     }
 }
    // Reads header from a chunk
    // leaves rdf file at Seek Position ready to read blockdata
    private void ReadHeader(ChunkPos pos)
    {
        long code = GetLinearRegionCoords(pos);

        this.pool[ConvertToRegion(pos)].file.Seek(this.pool[ConvertToRegion(pos)].index[code], SeekOrigin.Begin);
        this.pool[ConvertToRegion(pos)].file.Read(headerBuffer, 0, chunkHeaderSize);
    }
Example #4
0
    override public void Annihilate(bool clearFromSurface, bool returnResources, bool leaveRuins)
    {
        if (destroyed)
        {
            return;
        }
        else
        {
            destroyed = true;
        }
        bool     initiateCheckRequest = true;
        ChunkPos cpos = ChunkPos.zer0;

        if (basement != null)
        {
            cpos = basement.pos;
        }
        else
        {
            initiateCheckRequest = false;
        }
        PrepareBuildingForDestruction(clearFromSurface, returnResources, leaveRuins);
        if (initiateCheckRequest)
        {
            AddonCheckRequest(cpos);
        }

        Destroy(gameObject);
    }
    public Chunk GetChunk(int x, int z, ChunkStatus status, bool nonnull)
    {
        if (Thread.CurrentThread != _mainThread)
        {
            throw new Exception("Wrong Thread");
        }

        var positionHash = ChunkPos.AsLong(x, z);

        for (int i = 0; i < 4; i++)
        {
            if (_recentPositions[i] != positionHash || _recentStatuses[i] != status)
            {
                continue;
            }

            var recentChunk = _recentChunks[i];
            if (recentChunk != null || !nonnull)
            {
                return(recentChunk);
            }
        }

        var task  = ProvideChunk(x, z, status, nonnull);
        var chunk = task.GetAwaiter().GetResult();

        if (chunk == null && nonnull)
        {
            throw new Exception("Chunk not there when requested");
        }

        UpdateCache(positionHash, chunk, status);
        return(chunk);
    }
    // Start is called before the first frame update
    void Start()
    {
        this.renderDistance = World.renderDistance;

        regionHandler = new RegionFileHandler(renderDistance, newChunk);

        worldSeed = regionHandler.GetRealSeed();

        biomeHandler = new BiomeHandler(BiomeSeedFunction(worldSeed));

        this.worldGen = new WorldGenerator(worldSeed, BiomeSeedFunction(worldSeed), OffsetHashFunction(worldSeed), GenerationSeedFunction(worldSeed), biomeHandler, structHandler, this);

        // If character has been loaded
        if (regionHandler.playerFile.Length > 0)
        {
            player.position = regionHandler.LoadPlayer();
            PLAYERSPAWNED   = true;
        }

        int playerX = Mathf.FloorToInt(player.position.x / Chunk.chunkWidth);
        int playerZ = Mathf.FloorToInt(player.position.z / Chunk.chunkWidth);

        newChunk = new ChunkPos(playerX, playerZ);


        GetChunks(true);
    }
 // Checks if RegionFile represents ChunkPos, and loads correct RegionFile if not
 public void GetCorrectRegion(ChunkPos pos)
 {
     if (!CheckUsage(pos))
     {
         LoadRegionFile(pos);
     }
 }
Example #8
0
 //
 override public void SectionDeleted(ChunkPos pos)
 {
     if (basement == null && !TryToRebasement())
     {
         Annihilate(false, false, false);
     }
 }
 /// <summary>
 /// Returns whether a chunk is generated
 /// </summary>
 /// <param name="pos"></param>
 /// <returns></returns>
 public bool IsChunkGenerated(ChunkPos pos)
 {
     lock (_chunkMeshes)
     {
         return(_chunkMeshes.Exists(c => c.Chunk.Position.Equals(pos) && c.IsGenerated));
     }
 }
Example #10
0
    public Chunk(ChunkPos _pos)
    {
        //references
        pos = _pos;

        //object instantiation
        chunkObj     = new GameObject();
        meshFilter   = chunkObj.AddComponent <MeshFilter>();
        meshRenderer = chunkObj.AddComponent <MeshRenderer>();

        //material assignment
        materials[0]           = World.Instance.material;
        materials[1]           = World.Instance.transparentMaterial;
        meshRenderer.materials = materials;

        //setting transfroms
        chunkObj.transform.SetParent(World.Instance.transform);
        chunkObj.transform.position = new Vector3(pos.x * VoxelData.chunkWidth, 0f, pos.z * VoxelData.chunkWidth);
        chunkObj.name = "Chunk " + pos.x + ", " + pos.z;
        position      = chunkObj.transform.position;

        chunkData       = World.Instance.worldData.RequestChunk(new Vector2Int((int)position.x, (int)position.z), true);
        chunkData.chunk = this;

        World.Instance.AddChunkToUpdate(this);

        if (World.Instance.settings.enableAnimatedChunkLoading)
        {
            chunkObj.AddComponent <AnimateChunkLoading>();
        }
    }
Example #11
0
    public static void AddBlockRepresentation(IPlanable s, Plane basement, ref Block myBlock, bool checkPlanes)
    {
        var      chunk = basement.myChunk;
        ChunkPos cpos  = basement.pos;

        switch (basement.faceIndex)
        {
        case Block.FWD_FACE_INDEX: cpos = cpos.OneBlockForward(); break;

        case Block.RIGHT_FACE_INDEX: cpos = cpos.OneBlockRight(); break;

        case Block.BACK_FACE_INDEX: cpos = cpos.OneBlockBack(); break;

        case Block.LEFT_FACE_INDEX: cpos = cpos.OneBlockLeft(); break;

        case Block.UP_FACE_INDEX: cpos = cpos.OneBlockHigher(); break;

        case Block.DOWN_FACE_INDEX: cpos = cpos.OneBlockDown(); break;
        }
        myBlock = chunk.AddBlock(cpos, s, false, checkPlanes);
        if (myBlock == null)
        {
            s.Delete(true, true, false);
            return;
        }
        else
        {
            chunk.RecalculateVisibilityAtPoint(myBlock.pos, s.GetAffectionMask());
        }
    }
Example #12
0
    private BlockDistribution GenerateBlockDistribution(ChunkPos pos)
    {
        var               rnd = new System.Random(persistor.GetSeed() - pos.x * 31 - pos.z * 23);
        double            height;
        BlockDistribution blocks = new BlockDistribution();

        bool hasTree = false;

        for (int x = 0; x < TerrainChunk.CHUNK_SIZE + 2; x++)
        {
            for (int z = 0; z < TerrainChunk.CHUNK_SIZE + 2; z++)
            {
                height = Math.Floor(ComputeHeightAt(pos.x + x - 1, pos.z + z - 1));
                for (int y = 0; y < TerrainChunk.CHUNK_HEIGHT; y++)
                {
                    blocks[x, y, z] = GetForHeight(y, height);
                }

                if (!hasTree && x > 4 && x < 12 && z > 4 && z < 12)
                {
                    int r = rnd.Next(1, 115 + (int)Math.Pow(height, height / 65.0));
                    if (r == 2)
                    {
                        hasTree = true;
                        GenerateTree(rnd, blocks, x, (int)height + 1, z);
                    }
                }
            }
        }

        return(blocks);
    }
    public void addLoadChunk(ChunkPos chunkIdx, ushort loadPri, Asset.LOAD_LEVEL level)
    {
        if (chunkIdx.x < 0 || chunkIdx.y < 0 || chunkIdx.x >= chunkSplit || chunkIdx.y >= chunkSplit)
        {
            return;
        }

        Common.DEBUG_MSG("WorldManager::addLoadChunk: load(" +
                         (chunkIdx.x + 1) + "," + (chunkIdx.y + 1) + "), loaded=" + hasTerrainObjs[chunkIdx.x, chunkIdx.y, 0]);

        if (hasTerrainObjs[chunkIdx.x, chunkIdx.y, 0] == true)
        {
            return;
        }

        addLoadWorldObj(chunkIdx);
        Asset asset = new Asset();

        asset.type      = Asset.TYPE.TERRAIN;
        asset.loadPri   = loadPri;
        asset.loadLevel = level;
        asset.source    = getChunkName(chunkIdx) + ".unity3d";
        loader.inst.loadPool.addLoad(asset);

        hasTerrainObjs[chunkIdx.x, chunkIdx.y, 0] = true;
    }
Example #14
0
    // Receives a Chunk
    private void SendChunk(byte[] data)
    {
        ChunkPos pos = NetDecoder.ReadChunkPos(data, 1);

        this.cl.toLoad.Add(data);
        this.cl.toLoadChunk.Add(pos);
    }
Example #15
0
        public Chunk PeekChunk(ChunkPos chunkPos)
        {
            Chunk chunk;

            _chunkMap.TryGetValue(chunkPos, out chunk);
            return(chunk);
        }
Example #16
0
    /// <summary>
    /// Gets the <c>DataChunk</c> from the given <paramref name="pos"/>.
    /// </summary>
    /// <param name="pos">Chunk position.</param>
    /// <returns><c>DataChunk</c> that exists at <paramref name="pos"/>.</returns>
    public static DataChunk GetChunk(ChunkPos pos)
    {
        DataChunk chunk;

        _chunks.TryGetValue(pos, out chunk);
        return(chunk);
    }
Example #17
0
        private bool IsInViewingFrustum(GameClient gameClient, EntityOffset offset, ChunkPos chunkPos)
        {
            /* Check if the bounding sphere of the chunk is in the viewing frustum. */

            var df = (double)GeometryConstants.ChunkSize;

            // Determine the chunk center relative to the viewer.
            double dx = (chunkPos.X + 0.5) * df - offset.X;
            double dy = (chunkPos.Y + 0.5) * df - offset.Y;
            double dz = (chunkPos.Z + 0.5) * df - offset.Z;

            double t0, t1;

            // Perform mouselook rotation
            double ha = gameClient.PositionData.Placement.Orientation.Horizontal;
            double hc = Math.Cos(ha), hs = Math.Sin(ha);

            t0 = dx * hc - dz * hs; t1 = dz * hc + dx * hs; dx = t0; dz = t1;

            double va = -gameClient.PositionData.Placement.Orientation.Vertical;
            double vc = Math.Cos(va), vs = Math.Sin(va);

            t0 = dz * vc - dy * vs; t1 = dy * vc + dz * vs; dz = t0; dy = t1;

            // Check if the chunk is behind the viewer.
            if (dz > ChunkRadius && dz > ChunkRadius)
            {
                return(false);
            }

            /* TODO: We can discard even more chunks by taking the left, right, top and bottom planes into account. */

            return(true);
        }
Example #18
0
    // Turns on and off Torch
    public override int OnInteract(ChunkPos pos, int blockX, int blockY, int blockZ, ChunkLoader_Server cl)
    {
        ushort state    = cl.chunks[pos].metadata.GetState(blockX, blockY, blockZ);
        ushort newState = 0;

        if (state == ushort.MaxValue)
        {
            return(0);
        }
        else if (state >= 4)
        {
            cl.chunks[pos].metadata.AddToState(blockX, blockY, blockZ, -4);
            newState = (ushort)(state - 4);
        }
        else if (state >= 0 && state < 4)
        {
            cl.chunks[pos].metadata.AddToState(blockX, blockY, blockZ, 4);
            newState = (ushort)(state + 4);
        }

        NetMessage message = new NetMessage(NetCode.VFXCHANGE);

        message.VFXChange(pos, blockX, blockY, blockZ, 0, ushort.MaxValue, newState);
        cl.server.SendToClients(pos, message);

        return(2);
    }
    //note i dont want this to be a co-routine because... well... its fairly simple
    /// <summary>
    /// create a chunk if it doesn't exist
    /// </summary>
    /// <param name="pos">position of the chunk</param>
    public void CreateChunk(ChunkPos pos)
    {
        generatingChunk = true;
        ChunkGenerator chunkGen = null;

        chunkDictionary.TryGetValue(pos, out chunkGen);

        if (chunkGen == null)
        {

            //instantiate a chunk at the calculated position

            GameObject chunkObj = (GameObject)Instantiate(chunk, new Vector3(pos.x * chunkSize, 0f, pos.z * chunkSize), Quaternion.identity);
            chunkObj.transform.parent = transform;

            int actualChunkX = pos.x * chunkSize;
            int actualChunkZ = pos.z * chunkSize;

            //add the chunk object spawned to the dictionary... well the ChunkGenerator script part of the object anyways
            chunkDictionary.Add(pos, chunkObj.GetComponent<ChunkGenerator>());

            chunkObj.GetComponent<ChunkGenerator>().init(chunkSize, actualChunkX, actualChunkZ);

            chunkObj.name = "chunk_x" + pos.x + "_z" + pos.z; // set the name property to know where it is in the world through the inspector
        //            Debug.Log("derped out around here, name:" + chunkObj.name);
        }

        generatingChunk = false;
    }
Example #20
0
    // Re-acquires every chunk that is possibly not loaded and adds all chunks that need redraw (except borders) to redraw list
    private void FixUnloaded()
    {
        ChunkPos newChunk;

        this.message = new NetMessage(NetCode.REQUESTCHUNKLOAD);

        for (int x = -World.renderDistance; x < World.renderDistance; x++)
        {
            for (int z = -World.renderDistance; z < World.renderDistance; z++)
            {
                newChunk = new ChunkPos(this.currentChunk.x + x, this.currentChunk.z + z);

                if (!this.chunks.ContainsKey(newChunk) && !this.toLoadChunk.Contains(newChunk))
                {
                    this.message.RequestChunkLoad(newChunk);
                    client.Send(this.message.GetMessage(), this.message.size);
                    continue;
                }

                if (this.chunks.ContainsKey(newChunk))
                {
                    if (!this.chunks[newChunk].drawMain && !this.toDraw.Contains(newChunk))
                    {
                        this.toDraw.Add(newChunk);
                    }
                }
            }
        }
    }
Example #21
0
    // Client handling the creation of the VFX
    public override int OnVFXBuild(ChunkPos pos, int blockX, int blockY, int blockZ, int facing, ushort state, ChunkLoader cl)
    {
        Vector3 fireOffset;

        if (facing == 0)
        {
            fireOffset = new Vector3(0.15f, 0f, 0f);
        }
        else if (facing == 1)
        {
            fireOffset = new Vector3(0f, 0f, -0.15f);
        }
        else if (facing == 2)
        {
            fireOffset = new Vector3(-0.15f, 0f, 0f);
        }
        else if (facing == 3)
        {
            fireOffset = new Vector3(0f, 0f, 0.15f);
        }
        else
        {
            fireOffset = new Vector3(0f, 0f, 0f);
        }

        GameObject fire = GameObject.Instantiate(this.fireVFX, new Vector3(pos.x * Chunk.chunkWidth + blockX, blockY + 0.35f, pos.z * Chunk.chunkWidth + blockZ) + fireOffset, Quaternion.identity);

        fire.name = BuildVFXName(pos, blockX, blockY, blockZ);

        this.vfx.Add(pos, fire, active: true, isOnDemandLight: true);
        ControlFire(pos, blockX, blockY, blockZ, state);

        return(0);
    }
Example #22
0
    // Loads the chunk into the Chunkloader
    private void LoadChunk()
    {
        if (toLoad.Count > 0)
        {
            int min;

            // Sets the current iteration amount
            if (3 <= toLoad.Count)
            {
                min = 3;
            }
            else
            {
                min = toLoad.Count;
            }

            for (int i = 0; i < min; i++)
            {
                byte[] data = toLoad[0];

                int headerSize = RegionFileHandler.chunkHeaderSize;

                ChunkPos cp = NetDecoder.ReadChunkPos(data, 1);

                // Prevention
                if (this.chunks.ContainsKey(cp))
                {
                    this.chunks[cp].Destroy();
                    this.chunks.Remove(cp);
                }


                int blockDataSize = NetDecoder.ReadInt(data, 9);
                int hpDataSize    = NetDecoder.ReadInt(data, 13);
                int stateDataSize = NetDecoder.ReadInt(data, 17);

                this.chunks[cp]           = new Chunk(cp, this.rend, this.blockBook, this);
                this.chunks[cp].biomeName = BiomeHandler.ByteToBiome(data[21]);

                Compression.DecompressBlocksClient(this.chunks[cp], data, initialPos: 21 + headerSize);
                Compression.DecompressMetadataHPClient(this.chunks[cp], data, initialPos: 21 + headerSize + blockDataSize);
                Compression.DecompressMetadataStateClient(this.chunks[cp], data, initialPos: 21 + headerSize + blockDataSize + hpDataSize);

                if (this.vfx.data.ContainsKey(cp))
                {
                    this.vfx.RemoveChunk(cp);
                }

                this.vfx.NewChunk(cp);

                if (!this.toDraw.Contains(cp))
                {
                    this.toDraw.Add(cp);
                }

                toLoad.RemoveAt(0);
                toLoadChunk.RemoveAt(0);
            }
        }
    }
Example #23
0
 // Adds chunk to Update queue
 public void AddToUpdate(ChunkPos pos, bool noLight = false)
 {
     if (!noLight)
     {
         if (!toUpdate.Contains(pos))
         {
             toUpdate.Add(pos);
         }
         else
         {
             toUpdate.Remove(pos);
             toUpdate.Add(pos);
         }
     }
     else
     {
         if (!toUpdateNoLight.Contains(pos))
         {
             toUpdateNoLight.Add(pos);
         }
         else
         {
             toUpdateNoLight.Remove(pos);
             toUpdateNoLight.Add(pos);
         }
     }
 }
    public void onNewTerrain(ChunkPos currpos, UnityEngine.GameObject go)
    {
        Common.DEBUG_MSG("WorldManager::onNewTerrain: " + go.name + ", pos=" +
                         go.transform.position + ", dir=" + go.transform.rotation + ", scale=" + go.transform.localScale);

        autoSetNeighbors(currpos);
    }
        protected override void loadChunks(ChunkPos occupiedChunkPos)
        {
            int  x, y, z;
            bool flagX, flagY, flagZ, isReadOnly;

            for (x = -this.loadRadius; x <= this.loadRadius; x++)
            {
                for (y = -this.loadRadius; y <= this.loadRadius; y++)
                {
                    for (z = -this.loadRadius; z <= this.loadRadius; z++)
                    {
                        flagX = Math.Abs(x) == loadRadius;
                        flagY = Math.Abs(y) == loadRadius;
                        flagZ = Math.Abs(z) == loadRadius;

                        isReadOnly = flagX || flagY || flagZ;
                        NewChunkInstructions instructions = new NewChunkInstructions(x + occupiedChunkPos.x, y + occupiedChunkPos.y, z + occupiedChunkPos.z, isReadOnly);
                        Chunk chunk = world.getChunk(instructions.chunkPos);

                        if (chunk == null)
                        {
                            if (!this.buildQueue.Contains(instructions))
                            {
                                this.buildQueue.Enqueue(instructions);
                            }
                        }
                        else
                        {
                            chunk.isReadOnly = isReadOnly;
                        }
                    }
                }
            }
        }
Example #26
0
    private void RemoveBlockVisualisers(ChunkPos cpos) // удаление всей рендер-информации для данного блока
    {
        bool corrections = false;
        MeshVisualizeInfo mvi;
        int i = 0;

        while (i < blockVisualizersList.Count)
        {
            if (blockVisualizersList[i].pos == cpos)
            {
                mvi = blockVisualizersList[i].meshInfo;
                if (!redrawRequiredTypes.Contains(mvi))
                {
                    redrawRequiredTypes.Add(mvi);
                }
                blockVisualizersList.RemoveAt(i);
                corrections = true;
                continue;
            }
            else
            {
                i++;
            }
        }
        if (corrections)
        {
            chunkRenderUpdateRequired = true;
        }
    }
Example #27
0
    // Redraws lights in current and adjascent chunks in scene on Demand
    public void UpdateLights(ChunkPos pos, bool adjascent = true)
    {
        if (!VFXLoader.EXTRALIGHTSHADOWS)
        {
            return;
        }

        // Updates all lights in current chunk
        foreach (HDAdditionalLightData light in this.lightReference[pos])
        {
            light.RequestShadowMapRendering();
        }

        if (adjascent)
        {
            ChunkPos[] neighbors = { new ChunkPos(pos.x - 1, pos.z - 1), new ChunkPos(pos.x - 1, pos.z), new ChunkPos(pos.x - 1, pos.z + 1), new ChunkPos(pos.x, pos.z - 1), new ChunkPos(pos.x, pos.z + 1), new ChunkPos(pos.x + 1, pos.z - 1), new ChunkPos(pos.x + 1, pos.z), new ChunkPos(pos.x + 1, pos.z + 1) };

            // Updates all lights in neighbor chunks
            foreach (ChunkPos iterPos in neighbors)
            {
                if (ContainsLight(iterPos))
                {
                    foreach (HDAdditionalLightData light in this.lightReference[iterPos])
                    {
                        light.RequestShadowMapRendering();
                    }
                }
            }
        }
    }
    /*
     * BiomeHandler's main function
     * Used to assign a biome to a new chunk.
     * Play arround with the seed value in each of the 4 biome features to change the behaviour
     *      of the biome distribution.
     */
    public byte Assign(ChunkPos pos)
    {
        float currentAltitude    = Perlin.Noise(pos.x * BiomeHandlerData.featureModificationConstant * BiomeHandlerData.ax + ((dispersionSeed * BiomeHandlerData.ss) % 1000), pos.z * BiomeHandlerData.featureModificationConstant * BiomeHandlerData.az + ((dispersionSeed * BiomeHandlerData.sx) % 1000));
        float currentHumidity    = Perlin.Noise(pos.x * BiomeHandlerData.featureModificationConstant * BiomeHandlerData.bx + ((dispersionSeed * BiomeHandlerData.ss) % 1000), pos.z * BiomeHandlerData.featureModificationConstant * BiomeHandlerData.bz + ((dispersionSeed * BiomeHandlerData.sy) % 1000));
        float currentTemperature = Perlin.Noise(pos.x * BiomeHandlerData.featureModificationConstant * BiomeHandlerData.cx + ((dispersionSeed * BiomeHandlerData.ss) % 1000), pos.z * BiomeHandlerData.featureModificationConstant * BiomeHandlerData.cz + ((dispersionSeed * BiomeHandlerData.sz) % 1000));
        float currentLightning   = Perlin.Noise(pos.x * BiomeHandlerData.featureModificationConstant * BiomeHandlerData.dx + ((dispersionSeed * BiomeHandlerData.ss) % 1000), pos.z * BiomeHandlerData.featureModificationConstant * BiomeHandlerData.dz + ((dispersionSeed * BiomeHandlerData.sw) % 1000));

        float lowestDistance = 99;
        byte  lowestBiome    = 255;
        float distance;

        float4 currentSettings = new float4(currentAltitude, currentHumidity, currentTemperature, currentLightning);

        for (byte s = 0; s < amountOfBiomes; s++)
        {
            distance = BiomeHandler.Distance(currentSettings, BiomeHandlerData.codeToStats[s]);

            if (distance <= lowestDistance)
            {
                lowestDistance = distance;
                lowestBiome    = s;
            }
        }
        return(lowestBiome);
    }
Example #29
0
        private void SendChunkDataTo(EndPoint ep, GenericMessage msg)
        {
            var chp   = new ChunkPos((int)msg.ReadSignedInteger(), (int)msg.ReadSignedInteger());
            var chunk = _world.GetChunk(chp);

            if (!chunk.HasData)
            {
                _world.LoadChunk(chp);
            }

            var raw = chunk.GetRaw();

            var m = new GenericMessage();

            m.WriteUnsignedInteger(1);
            m.WriteSignedInteger((uint)chp.x);
            m.WriteSignedInteger((uint)chp.z);

            var data = new byte[raw.Length];

            Buffer.BlockCopy(raw, 0, data, 0, data.Length);

            m.WriteUnsignedInteger((uint)data.Length);
            m.WriteByteArray(data);

            _server.SendToAsync(ep, m);
        }
Example #30
0
    public void DeleteBlock(ChunkPos pos, bool compensateStructures)
    {
        // в сиквеле стоит пересмотреть всю иерархию классов ><
        //12.06 нет, я так не думаю
        // 24.04.2019 фига сколько времени прошло
        // 26.01.2020 ну привет
        Block b = GetBlock(pos);

        if (b == null)
        {
            return;
        }
        int x = pos.x, y = pos.y, z = pos.z;

        if (b.ContainSurface())
        {
            needSurfacesUpdate = true;
        }
        var affectionMask = b.GetAffectionMask();

        b.Annihilate(compensateStructures);
        blocks.Remove(b.pos);
        RemoveBlockVisualisers(b.pos);
        if (PoolMaster.useIlluminationSystem)
        {
            RecalculateIlluminationAtPoint(pos);
        }

        if (affectionMask != 0)
        {
            if ((affectionMask & (1 << Block.FWD_FACE_INDEX)) != 0)
            {
                GetBlock(pos.OneBlockForward())?.InitializePlane(Block.BACK_FACE_INDEX);
            }
            if ((affectionMask & (1 << Block.RIGHT_FACE_INDEX)) != 0)
            {
                GetBlock(pos.OneBlockRight())?.InitializePlane(Block.LEFT_FACE_INDEX);
            }
            if ((affectionMask & (1 << Block.BACK_FACE_INDEX)) != 0)
            {
                GetBlock(pos.OneBlockBack())?.InitializePlane(Block.FWD_FACE_INDEX);
            }
            if ((affectionMask & (1 << Block.UP_FACE_INDEX)) != 0)
            {
                GetBlock(pos.OneBlockHigher())?.InitializePlane(Block.DOWN_FACE_INDEX);
            }
            if ((affectionMask & (1 << Block.LEFT_FACE_INDEX)) != 0)
            {
                GetBlock(pos.OneBlockLeft())?.InitializePlane(Block.RIGHT_FACE_INDEX);
            }
            if ((affectionMask & (1 << Block.DOWN_FACE_INDEX)) != 0)
            {
                GetBlock(pos.OneBlockDown())?.InitializePlane(Block.UP_FACE_INDEX);
            }
            RecalculateVisibilityAtPoint(pos, affectionMask);
        }
        shadowsUpdateRequired   = true;
        chunkDataUpdateRequired = true;
        // chunkRenderUpdateRequired = true; < в свитче
    }
Example #31
0
    private void LateUpdate()
    {
        var position = tf.position;
        //get the terrain chunk (can't just use collider)
        int chunkPosX = Mathf.FloorToInt((position.x + offset.x) / 16f) * 16;
        int chunkPosZ = Mathf.FloorToInt((position.z + offset.z) / 16f) * 16;

        ChunkPos cp = new ChunkPos(chunkPosX, chunkPosZ);

        int bix = Mathf.FloorToInt(position.x + offset.x) - chunkPosX;
        int biy = Mathf.FloorToInt(position.y + offset.y);
        int biz = Mathf.FloorToInt(position.z + offset.z) - chunkPosZ;

        inBlock = TerrainGenerator.getBlock(cp, bix, biy, biz);

        if (text != null)
        {
            text.text = "" + inBlock;
        }

        /*if (Input.GetKeyDown(KeyCode.LeftControl))
         * {
         *      TerrainGenerator.updateChunk(cp, (blocks, updateBlock) =>
         *      {
         *              updateBlock(bix+1, biy, biz+1, BlockType.Dirt);
         *      });
         * }*/
    }
Example #32
0
 public IChunk this[ChunkPos pos]
 {
     get {
         TerrainChunk chunk;
         return (_chunks.TryGetValue(pos, out chunk)
                 ? (IChunk)chunk : new EmptyChunk(this, pos, default(BlockData)));
     }
 }
Example #33
0
    public TerrainChunk CreateChunk(ChunkPos pos)
    {
        if (_chunks.ContainsKey(pos))
            throw new InvalidOperationException(string.Format(
                "Chunk at {0} already exists", pos));

        var chunkObject = new GameObject("Chunk: " + pos) {
            hideFlags = HideFlags.HideInHierarchy };
        var chunk = chunkObject.AddComponent<TerrainChunk>();

        chunk.terrain = this;
        chunk.position = pos;

        chunk.transform.parent = transform;
        chunk.transform.localPosition = pos.ToVector3();
        chunk.transform.localRotation = Quaternion.identity;
        chunk.transform.localScale = Vector3.one;

        _chunks[pos] = chunk;
        return chunk;
    }
	public void onNewTerrain(ChunkPos currpos, UnityEngine.GameObject go)
	{
		Common.DEBUG_MSG("WorldManager::onNewTerrain: " + go.name + ", pos=" + 
			go.transform.position + ", dir=" + go.transform.rotation + ", scale=" + go.transform.localScale);
		
		autoSetNeighbors(currpos);
	}
    /// <summary>
    /// render the chunk at the given position, this assumes that the chunk has been generated beforehand, 
    /// if not it will call CreateChunk on it... as a safeguard...
    /// and it will create the chunks on each side of this, to be able to render the edges of this chunk properly
    /// </summary>
    /// <param name="pos">position of the chunk</param>
    public IEnumerator RenderChunk(ChunkPos pos)
    {
        generatingChunk = true;
        ChunkGenerator chunk = null;
        chunkDictionary.TryGetValue(pos, out chunk);

        if (chunk == null)
        {
            CreateChunk(pos);
            chunkDictionary.TryGetValue(pos, out chunk);
        }

        //generate the chunks on each side of the chunk, no need to render them, just generate, this is needed to calculate the edges of a chunk
        List<ChunkPos> positionsAroundTheChunk = new List<ChunkPos>();//why a list? why not, faster than arrays, and pretty syntax

        positionsAroundTheChunk.Add(new ChunkPos(pos.x+1, pos.z));
        positionsAroundTheChunk.Add(new ChunkPos(pos.x-1, pos.z));
        positionsAroundTheChunk.Add(new ChunkPos(pos.x, pos.z+1));
        positionsAroundTheChunk.Add(new ChunkPos(pos.x, pos.z-1));

        foreach (ChunkPos posToGen in positionsAroundTheChunk)
        {
            //make a new thread for each chunk needed to be generated
            CreateChunk(posToGen);
            yield return new WaitForSeconds(0.1f);
        }

        yield return new WaitForSeconds(0.05f); //wait a short while
        chunk.Render();
        generatingChunk = false;
    }
    IEnumerator GenerateChunksInASpiral()
    {
        generatingWorld = true;
        Vector3 playerPos = player.transform.position;
        //position of the player in "Chunk coords"
        int playerChunkXPos = (int)(playerPos.x / chunkSize);
        int playerChunkZPos = (int)(playerPos.z / chunkSize);

        //spiral loop variables
        Vector2 loopPos = new Vector2(playerChunkXPos, playerChunkZPos);
        dir currentDir = dir.xUp;
        bool addAnotherIteration = false;

        //loop that every time it runs through changes direction, every 2nd time it runs through adds another block to the end of the line,
        //and every 4th time ( thisloop/2 ) knows its made another layer
        //this results in something like http://gyazo.com/c8daf4c2a000e11d4ac004e00d9ad21b ... hopefully
        //gif from before fuckup #86 http://gyazo.com/1d8ffa8b586a99576c44f41491146eee
        int maxInARow = 5;
        for (int thisLoop = 0; (thisLoop/2) <= radiusToGenerateAroundPlayer; )
        {

            //create lines of chunks in the direction of 'currentDir', this is results in a spiral and player didn't change pos
            for (int delta = 0; delta <= thisLoop && !PlayerPosHasChanged; delta++)
            {
                #region generateChunkAtPos
                //wait while it finishes generating chunks
                while(generatingChunk)
                {
                    yield return new WaitForSeconds(2f);
                }
                ChunkPos pos = new ChunkPos((int)loopPos.x, (int)loopPos.y);

                if (loadedUp)// load the world up before rendering
                    CreateChunkAndRender(pos);
                else
                    CreateChunk(pos);

                    //yield return new WaitForEndOfFrame();

                #endregion

                //change position of next chunk depending on the direction the loop wants it to spawn in
                switch (currentDir)
                {
                    case dir.xDown:
                        loopPos.x--;
                        break;
                    case dir.xUp:
                        loopPos.x++;
                        break;
                    case dir.yDown:
                        loopPos.y--;
                        break;
                    case dir.yUp:
                        loopPos.y++;
                        break;
                }
                if (maxInARow <= 0)
                {
                    yield return new WaitForSeconds(0.3f);
                    maxInARow = 2;
                }
                maxInARow--;
            }

            yield return new WaitForSeconds(0.5f);

            //add another iteration to this loop every 2nd time it runs through
            if (addAnotherIteration)
            {
                thisLoop++;
                addAnotherIteration = false;
            }
            else
            {
                addAnotherIteration = true;
            }

            //switch direction of the loop
            if ((int)currentDir == 3)
                currentDir = 0;
            else
                currentDir++;
        }
        deleteOldChunks(playerChunkXPos, playerChunkZPos);

        yield return new WaitForSeconds(1f); //when the world has been generated around the player wait for a second before attempting to create it again
        if (!loadedUp)
            PlayerPosHasChanged = true;//make it re-run the loadworld when the map has been generated

        loadedUp = true;
        generatingWorld = false;
        spiralsInProgress--;
    }
 /// <summary>
 /// create and render the chunk
 /// </summary>
 /// <param name="pos">position of the chunk to create & render</param>
 public void CreateChunkAndRender(ChunkPos pos)
 {
     CreateChunk(pos);
     StartCoroutine(RenderChunk(pos));
 }
 /// <summary>
 /// finds the name of the file of where to put/get the chunk
 /// </summary>
 /// <param name="pos">position of the chunk</param>
 /// <returns></returns>
 public static string saveFileName(ChunkPos pos)
 {
     string fileName = pos.x + "," + pos.z + ".bin";
     return fileName;
 }
Example #39
0
 public EmptyChunk(Terrain terrain, ChunkPos pos, BlockData @default)
 {
     this.terrain = terrain;
     position = pos;
     _default = @default;
 }
	public void loadCurrentViewChunks()
	{
		if(RPG_Animation.instance == null)
		{
			Common.DEBUG_MSG("WorldManager::loadCurrentViewChunks: RPG_Animation=" + RPG_Animation.instance);
			return;
		}
		
		ChunkPos currentPos = atChunk();
		
		if(lastChunkPos.x == currentPos.x && lastChunkPos.y == currentPos.y)
			return;
		
		Vector3 playerpos = RPG_Animation.instance.transform.position;
		playerpos.y = 0.0f;
		
		Common.DEBUG_MSG("WorldManager::loadCurrentViewChunks: pos(" + playerpos + "), changeChunk(" + 
			(lastChunkPos.x + 1) + "," + (lastChunkPos.y + 1) + ") ==> (" + 
			(currentPos.x + 1) + "," + (currentPos.y + 1) + ")");

		lastChunkPos = currentPos;
		
		// center
		addLoadChunk(currentPos, 0, Asset.LOAD_LEVEL.LEVEL_ENTER_AFTER);
		
		for(int i=0; i<chunkSplit; i++)
		{
			for(int ii=0; ii<chunkSplit; ii++)
			{
				int xdiff = Math.Abs(i - currentPos.x);
				int ydiff = Math.Abs(ii - currentPos.y);
				if(xdiff <= 1 && ydiff <= 1)
				{
					if(hasTerrainObjs[i, ii, 0] == true)
					{
						continue;
					}

					ChunkPos cpos;
					cpos.x = i;
					cpos.y = ii;
					addLoadChunk(cpos, 1, Asset.LOAD_LEVEL.LEVEL_ENTER_AFTER);
				}
				else
				{
					if(xdiff <= 2 && ydiff <= 2)
					{
						continue;
					}
					
					if(canUnloadChunk == false)
						continue;
					
					if(hasTerrainObjs[i, ii, 0] == true)
					{
						Common.DEBUG_MSG("WorldManager::loadCurrentViewChunks: unload(" + (i + 1) + "," + (ii + 1) + ")");
						hasTerrainObjs[i, ii, 0] = false;
						UnityEngine.GameObject obj = terrainObjs[i, ii, 0];
						if(obj != null)
						{
							allterrainObjs.Remove(obj);
							UnityEngine.GameObject.Destroy(obj);
						}
						
						terrainObjs[i, ii, 0] = null;
						
						Asset asset = terrainAssetBundles[i, ii, 0];
						if(asset != null)
						{
							asset.bundle.Unload(true);
							terrainAssetBundles[i, ii, 0] = null;
						}
						
						clearSceneObjAtPoint(i, ii, false);
					}
				}
			}
		}
		
		loader.inst.loadPool.start();
	}
    public void init(int chunkSize, int actualChunkX, int actualChunkZ, bool generateColumnsPerFrame = false)
    {
        tallestPoint = 0;
        solid = new BlockData(BlockData.BlockType.stone, new Vector3(),20);

        this.chunkSize = chunkSize;
        actualChunkCoords = new ChunkPos(actualChunkX, actualChunkZ);
        filter = gameObject.GetComponent<MeshFilter>();
        collider = gameObject.GetComponent<MeshCollider>();

        WG = GetComponentInParent<WorldGenerator>();

        bool loaded = WorldSaver.LoadChunk(this);
        if (!loaded)
        {

            Blocks = new BlockData[chunkSize, airLimit, chunkSize];

            //fill the entire array of blocks with air
            for (int x = 0; x < chunkSize; x++)
            {

                for (int y = 0; y < airLimit; y++)
                {
                    for (int z = 0; z < chunkSize; z++)
                    {
                        Blocks[x, y, z] = new BlockData(BlockData.BlockType.air, new Vector3((actualChunkX + x), y, (actualChunkZ + z)),20);
                    }
                }
            }
            CalculateChunk(actualChunkX, actualChunkZ);
        }
    }
	public bool hasChunk(ChunkPos chunkIdx)
	{
		if(chunkIdx.x <= 0 || chunkIdx.y <= 0)
			return false;
		
		return hasTerrainObjs[chunkIdx.x, chunkIdx.y, 0];
	}
	void autoSetNeighbors(ChunkPos pos)
	{
		int arrayPos = 0;
		int terrainsLong = chunkSplit;
		int terrainsWide = chunkSplit;
		
		Terrain[] terrains = new Terrain[terrainsLong * terrainsWide];

		for(int y = 0; y < terrainsLong ; y++)
		{
			for(int x = 0; x < terrainsWide; x++)
			{
				if(terrainObjs[x, y, 0] != null)
					terrains[arrayPos] = terrainObjs[x, y, 0].GetComponent<Terrain>();
				else
					terrains[arrayPos] = null;
				
				arrayPos++;
			}
		}

		arrayPos = 0;
		for(int y = 0; y < terrainsLong ; y++)
		{
			for(int x = 0; x < terrainsWide; x++)
			{
				if(terrains[arrayPos] == null)
				{
					arrayPos++;
					continue;
				}

				if(y == 0)
				{
					if(x == 0)
						terrains[arrayPos].SetNeighbors(null, terrains[arrayPos + terrainsWide], terrains[arrayPos + 1], null);
					else if(x == terrainsWide - 1)
						terrains[arrayPos].SetNeighbors(terrains[arrayPos - 1], terrains[arrayPos + terrainsWide], null, null);
					else
						terrains[arrayPos].SetNeighbors(terrains[arrayPos - 1], terrains[arrayPos + terrainsWide], terrains[arrayPos + 1], null);
				}
				else if(y == terrainsLong - 1)
				{
					if(x == 0)
						terrains[arrayPos].SetNeighbors(null, null, terrains[arrayPos + 1], terrains[arrayPos - terrainsWide]);
					else if(x == terrainsWide - 1)
						terrains[arrayPos].SetNeighbors(terrains[arrayPos - 1], null, null, terrains[arrayPos - terrainsWide]);
					else
						terrains[arrayPos].SetNeighbors(terrains[arrayPos - 1], null, terrains[arrayPos + 1], terrains[arrayPos - terrainsWide]);
				}
				else
				{
					if(x == 0)
						terrains[arrayPos].SetNeighbors(null, terrains[arrayPos + terrainsWide], terrains[arrayPos + 1], terrains[arrayPos - terrainsWide]);
					else if(x == terrainsWide - 1)
						terrains[arrayPos].SetNeighbors(terrains[arrayPos - 1], terrains[arrayPos + terrainsWide], null, terrains[arrayPos - terrainsWide]);
					else
						terrains[arrayPos].SetNeighbors(terrains[arrayPos - 1], terrains[arrayPos + terrainsWide], terrains[arrayPos + 1], terrains[arrayPos - terrainsWide]);
				}
				
				arrayPos++;
			}	
		}
		
		/*
		for(int i = 0; i < terrainsWide*terrainsLong ; i++)
		{
			if(terrains[i] != null)
				terrains[i].Flush();
		}
		*/
	}
	public void addLoadChunk(ChunkPos chunkIdx, ushort loadPri, Asset.LOAD_LEVEL level)
	{
		if(chunkIdx.x < 0 || chunkIdx.y < 0 || chunkIdx.x >= chunkSplit || chunkIdx.y >= chunkSplit)
			return;
		
		Common.DEBUG_MSG("WorldManager::addLoadChunk: load(" + 
			(chunkIdx.x + 1) + "," + (chunkIdx.y + 1) + "), loaded=" + hasTerrainObjs[chunkIdx.x, chunkIdx.y, 0]);
		
		if(hasTerrainObjs[chunkIdx.x, chunkIdx.y, 0] == true)
			return;
		
		addLoadWorldObj(chunkIdx);
		Asset asset = new Asset();
		asset.type = Asset.TYPE.TERRAIN;
		asset.loadPri = loadPri;
		asset.loadLevel = level;
		asset.source = getChunkName(chunkIdx) + ".unity3d";
		loader.inst.loadPool.addLoad(asset);

		hasTerrainObjs[chunkIdx.x, chunkIdx.y, 0] = true;
	}
	public bool loadedChunk(ChunkPos chunkIdx)
	{
		if(chunkIdx.x <= 0 || chunkIdx.y <= 0)
			return false;
		
		UnityEngine.GameObject obj = terrainObjs[chunkIdx.x, chunkIdx.y, 0];
		if(obj != null)
		{
			return obj.GetComponent<Terrain>().enabled;
		}
		
		return false;
	}
	public void addLoadWorldObj(ChunkPos chunkIdx)
	{
		Vector3 currpos = RPG_Animation.instance.transform.position;
		currpos.y = 0.0f;
		
		worldObjs[chunkIdx.x, chunkIdx.y, 0].Sort(delegate(WorldSceneObject x, WorldSceneObject y) 
			{ 
				Vector3 pos1 = new Vector3(x.position.x, 0.0f, y.position.z);
				Vector3 pos2 = new Vector3(x.position.x, 0.0f, y.position.z);
				
				float dist1 = Vector3.Distance(pos1, currpos);
				float dist2 = Vector3.Distance(pos2, currpos);
				
				if(dist1 < dist2)
					return -1;

				if(dist1 > dist2)
					return 1;
				
				return 0;
			}
		);
		
		foreach(WorldSceneObject obj in worldObjs[chunkIdx.x, chunkIdx.y, 0])
		{
			Common.DEBUG_MSG("WorldManager::addLoadWorldObj:" + obj.asset.source +
				", isLoaded:" + obj.asset.isLoaded + ", loading:" + obj.asset.loading);
				
			if(obj.asset.isLoaded == false && obj.asset.loading == false)
			{
				SceneObject hasObj = null;
				if(parentScene.objs.TryGetValue(obj.idkey, out hasObj))
				{
					continue;
				}

				obj.asset.loadLevel = Asset.LOAD_LEVEL.LEVEL_ENTER_AFTER;
				
				parentScene.addSceneObject(obj.idkey, obj);
				obj.asset.refs.Add(obj.idkey);
				loader.inst.loadPool.addLoad(obj.asset);
			}
			else
			{
				if(obj.gameObject == null && obj.asset.isLoaded == true)
				{
					obj.Instantiate();
					obj.asset.refs.Remove(obj.idkey);
				}
			}
		}
	}
	public string getChunkName(ChunkPos chunkIdx)
	{
		return terrainName + "_" + (chunkIdx.y + 1) + "_" + (chunkIdx.x + 1);
	}