예제 #1
0
    // Deletes the connection between a client and a chunk
    private void RequestChunkUnload(byte[] data, ulong id)
    {
        ChunkPos   pos         = NetDecoder.ReadChunkPos(data, 1);
        NetMessage killMessage = new NetMessage(NetCode.ENTITYDELETE);

        if (this.playersInChunk.ContainsKey(pos))
        {
            foreach (ulong code in this.playersInChunk[pos])
            {
                if (code == id)
                {
                    continue;
                }

                this.connectionGraph[code].Remove(id);

                killMessage.EntityDelete(EntityType.PLAYER, code);
                this.Send(killMessage.GetMessage(), killMessage.size, id);
            }
        }

        if (this.entityHandler.Contains(EntityType.DROP, pos))
        {
            foreach (ulong itemCode in this.entityHandler.dropObject[pos].Keys)
            {
                killMessage.EntityDelete(EntityType.DROP, itemCode);
                this.Send(killMessage.GetMessage(), killMessage.size, id);
            }
        }

        this.cl.UnloadChunk(pos, id);
    }
예제 #2
0
    public void SendChunkPosMessage()
    {
        NetMessage message = new NetMessage(NetCode.CLIENTCHUNK);

        message.ClientChunk(this.lastPos, this.currentPos);
        this.client.Send(message.GetMessage(), message.size);
    }
예제 #3
0
        /// <summary>
        /// Receives a chat message.
        /// </summary>
        /// <returns>The chat message.</returns>
        public static string receiveChatMessage()
        {
            string colorFrom     = "CCCCFF";
            string returnMessage = "";

            // the time out is set to 10ms because we are going to pass here very often
            if (ConnexionUtils.host.Service(10, out ConnexionUtils.@event))
            {
                if (ENet.EventType.Receive == [email protected])
                {
                    Debug.Log("Reception d'un message");
                    Debug.Log("Message reçu sur le channel " + @event.ChannelID);

                    NetMessage messageReceived = NetMessage.GetRootAsNetMessage(new ByteBuffer(@event.Packet.GetBytes()));
                    if (messageReceived.MessageType == NetID.Chat)
                    {
                        Chat mesChat = new Chat();
                        mesChat = (Chat)messageReceived.GetMessage(mesChat);
                        Debug.Log("message de chat de " + mesChat.From + " : " + mesChat.Message);
                        if (mesChat.From == userName)
                        {
                            colorFrom = "FF8585";
                        }
                        returnMessage = "<b><color=#" + colorFrom + ">" + mesChat.From + ": " + "</color></b>" + mesChat.Message;
                    }
                }
            }
            else
            {
                Debug.LogError("Pas de message (pas de reception après 10ms)");
            }
            return(returnMessage);
        }
예제 #4
0
    private void InitWorld()
    {
        this.regionHandler = new RegionFileHandler(this);
        worldSeed          = regionHandler.GetRealSeed();
        biomeHandler       = new BiomeHandler();
        this.worldGen      = new WorldGenerator(worldSeed, biomeHandler, structHandler, this);
        biomeHandler.SetWorldGenerator(this.worldGen);

        print("Initializing World");

        // Sends the first player it's information
        PlayerData pdat      = this.regionHandler.LoadPlayer(this.server.firstConnectedID); // CHANGE TO OTHER ACCOUNTID
        Vector3    playerPos = pdat.GetPosition();
        Vector3    playerDir = pdat.GetDirection();

        pdat.SetOnline(true);

        this.regionHandler.InitDataFiles(new ChunkPos((int)(playerPos.x / Chunk.chunkWidth), (int)(playerPos.z / Chunk.chunkWidth)));

        HandleServerCommunication();
        NetMessage message = new NetMessage(NetCode.SENDSERVERINFO);

        message.SendServerInfo(playerPos.x, playerPos.y, playerPos.z, playerDir.x, playerDir.y, playerDir.z);
        this.server.Send(message.GetMessage(), message.size, this.server.firstConnectedID);
        this.INITIALIZEDWORLD = true;
        this.time.SetLock(false);
    }
