// 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); }
public void SendChunkPosMessage() { NetMessage message = new NetMessage(NetCode.CLIENTCHUNK); message.ClientChunk(this.lastPos, this.currentPos); this.client.Send(message.GetMessage(), message.size); }
/// <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); }
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); }
// 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); } }
// 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); }
// 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); }
// 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); }
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); }
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))); }
/* * // 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); } }
// 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); }
// 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); } }
// 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); }
// 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); } }
// 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); }
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); }
// 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); } } }
partial void ImplGetMessage(int length, ref NetMessage message) { message = NetMessage.GetMessage(length); }
partial void ImplRoomGetMessage(int size, ref NetMessage msg) { msg = NetMessage.GetMessage(size); }
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(); }
// 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(); } }
// 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; } }
// 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); } } } }
protected internal override NetMessage GetMessage(int size) { return(NetMessage.GetMessage(size)); }
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); }
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; } } }
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); }