예제 #1
0
    // Creates FireVFX on Load
    public override int OnLoad(CastCoord coord, ChunkLoader cl)
    {
        ushort? state = cl.chunks[coord.GetChunkPos()].metadata.GetState(coord.blockX, coord.blockY, coord.blockZ);
        Vector3 fireOffset;

        if (state == 0 || state == 4)
        {
            fireOffset = new Vector3(0.15f, 0f, 0f);
        }
        else if (state == 1 || state == 5)
        {
            fireOffset = new Vector3(0f, 0f, -0.15f);
        }
        else if (state == 2 || state == 6)
        {
            fireOffset = new Vector3(-0.15f, 0f, 0f);
        }
        else if (state == 3 || state == 7)
        {
            fireOffset = new Vector3(0f, 0f, 0.15f);
        }
        else
        {
            fireOffset = new Vector3(0f, 0f, 0f);
        }

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

        fire.name = BuildVFXName(coord.GetChunkPos(), coord.blockX, coord.blockY, coord.blockZ);
        this.vfx.Add(coord.GetChunkPos(), fire, active: true);

        ControlFire(coord.GetChunkPos(), coord.blockX, coord.blockY, coord.blockZ, state);

        return(1);
    }
예제 #2
0
    // Triggers DECAY BUD on this block
    public override void OnBlockUpdate(string type, int myX, int myY, int myZ, int budX, int budY, int budZ, int facing, ChunkLoader cl)
    {
        if (type == "decay")
        {
            CastCoord thisPos = new CastCoord(new Vector3(myX, myY, myZ));

            GetSurroundings(thisPos, this.decayDistance, cl);

            if (!RunLeavesRecursion(cl))
            {
                if (cl.chunks.ContainsKey(thisPos.GetChunkPos()))
                {
                    cl.chunks[thisPos.GetChunkPos()].data.SetCell(thisPos.blockX, thisPos.blockY, thisPos.blockZ, 0);
                    cl.chunks[thisPos.GetChunkPos()].metadata.Reset(thisPos.blockX, thisPos.blockY, thisPos.blockZ);
                    cl.budscheduler.ScheduleReload(thisPos.GetChunkPos(), 0, x: thisPos.blockX, y: thisPos.blockY, z: thisPos.blockZ);
                }

                // Applies Decay BUD to surrounding leaves if this one is invalid
                GetLastSurrounding(thisPos);

                foreach (CastCoord c in cache)
                {
                    EmitBUDTo("decay", c.GetWorldX(), c.GetWorldY(), c.GetWorldZ(), Random.Range(3, 12), cl);
                }
            }

            distances.Clear();
            openList.Clear();
            cache.Clear();
        }
    }
예제 #3
0
    // Triggers DECAY BUD on this block
    public override void OnBlockUpdate(BUDCode type, int myX, int myY, int myZ, int budX, int budY, int budZ, int facing, ChunkLoader_Server cl)
    {
        if (type == BUDCode.DECAY)
        {
            CastCoord thisPos = new CastCoord(new Vector3(myX, myY, myZ));

            GetSurroundings(thisPos, this.decayDistance, cl);

            if (!RunLeavesRecursion(cl))
            {
                if (cl.chunks.ContainsKey(thisPos.GetChunkPos()))
                {
                    cl.chunks[thisPos.GetChunkPos()].data.SetCell(thisPos.blockX, thisPos.blockY, thisPos.blockZ, 0);
                    cl.chunks[thisPos.GetChunkPos()].metadata.Reset(thisPos.blockX, thisPos.blockY, thisPos.blockZ);
                    this.Update(thisPos, BUDCode.BREAK, facing, cl);
                    cl.budscheduler.ScheduleSave(thisPos.GetChunkPos());
                }

                // Applies Decay BUD to surrounding leaves if this one is invalid
                GetLastSurrounding(thisPos);

                foreach (CastCoord c in cache)
                {
                    EmitBUDTo(BUDCode.DECAY, c.GetWorldX(), c.GetWorldY(), c.GetWorldZ(), Random.Range(minDecayTime, maxDecayTime), cl);
                }
            }

            distances.Clear();
            openList.Clear();
            cache.Clear();
        }
    }
