bool RayCastFast(Vector3 origin, Vector3 direction, out VoxelHitInfo hitInfo, float maxDistance = 0, bool createChunksIfNeeded = false, byte minOpaque = 0, ColliderTypes colliderTypes = ColliderTypes.AnyCollider)
        {
            bool voxelHit = RayCastFastVoxel(origin, direction, out hitInfo, maxDistance, createChunksIfNeeded, minOpaque);

            if ((colliderTypes & ColliderTypes.OnlyVoxels) != 0)
            {
                return(voxelHit);
            }

            if (voxelHit)
            {
                maxDistance = hitInfo.distance - 0.1f;
            }
            // Cast a normal raycast to detect normal gameobjects within ray
            RaycastHit hit;

            if (Physics.Raycast(origin + 0.3f * direction, direction, out hit, maxDistance - 0.3f))
            {
                hitInfo.distance = hit.distance;
                hitInfo.point    = hit.point;
                hitInfo.normal   = hit.normal;
                hitInfo.collider = hit.collider;

                // Check if gameobject is a dynamic voxel
                if (hit.collider != null)
                {
                    if ((colliderTypes & ColliderTypes.IgnorePlayer) != 0 && characterController != null && characterController.name.Equals(hit.collider.name))
                    {
                        return(false);
                    }
                    hitInfo.voxelIndex = -1;
                    VoxelPlaceholder placeholder = hit.collider.GetComponentInParent <VoxelPlaceholder> ();
                    if (placeholder != null)
                    {
                        hitInfo.chunk       = placeholder.chunk;
                        hitInfo.voxelIndex  = placeholder.voxelIndex;
                        hitInfo.voxel       = placeholder.chunk.voxels [placeholder.voxelIndex];
                        hitInfo.voxelCenter = placeholder.transform.position;
                        hitInfo.placeholder = placeholder;
                    }
                }
                return(true);
            }
            else
            {
                return(voxelHit);
            }
        }
Пример #2
0
        protected virtual void DoHit(int damage)
        {
            if (crosshairHitInfo.voxelIndex < 0)
            {
                return;
            }

            lastHitButtonPressed = Time.time;
            seekTarget           = crosshairHitInfo;
            // make character approach target if needed
            seeking = !TargetIsReachable();
            if (seeking)
            {
                seekAction = SeekAction.Hit;
            }
            else
            {
                StartCoroutine(CompleteHit(damage));
            }
        }
Пример #3
0
        /// <summary>
        /// Adds a torch.
        /// </summary>
        GameObject TorchAttachInt(VoxelHitInfo hitInfo, ItemDefinition torchDefinition = null, bool refreshChunks = true)
        {
            // Make sure the voxel exists (has not been removed just before this call) and is solid
            if (hitInfo.chunk.voxels [hitInfo.voxelIndex].hasContent != 1 || hitInfo.chunk.voxels [hitInfo.voxelIndex].opaque < FULL_OPAQUE)
            {
                return(null);
            }

            // Placeholder for attaching the torch
            VoxelPlaceholder placeHolder = GetVoxelPlaceholder(hitInfo.chunk, hitInfo.voxelIndex, true);

            if (placeHolder == null)
            {
                return(null);
            }

            // Position of the voxel containing the "light" of the torch
            Vector3 voxelLightPosition = hitInfo.voxelCenter + hitInfo.normal;

            VoxelChunk chunk;
            int        voxelIndex;

            if (!GetVoxelIndex(voxelLightPosition, out chunk, out voxelIndex))
            {
                return(null);
            }

            //  Make sure it's empty where the light gameobject will be placed
            if (chunk.voxels[voxelIndex].opaque >= 2)
            {
                return(null);
            }

            // Updates current chunk
            if (chunk.lightSources != null)
            {
                foreach (var x in chunk.lightSources)
                {
                    if (x.voxelIndex == voxelIndex)
                    {
                        // Restriction 2: no second torch on the same voxel index
                        return(null);
                    }
                }
            }

            if (torchDefinition == null)
            {
                // Get an inventory item with name Torch
                int itemCount = allItems.Count;
                for (int k = 0; k < itemCount; k++)
                {
                    if (allItems [k].item.category == ItemCategory.Torch)
                    {
                        torchDefinition = allItems [k].item;
                        break;
                    }
                }
            }
            if (torchDefinition == null)
            {
                return(null);
            }

            // Instantiate torch prefab
            GameObject torch = Instantiate <GameObject> (torchDefinition.prefab);

            torch.name = TORCH_NAME;

            // Parent the torch gameobject to the voxel placeholder
            torch.transform.SetParent(placeHolder.transform, false);

            // Position torch on the wall
            torch.transform.position = hitInfo.chunk.transform.position + GetVoxelChunkPosition(hitInfo.voxelIndex) + hitInfo.normal * 0.5f;

            // Rotate torch according to wall normal
            if (hitInfo.normal.y == -1)               // downwards
            {
                torch.transform.Rotate(180f, 0, 0);
            }
            else if (hitInfo.normal.y == 0)                 // side wall
            {
                torch.transform.Rotate(hitInfo.normal.z * 40f, 0, hitInfo.normal.x * -40f);
            }

            Item itemInfo = torch.AddComponent <Item> ();

            itemInfo.itemDefinition    = torchDefinition;
            itemInfo.canPickOnApproach = false;
            itemInfo.canBeDestroyed    = true;
            itemInfo.itemChunk         = hitInfo.chunk;
            itemInfo.itemVoxelIndex    = hitInfo.voxelIndex;

            // Add light source to chunk
            LightSource lightSource = new LightSource();

            lightSource.gameObject     = torch;
            lightSource.voxelIndex     = voxelIndex;
            lightSource.itemDefinition = torchDefinition;
            lightSource.hitInfo        = hitInfo;
            lightSource.lightIntensity = torchDefinition.lightIntensity;
            chunk.AddLightSource(lightSource);
            chunk.modified = true;

            // Add script to remove light source from chunk when torch or voxel is destroyed
            LightSourceRemoval sr = torch.AddComponent <LightSourceRemoval> ();

            sr.env   = this;
            sr.chunk = chunk;

            Light pointLight = torch.GetComponentInChildren <Light> ();

            if (pointLight != null)
            {
                pointLight.enabled = true;
            }

            // Make torch collider ignore player's collider to avoid collisions
            if (characterControllerCollider != null)
            {
                Physics.IgnoreCollision(torch.GetComponent <Collider> (), characterControllerCollider);
            }

            // Recompute lightmap
            if (refreshChunks)
            {
                UpdateChunkRR(chunk);
            }

            // Trigger torch event
            if (!isLoadingGame && OnTorchAttached != null)
            {
                OnTorchAttached(chunk, lightSource);
            }

            return(torch);
        }