예제 #5
0
    // Receives player position and adds it to PlayerPositions Dict
    private void ClientPlayerPosition(byte[] data, ulong id)
    {
        float3     pos, dir;
        ChunkPos   cp;
        NetMessage graphMessage = new NetMessage(NetCode.PLAYERDATA);

        pos = NetDecoder.ReadFloat3(data, 1);
        dir = NetDecoder.ReadFloat3(data, 13);

        this.cl.regionHandler.allPlayerData[id].SetPosition(pos.x, pos.y, pos.z);
        this.cl.regionHandler.allPlayerData[id].SetDirection(dir.x, dir.y, dir.z);

        cp = this.cl.regionHandler.allPlayerData[id].GetChunkPos();

        if (!this.entityHandler.Contains(EntityType.PLAYER, cp, id))
        {
            this.entityHandler.AddPlayer(cp, id, pos, dir);
        }

        this.entityHandler.SetPosition(EntityType.PLAYER, id, cp, pos);
        this.entityHandler.SetRotation(EntityType.PLAYER, id, cp, dir);


        // Propagates data to all network
        foreach (ulong code in this.connectionGraph[id])
        {
            graphMessage.PlayerData(this.cl.regionHandler.allPlayerData[id]);
            this.Send(graphMessage.GetMessage(), graphMessage.size, code);
        }
    }
예제 #6
0
    // Callback for connections received
    private void ConnectCallback(IAsyncResult result)
    {
        Socket client        = this.masterSocket.EndAccept(result);
        ulong  temporaryCode = GetCurrentCode();

        this.temporaryConnections[temporaryCode] = client;
        this.lengthPacket[temporaryCode]         = true;
        this.packetIndex[temporaryCode]          = 0;
        this.receiveBuffer[temporaryCode]        = new byte[receiveBufferSize];

        Debug.Log(client.RemoteEndPoint.ToString() + " has connected with temporary ID " + temporaryCode);

        // Check if there's trash in the network then flush it
        if (client.Available > 0)
        {
            Debug.Log("Removed trash from: " + temporaryCode);
            client.Receive(this.receiveBuffer[temporaryCode], client.Available, 0);
        }

        NetMessage message = new NetMessage(NetCode.ACCEPTEDCONNECT);

        this.Send(message.GetMessage(), message.size, temporaryCode, temporary: true);

        this.temporaryConnections[temporaryCode].BeginReceive(this.receiveBuffer[temporaryCode], 0, 4, 0, out this.err, new AsyncCallback(ReceiveCallback), temporaryCode);
        this.masterSocket.BeginAccept(new AsyncCallback(ConnectCallback), null);
    }
예제 #7
0
    // Captures client info
    private void SendClientInfo(byte[] data, ulong id)
    {
        NetMessage message        = new NetMessage(NetCode.SENDSERVERINFO);
        ulong      accountID      = NetDecoder.ReadUlong(data, 1);
        int        renderDistance = NetDecoder.ReadInt(data, 9);
        int        seed           = NetDecoder.ReadInt(data, 13);
        int        stringSize     = NetDecoder.ReadInt(data, 17);
        string     worldName      = NetDecoder.ReadString(data, 21, stringSize);

        playerRenderDistances[accountID] = renderDistance;

        if (this.isLocal)
        {
            World.worldName = worldName;
            World.worldSeed = seed;
        }

        // Sends Player Info
        if (this.cl.RECEIVEDWORLDDATA)
        {
            PlayerData pdat = this.cl.regionHandler.LoadPlayer(accountID);
            pdat.SetOnline(true);
            Vector3 playerPos = pdat.GetPosition();
            Vector3 playerDir = pdat.GetDirection();
            message.SendServerInfo(playerPos.x, playerPos.y, playerPos.z, playerDir.x, playerDir.y, playerDir.z);
            this.Send(message.GetMessage(), message.size, id, temporary: true);
        }

        // If AccountID is already online, erase all memory from that connection
        if (this.connections.ContainsKey(accountID))
        {
            Disconnect(accountID, DisconnectType.LOGINOVERWRITE);
        }

        // Assigns a fixed ID
        this.connections.Add(accountID, this.temporaryConnections[id]);
        this.temporaryConnections.Remove(id);

        this.lengthPacket[accountID] = true;
        this.packetIndex[accountID]  = 0;
        this.connectionGraph.Add(accountID, new HashSet <ulong>());

        this.receiveBuffer.Add(accountID, new byte[receiveBufferSize]);
        this.receiveBuffer.Remove(id);

        this.cl.RECEIVEDWORLDDATA = true;

        if (this.firstConnectedID == ulong.MaxValue)
        {
            this.firstConnectedID = accountID;
        }

        this.timeoutTimers.Add(accountID, DateTime.Now);

        Debug.Log("Temporary ID: " + id + " was assigned to ID: " + accountID);

        this.connections[accountID].BeginReceive(this.receiveBuffer[accountID], 0, 4, 0, out this.err, new AsyncCallback(ReceiveCallback), accountID);
    }