예제 #4
0
 // Returns block code of a castcoord
 public ushort GetState(CastCoord c)
 {
     if (this.chunks.ContainsKey(c.GetChunkPos()))
     {
         return(this.chunks[c.GetChunkPos()].metadata.GetState(c.blockX, c.blockY, c.blockZ));
     }
     else
     {
         return((ushort)(ushort.MaxValue / 2)); // Error Code
     }
 }
예제 #5
0
    // Receives Player Information saved on server on startup
    private void SendServerInfo(byte[] data)
    {
        float     x, y, z, xDir, yDir, zDir;
        CastCoord initialCoord;

        x    = NetDecoder.ReadFloat(data, 1);
        y    = NetDecoder.ReadFloat(data, 5);
        z    = NetDecoder.ReadFloat(data, 9);
        xDir = NetDecoder.ReadFloat(data, 13);
        yDir = NetDecoder.ReadFloat(data, 17);
        zDir = NetDecoder.ReadFloat(data, 21);

        this.cl.PLAYERSPAWNED = true;
        this.cl.playerX       = x;
        this.cl.playerY       = y;
        this.cl.playerZ       = z;
        this.cl.playerDirX    = xDir;
        this.cl.playerDirY    = yDir;
        this.cl.playerDirZ    = zDir;

        // Finds current Chunk and sends position data
        initialCoord = new CastCoord(x, y, z);
        this.cl.time.SetCurrentChunkPos(initialCoord.GetChunkPos());
        this.cl.time.SendChunkPosMessage();
    }
예제 #6
0
    // Breaks Torch if broken
    public override void OnBlockUpdate(string type, int x, int y, int z, int budX, int budY, int budZ, int facing, ChunkLoader cl)
    {
        if (facing >= 4)
        {
            return;
        }

        CastCoord aux = new CastCoord(new Vector3(x, y, z));

        if (type == "load")
        {
            this.OnLoad(aux, cl);
        }

        ChunkPos thisPos = aux.GetChunkPos(); //new ChunkPos(Mathf.FloorToInt(x/Chunk.chunkWidth), Mathf.FloorToInt(z/Chunk.chunkWidth));
        int      X       = aux.blockX;        //x%Chunk.chunkWidth;
        int      Y       = aux.blockY;        //y%Chunk.chunkDepth;
        int      Z       = aux.blockZ;        //z%Chunk.chunkWidth;

        aux = new CastCoord(new Vector3(budX, budY, budZ));
        ChunkPos budPos = aux.GetChunkPos(); //new ChunkPos(Mathf.FloorToInt(budX/Chunk.chunkWidth), Mathf.FloorToInt(budZ/Chunk.chunkWidth));
        int      bX     = aux.blockX;        //budX%Chunk.chunkWidth;
        int      bY     = aux.blockY;        //budY%Chunk.chunkDepth;
        int      bZ     = aux.blockZ;        //budZ%Chunk.chunkWidth;

        ushort state = cl.chunks[thisPos].metadata.GetState(X, Y, Z);

        // Breaks Torch if broken attached block
        if (type == "break" && (facing == state || facing + 4 == state))
        {
            cl.chunks[thisPos].data.SetCell(X, Y, Z, 0);
            this.OnBreak(thisPos, X, Y, Z, cl);
            EraseMetadata(thisPos, X, Y, Z, cl);
        }
        // Breaks Torch if changed block is not solid
        else if (type == "change")
        {
            int blockCode = cl.chunks[budPos].data.GetCell(bX, bY, bZ);

            if (blockCode >= 0)
            {
                // If changed block is not solid, break
                if (!cl.blockBook.blocks[blockCode].solid)
                {
                    cl.chunks[thisPos].data.SetCell(X, Y, Z, 0);
                    this.OnBreak(thisPos, X, Y, Z, cl);
                    EraseMetadata(thisPos, X, Y, Z, cl);
                }
            }
            else
            {
                if (!cl.blockBook.objects[ushort.MaxValue - blockCode].solid)
                {
                    cl.chunks[thisPos].data.SetCell(X, Y, Z, 0);
                    this.OnBreak(thisPos, X, Y, Z, cl);
                    EraseMetadata(thisPos, X, Y, Z, cl);
                }
            }
        }
    }