Пример #4
0
        void LoadSaveBinaryFileFormat_4(BinaryReader br, bool preservePlayerPosition = false)
        {
            // Character controller transform position
            Vector3 v = DecodeVector3Binary(br);

            if (!preservePlayerPosition)
            {
                characterController.transform.position = v;
            }
            // Character controller transform rotation
            Vector3 angles = DecodeVector3Binary(br);

            if (!preservePlayerPosition)
            {
                characterController.transform.rotation = Quaternion.Euler(angles);
            }
            // Character controller's camera local rotation
            angles = DecodeVector3Binary(br);
            if (!preservePlayerPosition)
            {
                cameraMain.transform.localRotation = Quaternion.Euler(angles);
                // Pass initial rotation to mouseLook script
                characterController.GetComponent <VoxelPlayFirstPersonController> ().mouseLook.Init(characterController.transform, cameraMain.transform, null);
            }

            // Read voxel definition table
            InitSaveGameStructs();
            int vdCount = br.ReadInt16();

            for (int k = 0; k < vdCount; k++)
            {
                saveVoxelDefinitionsList.Add(br.ReadString());
            }

            int             numChunks       = br.ReadInt32();
            VoxelDefinition voxelDefinition = defaultVoxel;
            int             prevVdIndex     = -1;
            Color32         voxelColor      = Misc.color32White;

            for (int c = 0; c < numChunks; c++)
            {
                // Read chunks
                // Get chunk position
                Vector3    chunkPosition  = DecodeVector3Binary(br);
                VoxelChunk chunk          = GetChunkUnpopulated(chunkPosition);
                byte       isAboveSurface = br.ReadByte();
                chunk.isAboveSurface = isAboveSurface == 1;
                chunk.back           = chunk.bottom = chunk.left = chunk.right = chunk.forward = chunk.top = null;
                chunk.allowTrees     = false;
                chunk.modified       = true;
                chunk.isPopulated    = true;
                chunk.voxelSignature = chunk.lightmapSignature = -1;
                chunk.renderState    = ChunkRenderState.Pending;
                SetChunkOctreeIsDirty(chunkPosition, false);
                ChunkClearFast(chunk);
                // Read voxels
                int numWords = br.ReadInt16();
                for (int k = 0; k < numWords; k++)
                {
                    // Voxel definition
                    int vdIndex = br.ReadInt16();
                    if (prevVdIndex != vdIndex)
                    {
                        if (vdIndex >= 0 && vdIndex < vdCount)
                        {
                            voxelDefinition = GetVoxelDefinition(saveVoxelDefinitionsList [vdIndex]);
                            prevVdIndex     = vdIndex;
                        }
                    }
                    // RGB
                    voxelColor.r = br.ReadByte();
                    voxelColor.g = br.ReadByte();
                    voxelColor.b = br.ReadByte();
                    // Voxel index
                    int voxelIndex = br.ReadInt16();
                    // Repetitions
                    int repetitions = br.ReadInt16();

                    if (voxelDefinition == null)
                    {
                        continue;
                    }

                    // Water level (only for transparent)
                    byte waterLevel = 15;
                    if (voxelDefinition.renderType == RenderType.Water)
                    {
                        waterLevel = br.ReadByte();
                    }
                    if (voxelDefinition.renderType == RenderType.Custom)
                    {
                        byte hasCustomRotation = br.ReadByte();
                        if (hasCustomRotation == 1)
                        {
                            Vector3 voxelAngles = DecodeVector3Binary(br);
                            saveVoxelCustomRotations.Add(GetVoxelPosition(chunkPosition, voxelIndex), voxelAngles);
                        }
                    }
                    for (int i = 0; i < repetitions; i++)
                    {
                        chunk.voxels [voxelIndex + i].Set(voxelDefinition, voxelColor);
                        if (voxelDefinition.renderType == RenderType.Water)
                        {
                            chunk.voxels [voxelIndex + i].SetWaterLevel(waterLevel);
                        }
                    }
                }
                // Read light sources
                int          lightCount = br.ReadInt16();
                VoxelHitInfo hitInfo    = new VoxelHitInfo();
                for (int k = 0; k < lightCount; k++)
                {
                    // Voxel index
                    hitInfo.voxelIndex = br.ReadInt16();
                    // Voxel center
                    hitInfo.voxelCenter = GetVoxelPosition(chunkPosition, hitInfo.voxelIndex);
                    // Normal
                    hitInfo.normal = DecodeVector3Binary(br);
                    hitInfo.chunk  = chunk;
                    TorchAttach(hitInfo);
                }
            }
        }
Пример #5
0
        void LoadGameBinaryFileFormat_10(BinaryReader br, bool preservePlayerPosition = false)
        {
            // Character controller transform position & rotation
            Vector3 pos = DecodeVector3Binary(br);
            Vector3 characterRotationAngles   = DecodeVector3Binary(br);
            Vector3 cameraLocalRotationAngles = DecodeVector3Binary(br);

            if (!preservePlayerPosition)
            {
                if (characterController != null)
                {
                    characterController.transform.position = pos;
                    characterController.transform.rotation = Quaternion.Euler(characterRotationAngles);
                    cameraMain.transform.localRotation     = Quaternion.Euler(cameraLocalRotationAngles);
                    characterController.UpdateLook();
                }
            }

            InitSaveGameStructs();
            // Read voxel definition table
            int vdCount = br.ReadInt16();

            for (int k = 0; k < vdCount; k++)
            {
                saveVoxelDefinitionsList.Add(br.ReadString());
            }
            // Read item definition table
            int idCount = br.ReadInt16();

            for (int k = 0; k < idCount; k++)
            {
                saveItemDefinitionsList.Add(br.ReadString());
            }

            int             numChunks       = br.ReadInt32();
            VoxelDefinition voxelDefinition = defaultVoxel;
            int             prevVdIndex     = -1;
            Color32         voxelColor      = Misc.color32White;

            for (int c = 0; c < numChunks; c++)
            {
                // Read chunks
                // Get chunk position
                Vector3    chunkPosition  = DecodeVector3Binary(br);
                VoxelChunk chunk          = GetChunkUnpopulated(chunkPosition);
                byte       isAboveSurface = br.ReadByte();
                chunk.isAboveSurface = isAboveSurface == 1;
                chunk.back           = chunk.bottom = chunk.left = chunk.right = chunk.forward = chunk.top = null;
                chunk.allowTrees     = false;
                chunk.modified       = true;
                chunk.isPopulated    = true;
                chunk.voxelSignature = chunk.lightmapSignature = -1;
                chunk.renderState    = ChunkRenderState.Pending;
                SetChunkOctreeIsDirty(chunkPosition, false);
                ChunkClearFast(chunk);
                // Read voxels
                int numWords = br.ReadInt16();
                for (int k = 0; k < numWords; k++)
                {
                    // Voxel definition
                    int vdIndex = br.ReadInt16();
                    if (prevVdIndex != vdIndex)
                    {
                        if (vdIndex >= 0 && vdIndex < vdCount)
                        {
                            voxelDefinition = GetVoxelDefinition(saveVoxelDefinitionsList [vdIndex]);
                            prevVdIndex     = vdIndex;
                        }
                    }
                    // RGB
                    voxelColor.r = br.ReadByte();
                    voxelColor.g = br.ReadByte();
                    voxelColor.b = br.ReadByte();
                    // Voxel index
                    int voxelIndex = br.ReadInt16();
                    // Repetitions
                    int repetitions = br.ReadInt16();

                    byte flags             = br.ReadByte();
                    byte hasCustomRotation = br.ReadByte();

                    if (voxelDefinition == null)
                    {
                        continue;
                    }

                    // Custom voxel flags
                    if (voxelDefinition.renderType == RenderType.Custom)
                    {
                        flags &= 0xF; // custom voxels do not store texture rotation; their transform has the final rotation
                        if (hasCustomRotation == 1)
                        {
                            Vector3 voxelAngles = DecodeVector3Binary(br);
                            delayedVoxelCustomRotations.Add(GetVoxelPosition(chunkPosition, voxelIndex), voxelAngles);
                        }
                    }
                    for (int i = 0; i < repetitions; i++)
                    {
                        chunk.voxels [voxelIndex + i].Set(voxelDefinition, voxelColor);
                        if (voxelDefinition.renderType == RenderType.Water || voxelDefinition.renderType.supportsTextureRotation())
                        {
                            chunk.voxels [voxelIndex + i].SetFlags(flags);
                        }
                        if (voxelDefinition.lightIntensity > 0)
                        {
                            chunk.AddLightSource(voxelIndex + i, voxelDefinition.lightIntensity);
                        }
                    }
                }
                // Read light sources
                int          lightCount = br.ReadInt16();
                VoxelHitInfo hitInfo    = new VoxelHitInfo();
                for (int k = 0; k < lightCount; k++)
                {
                    // Voxel index
                    hitInfo.voxelIndex = br.ReadInt16();
                    // Voxel center
                    hitInfo.voxelCenter = GetVoxelPosition(chunkPosition, hitInfo.voxelIndex);
                    // Normal
                    hitInfo.normal = DecodeVector3Binary(br);
                    hitInfo.chunk  = chunk;
                    // Item definition
                    int itemIndex = br.ReadInt16();
                    if (itemIndex < 0 || itemIndex >= idCount)
                    {
                        continue;
                    }
                    string         itemDefinitionName = saveItemDefinitionsList [itemIndex];
                    ItemDefinition itemDefinition     = GetItemDefinition(itemDefinitionName);
                    TorchAttach(hitInfo, itemDefinition);
                }
                // Read items
                int itemCount = br.ReadInt16();
                for (int k = 0; k < itemCount; k++)
                {
                    // Voxel index
                    int itemIndex = br.ReadInt16();
                    if (itemIndex < 0 || itemIndex >= idCount)
                    {
                        continue;
                    }
                    string  itemDefinitionName = saveItemDefinitionsList [itemIndex];
                    Vector3 itemPosition       = DecodeVector3Binary(br);
                    int     quantity           = br.ReadInt16();
                    ItemSpawn(itemDefinitionName, itemPosition, quantity);
                }
            }
            // Destroy any object with VoxelPlaySaveThis component to avoid repetitions
            VoxelPlaySaveThis [] gos = FindObjectsOfType <VoxelPlaySaveThis> ();
            for (int k = 0; k < gos.Length; k++)
            {
                DestroyImmediate(gos [k].gameObject);
            }
            // Load gameobjects
            int goCount = br.ReadInt16();
            Dictionary <string, string> data = new Dictionary <string, string> ();

            for (int k = 0; k < goCount; k++)
            {
                string     prefabPath = br.ReadString();
                GameObject o          = Resources.Load <GameObject> (prefabPath);
                if (o != null)
                {
                    o      = Instantiate <GameObject> (o) as GameObject;
                    o.name = br.ReadString();
                    VoxelPlaySaveThis go = o.GetComponent <VoxelPlaySaveThis> ();
                    if (go == null)
                    {
                        DestroyImmediate(o);
                        continue;
                    }
                    o.transform.position    = DecodeVector3Binary(br);
                    o.transform.eulerAngles = DecodeVector3Binary(br);
                    o.transform.localScale  = DecodeVector3Binary(br);
                    data.Clear();
                    Int16 dataCount = br.ReadInt16();
                    for (int j = 0; j < dataCount; j++)
                    {
                        string key   = br.ReadString();
                        string value = br.ReadString();
                        data [key] = value;
                    }
                    go.SendMessage("OnLoadGame", data);
                }
            }
        }
