diff --git a/src/SampSharp.GameMode/Events/NPCConnectionEventArgs.cs b/src/SampSharp.GameMode/Events/NPCConnectionEventArgs.cs new file mode 100644 index 000000000..9abf476bc --- /dev/null +++ b/src/SampSharp.GameMode/Events/NPCConnectionEventArgs.cs @@ -0,0 +1,42 @@ +// SampSharp +// Copyright 2017 Tim Potze +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +using SampSharp.GameMode.World; +using System; + +namespace SampSharp.GameMode.Events +{ + /// + /// Provides data for the NPC connection event. + /// + public class NPCConnectionEventArgs : EventArgs + { + /// + /// Initializes a new instance of the NPCConnectionEventArgs class. + /// + /// of the NPC. + public NPCConnectionEventArgs(BasePlayer npcBasePlayer) + { + NPCBasePlayer = npcBasePlayer; + } + + // Not using Player here as we don't delete the object when + // the player fails to connect to the server. + + /// + /// Gets the NPC's trying to connect. + /// + public BasePlayer NPCBasePlayer { get; } + } +} \ No newline at end of file diff --git a/src/SampSharp.GameMode/SAMP/Server.cs b/src/SampSharp.GameMode/SAMP/Server.cs index c43726294..12f53166a 100644 --- a/src/SampSharp.GameMode/SAMP/Server.cs +++ b/src/SampSharp.GameMode/SAMP/Server.cs @@ -160,34 +160,24 @@ public static void SendRconCommand(string command) } /// - /// Connect an NPC to the server. + /// Connects an NPC to the server. /// /// The name the NPC should connect as. Must follow the same rules as normal player names. /// The NPC script name that is located in the npcmodes folder (without the .amx extension). /// - /// An instance of based on the first available player slot. If no slots are available, - /// null. + /// An instance of /// - public static BasePlayer ConnectNPC(string name, string script) + public static NPC ConnectNPC(string name, string script) { - var id = -1; - var max = MaxPlayers; + if (BasePlayer.FindByName(name) != null) + throw new Exception($"The name \"{name}\" is already used in game"); - for (var i = 0; i < max; i++) - if (!ServerInternal.Instance.IsPlayerConnected(i)) - id = i; - - if (id == -1) - return null; - - ServerInternal.Instance.ConnectNPC(name, script); - var result = BasePlayer.FindOrCreate(id); - result.IsNpcOverride = true; - return result; + NPC npc = new NPC(name, script); + return npc; } /// - /// Set the world weather for all players. + /// Sets the world weather for all players. /// /// The weather to set. public static void SetWeather(int weatherid) diff --git a/src/SampSharp.GameMode/World/BasePlayer.cs b/src/SampSharp.GameMode/World/BasePlayer.cs index feaecb644..31132e90c 100644 --- a/src/SampSharp.GameMode/World/BasePlayer.cs +++ b/src/SampSharp.GameMode/World/BasePlayer.cs @@ -58,6 +58,26 @@ public partial class BasePlayer : IdentifiedPool, IWorldObject /// Maximum length of the text in a chat bubble. /// public const int MaxChatBubbleLength = 144; + + /// + /// Finds a from the given + /// + /// The name of the BasePlayer to find + /// The found BasePlayer + public static BasePlayer FindByName(string name) + { + BasePlayer result = null; + for (int i = 0; i < Server.MaxPlayers; i++) + { + if (BasePlayer.Find(i) != null) + { + BasePlayer p = BasePlayer.Find(i); + if (p.Name.Equals(name)) + result = p; + } + } + return result; + } #region Constructors diff --git a/src/SampSharp.GameMode/World/NPC.cs b/src/SampSharp.GameMode/World/NPC.cs new file mode 100644 index 000000000..a17542798 --- /dev/null +++ b/src/SampSharp.GameMode/World/NPC.cs @@ -0,0 +1,75 @@ +// SampSharp +// Copyright 2017 Tim Potze +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +using SampSharp.GameMode.Events; +using System; +using static SampSharp.GameMode.SAMP.Server; + +namespace SampSharp.GameMode.World +{ + /// + /// Represents a SA-MP NPC + /// + public class NPC + { + internal string Name { get; } + + #region Constructors + + /// + /// Initialize a new instance of the class. + /// + /// The name the NPC should connect as. Must follow the same rules as normal player names. + /// The NPC script name that is located in the npcmodes folder (without the .amx extension). + public NPC(string name, string script) + { + this.Name = name; + BaseMode.Instance.PlayerConnected += (p, e) => this.OnNPCConnect(p as BasePlayer); + ServerInternal.Instance.ConnectNPC(name, script); + } + #endregion + + #region Callbacks + + private void OnNPCConnect(BasePlayer p) + { + if(p.Name.Equals(Name) && p.IsNPC) + { + PlayerInstance = p; + Connected?.Invoke(this, new NPCConnectionEventArgs(p)); + } + + } + + #endregion + + #region Properties + + /// + /// The of the NPC + /// + public BasePlayer PlayerInstance { get; set; } + + #endregion + + #region Events + + /// + /// Occurs when the NPC instance has been connected + /// + public event EventHandler Connected; + + #endregion + } +}