예제 #7
0
    // Creates FireVFX on Load
    public override int OnLoad(CastCoord coord, ChunkLoader_Server cl)
    {
        ushort state = cl.chunks[coord.GetChunkPos()].metadata.GetState(coord.blockX, coord.blockY, coord.blockZ);
        int    facing;

        if (state >= 4)
        {
            facing = state - 4;
        }
        else
        {
            facing = state;
        }

        NetMessage message = new NetMessage(NetCode.VFXDATA);

        message.VFXData(coord.GetChunkPos(), coord.blockX, coord.blockY, coord.blockZ, facing, ushort.MaxValue, state);

        cl.vfx.Add(coord.GetChunkPos(), BuildVFXName(coord.GetChunkPos(), coord.blockX, coord.blockY, coord.blockZ), message);
        cl.server.SendToClients(coord.GetChunkPos(), message);
        return(1);
    }
예제 #8
0
    // Block Placing mechanic
    private bool PlaceBlock(ushort blockCode)
    {
        // Won't happen if not raycasting something or if block is in player's body or head
        if (!current.active || (CastCoord.Eq(lastCoord, playerHead) && loader.blockBook.CheckSolid(blockCode)) || (CastCoord.Eq(lastCoord, playerBody) && loader.blockBook.CheckSolid(blockCode)))
        {
            return(false);
        }

        NetMessage message = new NetMessage(NetCode.DIRECTBLOCKUPDATE);

        message.DirectBlockUpdate(BUDCode.PLACE, lastCoord.GetChunkPos(), lastCoord.blockX, lastCoord.blockY, lastCoord.blockZ, facing, blockCode, ushort.MaxValue, ushort.MaxValue);
        this.loader.client.Send(message.GetMessage(), message.size);
        return(true);
    }
예제 #9
0
    public ulong AddItem(float3 pos, float3 rot, float3 move, ushort itemCode, byte amount, ulong playerCode, ChunkLoader_Server cl)
    {
        CastCoord coord        = new CastCoord(pos);
        ChunkPos  chunk        = coord.GetChunkPos();
        ulong     assignedCode = this.availableDropCodes.Pop();

        if (!this.dropObject.ContainsKey(chunk))
        {
            this.dropObject.Add(chunk, new Dictionary <ulong, DroppedItemAI>());
        }

        this.dropObject[chunk].Add(assignedCode, new DroppedItemAI(pos, rot, move, assignedCode, itemCode, amount, playerCode, this, cl));

        return(assignedCode);
    }
예제 #10
0
    // Block Breaking mechanic
    public void BreakBlock()
    {
        if (!current.active)
        {
            return;
        }

        ChunkPos toUpdate  = new ChunkPos(current.chunkX, current.chunkZ);
        ushort   blockCode = loader.chunks[toUpdate].data.GetCell(current.blockX, current.blockY, current.blockZ);
        ushort   state     = loader.chunks[toUpdate].metadata.GetState(current.blockX, current.blockY, current.blockZ);
        ushort   hp        = loader.chunks[toUpdate].metadata.GetHP(current.blockX, current.blockY, current.blockZ);

        NetMessage message = new NetMessage(NetCode.BLOCKDAMAGE);

        message.BlockDamage(current.GetChunkPos(), current.blockX, current.blockY, current.blockZ, this.blockDamage, false);
        this.loader.client.Send(message.GetMessage(), message.size);
    }
예제 #11
0
    // Triggers Blocktype.OnInteract()
    public void Interact()
    {
        loader.chunks[playerBody.GetChunkPos()].PrintDrawStage();

        if (!current.active)
        {
            return;
        }


        ChunkPos toUpdate  = new ChunkPos(current.chunkX, current.chunkZ);
        int      blockCode = loader.chunks[toUpdate].data.GetCell(current.blockX, current.blockY, current.blockZ);

        NetMessage message = new NetMessage(NetCode.INTERACT);

        message.Interact(toUpdate, current.blockX, current.blockY, current.blockZ, facing);
        this.loader.client.Send(message.GetMessage(), message.size);
    }