Пример #6
0
        void WriteChunkData_7(BinaryWriter bw, VoxelChunk chunk)
        {
            // Chunk position
            EncodeVector3Binary(bw, chunk.position);
            bw.Write(chunk.isAboveSurface ? (byte)1 : (byte)0);

            int             voxelDefinitionIndex = 0;
            VoxelDefinition prevVD = null;


            // Count voxels words
            int k        = 0;
            int numWords = 0;

            while (k < chunk.voxels.Length)
            {
                if (chunk.voxels [k].hasContent == 1)
                {
                    VoxelDefinition voxelDefinition = chunk.voxels [k].type;
                    if (voxelDefinition.isDynamic)
                    {
                        k++;
                        continue;
                    }
                    if (voxelDefinition != prevVD)
                    {
                        if (!saveVoxelDefinitionsDict.TryGetValue(voxelDefinition, out voxelDefinitionIndex))
                        {
                            k++;
                            continue;
                        }
                        prevVD = voxelDefinition;
                    }
                    Color32 tintColor = chunk.voxels [k].color;
                    int     flags     = 0;
                    if (voxelDefinition.renderType == RenderType.Water || voxelDefinition.renderType.supportsTextureRotation())
                    {
                        flags = chunk.voxels [k].GetFlags();
                    }
                    k++;
                    while (k < chunk.voxels.Length && chunk.voxels [k].type == voxelDefinition && chunk.voxels [k].color.r == tintColor.r && chunk.voxels [k].color.g == tintColor.g && chunk.voxels [k].color.b == tintColor.b && voxelDefinition.renderType != RenderType.Custom && chunk.voxels [k].GetFlags() == flags)
                    {
                        k++;
                    }
                    numWords++;
                }
                else
                {
                    k++;
                }
            }
            bw.Write((Int16)numWords);

            // Write voxels
            k = 0;
            while (k < chunk.voxels.Length)
            {
                if (chunk.voxels [k].hasContent == 1)
                {
                    int             voxelIndex      = k;
                    VoxelDefinition voxelDefinition = chunk.voxels [k].type;
                    if (voxelDefinition.isDynamic)
                    {
                        k++;
                        continue;
                    }
                    if (voxelDefinition != prevVD)
                    {
                        if (!saveVoxelDefinitionsDict.TryGetValue(voxelDefinition, out voxelDefinitionIndex))
                        {
                            k++;
                            continue;
                        }
                        prevVD = voxelDefinition;
                    }
                    Color32 tintColor = chunk.voxels [k].color;
                    byte    flags     = 0;
                    if (voxelDefinition.renderType == RenderType.Water || voxelDefinition.renderType.supportsTextureRotation())
                    {
                        flags = chunk.voxels [k].GetFlags();
                    }
                    int repetitions = 1;
                    k++;
                    while (k < chunk.voxels.Length && chunk.voxels [k].type == voxelDefinition && chunk.voxels [k].color.r == tintColor.r && chunk.voxels [k].color.g == tintColor.g && chunk.voxels [k].color.b == tintColor.b && voxelDefinition.renderType != RenderType.Custom && chunk.voxels [k].GetFlags() == flags)
                    {
                        repetitions++;
                        k++;
                    }
                    bw.Write((Int16)voxelDefinitionIndex);
                    bw.Write(tintColor.r);
                    bw.Write(tintColor.g);
                    bw.Write(tintColor.b);
                    bw.Write((Int16)voxelIndex);
                    bw.Write((Int16)repetitions);
                    bw.Write(flags);
                    if (voxelDefinition.renderType == RenderType.Custom)
                    {
                        // Check rotation
                        VoxelPlaceholder placeholder = GetVoxelPlaceholder(chunk, voxelIndex, false);
                        if (placeholder != null)
                        {
                            Vector3 angles = placeholder.transform.eulerAngles;
                            if (angles.x != 0 || angles.y != 0 || angles.z != 0)
                            {
                                bw.Write((byte)1);                                  // has rotation
                                EncodeVector3Binary(bw, angles);
                            }
                            else
                            {
                                bw.Write((byte)0);
                            }
                        }
                        else
                        {
                            bw.Write((byte)0);
                        }
                    }
                    else
                    {
                        bw.Write((byte)0);
                    }
                }
                else
                {
                    k++;
                }
            }

            // Write number of light sources
            int lightCount = chunk.lightSources != null ? chunk.lightSources.Count : 0;

            bw.Write((Int16)lightCount);
            if (lightCount > 0)
            {
                for (k = 0; k < lightCount; k++)
                {
                    VoxelHitInfo hi = chunk.lightSources [k].hitInfo;
                    bw.Write((Int16)hi.voxelIndex);
                    EncodeVector3Binary(bw, hi.normal);
                }
            }

            // Write number of items
            int itemCount = chunk.items != null ? chunk.items.count : 0;

            bw.Write((Int16)itemCount);
            if (itemCount > 0)
            {
                for (k = 0; k < itemCount; k++)
                {
                    Item item = chunk.items.values [k];
                    if (item == null || item.itemDefinition == null)
                    {
                        continue;
                    }
                    ItemDefinition id = item.itemDefinition;
                    int            idIndex;
                    if (saveItemDefinitionsDict.TryGetValue(id, out idIndex))
                    {
                        bw.Write((Int16)idIndex);
                        EncodeVector3Binary(bw, item.transform.position);
                        bw.Write((Int16)item.quantity);
                    }
                }
            }
        }
        void LoadGameBinaryFileFormat_7(BinaryReader br, bool preservePlayerPosition = false)
        {
            // Character controller transform position & rotation
            Vector3 pos = DecodeVector3Binary(br);
            Vector3 characterRotationAngles   = DecodeVector3Binary(br);
            Vector3 cameraLocalRotationAngles = DecodeVector3Binary(br);

            if (!preservePlayerPosition)
            {
                if (characterController != null)
                {
                    characterController.transform.position = pos;
                    characterController.transform.rotation = Quaternion.Euler(characterRotationAngles);
                    cameraMain.transform.localRotation     = Quaternion.Euler(cameraLocalRotationAngles);
                    characterController.UpdateLook();
                }
            }

            InitSaveGameStructs();
            // Read voxel definition table
            int vdCount = br.ReadInt16();

            for (int k = 0; k < vdCount; k++)
            {
                saveVoxelDefinitionsList.Add(br.ReadString());
            }
            // Read item definition table
            int idCount = br.ReadInt16();

            for (int k = 0; k < idCount; k++)
            {
                saveItemDefinitionsList.Add(br.ReadString());
            }

            int             numChunks       = br.ReadInt32();
            VoxelDefinition voxelDefinition = defaultVoxel;
            int             prevVdIndex     = -1;
            Color32         voxelColor      = Misc.color32White;

            for (int c = 0; c < numChunks; c++)
            {
                // Read chunks
                // Get chunk position
                Vector3    chunkPosition  = DecodeVector3Binary(br);
                VoxelChunk chunk          = GetChunkUnpopulated(chunkPosition);
                byte       isAboveSurface = br.ReadByte();
                chunk.isAboveSurface = isAboveSurface == 1;
                chunk.back           = chunk.bottom = chunk.left = chunk.right = chunk.forward = chunk.top = null;
                chunk.allowTrees     = false;
                chunk.modified       = true;
                chunk.isPopulated    = true;
                chunk.voxelSignature = chunk.lightmapSignature = -1;
                chunk.renderState    = ChunkRenderState.Pending;
                SetChunkOctreeIsDirty(chunkPosition, false);
                ChunkClearFast(chunk);
                // Read voxels
                int numWords = br.ReadInt16();
                for (int k = 0; k < numWords; k++)
                {
                    // Voxel definition
                    int vdIndex = br.ReadInt16();
                    if (prevVdIndex != vdIndex)
                    {
                        if (vdIndex >= 0 && vdIndex < vdCount)
                        {
                            voxelDefinition = GetVoxelDefinition(saveVoxelDefinitionsList [vdIndex]);
                            prevVdIndex     = vdIndex;
                        }
                    }
                    // RGB
                    voxelColor.r = br.ReadByte();
                    voxelColor.g = br.ReadByte();
                    voxelColor.b = br.ReadByte();
                    // Voxel index
                    int voxelIndex = br.ReadInt16();
                    // Repetitions
                    int repetitions = br.ReadInt16();

                    byte flags             = br.ReadByte();
                    byte hasCustomRotation = br.ReadByte();

                    if (voxelDefinition == null)
                    {
                        continue;
                    }

                    // Custom voxel flags
                    if (voxelDefinition.renderType == RenderType.Custom)
                    {
                        if (hasCustomRotation == 1)
                        {
                            Vector3 voxelAngles = DecodeVector3Binary(br);
                            delayedVoxelCustomRotations.Add(GetVoxelPosition(chunkPosition, voxelIndex), voxelAngles);
                        }
                    }
                    for (int i = 0; i < repetitions; i++)
                    {
                        chunk.voxels [voxelIndex + i].Set(voxelDefinition, voxelColor);
                        if (voxelDefinition.renderType == RenderType.Water || voxelDefinition.renderType.supportsTextureRotation())
                        {
                            chunk.voxels [voxelIndex + i].SetFlags(flags);
                        }
                    }
                }
                // Read light sources
                int          lightCount = br.ReadInt16();
                VoxelHitInfo hitInfo    = new VoxelHitInfo();
                for (int k = 0; k < lightCount; k++)
                {
                    // Voxel index
                    hitInfo.voxelIndex = br.ReadInt16();
                    // Voxel center
                    hitInfo.voxelCenter = GetVoxelPosition(chunkPosition, hitInfo.voxelIndex);
                    // Normal
                    hitInfo.normal = DecodeVector3Binary(br);
                    hitInfo.chunk  = chunk;
                    TorchAttach(hitInfo);
                }
                // Read items
                int itemCount = br.ReadInt16();
                for (int k = 0; k < itemCount; k++)
                {
                    // Voxel index
                    int itemIndex = br.ReadInt16();
                    if (itemIndex < 0 || itemIndex >= idCount)
                    {
                        continue;
                    }
                    string  itemDefinitionName = saveItemDefinitionsList [itemIndex];
                    Vector3 itemPosition       = DecodeVector3Binary(br);
                    int     quantity           = br.ReadInt16();
                    ItemSpawn(itemDefinitionName, itemPosition, quantity);
                }
            }
        }
        /// <summary>
        /// Performs the voxel damage.
        /// </summary>
        /// <returns>The actual damage taken by the voxe.</returns>
        /// <param name="hitInfo">Hit info.</param>
        /// <param name="damage">Damage.</param>
        /// <param name="addParticles">If set to <c>true</c> add particles.</param>
        int DamageVoxelFast(ref VoxelHitInfo hitInfo, int damage, bool addParticles, bool playSound, bool allowDamageEvent = true)
        {
            VoxelChunk chunk = hitInfo.chunk;

            if (hitInfo.voxel.typeIndex == 0)
            {
                return(0);
            }
            VoxelDefinition voxelType = hitInfo.voxel.type;
            byte            voxelTypeResistancePoints = voxelType.resistancePoints;

            if (buildMode)
            {
                if (damage > 0)
                {
                    damage = 255;
                }
            }
            else
            {
                if (voxelTypeResistancePoints == (byte)0)
                {
                    damage = 0;
                }
                else if (voxelTypeResistancePoints == (byte)255)
                {
                    if (playSound)
                    {
                        PlayImpactSound(hitInfo.voxel.type.impactSound, hitInfo.voxelCenter);
                    }
                    damage = 0;
                }
            }

            if (allowDamageEvent && OnVoxelDamaged != null)
            {
                OnVoxelDamaged(chunk, hitInfo.voxelIndex, ref damage);
            }

            if (damage == 0)
            {
                return(0);
            }

            // Gets ambient light near surface
            float voxelLight = GetVoxelLight(hitInfo.point + hitInfo.normal * 0.5f);

            // Get voxel damage indicator GO's name
            bool             destroyed            = voxelType.renderType == RenderType.CutoutCross;
            int              resistancePointsLeft = 0;
            VoxelPlaceholder placeholder          = null;

            if (!destroyed)
            {
                placeholder          = GetVoxelPlaceholder(chunk, hitInfo.voxelIndex, true);
                resistancePointsLeft = placeholder.resistancePointsLeft - damage;
                if (resistancePointsLeft < 0)
                {
                    resistancePointsLeft = 0;
                    destroyed            = true;
                }
                placeholder.resistancePointsLeft = resistancePointsLeft;
            }

            if (voxelType.renderType == RenderType.Empty)
            {
                addParticles = false;
            }

            int particlesAmount;

            if (destroyed)
            {
                // Add recoverable voxel on the scene (not for vegetation)
                if (voxelType.renderType != RenderType.Empty && voxelType.renderType != RenderType.CutoutCross && voxelType.canBeCollected && !buildMode)
                {
                    bool create = true;

                    if (OnVoxelBeforeDropItem != null)
                    {
                        OnVoxelBeforeDropItem(chunk, hitInfo, out create);
                    }
                    if (create)
                    {
                        CreateRecoverableVoxel(hitInfo.voxelCenter, voxelDefinitions [hitInfo.voxel.typeIndex], hitInfo.voxel.color);
                    }
                }

                // Destroy the voxel
                VoxelDestroyFast(chunk, hitInfo.voxelIndex);

                // Check if grass is on top and remove it as well
                VoxelChunk topChunk;
                int        topIndex;
                if (GetVoxelIndex(hitInfo.voxelCenter + Misc.vector3up, out topChunk, out topIndex, false))
                {
                    if (topChunk.voxels [topIndex].typeIndex != 0 && voxelDefinitions [topChunk.voxels [topIndex].typeIndex].renderType == RenderType.CutoutCross)
                    {
                        byte light = topChunk.voxels [topIndex].lightMesh;
                        topChunk.voxels [topIndex].Clear(light);
                        topChunk.modified = true;
                    }
                }

                // Max particles
                particlesAmount = 20;

                if (playSound)
                {
                    PlayDestructionSound(voxelDefinitions [hitInfo.voxel.typeIndex].destructionSound, hitInfo.voxelCenter);
                }
            }
            else
            {
                // Add damage indicator
                if (placeholder == null)
                {
                    placeholder = GetVoxelPlaceholder(chunk, hitInfo.voxelIndex, true);
                }
                if (placeholder.damageIndicator == null)
                {
                    if (damagedVoxelPrefab == null)
                    {
                        damagedVoxelPrefab = Resources.Load <GameObject> ("VoxelPlay/Prefabs/DamagedVoxel");
                    }
                    GameObject g = Instantiate <GameObject> (damagedVoxelPrefab);
                    g.name = DAMAGE_INDICATOR;
                    Transform tDamageIndicator = g.transform;
                    placeholder.damageIndicator = tDamageIndicator.GetComponent <Renderer> ();
                    tDamageIndicator.SetParent(placeholder.transform, false);
                    tDamageIndicator.localPosition = placeholder.bounds.center;
                    tDamageIndicator.localScale    = placeholder.bounds.size * 1.001f;
                }

                int textureIndex = FastMath.FloorToInt((5f * resistancePointsLeft) / voxelTypeResistancePoints);
                if (world.voxelDamageTextures.Length > 0)
                {
                    if (textureIndex >= world.voxelDamageTextures.Length)
                    {
                        textureIndex = world.voxelDamageTextures.Length - 1;
                    }
                    Material mi = placeholder.damageIndicatorMaterial;                     // gets a copy of material the first time it's used
                    mi.mainTexture = world.voxelDamageTextures [textureIndex];
                    mi.SetFloat("_VoxelLight", voxelLight);
                    placeholder.damageIndicator.enabled = true;
                }

                // Particle amount depending of damage
                particlesAmount = (6 - textureIndex) + 3;

                // Sets health recovery for the voxel
                placeholder.StartHealthRecovery(chunk, hitInfo.voxelIndex, world.damageDuration);

                if (playSound)
                {
                    PlayImpactSound(voxelDefinitions [hitInfo.voxel.typeIndex].impactSound, hitInfo.voxelCenter);
                }
            }

            // Add random particles
            if (!addParticles)
            {
                particlesAmount = 0;
            }
            for (int k = 0; k < particlesAmount; k++)
            {
                int ppeIndex = GetParticleFromPool();
                if (ppeIndex < 0)
                {
                    continue;
                }

                // Scale of particle
                Renderer particleRenderer = particlePool [ppeIndex].renderer;
                if (destroyed)
                {
                    if (voxelType.renderType == RenderType.CutoutCross)                         // smaller particles for vegetation
                    {
                        particleRenderer.transform.localScale = Misc.vector3one * Random.Range(0.03f, 0.04f);
                    }
                    else
                    {
                        particleRenderer.transform.localScale = Misc.vector3one * Random.Range(0.04f, 0.1f);
                    }
                }
                else
                {
                    particleRenderer.transform.localScale = Misc.vector3one * Random.Range(0.03f, 0.06f);
                }

                // Set particle texture
                Material instanceMat = particleRenderer.sharedMaterial;
                SetParticleMaterialTextures(instanceMat, voxelDefinitions [hitInfo.voxel.typeIndex], hitInfo.voxel.color);
                instanceMat.mainTextureOffset = new Vector2(Random.value, Random.value);
                instanceMat.mainTextureScale  = Misc.vector2one * 0.05f;
                instanceMat.SetFloat("_VoxelLight", voxelLight);
                instanceMat.SetFloat("_FlashDelay", 0);

                // Set position
                Rigidbody rb = particlePool [ppeIndex].rigidBody;
                if (destroyed)
                {
                    Vector3 expelDir = Random.insideUnitSphere;
                    Vector3 pos      = hitInfo.voxelCenter + expelDir;
                    particleRenderer.transform.position = pos;
                    rb.AddForce(expelDir * (Random.value * 125f));
                }
                else
                {
                    Vector3 pos = hitInfo.point;
                    Vector3 v1  = new Vector3(-hitInfo.normal.y, hitInfo.normal.z, hitInfo.normal.x);
                    Vector3 v2  = new Vector3(-hitInfo.normal.z, hitInfo.normal.x, hitInfo.normal.y);
                    Vector3 dx  = (Random.value - 0.5f) * 0.7f * v1;
                    Vector3 dy  = (Random.value - 0.5f) * 0.7f * v2;
                    particleRenderer.transform.position = pos + hitInfo.normal * 0.001f + dx + dy;
                    rb.AddForce(cameraMain.transform.forward * (Random.value * -125f));
                }
                rb.AddForce(Misc.vector3up * 25f);
                rb.AddTorque(Random.onUnitSphere * 100f);
                rb.useGravity = true;

                // Self-destruct
                particlePool [ppeIndex].destructionTime = Time.time + 2.5f + Random.value;
            }

            return(damage);
        }
        bool HitVoxelFast(Vector3 origin, Vector3 direction, int damage, out VoxelHitInfo hitInfo, float maxDistance = 0, int damageRadius = 1, bool addParticles = true, bool playSound = true, bool allowDamageEvent = true)
        {
            RayCastFast(origin, direction, out hitInfo, maxDistance, false, 0, ColliderTypes.IgnorePlayer);
            VoxelChunk chunk = hitInfo.chunk;

            if (chunk == null || hitInfo.voxelIndex < 0)
            {
                lastHitInfo.chunk      = null;
                lastHitInfo.voxelIndex = -1;
                return(false);
            }

            lastHitInfo = hitInfo;
            DamageVoxelFast(ref hitInfo, damage, addParticles, playSound, allowDamageEvent);

            bool button1Pressed = input.GetButton(InputButtonNames.Button1);
            bool button2Pressed = input.GetButton(InputButtonNames.Button2);

            if ((button1Pressed || button2Pressed) && OnVoxelClick != null)
            {
                OnVoxelClick(chunk, hitInfo.voxelIndex, button1Pressed ? 0 : 1, hitInfo);
            }

            if (damageRadius > 1)
            {
                Vector3 otherPos;
                Vector3 explosionPosition = hitInfo.voxelCenter + hitInfo.normal * damageRadius;
                damageRadius--;

                for (int y = -damageRadius; y <= damageRadius; y++)
                {
                    otherPos.y = lastHitInfo.voxelCenter.y + y;
                    for (int z = -damageRadius; z <= damageRadius; z++)
                    {
                        otherPos.z = lastHitInfo.voxelCenter.z + z;
                        for (int x = -damageRadius; x <= damageRadius; x++)
                        {
                            if (x == 0 && z == 0 && y == 0)
                            {
                                continue;
                            }
                            VoxelChunk otherChunk;
                            int        otherIndex;
                            otherPos.x = lastHitInfo.voxelCenter.x + x;
                            if (GetVoxelIndex(otherPos, out otherChunk, out otherIndex, false))
                            {
                                if (GetVoxelVisibility(otherChunk, otherIndex))
                                {
                                    FastVector.NormalizedDirection(ref explosionPosition, ref otherPos, ref direction);
                                    if (RayCast(explosionPosition, direction, out hitInfo))
                                    {
                                        DamageVoxelFast(ref hitInfo, damage, addParticles, playSound, allowDamageEvent);
                                    }
                                }
                            }
                        }
                    }
                }
            }

            return(true);
        }
        VoxelChunk RayCastFastVoxel(Vector3 origin, Vector3 direction, out VoxelHitInfo hitInfo, float maxDistance = 0, bool createChunksIfNeeded = false, byte minOpaque = 0)
        {
#if DEBUG_RAYCAST
            GameObject o;
#endif

            float maxDistanceSqr = maxDistance == 0 ? 1000 * 1000 : maxDistance * maxDistance;

            // Ray march throuch chunks until hit one loaded chunk
            Vector3    position = origin;
            VoxelChunk chunk    = null;
            hitInfo            = new VoxelHitInfo();
            hitInfo.voxelIndex = -1;

            Vector3 viewDirSign = new Vector3(Mathf.Sign(direction.x), Mathf.Sign(direction.y), Mathf.Sign(direction.z));
            Vector3 viewSign    = (viewDirSign + Misc.vector3one) * 0.5f;          // 0 = left, 1 = right

            float vxz, vzy, vxy;
            if (direction.y != 0)
            {
                float a = direction.x / direction.y;
                float b = direction.z / direction.y;
                vxz = Mathf.Sqrt(1f + a * a + b * b);
            }
            else
            {
                vxz = 1000000f;
            }
            if (direction.x != 0)
            {
                float a = direction.z / direction.x;
                float b = direction.y / direction.x;
                vzy = Mathf.Sqrt(1f + a * a + b * b);
            }
            else
            {
                vzy = 1000000f;
            }
            if (direction.z != 0)
            {
                float a = direction.x / direction.z;
                float b = direction.y / direction.z;
                vxy = Mathf.Sqrt(1f + a * a + b * b);
            }
            else
            {
                vxy = 1000000f;
            }

            Vector3 v3                = new Vector3(vzy, vxz, vxy);
            Vector3 viewSign16        = viewSign * 16f;
            Vector3 viewDirSignOffset = viewDirSign * 0.002f;

            int     chunkX, chunkY, chunkZ;
            int     chunkCount = 0;
            float   t;
            Vector3 normal = Misc.vector3zero, db;
//			bool notFirstVoxel = false;

            while (chunkCount++ < 500)               // safety counter to avoid any potential infinite loop

            // Check max distance
            {
                float distSqr = (position.x - origin.x) * (position.x - origin.x) + (position.y - origin.y) * (position.y - origin.y) + (position.z - origin.z) * (position.z - origin.z);
                if (distSqr > maxDistanceSqr)
                {
                    return(null);
                }


#if DEBUG_RAYCAST
                o = GameObject.CreatePrimitive(PrimitiveType.Cube);
                o.transform.localScale = Misc.Vector3one * 0.15f;
                o.transform.position   = position;
                DestroyImmediate(o.GetComponent <Collider>());
                o.GetComponent <Renderer>().material.color = Color.blue;
#endif

                chunkX = FastMath.FloorToInt(position.x / 16f);
                chunkY = FastMath.FloorToInt(position.y / 16f);
                chunkZ = FastMath.FloorToInt(position.z / 16f);

                chunk = null;
                if (createChunksIfNeeded)
                {
                    chunk = GetChunkOrCreate(chunkX, chunkY, chunkZ);
                }
                else
                {
                    int x00  = WORLD_SIZE_DEPTH * WORLD_SIZE_HEIGHT * (chunkX + WORLD_SIZE_WIDTH);
                    int y00  = WORLD_SIZE_DEPTH * (chunkY + WORLD_SIZE_HEIGHT);
                    int hash = x00 + y00 + chunkZ;
                    chunk = GetChunkIfExists(hash);
                }

                chunkX *= 16;
                chunkY *= 16;
                chunkZ *= 16;

                if (chunk)
                {
                    // Ray-march through chunk
                    Voxel[] voxels     = chunk.voxels;
                    Vector3 inPosition = position;

                    for (int k = 0; k < 64; k++)
                    {
#if DEBUG_RAYCAST
                        o = GameObject.CreatePrimitive(PrimitiveType.Sphere);
                        o.transform.localScale = Misc.Vector3one * 0.1f;
                        o.transform.position   = inPosition;
                        DestroyImmediate(o.GetComponent <Collider>());
                        o.GetComponent <Renderer>().material.color = Color.yellow;
#endif

                        // Check voxel content
                        int fy = FastMath.FloorToInt(inPosition.y);
                        int py = fy - chunkY;
                        int fz = FastMath.FloorToInt(inPosition.z);
                        int pz = fz - chunkZ;
                        int fx = FastMath.FloorToInt(inPosition.x);
                        int px = fx - chunkX;
                        if (px < 0 || px > 15 || py < 0 || py > 15 || pz < 0 || pz > 15)
                        {
                            break;
                        }

                        int voxelIndex = py * ONE_Y_ROW + pz * ONE_Z_ROW + px;
                        if (voxels [voxelIndex].hasContent == 1 && !voxels [voxelIndex].type.ignoresRayCast && (minOpaque == 255 || voxels [voxelIndex].opaque >= minOpaque))
                        {
                            VoxelDefinition vd = voxelDefinitions [voxels [voxelIndex].typeIndex];
                            if (vd.renderType != RenderType.Custom || !vd.modelUsesCollider)
                            {
                                // Check max distance
                                distSqr = (inPosition.x - origin.x) * (inPosition.x - origin.x) + (inPosition.y - origin.y) * (inPosition.y - origin.y) + (inPosition.z - origin.z) * (inPosition.z - origin.z);
                                if (distSqr > maxDistanceSqr)
                                {
                                    return(null);
                                }

                                // Check water level or grass height
                                float voxelHeight = 0;
                                if (vd.renderType == RenderType.Water)
                                {
                                    voxelHeight = voxels [voxelIndex].GetWaterLevel() / 15f;
                                }
                                else if (vd.renderType == RenderType.CutoutCross)
                                {
                                    voxelHeight = vd.scale.y;
                                }
                                bool    hit         = true;
                                Vector3 voxelCenter = new Vector3(chunkX + px + 0.5f, chunkY + py + 0.5f, chunkZ + pz + 0.5f);
                                Vector3 localHitPos = inPosition - voxelCenter;
                                if (voxelHeight > 0 && voxelHeight < 1f && direction.y != 0)
                                {
                                    t = localHitPos.y + 0.5f - voxelHeight;
                                    if (t > 0)
                                    {
                                        t            = t * Mathf.Sqrt(1 + (direction.x * direction.x + direction.z * direction.z) / (direction.y * direction.y));
                                        localHitPos += t * direction;
                                        hit          = localHitPos.x >= -0.5f && localHitPos.x <= 0.5f && localHitPos.z >= -0.5f && localHitPos.z <= 0.5f;
                                    }
                                }
                                if (hit)
                                {
                                    hitInfo             = new VoxelHitInfo();
                                    hitInfo.chunk       = chunk;
                                    hitInfo.voxel       = voxels [voxelIndex];
                                    hitInfo.point       = inPosition - normal;
                                    hitInfo.distance    = Mathf.Sqrt(distSqr);
                                    hitInfo.voxelIndex  = voxelIndex;
                                    hitInfo.voxelCenter = voxelCenter;
                                    if (localHitPos.y >= 0.495)
                                    {
                                        hitInfo.normal = Misc.vector3up;
                                    }
                                    else if (localHitPos.y <= -0.495)
                                    {
                                        hitInfo.normal = Misc.vector3down;
                                    }
                                    else if (localHitPos.x < -0.495)
                                    {
                                        hitInfo.normal = Misc.vector3left;
                                    }
                                    else if (localHitPos.x > 0.495)
                                    {
                                        hitInfo.normal = Misc.vector3right;
                                    }
                                    else if (localHitPos.z < -0.495)
                                    {
                                        hitInfo.normal = Misc.vector3back;
                                    }
                                    else if (localHitPos.z > 0.495)
                                    {
                                        hitInfo.normal = Misc.vector3forward;
                                    }

#if DEBUG_RAYCAST
                                    o = GameObject.CreatePrimitive(PrimitiveType.Sphere);
                                    o.transform.localScale = Misc.Vector3one * 0.15f;
                                    o.transform.position   = inPosition;
                                    DestroyImmediate(o.GetComponent <Collider>());
                                    o.GetComponent <Renderer>().material.color = Color.red;
#endif

                                    return(chunk);
                                }
                            }
                        }

                        db.x = (fx + viewSign.x - inPosition.x) * v3.x;
                        db.y = (fy + viewSign.y - inPosition.y) * v3.y;
                        db.z = (fz + viewSign.z - inPosition.z) * v3.z;

                        db.x = db.x < 0 ? -db.x : db.x;
                        db.y = db.y < 0 ? -db.y : db.y;
                        db.z = db.z < 0 ? -db.z : db.z;

                        t        = db.x;
                        normal.x = viewDirSignOffset.x;
                        normal.y = 0;
                        normal.z = 0;
                        if (db.y < t)
                        {
                            t        = db.y;
                            normal.x = 0;
                            normal.y = viewDirSignOffset.y;
                        }
                        if (db.z < t)
                        {
                            t        = db.z;
                            normal.x = 0;
                            normal.y = 0;
                            normal.z = viewDirSignOffset.z;
                        }

                        inPosition.x += direction.x * t + normal.x;
                        inPosition.y += direction.y * t + normal.y;
                        inPosition.z += direction.z * t + normal.z;

//						notFirstVoxel = true;
                    }
                }

                db.x = (chunkX + viewSign16.x - position.x) * v3.x;
                db.y = (chunkY + viewSign16.y - position.y) * v3.y;
                db.z = (chunkZ + viewSign16.z - position.z) * v3.z;

                db.x = db.x < 0 ? -db.x : db.x;
                db.y = db.y < 0 ? -db.y : db.y;
                db.z = db.z < 0 ? -db.z : db.z;

                t        = db.x;
                normal.x = viewDirSignOffset.x;
                normal.y = 0;
                normal.z = 0;
                if (db.y < t)
                {
                    t        = db.y;
                    normal.x = 0;
                    normal.y = viewDirSignOffset.y;
                }
                if (db.z < t)
                {
                    t        = db.z;
                    normal.x = 0;
                    normal.y = 0;
                    normal.z = viewDirSignOffset.z;
                }

                position.x += direction.x * t + normal.x;
                position.y += direction.y * t + normal.y;
                position.z += direction.z * t + normal.z;

//				notFirstVoxel = true;
            }
            return(null);
        }