예제 #8
0
    // Receives a failed request notification from server and immediately re-tries
    private void FailedChunkRequest(byte[] data)
    {
        ChunkPos pos = NetDecoder.ReadChunkPos(data, 1);

        NetMessage message = new NetMessage(NetCode.REQUESTCHUNKLOAD);

        message.RequestChunkLoad(pos);
        this.Send(message.GetMessage(), message.size);
    }
예제 #9
0
        private static void DataAvailable(NetworkStream s)
        {
            var b = new byte[NetMessage.MS_LENGTH];

            s.Read(b, 0, b.Length);
            var ms   = NetMessage.GetMessage(b);
            var data = Connection.ReadString(s);

            processMessage(ms, data);
        }
예제 #10
0
        private static void processBuffer(byte[] readStream)
        {
            if (readStream.Length < NetMessage.MS_LENGTH)
            {
                return;
            }
            var head = NetMessage.SubArray(readStream, 0, NetMessage.MS_LENGTH);
            var ms   = NetMessage.GetMessage(head);

            processMessage(ms, Encoding.Unicode.GetString(NetMessage.SubArray(readStream, NetMessage.MS_LENGTH, readStream.Length - NetMessage.MS_LENGTH)));
        }
예제 #11
0
    /*
     * // Auxiliary Functions
     */

    // Send input message to all Clients connected to a given Chunk
    public void SendToClients(ChunkPos pos, NetMessage message)
    {
        if (!this.cl.loadedChunks.ContainsKey(pos))
        {
            return;
        }

        foreach (ulong i in this.cl.loadedChunks[pos])
        {
            this.Send(message.GetMessage(), message.size, i);
        }
    }
예제 #12
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);
    }
예제 #13
0
    // Send input message to all Clients connected to a given Chunk except the given one
    public void SendToClientsExcept(ChunkPos pos, NetMessage message, ulong exception)
    {
        if (!this.cl.loadedChunks.ContainsKey(pos))
        {
            return;
        }

        foreach (ulong i in this.cl.loadedChunks[pos])
        {
            if (i == exception)
            {
                continue;
            }
            this.Send(message.GetMessage(), message.size, i);
        }
    }
예제 #14
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);
    }
예제 #15
0
    // Sends chunk information to all requesting clients
    private void SendChunkToRequestingClients(ChunkPos pos)
    {
        NetMessage message;

        // If there was no request for this chunk yet
        if (!this.loadedChunks.ContainsKey(pos))
        {
            return;
        }

        foreach (ulong id in this.loadedChunks[pos])
        {
            message = new NetMessage(NetCode.SENDCHUNK);
            message.SendChunk(this.chunks[pos]);
            this.server.Send(message.GetMessage(), message.size, id);
        }
    }
예제 #16
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);
    }
예제 #17
0
    public void OnDrop()
    {
        if (playerEvents.hotbar.GetSlot(PlayerEvents.hotbarSlot) == null)
        {
            return;
        }

        ItemID    id = playerEvents.hotbar.GetSlot(PlayerEvents.hotbarSlot).GetID();
        ItemStack its;
        byte      amount;

        if (!MainControllerManager.ctrl)
        {
            if (playerEvents.hotbar.GetSlot(PlayerEvents.hotbarSlot).Decrement())
            {
                playerEvents.hotbar.SetNull(PlayerEvents.hotbarSlot);
            }

            amount = 1;
            its    = new ItemStack(id, amount);
        }
        else
        {
            amount = playerEvents.hotbar.GetSlot(PlayerEvents.hotbarSlot).GetAmount();
            playerEvents.hotbar.SetNull(PlayerEvents.hotbarSlot);

            its = new ItemStack(id, amount);
        }


        Vector3 force = this.playerCamera.forward / 5f;

        NetMessage message = new NetMessage(NetCode.DROPITEM);

        message.DropItem(this.playerCamera.position.x, this.playerCamera.position.y, this.playerCamera.position.z, this.playerCamera.rotation.x, this.playerCamera.rotation.y, this.playerCamera.rotation.z, force.x, force.y, force.z, (ushort)id, amount);
        this.cl.client.Send(message.GetMessage(), message.size);

        playerEvents.DrawHotbarSlot(PlayerEvents.hotbarSlot);
        playerEvents.DrawItemEntity(playerEvents.hotbar.GetSlot(PlayerEvents.hotbarSlot));
        playerEvents.invUIPlayer.DrawSlot(1, PlayerEvents.hotbarSlot);
    }
