internal static void InitializeTypes() { var Instances = new SortedList <string, NetworkedEntity>(); foreach (Type t in GameServer.Instance.GetType().Assembly.GetTypes()) { if (t.IsSubclassOf(typeof(NetworkedEntity)) && !t.IsAbstract) { ConstructorInfo c = t.GetConstructor(Type.EmptyTypes); if (c != null) { NetworkedEntity ent = c.Invoke(Type.EmptyTypes) as NetworkedEntity; if (Instances.ContainsKey(ent.NetworkedType)) { Console.Error.WriteLine("Duplicate network type detected - {1} and {2} both use the same NetworkedType: {0}", ent.NetworkedType, c.DeclaringType.Name, Instances[ent.NetworkedType].GetType().Name); } else { Instances.Add(ent.NetworkedType, ent); } } } } NetworkTableHash = GetNetworkTableHash(Instances.Values); }
protected virtual bool Initialize() { Console.WriteLine("Initializing..."); NetworkedEntity.InitializeTypes(); if (IsMultiplayer) { Networking = new ServerNetworking(NetworkPort, IsDedicated ? MaxClients : (MaxClients - 1)); Networking.Connected += (o, e) => { RemoteClient.Create(e.Connection); Console.WriteLine("Remote hail: " + e.Connection.RemoteHailMessage); }; Networking.Disconnected += (o, e) => { long id = e.Connection.UniqueID; bool deliberate = true; // true means disconnected, false means timed out ClientDisconnected(Client.GetByID(id), deliberate); Client.AllClients.Remove(id); }; } return(true); }
private void SendSnapshot() { OutboundMessage m = OutboundMessage.CreateUnreliable((byte)EngineMessage.Snapshot); m.Write(GameServer.Instance.CurrentTick); // now step through all entities, decide what to send. Will either be: // No change (sends nothing) // New entity / full update of entity (Full) // Partial update of entity (Partial) // Forget about this entity (Delete) // ID reassigned, full update of new entity (Replace) foreach (Entity e in Entity.AllEntities) { if (!e.IsNetworked) { continue; } NetworkedEntity ne = e as NetworkedEntity; if (ne.IsDeleted || !ne.HasChanges(this)) { continue; } if (!ne.ShouldSendToClient(this)) { if (KnownEntities.ContainsKey(ne.EntityID)) { DeletedEntities.Add(ne.EntityID, false); // the client shouldn't see this entity any more, so delete it on their end } continue; } m.Write(ne.EntityID); EntitySnapshotType updateType; if (KnownEntities.ContainsKey(ne.EntityID)) { if (DeletedEntities.ContainsKey(ne.EntityID)) { // Reusing an entity ID the client is still using for something else. Ensure it knows the old should be deleted. // Also, don't include it on the Delete list - the Replace accounts for that. updateType = EntitySnapshotType.Replace; DeletedEntities.Remove(ne.EntityID); } else { updateType = NeedsFullUpdate ? EntitySnapshotType.Full : EntitySnapshotType.Partial; } } else { updateType = EntitySnapshotType.Full; KnownEntities[ne.EntityID] = true; } m.Write((byte)updateType); ne.WriteSnapshot(m, this, updateType == EntitySnapshotType.Partial); } foreach (ushort entityID in DeletedEntities.Keys) { m.Write(entityID); m.Write((byte)EntitySnapshotType.Delete); KnownEntities.Remove(entityID); } DeletedEntities.Clear(); Send(m); NeedsFullUpdate = false; }