Пример #11
0
        void CheckCommonKeys()
        {
            bool leftAltPressed     = input.GetButton(InputButtonNames.LeftAlt);
            bool leftShiftPressed   = input.GetButton(InputButtonNames.LeftShift);
            bool leftControlPressed = input.GetButton(InputButtonNames.LeftControl);

            bool fire1Clicked = false;
            bool fire2Clicked = false;

            bool overUI = EventSystem.current.IsPointerOverGameObject();

            if (!overUI)
            {
                fire1Clicked = input.GetButtonDown(InputButtonNames.Button1);
                fire2Clicked = input.GetButtonClick(InputButtonNames.Button2);
            }

            if (!leftShiftPressed && !leftAltPressed && !leftControlPressed)
            {
                if (crosshairOnBlock && input.GetButtonClick(InputButtonNames.Button1))
                {
                    env.TriggerVoxelClickEvent(crosshairHitInfo.chunk, crosshairHitInfo.voxelIndex, 0);
                }
                if (fire1Clicked)
                {
                    firePressed = true;
                    if (ModelPreviewCancel())
                    {
                        firePressed          = false;
                        lastHitButtonPressed = Time.time + 0.5f;
                    }
                    if (firePressed && Time.time - lastHitButtonPressed > player.GetHitDelay())
                    {
                        timeSeeking       = Time.time;
                        lastReachDistance = float.MaxValue;
                        if (crosshairHitInfo.item != null)
                        {
                            crosshairHitInfo.item.PickItem();
                            crosshairOnBlock = false;
                            firePressed      = false;
                        }
                        else
                        {
                            DoHit(player.GetHitDamage());
                        }
                    }
                }

                if (fire2Clicked)
                {
                    timeSeeking       = Time.time;
                    lastReachDistance = float.MaxValue;
                    seekTarget        = crosshairHitInfo;
                    // make character approach target if needed
                    seeking = !TargetIsReachable(true);
                    if (seeking)
                    {
                        seekAction = SeekAction.Move;
                    }
                    else
                    {
                        DoBuild(curPos, transform.forward, crosshairHitInfo.voxelCenter);
                    }
                }
            }


            if (input.GetButtonDown(InputButtonNames.Build))
            {
                env.SetBuildMode(!env.buildMode);
                if (env.buildMode)
                {
                    env.ShowMessage("<color=green>Entered <color=yellow>Build Mode</color>. Press <color=white>B</color> to cancel.</color>");
                }
                else
                {
                    env.ShowMessage("<color=green>Back to <color=yellow>Normal Mode</color>.</color>");
                }
            }
            else if (input.GetButtonDown(InputButtonNames.SeeThroughUp))
            {
                env.seeThroughHeightOffset++;
            }
            else if (input.GetButtonDown(InputButtonNames.SeeThroughDown))
            {
                env.seeThroughHeightOffset--;
            }
        }
        void LoadSaveFileFormat_1_0(StringReader sr, bool preservePlayerPosition = false)
        {
            // Character controller transform position
            Vector3 v = DecodeVector3(sr.ReadLine());

            characterController.transform.position = v;
            // Character controller transform rotation
            Vector3 angles = DecodeVector3(sr.ReadLine());

            if (!preservePlayerPosition)
            {
                characterController.transform.rotation = Quaternion.Euler(angles);
            }
            // Character controller's camera local rotation
            angles = DecodeVector3(sr.ReadLine());
            if (!preservePlayerPosition)
            {
                cameraMain.transform.localRotation = Quaternion.Euler(angles);
                // Pass initial rotation to mouseLook script
                characterController.GetComponent <VoxelPlayFirstPersonController>().mouseLook.Init(characterController.transform, cameraMain.transform, null);
            }

            // Read voxel definition table
            InitSaveGameStructs();
            int vdCount = int.Parse(sr.ReadLine());

            for (int k = 0; k < vdCount; k++)
            {
                saveVoxelDefinitionsList.Add(sr.ReadLine());
            }

            // Read chunks
            int chunkX, chunkY, chunkZ;

            while (true)
            {
                string line = sr.ReadLine();
                if (line == null)
                {
                    return;
                }
                // Get chunk position
                Vector3 chunkPosition = DecodeVector3(line);
                GetChunkCoordinates(chunkPosition, out chunkX, out chunkY, out chunkZ);
                VoxelChunk chunk = GetChunkOrCreate(chunkX, chunkY, chunkZ);
                chunk.modified = true;
                ChunkClearFast(chunk);
                line = sr.ReadLine();
                if (line == null)
                {
                    return;
                }
                // Read voxels
                int numWords = int.Parse(line, CultureInfo.InvariantCulture);
                for (int k = 0; k < numWords; k++)
                {
                    line = sr.ReadLine();
                    if (line == null)
                    {
                        return;
                    }
                    string[] wordData = line.Split(LOAD_DATA_SEPARATOR);
                    if (wordData.Length != 3)
                    {
                        continue;
                    }
                    // Voxel definition
                    int             vdIndex         = int.Parse(wordData[0]);
                    VoxelDefinition voxelDefinition = GetVoxelDefinition(saveVoxelDefinitionsList[vdIndex]);
                    if (voxelDefinition == null)
                    {
                        voxelDefinition = defaultVoxel;                         // should not happen
                    }
                    // Voxel index
                    int voxelIndex = int.Parse(wordData[1]);
                    // Repetitions
                    int repetitions = int.Parse(wordData[2]);
                    for (int i = 0; i < repetitions; i++)
                    {
                        chunk.voxels[voxelIndex + i].Set(voxelDefinition, Misc.color32White);
                    }
                    ChunkRequestRefresh(chunk, true, true);
                }
                // Read light sources
                line = sr.ReadLine();
                if (line == null)
                {
                    return;
                }
                int          lightCount = int.Parse(line);
                VoxelHitInfo hitInfo    = new VoxelHitInfo();
                for (int k = 0; k < lightCount; k++)
                {
                    // Voxel index
                    line = sr.ReadLine();
                    if (line == null)
                    {
                        return;
                    }
                    hitInfo.voxelIndex = int.Parse(line);
                    // Voxel center
                    line = sr.ReadLine();
                    if (line == null)
                    {
                        return;
                    }
                    hitInfo.voxelCenter = DecodeVector3(line);
                    // Normal
                    line = sr.ReadLine();
                    if (line == null)
                    {
                        return;
                    }
                    hitInfo.normal = DecodeVector3(line);
                    hitInfo.chunk  = chunk;
                    TorchAttach(hitInfo);
                }
            }
        }