예제 #18
0
    // Gets chunk information to player
    private void RequestChunkLoad(byte[] data, ulong id)
    {
        ChunkPos pos = NetDecoder.ReadChunkPos(data, 1);

        // If is loaded
        if (this.cl.chunks.ContainsKey(pos) && this.cl.chunks[pos].needsGeneration == 0)
        {
            if (!this.cl.loadedChunks.ContainsKey(pos))
            {
                this.cl.loadedChunks.Add(pos, new HashSet <ulong>());
            }

            if (!this.cl.loadedChunks[pos].Contains(id))
            {
                this.cl.loadedChunks[pos].Add(id);
            }

            NetMessage message = new NetMessage(NetCode.SENDCHUNK);
            message.SendChunk(this.cl.chunks[pos]);

            this.Send(message.GetMessage(), message.size, id);
        }
        else
        {
            // If it's not loaded yet
            if (!this.cl.toLoad.Contains(pos))
            {
                this.cl.toLoad.Add(pos);
            }

            NetMessage message = new NetMessage(NetCode.FAILEDCHUNKREQUEST);
            message.FailedChunkRequest(pos);
            this.Send(message.GetMessage(), message.size, id);

            return;
        }

        NetMessage playerMessage = new NetMessage(NetCode.PLAYERDATA);

        // Sends logged in players data
        if (this.playersInChunk.ContainsKey(pos))
        {
            foreach (ulong code in this.playersInChunk[pos])
            {
                if (code == id)
                {
                    continue;
                }
                if (this.cl.regionHandler.allPlayerData[code].IsOnline())
                {
                    this.connectionGraph[code].Add(id);
                    playerMessage.PlayerData(this.cl.regionHandler.allPlayerData[code]);
                    this.Send(playerMessage.GetMessage(), playerMessage.size, id);
                }
            }
        }

        NetMessage itemMessage = new NetMessage(NetCode.ITEMENTITYDATA);

        // Connects new Dropped items to player
        if (this.entityHandler.Contains(EntityType.DROP, pos))
        {
            foreach (ulong itemCode in this.entityHandler.dropObject[pos].Keys)
            {
                itemMessage.ItemEntityData(this.entityHandler.dropObject[pos][itemCode].position.x, this.entityHandler.dropObject[pos][itemCode].position.y, this.entityHandler.dropObject[pos][itemCode].position.z, this.entityHandler.dropObject[pos][itemCode].rotation.x, this.entityHandler.dropObject[pos][itemCode].rotation.y, this.entityHandler.dropObject[pos][itemCode].rotation.z, (ushort)this.entityHandler.dropObject[pos][itemCode].its.GetID(), this.entityHandler.dropObject[pos][itemCode].its.GetAmount(), itemCode);
            }
        }
    }
예제 #19
0
 partial void ImplGetMessage(int length, ref NetMessage message)
 {
     message = NetMessage.GetMessage(length);
 }
예제 #20
0
 partial void ImplRoomGetMessage(int size, ref NetMessage msg)
 {
     msg = NetMessage.GetMessage(size);
 }