예제 #12
0
    // Receives a Drop Item notification and creates the DropItemAI Entity
    private void DropItem(byte[] data, ulong id)
    {
        float3     pos, rot, move;
        ushort     itemCode;
        byte       amount;
        NetMessage message = new NetMessage(NetCode.ITEMENTITYDATA);

        pos      = NetDecoder.ReadFloat3(data, 1);
        rot      = NetDecoder.ReadFloat3(data, 13);
        move     = NetDecoder.ReadFloat3(data, 25);
        itemCode = NetDecoder.ReadUshort(data, 37);
        amount   = data[39];

        CastCoord coord = new CastCoord(pos);
        ChunkPos  cp    = coord.GetChunkPos();

        ulong code = this.entityHandler.AddItem(pos, rot, move, itemCode, amount, id, this.cl);

        message.ItemEntityData(pos.x, pos.y, pos.z, rot.x, rot.y, rot.z, itemCode, amount, code);
        this.SendToClients(cp, message);
    }
예제 #13
0
    // Returns two Voxeldata-like array of blocks and states respectively
    public bool GetField(CastCoord c, int2 radius, ref ushort[] blocks, ref ushort[] states)
    {
        if (!this.chunks.ContainsKey(c.GetChunkPos()))
        {
            return(false);
        }

        int      minX, minZ;
        int      cX, cY, cZ;
        int      minBoundsX, minBoundsY, minBoundsZ;
        ChunkPos pos;
        ChunkPos middleChunk = c.GetChunkPos();

        // Set affected chunks
        minX = ChunkOperation(c.blockX, radius.x, Chunk.chunkWidth);
        minZ = ChunkOperation(c.blockZ, radius.x, Chunk.chunkWidth);

        // Set border chunk bounds
        minBoundsX = NegativeFlip(c.blockX - radius.x, Chunk.chunkWidth);
        minBoundsZ = NegativeFlip(c.blockZ - radius.x, Chunk.chunkWidth);
        minBoundsY = c.blockY - radius.y;

        // Initial Pos
        pos = new ChunkPos(middleChunk.x + minX, middleChunk.z + minZ);
        cX  = minBoundsX;

        for (int x = 0; x < (radius.x * 2 + 1); x++)
        {
            // If X goes to another chunk
            if (cX >= Chunk.chunkWidth)
            {
                pos = new ChunkPos(pos.x + 1, middleChunk.z);
                cX  = 0;
            }
            // If chunk doesn't exist
            if (!this.chunks.ContainsKey(pos))
            {
                cX++;
                continue;
            }
            cY = minBoundsY;
            for (int y = 0; y < (radius.y * 2 + 1); y++)
            {
                cZ = minBoundsZ;
                // Set Y Limits
                if (cY < 0 || cY >= Chunk.chunkDepth)
                {
                    cY++;
                    pos = new ChunkPos(pos.x, middleChunk.z);
                    continue;
                }

                for (int z = 0; z < (radius.x * 2 + 1); z++)
                {
                    // If Z goes to another chunk
                    if (cZ >= Chunk.chunkWidth)
                    {
                        pos = new ChunkPos(pos.x, pos.z + 1);
                        cZ  = 0;
                    }
                    // If chunk doesn't exist
                    if (!this.chunks.ContainsKey(pos))
                    {
                        cZ++;
                        continue;
                    }

                    blocks[x * (radius.x * 2 + 1) * (radius.y * 2 + 1) + y * (radius.x * 2 + 1) + z] = this.chunks[pos].data.GetCell(cX, cY, cZ);
                    states[x * (radius.x * 2 + 1) * (radius.y * 2 + 1) + y * (radius.x * 2 + 1) + z] = this.chunks[pos].metadata.GetState(cX, cY, cZ);
                    cZ++;
                }
                pos = new ChunkPos(pos.x, middleChunk.z);
                cY++;
            }
            cX++;
        }

        return(true);
    }