Пример #13
0
        void WriteChunkData1_2(TextWriter sw, VoxelChunk chunk)
        {
            // Chunk position
            sw.WriteLine(chunk.position.x + "," + chunk.position.y + "," + chunk.position.z);
            if (sb == null)
            {
                sb = new StringBuilder();
            }
            else
            {
                sb.Length = 0;
            }
            int k        = 0;
            int numWords = 0;

            // Compute voxels
            while (k < chunk.voxels.Length)
            {
                if (chunk.voxels[k].hasContent == 1)
                {
                    int             voxelIndex      = k;
                    VoxelDefinition voxelDefinition = chunk.voxels[k].type;
                    int             voxelDefinitionIndex;
                    if (!saveVoxelDefinitionsDict.TryGetValue(voxelDefinition, out voxelDefinitionIndex))
                    {
                        continue;
                    }
                    Color32 tintColor  = chunk.voxels[k].color;
                    int     waterLevel = 15;
                    if (voxelDefinition.renderType == RenderType.Water)
                    {
                        waterLevel = chunk.voxels [k].GetWaterLevel();
                    }
                    int repetitions = 1;
                    k++;
                    while (k < chunk.voxels.Length && chunk.voxels[k].type == voxelDefinition && chunk.voxels[k].color.r == tintColor.r && chunk.voxels[k].color.g == tintColor.g && chunk.voxels[k].color.b == tintColor.b && chunk.voxels[k].GetWaterLevel() == waterLevel)
                    {
                        repetitions++;
                        k++;
                    }
                    if (numWords > 0)
                    {
                        sb.AppendLine();
                    }
                    sb.Append(voxelDefinitionIndex);
                    sb.Append(",");
                    sb.Append(tintColor.r);
                    sb.Append(",");
                    sb.Append(tintColor.g);
                    sb.Append(",");
                    sb.Append(tintColor.b);
                    sb.Append(",");
                    sb.Append(voxelIndex);
                    sb.Append(",");
                    sb.Append(repetitions);
                    if (voxelDefinition.renderType == RenderType.Water)
                    {
                        sb.Append(",");
                        sb.Append(waterLevel);
                    }
                    numWords++;
                }
                else
                {
                    k++;
                }
            }

            // Write number of voxels
            sw.WriteLine(numWords);
            if (numWords > 0)
            {
                // Write voxels data
                sw.WriteLine(sb.ToString());
            }

            // Write number of light sources
            int lightCount = chunk.lightSources != null ? chunk.lightSources.Count : 0;

            sb.Length = 0;
            sb.Append(lightCount.ToString());
            if (lightCount > 0)
            {
                for (k = 0; k < lightCount; k++)
                {
                    VoxelHitInfo hi = chunk.lightSources[k].hitInfo;
                    sb.AppendLine();
                    sb.AppendLine(hi.voxelIndex.ToString());
                    sb.Append(hi.voxelCenter.x);
                    sb.Append(",");
                    sb.Append(hi.voxelCenter.y);
                    sb.Append(",");
                    sb.AppendLine(hi.voxelCenter.z.ToString());
                    sb.Append(hi.normal.x);
                    sb.Append(",");
                    sb.Append(hi.normal.y);
                    sb.Append(",");
                    sb.Append(hi.normal.z);
                }
            }
            sw.WriteLine(sb.ToString());
        }
        void ModelPlaceTorches(Vector3 position, ModelDefinition model, int rotationDegrees = 0)
        {
            if (model == null || model.torches == null)
            {
                return;
            }
            FastVector.Floor(ref position);
            Vector3 pos;
            int     modelOneYRow = model.sizeZ * model.sizeX;
            int     modelOneZRow = model.sizeX;
            int     halfSizeX    = model.sizeX / 2;
            int     halfSizeZ    = model.sizeZ / 2;

            if (rotationDegrees == 360)
            {
                switch (UnityEngine.Random.Range(0, 4))
                {
                case 0:
                    rotationDegrees = 90;
                    break;

                case 1:
                    rotationDegrees = 180;
                    break;

                case 2:
                    rotationDegrees = 270;
                    break;
                }
            }

            // ensure all voxel definitions are present
            int tmp;

            for (int b = 0; b < model.torches.Length; b++)
            {
                int     bitIndex = model.torches [b].voxelIndex;
                int     py       = bitIndex / modelOneYRow;
                int     remy     = bitIndex - py * modelOneYRow;
                int     pz       = remy / modelOneZRow;
                int     px       = remy - pz * modelOneZRow;
                Vector3 normal   = model.torches [b].normal;
                switch (rotationDegrees)
                {
                case 90:
                    tmp      = px;
                    px       = halfSizeZ - pz;
                    pz       = halfSizeX - tmp;
                    tmp      = (int)normal.x;
                    normal.x = normal.z;
                    normal.z = -tmp;
                    break;

                case 180:
                    px       = halfSizeX - px;
                    pz       = halfSizeZ - pz;
                    normal.x = -normal.x;
                    normal.z = -normal.z;
                    break;

                case 270:
                    tmp      = px;
                    px       = pz - halfSizeZ;
                    pz       = tmp - halfSizeX;
                    tmp      = (int)normal.x;
                    normal.x = normal.z;
                    normal.z = tmp;
                    break;

                default:
                    px -= halfSizeX;
                    pz -= halfSizeZ;
                    break;
                }

                pos.x = position.x + model.offsetX + px;
                pos.y = position.y + model.offsetY + py;
                pos.z = position.z + model.offsetZ + pz;
                pos  -= normal;

                VoxelChunk   chunk;
                int          voxelIndex;
                VoxelHitInfo hitInfo = new VoxelHitInfo();
                if (GetVoxelIndex(pos, out chunk, out voxelIndex))
                {
                    hitInfo.chunk       = chunk;
                    hitInfo.voxelIndex  = voxelIndex;
                    hitInfo.normal      = normal;
                    hitInfo.voxelCenter = pos + Misc.vector3half;
                    TorchAttach(hitInfo, model.torches [b].itemDefinition, false);
                }
            }
        }