예제 #21
0
        partial void ImplRoomRead()
        {
            if (PlayerServer == null)
            {
                return;
            }

            var messages = m_messages;

            _lastRoomFrameSize = PlayerServer.ReadMessages(messages);

// ReSharper disable once ForCanBeConvertedToForeach
            for (int i = 0; i < messages.Count; i++)
            {
                var msg              = NetMessage.GetMessage(messages[i].Data.Length);
                var msgType          = messages[i].MessageType;
                var method           = messages[i].DeliveryMethod;
                var senderConnection = messages[i].SenderConnection;
                messages[i].Clone(msg);
                msg.Sender = senderConnection;
                PlayerServer.Recycle(messages[i]);

                if (msgType == NetIncomingMessageType.Data)
                {
                    var sender = GetPlayer(senderConnection);
                    sender.ConsumeData(msg);
                }
                else if (msgType == NetIncomingMessageType.DebugMessage)
                {
                    Debug.Log(msg.ReadString());
                }
                else if (msgType == NetIncomingMessageType.WarningMessage)
                {
                    Debug.LogWarning(msg.ReadString());
                }
                else if (msgType == NetIncomingMessageType.ConnectionLatencyUpdated)
                {
                    var latency = msg.ReadFloat();
                    //todo: do something with this latency.
                }
                else if (msgType == NetIncomingMessageType.ErrorMessage)
                {
                    Debug.LogError(msg.ReadString());
                }
                else if (msgType == NetIncomingMessageType.ConnectionApproval)
                {
                    var player = ConstructNetData != null ? new Player(this, ConstructNetData()) : new Player(this);
                    player.Connection    = senderConnection;
                    senderConnection.Tag = player;
                    if (_players.Count > Configuration.MaximumPlayers)
                    {
                        senderConnection.Deny(DtoPMsgs.NoRoom);
                    }
                    else
                    {
                        Guid token;
                        if (msg.ReadGuid(out token))
                        {
                            VerifyPlayerConnecting(player, token);
                        }
                        else
                        {
                            senderConnection.Deny(DtoPMsgs.BadToken);
                        }
                    }
                }
                else if (msgType == NetIncomingMessageType.StatusChanged)
                {
                    var status       = (NetConnectionStatus)msg.ReadByte();
                    var statusReason = msg.ReadString();
                    Debug.Log($"ServerStatus for {status}: {statusReason}, {senderConnection}");

                    if (status == NetConnectionStatus.Connected)
                    {
                        AddPlayer(senderConnection);
                    }
                    else if (status == NetConnectionStatus.Disconnected)
                    {
                        RemovePlayer(senderConnection);
                    }
                }
                else if (msgType == NetIncomingMessageType.Error)
                {
                    Debug.LogException(new Exception(msg.ReadString())
                    {
                        Source = "Room.Lidgren.IplementationQueueRead [Lidgren PlayerServer Error]"
                    });                                                                                                                               //this should really never happen...
                }
                else
                {
                    Debug.LogWarning($"Uknown message type {msgType} from player {senderConnection}");
                }

                NetMessage.RecycleMessage(msg);
            }
            messages.Clear();
            VerifyWaitingPlayers();
        }
예제 #22
0
    // Receives a disconnect call from client
    private void Disconnect(ulong id, DisconnectType type)
    {
        if (!this.connections.ContainsKey(id))
        {
            return;
        }

        List <ChunkPos> toRemove    = new List <ChunkPos>();
        NetMessage      killMessage = new NetMessage(NetCode.ENTITYDELETE);

        killMessage.EntityDelete(EntityType.PLAYER, id);

        // Captures and removes all chunks
        foreach (KeyValuePair <ChunkPos, HashSet <ulong> > item in this.cl.loadedChunks)
        {
            if (this.cl.loadedChunks[item.Key].Contains(id))
            {
                toRemove.Add(item.Key);
            }
        }

        foreach (ChunkPos pos in toRemove)
        {
            this.cl.UnloadChunk(pos, id);
        }

        this.connections[id].Close();
        this.connections.Remove(id);
        this.timeoutTimers.Remove(id);
        this.lengthPacket.Remove(id);
        this.dataBuffer.Remove(id);
        this.packetIndex.Remove(id);
        this.packetSize.Remove(id);
        this.playerRenderDistances.Remove(id);
        this.connectionGraph.Remove(id);
        this.receiveBuffer.Remove(id);

        this.entityHandler.Remove(EntityType.PLAYER, this.cl.regionHandler.allPlayerData[id].GetChunkPos(), id);

        foreach (ulong code in this.cl.regionHandler.allPlayerData.Keys)
        {
            if (code == id)
            {
                continue;
            }
            // If iterates through non-online user
            if (!this.cl.regionHandler.allPlayerData[code].IsOnline())
            {
                continue;
            }
            // If finds connection to it, erase
            if (this.connectionGraph[code].Contains(id))
            {
                this.connectionGraph[code].Remove(id);
                this.Send(killMessage.GetMessage(), killMessage.size, code);
            }
        }

        this.cl.regionHandler.SavePlayers();
        this.cl.regionHandler.allPlayerData[id].SetOnline(false);

        if (this.playersInChunk.ContainsKey(this.cl.regionHandler.allPlayerData[id].GetChunkPos()))
        {
            if (this.playersInChunk[this.cl.regionHandler.allPlayerData[id].GetChunkPos()].Count > 1)
            {
                this.playersInChunk[this.cl.regionHandler.allPlayerData[id].GetChunkPos()].Remove(id);
            }
            else
            {
                this.playersInChunk.Remove(this.cl.regionHandler.allPlayerData[id].GetChunkPos());
            }
        }

        if (type == DisconnectType.QUIT)
        {
            Debug.Log("ID: " + id + " has disconnected");
        }
        else if (type == DisconnectType.LOSTCONNECTION)
        {
            Debug.Log("ID: " + id + " has lost connection");
        }
        else if (type == DisconnectType.TIMEDOUT)
        {
            Debug.Log("ID: " + id + " has timed out");
        }
        else if (type == DisconnectType.LOGINOVERWRITE)
        {
            Debug.Log("ID: " + id + " has overwritten it's login");
        }
        else
        {
            Debug.Log("ID: " + id + " has quit due to unknown issue");
        }

        if (this.isLocal)
        {
            Application.Quit();
        }
    }