예제 #14
0
    // Breaks Torch if broken
    public override void OnBlockUpdate(BUDCode type, int x, int y, int z, int budX, int budY, int budZ, int facing, ChunkLoader_Server cl)
    {
        if (facing >= 4)
        {
            return;
        }

        CastCoord aux = new CastCoord(new Vector3(x, y, z));

        if (type == BUDCode.LOAD)
        {
            this.OnLoad(aux, cl);
        }

        ChunkPos thisPos = aux.GetChunkPos(); //new ChunkPos(Mathf.FloorToInt(x/Chunk.chunkWidth), Mathf.FloorToInt(z/Chunk.chunkWidth));
        int      X       = aux.blockX;        //x%Chunk.chunkWidth;
        int      Y       = aux.blockY;        //y%Chunk.chunkDepth;
        int      Z       = aux.blockZ;        //z%Chunk.chunkWidth;

        aux = new CastCoord(new Vector3(budX, budY, budZ));
        ChunkPos budPos = aux.GetChunkPos(); //new ChunkPos(Mathf.FloorToInt(budX/Chunk.chunkWidth), Mathf.FloorToInt(budZ/Chunk.chunkWidth));
        int      bX     = aux.blockX;        //budX%Chunk.chunkWidth;
        int      bY     = aux.blockY;        //budY%Chunk.chunkDepth;
        int      bZ     = aux.blockZ;        //budZ%Chunk.chunkWidth;

        ushort state = cl.chunks[thisPos].metadata.GetState(X, Y, Z);

        // Breaks Torch if broken attached block
        if (type == BUDCode.BREAK && (facing == state || facing + 4 == state))
        {
            cl.chunks[thisPos].data.SetCell(X, Y, Z, 0);
            this.OnBreak(thisPos, X, Y, Z, cl);

            NetMessage message = new NetMessage(NetCode.DIRECTBLOCKUPDATE);
            message.DirectBlockUpdate(BUDCode.BREAK, thisPos, X, Y, Z, facing, ushort.MaxValue, state, 0);
            cl.server.SendToClients(thisPos, message);

            EraseMetadata(thisPos, X, Y, Z, cl);
        }
        // Breaks Torch if changed block is not solid
        else if (type == BUDCode.CHANGE)
        {
            int blockCode = cl.chunks[budPos].data.GetCell(bX, bY, bZ);

            if (blockCode >= 0)
            {
                // If changed block is not solid, break
                if (!cl.blockBook.blocks[blockCode].solid)
                {
                    cl.chunks[thisPos].data.SetCell(X, Y, Z, 0);
                    this.OnBreak(thisPos, X, Y, Z, cl);

                    NetMessage message = new NetMessage(NetCode.DIRECTBLOCKUPDATE);
                    message.DirectBlockUpdate(BUDCode.BREAK, thisPos, X, Y, Z, facing, ushort.MaxValue, state, 0);
                    cl.server.SendToClients(thisPos, message);

                    EraseMetadata(thisPos, X, Y, Z, cl);
                }
            }
            else
            {
                if (!cl.blockBook.objects[ushort.MaxValue - blockCode].solid)
                {
                    cl.chunks[thisPos].data.SetCell(X, Y, Z, 0);
                    this.OnBreak(thisPos, X, Y, Z, cl);

                    NetMessage message = new NetMessage(NetCode.DIRECTBLOCKUPDATE);
                    message.DirectBlockUpdate(BUDCode.BREAK, thisPos, X, Y, Z, facing, ushort.MaxValue, state, 0);
                    cl.server.SendToClients(thisPos, message);

                    EraseMetadata(thisPos, X, Y, Z, cl);
                }
            }
        }
    }