예제 #23
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;
        }
    }
예제 #24
0
    // Receives the client's current chunk and finds the connections it has with other players
    private void ClientChunk(byte[] data, ulong id)
    {
        ChunkPos lastPos = NetDecoder.ReadChunkPos(data, 1);
        ChunkPos newPos  = NetDecoder.ReadChunkPos(data, 9);

        // Removes last ChunkPos if exists
        if (lastPos != newPos)
        {
            if (this.playersInChunk.ContainsKey(lastPos))
            {
                if (this.playersInChunk[lastPos].Count > 1)
                {
                    this.playersInChunk[lastPos].Remove(id);
                }
                else
                {
                    this.playersInChunk.Remove(lastPos);
                }

                if (this.entityHandler.Contains(EntityType.PLAYER, lastPos, id))
                {
                    this.entityHandler.Remove(EntityType.PLAYER, lastPos, id);
                }
            }
        }

        // Add new ChunkPos
        if (!this.playersInChunk.ContainsKey(newPos))
        {
            this.playersInChunk.Add(newPos, new HashSet <ulong>()
            {
                id
            });
        }
        else
        {
            this.playersInChunk[newPos].Add(id);
        }

        // Finds the connections
        ChunkPos   targetPos;
        NetMessage killMessage = new NetMessage(NetCode.ENTITYDELETE);

        foreach (ulong code in this.cl.regionHandler.allPlayerData.Keys)
        {
            // If iterates through itself
            if (code == id)
            {
                continue;
            }
            // If iterates through non-online user
            if (!this.cl.regionHandler.allPlayerData[code].IsOnline())
            {
                continue;
            }

            // Check if code should still be connected
            if (this.connectionGraph[id].Contains(code))
            {
                targetPos = this.cl.regionHandler.allPlayerData[code].GetChunkPos();
                if (!this.cl.loadedChunks.ContainsKey(newPos))
                {
                    this.cl.loadedChunks.Add(newPos, new HashSet <ulong>());
                }
                if (!this.cl.loadedChunks[newPos].Contains(code))
                {
                    this.connectionGraph[id].Remove(code);
                    killMessage.EntityDelete(EntityType.PLAYER, id);
                    this.Send(killMessage.GetMessage(), killMessage.size, code);
                }
            }
            // Check if code should be connected
            else
            {
                if (!this.cl.loadedChunks.ContainsKey(newPos))
                {
                    this.cl.loadedChunks.Add(newPos, new HashSet <ulong>());
                }

                if (this.cl.loadedChunks[newPos].Contains(code))
                {
                    NetMessage liveMessage = new NetMessage(NetCode.PLAYERDATA);

                    this.connectionGraph[id].Add(code);
                    liveMessage.PlayerData(this.cl.regionHandler.allPlayerData[id]);
                    this.Send(liveMessage.GetMessage(), liveMessage.size, code);
                }
            }
        }
    }
예제 #25
0
 protected internal override NetMessage GetMessage(int size)
 {
     return(NetMessage.GetMessage(size));
 }
예제 #26
0
        protected internal override void ReadQueue()
        {
            if (DispatchClient == null)
            {
                return;
            }

            var messages = new List <NetIncomingMessage>(_lastQueueSize * 2);

            _lastQueueSize = DispatchClient.ReadMessages(messages);
            // ReSharper disable once ForCanBeConvertedToForeach
            for (int i = 0; i < messages.Count; i++)
            {
                var msgType = messages[i].MessageType;
                var msg     = NetMessage.GetMessage(messages[i].Data.Length);
                messages[i].Clone(msg);
                msg.Sender = messages[i].SenderConnection;
                DispatchClient.Recycle(messages[i]);

                if (msgType == NetIncomingMessageType.Data)
                {
                    ConsumeData(msg);
                }
                else if (msgType == NetIncomingMessageType.DebugMessage)
                {
                    Debug.Log(msg.ReadString());
                }
                else if (msgType == NetIncomingMessageType.WarningMessage)
                {
                    var str = msg.ReadString();
                    if (!str.StartsWith("Received unhandled library message Acknowledge"))
                    {
                        Debug.LogWarning(str);
                    }
                }
                else if (msgType == NetIncomingMessageType.StatusChanged)
                {
                    var status       = (NetConnectionStatus)msg.ReadByte();
                    var statusReason = msg.ReadString();
                    if (status == NetConnectionStatus.Connected)
                    {
                        var serverConn = DispatchClient.ServerConnection;
                        if (serverConn == null)
                        {
                            throw new NullReferenceException("Could not get server connection after connected");
                        }
                        var remsg = serverConn.RemoteHailMessage;
                        if (remsg == null)
                        {
                            throw new NullReferenceException("Could not get room guid");
                        }
                        if (!remsg.ReadBytes(16, out var gid))
                        {
                            throw new Exception("Could not read room guid");
                        }

                        Connected(new Guid(gid), serverConn);
                    }
                    else if (status == NetConnectionStatus.Disconnected)
                    {
                        Disconnected();
                    }
                    else
                    {
                        Debug.Log($"DConn ServerStatus: {status}, {statusReason}");
                    }
                    UpdateConnectionStatus(status.ToPNet());
                }
                else if (msgType == NetIncomingMessageType.Error)
                {
                    Debug.LogException(new Exception(msg.ReadString())
                    {
                        Source = "Room.Lidgren.ImplementationQueueRead [Lidgren DispatchClient Error]"
                    });                                                                                                                                     //this should really never happen...
                }
                else
                {
                    Debug.LogWarning($"Unknown message type {msgType} from server");
                }

                NetMessage.RecycleMessage(msg);
            }
        }
        partial void ImplDispatchRead()
        {
            if (DispatchClient == null)
            {
                return;
            }

            var messages = m_messages;

            _lastDispatchSize = DispatchClient.ReadMessages(messages);
            // ReSharper disable once ForCanBeConvertedToForeach
            for (int i = 0; i < messages.Count; i++)
            {
                var msgType = messages[i].MessageType;
                var msg     = NetMessage.GetMessage(messages[i].Data.Length);
                messages[i].Clone(msg);
                msg.Sender = messages[i].SenderConnection;
                DispatchClient.Recycle(messages[i]);

                if (msgType == NetIncomingMessageType.Data)
                {
                    if (Server != null)
                    {
                        Server.ConsumeData(msg);
                    }
                    else
                    {
                        Debug.LogWarning("Received server data when not connected");
                    }
                }
                else if (msgType == NetIncomingMessageType.DebugMessage)
                {
                    Debug.Log(msg.ReadString());
                }
                else if (msgType == NetIncomingMessageType.WarningMessage)
                {
                    var str = msg.ReadString();
                    if (!str.StartsWith("Received unhandled library message Acknowledge"))
                    {
                        Debug.LogWarning(str);
                    }
                }
                else if (msgType == NetIncomingMessageType.StatusChanged)
                {
                    var status       = (NetConnectionStatus)msg.ReadByte();
                    var statusReason = msg.ReadString();
                    if (status == NetConnectionStatus.Connected)
                    {
                        var serverConn = DispatchClient.ServerConnection;
                        if (serverConn == null)
                        {
                            throw new NullReferenceException("Could not get server connection after connected");
                        }
                        var remsg = serverConn.RemoteHailMessage;
                        if (remsg == null)
                        {
                            throw new NullReferenceException("Could not get room guid");
                        }
                        byte[] gid;
                        if (!remsg.ReadBytes(16, out gid))
                        {
                            throw new Exception("Could not read room guid");
                        }
                        RoomId = new Guid(gid);
                        Debug.Log($"Connected to dispatcher. Id is {RoomId}");
                        Server = new Server(this)
                        {
                            Connection = serverConn
                        };
                    }
                    else if (status == NetConnectionStatus.Disconnected)
                    {
                        Server = null;
                        RoomId = Guid.Empty;
                        Debug.Log("Disconnected from dispatcher");
                    }
                    else
                    {
                        Debug.Log($"DConn ServerStatus: {status}, {statusReason}");
                    }
                    ServerStatus = status.ToPNet();
                    ServerStatusChanged?.Invoke();
                }
                else if (msgType == NetIncomingMessageType.Error)
                {
                    Debug.LogException(new Exception(msg.ReadString())
                    {
                        Source = "Room.Lidgren.ImplementationQueueRead [Lidgren DispatchClient Error]"
                    });                                                                                                                                     //this should really never happen...
                }
                else
                {
                    Debug.LogWarning($"Unknown message type {msgType} from server");
                }

                NetMessage.RecycleMessage(msg);
            }
            messages.Clear();
        }
 partial void ImplServerGetMessage(int size, ref NetMessage msg)
 {
     msg = NetMessage.GetMessage(size);
 }