예제 #15
0
    // Sends a direct action BUD to a block
    // ComesFromMessage flag is used to call this function from within the Server Code and not triggered by any message
    private void DirectBlockUpdate(byte[] data, ulong id, bool comesFromMessage = true)
    {
        ChunkPos   pos;
        int        x, y, z, facing;
        ushort     blockCode, state, hp;
        BUDCode    type;
        NetMessage message;

        pos       = NetDecoder.ReadChunkPos(data, 1);
        x         = NetDecoder.ReadInt(data, 9);
        y         = NetDecoder.ReadInt(data, 13);
        z         = NetDecoder.ReadInt(data, 17);
        facing    = NetDecoder.ReadInt(data, 21);
        blockCode = NetDecoder.ReadUshort(data, 25);
        state     = 0;
        hp        = 0;


        if (comesFromMessage)
        {
            state = NetDecoder.ReadUshort(data, 27);
            hp    = NetDecoder.ReadUshort(data, 29);
            type  = (BUDCode)NetDecoder.ReadInt(data, 31);
        }
        else
        {
            type = (BUDCode)NetDecoder.ReadInt(data, 27);
        }

        CastCoord lastCoord = new CastCoord(pos, x, y, z);

        switch (type)
        {
        case BUDCode.PLACE:
            // if chunk is still loaded
            if (this.cl.chunks.ContainsKey(lastCoord.GetChunkPos()))
            {
                // if it's a block
                if (blockCode <= ushort.MaxValue / 2)
                {
                    // if placement rules fail
                    if (!cl.blockBook.blocks[blockCode].PlacementRule(lastCoord.GetChunkPos(), lastCoord.blockX, lastCoord.blockY, lastCoord.blockZ, facing, cl))
                    {
                        NetMessage denied = new NetMessage(NetCode.PLACEMENTDENIED);
                        this.Send(denied.GetMessage(), denied.size, id);
                        return;
                    }
                }
                // if it's an object
                else
                {
                    if (!cl.blockBook.objects[ushort.MaxValue - blockCode].PlacementRule(lastCoord.GetChunkPos(), lastCoord.blockX, lastCoord.blockY, lastCoord.blockZ, facing, cl))
                    {
                        NetMessage denied = new NetMessage(NetCode.PLACEMENTDENIED);
                        this.Send(denied.GetMessage(), denied.size, id);
                        return;
                    }
                }

                // Check if is trying to put block on players
                if (this.playersInChunk.ContainsKey(pos))
                {
                    foreach (ulong code in this.playersInChunk[pos])
                    {
                        if (code == id)
                        {
                            continue;
                        }

                        if (!this.cl.regionHandler.allPlayerData[code].CheckValidPlacement(lastCoord.GetWorldX(), lastCoord.GetWorldY(), lastCoord.GetWorldZ()))
                        {
                            NetMessage denied = new NetMessage(NetCode.PLACEMENTDENIED);
                            this.Send(denied.GetMessage(), denied.size, id);
                            return;
                        }
                    }
                }

                // If doesn't have special place handling
                if (!cl.blockBook.CheckCustomPlace(blockCode))
                {
                    // Actually places block/asset into terrain
                    cl.chunks[lastCoord.GetChunkPos()].data.SetCell(lastCoord.blockX, lastCoord.blockY, lastCoord.blockZ, blockCode);
                    //cl.budscheduler.ScheduleReload(lastCoord.GetChunkPos(), 0);
                    EmitBlockUpdate(BUDCode.CHANGE, lastCoord.GetWorldX(), lastCoord.GetWorldY(), lastCoord.GetWorldZ(), 0, cl);


                    // Applies OnPlace Event
                    if (blockCode <= ushort.MaxValue / 2)
                    {
                        cl.blockBook.blocks[blockCode].OnPlace(lastCoord.GetChunkPos(), lastCoord.blockX, lastCoord.blockY, lastCoord.blockZ, facing, cl);
                    }
                    else
                    {
                        cl.blockBook.objects[ushort.MaxValue - blockCode].OnPlace(lastCoord.GetChunkPos(), lastCoord.blockX, lastCoord.blockY, lastCoord.blockZ, facing, cl);
                    }

                    // Sends the updated voxel to loaded clients
                    message = new NetMessage(NetCode.DIRECTBLOCKUPDATE);
                    message.DirectBlockUpdate(BUDCode.PLACE, lastCoord.GetChunkPos(), lastCoord.blockX, lastCoord.blockY, lastCoord.blockZ, facing, blockCode, this.cl.chunks[lastCoord.GetChunkPos()].metadata.GetState(lastCoord.blockX, lastCoord.blockY, lastCoord.blockZ), this.cl.chunks[lastCoord.GetChunkPos()].metadata.GetHP(lastCoord.blockX, lastCoord.blockY, lastCoord.blockZ));
                    SendToClients(lastCoord.GetChunkPos(), message);

                    this.cl.regionHandler.SaveChunk(this.cl.chunks[pos]);
                }

                // If has special handling
                else
                {
                    // Actually places block/asset into terrain
                    this.cl.chunks[lastCoord.GetChunkPos()].data.SetCell(lastCoord.blockX, lastCoord.blockY, lastCoord.blockZ, blockCode);

                    if (blockCode <= ushort.MaxValue / 2)
                    {
                        cl.blockBook.blocks[blockCode].OnPlace(lastCoord.GetChunkPos(), lastCoord.blockX, lastCoord.blockY, lastCoord.blockZ, facing, cl);
                    }
                    else
                    {
                        cl.blockBook.objects[ushort.MaxValue - blockCode].OnPlace(lastCoord.GetChunkPos(), lastCoord.blockX, lastCoord.blockY, lastCoord.blockZ, facing, cl);
                    }
                }

                // Make entities in this chunk update their TerrainVision
                this.entityHandler.SetRefreshVision(EntityType.DROP, lastCoord.GetChunkPos());
            }
            break;

        case BUDCode.SETSTATE:
            if (this.cl.chunks.ContainsKey(lastCoord.GetChunkPos()))
            {
                this.cl.chunks[lastCoord.GetChunkPos()].metadata.SetState(lastCoord.blockX, lastCoord.blockY, lastCoord.blockZ, blockCode);
                this.entityHandler.SetRefreshVision(EntityType.DROP, lastCoord.GetChunkPos());
            }
            break;

        case BUDCode.BREAK:
            // If doesn't has special break handling
            if (!this.cl.blockBook.CheckCustomBreak(blockCode))
            {
                // Actually breaks new block and updates chunk
                this.cl.chunks[pos].data.SetCell(lastCoord.blockX, lastCoord.blockY, lastCoord.blockZ, 0);
                this.cl.chunks[pos].metadata.Reset(lastCoord.blockX, lastCoord.blockY, lastCoord.blockZ);

                // Triggers OnBreak
                if (blockCode <= ushort.MaxValue / 2)
                {
                    this.cl.blockBook.blocks[blockCode].OnBreak(pos, lastCoord.blockX, lastCoord.blockY, lastCoord.blockZ, this.cl);
                }
                else
                {
                    this.cl.blockBook.objects[ushort.MaxValue - blockCode].OnBreak(pos, lastCoord.blockX, lastCoord.blockY, lastCoord.blockZ, this.cl);
                }

                EmitBlockUpdate(BUDCode.BREAK, lastCoord.GetWorldX(), lastCoord.GetWorldY(), lastCoord.GetWorldZ(), 0, this.cl);
            }
            // If has special break handlings
            else
            {
                if (blockCode <= ushort.MaxValue / 2)
                {
                    this.cl.blockBook.blocks[blockCode].OnBreak(pos, lastCoord.blockX, lastCoord.blockY, lastCoord.blockZ, this.cl);
                }
                else
                {
                    this.cl.blockBook.objects[ushort.MaxValue - blockCode].OnBreak(pos, lastCoord.blockX, lastCoord.blockY, lastCoord.blockZ, this.cl);
                }
            }

            // Sends the updated voxel to loaded clients
            this.entityHandler.SetRefreshVision(EntityType.DROP, lastCoord.GetChunkPos());
            message = new NetMessage(NetCode.DIRECTBLOCKUPDATE);
            message.DirectBlockUpdate(BUDCode.BREAK, lastCoord.GetChunkPos(), lastCoord.blockX, lastCoord.blockY, lastCoord.blockZ, facing, 0, ushort.MaxValue, ushort.MaxValue);
            SendToClients(lastCoord.GetChunkPos(), message);
            this.cl.regionHandler.SaveChunk(this.cl.chunks[pos]);

            break;

        case BUDCode.LOAD:
            // HP is set as the Chunk Coordinates vs World Coordinates flag
            if (hp == ushort.MaxValue)
            {
                lastCoord = new CastCoord(new Vector3(lastCoord.blockX, lastCoord.blockY, lastCoord.blockZ));
            }

            blockCode = this.cl.GetBlock(lastCoord);

            if (this.cl.chunks.ContainsKey(lastCoord.GetChunkPos()))
            {
                if (blockCode <= ushort.MaxValue / 2)
                {
                    this.cl.blockBook.blocks[blockCode].OnLoad(lastCoord, this.cl);
                }
                else
                {
                    this.cl.blockBook.objects[ushort.MaxValue - blockCode].OnLoad(lastCoord, this.cl);
                }
            }
            break;

        default:
            break;
        }
    }