예제 #29
0
    void Update()
    {
        if (!this.LOCKTIME && !isClient)
        {
            // If there are no players in the server, don't run
            if (this.server.connections.Count == 0)
            {
                return;
            }

            ticks     += Time.deltaTime * TimeOfDay.tickRate;
            faketicks += Time.deltaTime;

            if (ticks >= TimeOfDay.ticksForMinute)
            {
                ticks = 0f;
                minutes++;
                this.SENDTIMEFLAG = true;
                this.CHECKTIMEOUT = true;
            }

            if (minutes >= 60)
            {
                minutes = 0;
                hours++;
            }

            if (hours >= 24)
            {
                hours = 0;
                days++;
            }

            // If server, sends time update to client
            if (this.SENDTIMEFLAG && !this.isClient)
            {
                NetMessage message = new NetMessage(NetCode.SENDGAMETIME);
                message.SendGameTime(this.days, this.hours, this.minutes);
                this.server.SendAll(message.GetMessage(), message.size);

                this.SENDTIMEFLAG = false;
            }

            // If server, checks for timeouts
            if (this.CHECKTIMEOUT && !this.isClient)
            {
                this.server.CheckTimeout();
                this.CHECKTIMEOUT = false;
            }

            if (faketicks >= TimeOfDay.timeRate)
            {
                if (this.server != null)
                {
                    this.server.entityHandler.RunEntities();
                }
                faketicks = 0f;
            }
        }
        else if (isClient)
        {
            faketicks += Time.deltaTime;

            if (faketicks >= TimeOfDay.timeRate)
            {
                SendPlayerPosition();
                faketicks = 0f;
            }
        }
    }
예제 #30
0
        private void RoomCallback(object peer)
        {
            var netPeer = peer as NetServer;

            if (netPeer == null)
            {
                return;
            }

            var lmsg = netPeer.ReadMessage();

            var msgType = lmsg.MessageType;
            var sender  = lmsg.SenderEndPoint;
            var sConn   = lmsg.SenderConnection;
            var seq     = lmsg.SequenceChannel;
            var msg     = NetMessage.GetMessage(lmsg.Data.Length);

            lmsg.Clone(msg);
            msg.Sender = lmsg.SenderConnection;
            netPeer.Recycle(lmsg);

            if (msgType == NetIncomingMessageType.Data)
            {
                var room = GetRoom(sConn);
                if (room != null)
                {
                    room.ConsumeData(msg);
                }
                else
                {
                    Debug.LogError($"Unknown room {sender} sent {msg.LengthBytes} bytes of data");
                    sConn.Disconnect(DtoRMsgs.UnknownRoom);
                }
            }
            else if (msgType == NetIncomingMessageType.DebugMessage)
            {
                Debug.Log(msg.ReadString());
            }
            else if (msgType == NetIncomingMessageType.ConnectionApproval)
            {
                LidgrenApproveRoomConnection(sConn, sender, msg);
            }
            else if (msgType == NetIncomingMessageType.StatusChanged)
            {
                var status       = (NetConnectionStatus)msg.ReadByte();
                var statusReason = msg.ReadString();

                if (status == NetConnectionStatus.Connected)
                {
                    var room = sConn.Tag as Room;
                    if (room == null)
                    {
                        throw new NullReferenceException("A connection joined from " + sConn + ", but it did not have a room set in the Tag property");
                    }

                    AddRoom(room);
                    UpdateRoomsOfNewRoom(room);

                    Debug.Log($"Room connected: {room.RoomId} - {sender} @ {room.Address}");
                }
                else if (status == NetConnectionStatus.Disconnecting || status == NetConnectionStatus.Disconnected)
                {
                    var oldRoom = GetRoom(sConn);
                    if (oldRoom != null)
                    {
                        RemoveRoom(oldRoom);
                        sConn.Tag = null;

                        //todo: move all players in the room to a new room.
                    }
                }

                Debug.Log($"Room status: {status}, {statusReason}");
            }
            else if (msgType == NetIncomingMessageType.WarningMessage)
            {
                Debug.LogWarning(msg.ReadString());
            }
            else if (msgType == NetIncomingMessageType.Error)
            {
                Debug.LogException(new Exception(msg.ReadString())
                {
                    Source = "Server.Lidgren.RoomCallback [Errored Lidgren Message]"
                });                                                                                                                    //this should really never happen...
            }

            NetMessage.RecycleMessage(msg);
        }