예제 #16
0
    public ChunkPos GetChunkPos()
    {
        CastCoord coord = new CastCoord(this.posX, this.posY, this.posZ);

        return(coord.GetChunkPos());
    }
예제 #17
0
    // Update is called once per frame
    void Update()
    {
        // Gets this Unity Tick time
        this.newTime = schedulerTime.GetBUDTime();

        // Checks if BUD Tick has changed
        if (this.newTime != this.currentTime)
        {
            bool shouldClean = false;

            this.currentDealocTime++;

            // Removes past queues if frame skipped to prevent Memory Leak
            if (currentDealocTime == byte.MaxValue)
            {
                currentDealocTime = 0;

                foreach (string s in this.data.Keys)
                {
                    if (schedulerTime.IsPast(s))
                    {
                        cachedString = s;
                        shouldClean  = true;
                        break;
                    }
                }

                if (shouldClean)
                {
                    shouldClean = false;
                    this.data.Remove(cachedString);
                }
            }

            // Saves the World Data every second
            if (loader.regionHandler != null)
            {
                loader.regionHandler.SaveWorld();
            }

            // Batch Chunk Saver
            if (SaveCount() > 0)
            {
                foreach (ChunkPos pos in this.toSave[this.currentTime])
                {
                    if (loader.chunks.ContainsKey(pos))
                    {
                        loader.regionHandler.SaveChunk(loader.chunks[pos]);
                    }
                }
            }

            this.currentBUDonFrame = 0;

            // Pops all elements of BUD
            if (this.data.ContainsKey(this.currentTime))
            {
                if (this.data[this.currentTime].Count > 0)
                {
                    PassToNextTick();
                }
            }

            // Frees memory of previous BUD Tick
            this.data.Remove(this.currentTime);
            this.toSave.Remove(this.currentTime);
            this.currentTime = this.newTime;
        }

        // Iterates through frame's list and triggers BUD
        if (DataCount() > 0)
        {
            for (currentBUDonFrame = 0; currentBUDonFrame < BUDperFrame; currentBUDonFrame++)
            {
                if (this.data[this.currentTime].Count > 0)
                {
                    cachedCoord = new CastCoord(new Vector3(this.data[this.currentTime][0].x, this.data[this.currentTime][0].y, this.data[this.currentTime][0].z));

                    // If BUDSignal is still in the loaded area
                    if (loader.chunks.ContainsKey(cachedCoord.GetChunkPos()))
                    {
                        cachedCode = loader.chunks[cachedCoord.GetChunkPos()].data.GetCell(cachedCoord.blockX, cachedCoord.blockY, cachedCoord.blockZ);

                        if (cachedCode <= ushort.MaxValue / 2)
                        {
                            loader.blockBook.blocks[cachedCode].OnBlockUpdate(this.data[this.currentTime][0].type, this.data[this.currentTime][0].x, this.data[this.currentTime][0].y, this.data[this.currentTime][0].z, this.data[this.currentTime][0].budX, this.data[this.currentTime][0].budY, this.data[this.currentTime][0].budZ, this.data[this.currentTime][0].facing, loader);
                        }
                        else
                        {
                            loader.blockBook.objects[ushort.MaxValue - cachedCode].OnBlockUpdate(this.data[this.currentTime][0].type, this.data[this.currentTime][0].x, this.data[this.currentTime][0].y, this.data[this.currentTime][0].z, this.data[this.currentTime][0].budX, this.data[this.currentTime][0].budY, this.data[this.currentTime][0].budZ, this.data[this.currentTime][0].facing, loader);
                        }
                    }

                    this.data[this.currentTime].RemoveAt(0);
                }
                else
                {
                    break;
                }
            }
        }
    }
예제 #18
0
 // Sends a DirectBlockUpdate call to users
 public void Update(CastCoord c, BUDCode type, int facing, ChunkLoader_Server cl)
 {
     this.reloadMessage = new NetMessage(NetCode.DIRECTBLOCKUPDATE);
     this.reloadMessage.DirectBlockUpdate(type, c.GetChunkPos(), c.blockX, c.blockY, c.blockZ, facing, 0, cl.GetState(c), ushort.MaxValue);
     cl.server.SendToClients(c.GetChunkPos(), this.reloadMessage);
 }