From 8ca94a1dcfabcad47d27598b515a2b2a889d6d0d Mon Sep 17 00:00:00 2001 From: LastExceed Date: Sun, 30 Sep 2018 09:20:06 +0200 Subject: [PATCH 01/18] introduce events part1 --- Server/{Addon => Extensions}/AntiCheat.cs | 47 +++++---- Server/Extensions/ChatCommands.cs | 84 +++++++++++++++ Server/Extensions/Extensions.cs | 12 +++ Server/Extensions/Pvp.cs | 19 ++++ Server/Extensions/Tombstones.cs | 45 +++++++++ Server/Server.cs | 118 ++-------------------- Server/Server_Events.cs | 28 +++++ 7 files changed, 227 insertions(+), 126 deletions(-) rename Server/{Addon => Extensions}/AntiCheat.cs (68%) create mode 100644 Server/Extensions/ChatCommands.cs create mode 100644 Server/Extensions/Extensions.cs create mode 100644 Server/Extensions/Pvp.cs create mode 100644 Server/Extensions/Tombstones.cs create mode 100644 Server/Server_Events.cs diff --git a/Server/Addon/AntiCheat.cs b/Server/Extensions/AntiCheat.cs similarity index 68% rename from Server/Addon/AntiCheat.cs rename to Server/Extensions/AntiCheat.cs index d3c707c..4684778 100644 --- a/Server/Addon/AntiCheat.cs +++ b/Server/Extensions/AntiCheat.cs @@ -1,17 +1,31 @@ using Resources; using Resources.Packet; +using System; +using System.Collections.Generic; +using System.Text; -namespace Server.Addon { - class AntiCheat { - public static string Inspect(EntityUpdate current, EntityUpdate previous) { +namespace Server.Extensions { + public static class AntiCheat { + public static void Init() { + Server.EntityUpdated += That; + } + + private static void That(EntityUpdate entityUpdate, Player player) { + string ACmessage = Inspect(entityUpdate, player.entity); + if (ACmessage != null) { + Server.Kick(player, ACmessage); + } + } + + private static string Inspect(EntityUpdate current, EntityUpdate previous) { if (current.guid != previous.guid) { return "guid"; } if (current.hostility != null && current.hostility != 0) { return "hostility"; } - if(current.appearance != null) { - if((current.appearance.character_size.x != 0.8000000119f && current.appearance.character_size.x != 0.9600000381f && current.appearance.character_size.x != 1.039999962f) || + if (current.appearance != null) { + if ((current.appearance.character_size.x != 0.8000000119f && current.appearance.character_size.x != 0.9600000381f && current.appearance.character_size.x != 1.039999962f) || (current.appearance.character_size.y != 0.8000000119f && current.appearance.character_size.y != 0.9600000381f && current.appearance.character_size.y != 1.039999962f) || (current.appearance.character_size.z != 1.799999952f && current.appearance.character_size.z != 2.160000086f && current.appearance.character_size.z != 2.339999914f) || (current.appearance.head_size != 0.8999999762f && current.appearance.head_size != 1.00999999f) || @@ -26,13 +40,13 @@ public static string Inspect(EntityUpdate current, EntityUpdate previous) { return "appearance"; } } - if(current.charge != null && current.charge > 1){ //(current.MP ?? previous.MP)) { + if (current.charge != null && current.charge > 1) { //(current.MP ?? previous.MP)) { return "MP charge"; } - if(current.HP != null && current.HP > 3333) { + if (current.HP != null && current.HP > 3333) { return "HP"; } - if(current.MP != null && current.MP > 1) { + if (current.MP != null && current.MP > 1) { return "MP"; } //if(current.multipliers != null) { @@ -44,27 +58,27 @@ public static string Inspect(EntityUpdate current, EntityUpdate previous) { // return "multipliers"; // } //} - if(current.level != null && current.level > 500) { + if (current.level != null && current.level > 500) { return "level"; } - if(current.consumable != null) { - if(current.consumable.type == ItemType.Food && + if (current.consumable != null) { + if (current.consumable.type == ItemType.Food && current.consumable.subtype == 1 || current.consumable.level > 647 || current.consumable.rarity != 0) { //return "consumable"; } } - if(current.equipment != null) { - foreach(Item item in current.equipment) { - if(item.type != 0 && + if (current.equipment != null) { + foreach (Item item in current.equipment) { + if (item.type != 0 && (item.level > 647 || (byte)item.rarity > 4)) { return "equipment"; } } } - if(current.skillDistribution != null) { - if(current.skillDistribution.petmaster + + if (current.skillDistribution != null) { + if (current.skillDistribution.petmaster + current.skillDistribution.petriding + current.skillDistribution.sailing + current.skillDistribution.climbing + @@ -82,4 +96,3 @@ public static string Inspect(EntityUpdate current, EntityUpdate previous) { } } } -//block diff --git a/Server/Extensions/ChatCommands.cs b/Server/Extensions/ChatCommands.cs new file mode 100644 index 0000000..bbaa26f --- /dev/null +++ b/Server/Extensions/ChatCommands.cs @@ -0,0 +1,84 @@ +using Resources; +using Resources.Datagram; +using Resources.Packet; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Server.Extensions { + public static class ChatCommands { + public static void Init() { + Server.ChatMessageReceived += ParseAsCommand; + } + + private static void ParseAsCommand(string message, Player source) { + if (!message.StartsWith("/")) { + return; + } + var parameters = message.Substring(1).Split(" "); + var command = parameters[0].ToLower(); + switch (command) { + case "kick": + case "btfo": + case "ban": + #region ban + if (source.entity.name != "BLACKROCK") { + Server.Notify(source, "no permission"); + break; + } + if (parameters.Length == 1) { + Server.Notify(source, string.Format("usage example: /kick blackrock")); + break; + } + var target = Server.players.FirstOrDefault(x => x.entity.name.Contains(parameters[1])); + if (target == null) { + Server.Notify(source, "invalid target"); + break; + }; + var reason = "no reason specified"; + if (parameters.Length > 2) { + reason = parameters[2]; + } + if (command == "kick") { + Server.Kick(target, reason); + break; + } + target.writer.Write((byte)ServerPacketID.BTFO); + target.writer.Write(reason); + if (command == "ban") { + Server.Database.BanUser(target.entity.name, (int)target.IP.Address, target.MAC, reason); + } + Server.RemovePlayerEntity(target, false); + break; + #endregion + case "bleeding": + + break; + case "time": + #region time + if (parameters.Length == 1) { + Server.Notify(source, string.Format("usage example: /time 12:00")); + break; + } + var clock = parameters[1].Split(":"); + if (clock.Length < 2 || + !int.TryParse(clock[0], out int hour) || + !int.TryParse(clock[1], out int minute)) { + Server.Notify(source, string.Format("invalid syntax")); + break; + } + var inGameTime = new InGameTime() { + Milliseconds = (hour * 60 + minute) * 60000, + }; + Server.SendUDP(inGameTime.data, source); + break; + #endregion + default: + Server.Notify(source, string.Format("unknown command '{0}'", parameters[0])); + break; + } + break; + } + } +} diff --git a/Server/Extensions/Extensions.cs b/Server/Extensions/Extensions.cs new file mode 100644 index 0000000..c15b1be --- /dev/null +++ b/Server/Extensions/Extensions.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Server.Extensions { + public static class Extensions { + public static void Init() { + AntiCheat.Init(); + Pvp.Init(); + } + } +} diff --git a/Server/Extensions/Pvp.cs b/Server/Extensions/Pvp.cs new file mode 100644 index 0000000..77f7440 --- /dev/null +++ b/Server/Extensions/Pvp.cs @@ -0,0 +1,19 @@ +using Resources; +using Resources.Packet; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Server.Extensions { + public static class Pvp { + public static void Init() { + Server.EntityUpdated += EnableFriendlyFireFlag; + } + + private static void EnableFriendlyFireFlag(EntityUpdate entityUpdate, Player player) { + entityUpdate.entityFlags |= 1 << 5; + + + } + } +} diff --git a/Server/Extensions/Tombstones.cs b/Server/Extensions/Tombstones.cs new file mode 100644 index 0000000..6b6d664 --- /dev/null +++ b/Server/Extensions/Tombstones.cs @@ -0,0 +1,45 @@ +using Resources; +using Resources.Datagram; +using Resources.Packet; +using Resources.Utilities; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Server.Extensions { + public static class Tombstones { + public static void Init() { + Server.EntityUpdated += SpawnTomb; + } + + private static void SpawnTomb(EntityUpdate entityUpdate, Player player) { + if (entityUpdate.HP <= 0 && (player.entity.HP > 0 || player.entity.HP == null)) { + var tombstone = new EntityUpdate() { + guid = Server.AssignGuid(), + position = entityUpdate.position ?? player.entity.position, + hostility = Hostility.Neutral, + entityType = EntityType.None, + appearance = new EntityUpdate.Appearance() { + character_size = new FloatVector() { + x = 1, + y = 1, + z = 1, + }, + head_model = 2155, + head_size = 1 + }, + HP = 100, + name = "tombstone" + }; + player.tomb = (ushort)tombstone.guid; + Server.BroadcastUDP(tombstone.CreateDatagram()); + } + else if (player.entity.HP <= 0 && entityUpdate.HP > 0 && player.tomb != null) { + var rde = new RemoveDynamicEntity() { + Guid = (ushort)player.tomb, + }; + Server.BroadcastUDP(rde.data); + } + } + } +} diff --git a/Server/Server.cs b/Server/Server.cs index 92772fa..168fc37 100644 --- a/Server/Server.cs +++ b/Server/Server.cs @@ -17,7 +17,7 @@ using Resources.Utilities; namespace Server { - public static class Server { + public static partial class Server { public static UdpClient udpClient; public static TcpListener tcpListener; public static List players = new List(); @@ -242,47 +242,7 @@ private static void ProcessDatagram(byte[] datagram, Player source) { case DatagramID.DynamicUpdate: #region entityUpdate var entityUpdate = new EntityUpdate(datagram); - #region antiCheat - string ACmessage = AntiCheat.Inspect(entityUpdate, source.entity); - if (ACmessage != null) Kick(source, ACmessage); - #endregion - #region announce - if (entityUpdate.name != null) { - //Announce.Join(entityUpdate.name, player.entityData.name, players); - } - #endregion - #region pvp - entityUpdate.entityFlags |= 1 << 5; //enable friendly fire flag for pvp - #endregion - #region tombstone - if (entityUpdate.HP <= 0 && (source.entity.HP > 0 || source.entity.HP == null)) { - var tombstone = new EntityUpdate() { - guid = AssignGuid(), - position = entityUpdate.position ?? source.entity.position, - hostility = Hostility.Neutral, - entityType = EntityType.None, - appearance = new EntityUpdate.Appearance() { - character_size = new FloatVector() { - x = 1, - y = 1, - z = 1, - }, - head_model = 2155, - head_size = 1 - }, - HP = 100, - name = "tombstone" - }; - source.tomb = (ushort)tombstone.guid; - BroadcastUDP(tombstone.CreateDatagram()); - } - else if (source.entity.HP <= 0 && entityUpdate.HP > 0 && source.tomb != null) { - var rde = new RemoveDynamicEntity() { - Guid = (ushort)source.tomb, - }; - BroadcastUDP(rde.data); - } - #endregion + EntityUpdated(entityUpdate, source); entityUpdate.Merge(source.entity); BroadcastUDP(entityUpdate.CreateDatagram(), source); break; @@ -290,6 +250,7 @@ private static void ProcessDatagram(byte[] datagram, Player source) { case DatagramID.Attack: #region attack var attack = new Attack(datagram); + EntityAttacked(attack, source); source.lastTarget = attack.Target; var target = players.FirstOrDefault(p => p.entity?.guid == attack.Target); if (target != null) SendUDP(attack.data, target); @@ -298,105 +259,44 @@ private static void ProcessDatagram(byte[] datagram, Player source) { case DatagramID.Projectile: #region Projectile var projectile = new Projectile(datagram); + ProjectileCreated(projectile, source); BroadcastUDP(projectile.data, source); //pass to all players except source break; #endregion case DatagramID.Proc: #region proc var proc = new Proc(datagram); + PassiveProcced(proc, source); BroadcastUDP(proc.data, source); //pass to all players except source break; #endregion case DatagramID.Chat: #region chat var chat = new Chat(datagram); - - if (chat.Text.StartsWith("/")) { - var parameters = chat.Text.Substring(1).Split(" "); - var command = parameters[0].ToLower(); - switch (command) { - case "kick": - case "btfo": - case "ban": - #region ban - if (source.entity.name != "BLACKROCK") { - Notify(source, "no permission"); - break; - } - if (parameters.Length == 1) { - Notify(source, string.Format("usage example: /kick blackrock")); - break; - } - target = players.FirstOrDefault(x => x.entity.name.Contains(parameters[1])); - if (target == null) { - Notify(source, "invalid target"); - break; - }; - var reason = "no reason specified"; - if (parameters.Length > 2) { - reason = parameters[2]; - } - if (command == "kick") { - Kick(target, reason); - break; - } - target.writer.Write((byte)ServerPacketID.BTFO); - target.writer.Write(reason); - if (command == "ban") { - Database.BanUser(target.entity.name, (int)target.IP.Address, target.MAC, reason); - } - RemovePlayerEntity(target, false); - break; - #endregion - case "bleeding": - - break; - case "time": - #region time - if (parameters.Length == 1) { - Notify(source, string.Format("usage example: /time 12:00")); - break; - } - var clock = parameters[1].Split(":"); - if (clock.Length < 2 || - !int.TryParse(clock[0], out int hour) || - !int.TryParse(clock[1], out int minute)) { - Notify(source, string.Format("invalid syntax")); - break; - } - var inGameTime = new InGameTime() { - Milliseconds = (hour * 60 + minute) * 60000, - }; - SendUDP(inGameTime.data, source); - break; - #endregion - default: - Notify(source, string.Format("unknown command '{0}'", parameters[0])); - break; - } - break; - } + ChatMessageReceived(chat.Text, source); Log.Print(dynamicEntities[chat.Sender].name + ": ", ConsoleColor.Cyan); Log.PrintLn(chat.Text, ConsoleColor.White, false); - BroadcastUDP(chat.data, null); //pass to all players break; #endregion case DatagramID.Interaction: #region interaction var interaction = new Interaction(datagram); + EntityInteracted(interaction, source); BroadcastUDP(interaction.data, source); //pass to all players except source break; #endregion case DatagramID.RemoveDynamicEntity: #region removeDynamicEntity var remove = new RemoveDynamicEntity(datagram); + EntityRemoved(remove, source); RemovePlayerEntity(source, true); break; #endregion case DatagramID.SpecialMove: #region specialMove var specialMove = new SpecialMove(datagram); + SpecialMoveUsed(specialMove, source); switch (specialMove.Id) { case SpecialMoveID.Taunt: target = players.FirstOrDefault(p => p.entity.guid == specialMove.Guid); diff --git a/Server/Server_Events.cs b/Server/Server_Events.cs new file mode 100644 index 0000000..e474318 --- /dev/null +++ b/Server/Server_Events.cs @@ -0,0 +1,28 @@ +using Resources; +using Resources.Datagram; +using Resources.Packet; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Server { + public delegate void EntityUpdatedEventHandler(EntityUpdate entityUpdate, Player source); + public delegate void EntityAttackedEventHandler(Attack datagram, Player source); + public delegate void ProjectileCreatedEventHandler(Projectile datagram, Player source); + public delegate void PassiveProccedEventHandler(Proc datagram, Player source); + public delegate void ChatMessageReceivedEventHandler(string message, Player source); + public delegate void EntityInteractedEventHandler(Interaction datagram, Player source); + public delegate void EntityRemovedEventHandler(RemoveDynamicEntity datagram, Player source); + public delegate void SpecialMoveUsedEventHandler(SpecialMove datagram, Player source); + + public static partial class Server { + public static event EntityUpdatedEventHandler EntityUpdated; + public static event EntityAttackedEventHandler EntityAttacked; + public static event ProjectileCreatedEventHandler ProjectileCreated; + public static event PassiveProccedEventHandler PassiveProcced; + public static event ChatMessageReceivedEventHandler ChatMessageReceived; + public static event EntityInteractedEventHandler EntityInteracted; + public static event EntityRemovedEventHandler EntityRemoved; + public static event SpecialMoveUsedEventHandler SpecialMoveUsed; + } +} From 38f8eeb84dc24987c7d41aff429d0ccdcb34cdb3 Mon Sep 17 00:00:00 2001 From: LastExceed Date: Sun, 30 Sep 2018 10:42:23 +0200 Subject: [PATCH 02/18] introduce events part2 --- Server/Extensions/ChatCommands.cs | 3 +- Server/Extensions/Extensions.cs | 2 + Server/Extensions/Models.cs | 83 +++++++++++++++++++++++ Server/Extensions/SpecialMoves.cs | 40 +++++++++++ Server/Server.cs | 106 ++---------------------------- 5 files changed, 133 insertions(+), 101 deletions(-) create mode 100644 Server/Extensions/Models.cs create mode 100644 Server/Extensions/SpecialMoves.cs diff --git a/Server/Extensions/ChatCommands.cs b/Server/Extensions/ChatCommands.cs index bbaa26f..65adc21 100644 --- a/Server/Extensions/ChatCommands.cs +++ b/Server/Extensions/ChatCommands.cs @@ -47,7 +47,7 @@ private static void ParseAsCommand(string message, Player source) { target.writer.Write((byte)ServerPacketID.BTFO); target.writer.Write(reason); if (command == "ban") { - Server.Database.BanUser(target.entity.name, (int)target.IP.Address, target.MAC, reason); + Server.userDatabase.BanUser(target.entity.name, (int)target.IP.Address, target.MAC, reason); } Server.RemovePlayerEntity(target, false); break; @@ -78,7 +78,6 @@ private static void ParseAsCommand(string message, Player source) { Server.Notify(source, string.Format("unknown command '{0}'", parameters[0])); break; } - break; } } } diff --git a/Server/Extensions/Extensions.cs b/Server/Extensions/Extensions.cs index c15b1be..f15bad9 100644 --- a/Server/Extensions/Extensions.cs +++ b/Server/Extensions/Extensions.cs @@ -7,6 +7,8 @@ public static class Extensions { public static void Init() { AntiCheat.Init(); Pvp.Init(); + ChatCommands.Init(); + SpecialMoves.Init(); } } } diff --git a/Server/Extensions/Models.cs b/Server/Extensions/Models.cs new file mode 100644 index 0000000..51e9357 --- /dev/null +++ b/Server/Extensions/Models.cs @@ -0,0 +1,83 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Server.Extensions { + public static class Models { + public static void Init() { + + } + + private static void Placeholder() { + #region models + //var rnd = new Random(); + //for (int i = 8286946; i < 8286946 + 512; i++) { + // for (int j = 8344456; j < 8344456 + 512; j++) { + // var block = new ServerUpdate.BlockDelta() { + // color = new Resources.Utilities.ByteVector() { + // x = 0, + // y = 0, + // z = (byte)rnd.Next(0, 255), + // }, + // type = BlockType.solid, + // position = new Resources.Utilities.IntVector() { + // x = i, + // y = j, + // z = 208, + // }, + // }; + // worldUpdate.blockDeltas.Add(block); + // } + //} + //x = 543093329157, + //y = 546862296355, + //z = 14423162 + //ZoxModel model = JsonConvert.DeserializeObject(File.ReadAllText("models/Fulcnix_exceedspawn.zox")); + //model.Parse(worldUpdate, 8286883, 8344394, 200); + //model = JsonConvert.DeserializeObject(File.ReadAllText("models/Aster_Tavern2.zox")); + //model.Parse(worldUpdate, 8287010, 8344432, 200); + //model = JsonConvert.DeserializeObject(File.ReadAllText("models/Aster_Tavern1.zox")); + //model.Parse(worldUpdate, 8286919, 8344315, 212); + //model = JsonConvert.DeserializeObject(File.ReadAllText("models/arena/aster_arena.zox")); + //model.Parse(worldUpdate, 8286775, 8344392, 207); + //model = JsonConvert.DeserializeObject(File.ReadAllText("models/michael_project1.zox")); + //model.Parse(worldUpdate, 8286898, 8344375, 213); + //model = JsonConvert.DeserializeObject(File.ReadAllText("models/arena/fulcnix_hall.zox")); + //model.Parse(worldUpdate, 8286885, 8344505, 208); + //model = JsonConvert.DeserializeObject(File.ReadAllText("models/arena/fulcnix_hall.zox")); + //model.Parse(worldUpdate, 8286885, 8344629, 208); + //model = JsonConvert.DeserializeObject(File.ReadAllText("models/Tiecz_MountainArena.zox")); + //model.Parse(worldUpdate, 8286885, 8344759, 208); + ////8397006, 8396937, 127 //near spawn + //model = JsonConvert.DeserializeObject(File.ReadAllText("models/Aster_CloudyDay11.zox")); + //model.Parse(worldUpdate, 8286770, 8344262, 207); + //model = JsonConvert.DeserializeObject(File.ReadAllText("models/Aster_CloudyDay12.zox")); + //model.Parse(worldUpdate, 8286770, 8344136, 207); + //model = JsonConvert.DeserializeObject(File.ReadAllText("models/Aster_CloudyDay13.zox")); + //model.Parse(worldUpdate, 8286770, 8344010, 207); + //model = JsonConvert.DeserializeObject(File.ReadAllText("models/Aster_CloudyDay14.zox")); + //model.Parse(worldUpdate, 8286770, 8344010, 333); + //model = JsonConvert.DeserializeObject(File.ReadAllText("models/Aster_CloudyDay01.zox")); + //model.Parse(worldUpdate, 8286644, 8344010, 333); + //model = JsonConvert.DeserializeObject(File.ReadAllText("models/Aster_CloudyDay02.zox")); + //model.Parse(worldUpdate, 8286118, 8344010, 333); + //model = JsonConvert.DeserializeObject(File.ReadAllText("models/Aster_CloudyDay03.zox")); + //model.Parse(worldUpdate, 8285992, 8344010, 333); + //model = JsonConvert.DeserializeObject(File.ReadAllText("models/Aster_CloudyDay04.zox")); + //model.Parse(worldUpdate, 8285992, 8344136, 333); + //model = JsonConvert.DeserializeObject(File.ReadAllText("models/Aster_CloudyDay05.zox")); + //model.Parse(worldUpdate, 8285992, 8344262, 333); + //model = JsonConvert.DeserializeObject(File.ReadAllText("models/Aster_CloudyDay06.zox")); + //model.Parse(worldUpdate, 8286118, 8344262, 333); + //model = JsonConvert.DeserializeObject(File.ReadAllText("models/Aster_CloudyDay07.zox")); + //model.Parse(worldUpdate, 8286118, 8344136, 333); + //model = JsonConvert.DeserializeObject(File.ReadAllText("models/Aster_CloudyDay08.zox")); + //model.Parse(worldUpdate, 8286244, 8344136, 333); + //model = JsonConvert.DeserializeObject(File.ReadAllText("models/Aster_CloudyDay09.zox")); + //model.Parse(worldUpdate, 8286244, 8344262, 333); + //model = JsonConvert.DeserializeObject(File.ReadAllText("models/Aster_CloudyDay10.zox")); + //model.Parse(worldUpdate, 8286770, 8344262, 333); + #endregion + } + } +} diff --git a/Server/Extensions/SpecialMoves.cs b/Server/Extensions/SpecialMoves.cs new file mode 100644 index 0000000..f12481c --- /dev/null +++ b/Server/Extensions/SpecialMoves.cs @@ -0,0 +1,40 @@ +using Resources; +using Resources.Datagram; +using Resources.Packet; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Server.Extensions { + public static class SpecialMoves { + public static void Init() { + Server.SpecialMoveUsed += OnSpecialMove; + } + + private static void OnSpecialMove(SpecialMove specialMove, Player source) { + switch (specialMove.Id) { + case SpecialMoveID.Taunt: + var target = Server.players.FirstOrDefault(p => p.entity.guid == specialMove.Guid); + if (target != null) { + specialMove.Guid = (ushort)source.entity.guid; + Server.SendUDP(specialMove.data, target); + } + break; + case SpecialMoveID.SmokeBomb: + Server.BroadcastUDP(specialMove.data, source); + break; + case SpecialMoveID.CursedArrow: + case SpecialMoveID.ArrowRain: + case SpecialMoveID.Shrapnel: + case SpecialMoveID.IceWave: + case SpecialMoveID.Confusion: + case SpecialMoveID.ShadowStep: + Server.BroadcastUDP(specialMove.data); + break; + default: + break; + } + } + } +} diff --git a/Server/Server.cs b/Server/Server.cs index 168fc37..91e275a 100644 --- a/Server/Server.cs +++ b/Server/Server.cs @@ -22,82 +22,12 @@ public static partial class Server { public static TcpListener tcpListener; public static List players = new List(); public static Dictionary dynamicEntities = new Dictionary(); - public static UserDatabase Database; + public static UserDatabase userDatabase; public static void Start(int port) { Log.PrintLn("server starting..."); - Database = new UserDatabase(); - Database.Database.Migrate(); //Ensure database exists - - #region models - //var rnd = new Random(); - //for (int i = 8286946; i < 8286946 + 512; i++) { - // for (int j = 8344456; j < 8344456 + 512; j++) { - // var block = new ServerUpdate.BlockDelta() { - // color = new Resources.Utilities.ByteVector() { - // x = 0, - // y = 0, - // z = (byte)rnd.Next(0, 255), - // }, - // type = BlockType.solid, - // position = new Resources.Utilities.IntVector() { - // x = i, - // y = j, - // z = 208, - // }, - // }; - // worldUpdate.blockDeltas.Add(block); - // } - //} - //x = 543093329157, - //y = 546862296355, - //z = 14423162 - //ZoxModel model = JsonConvert.DeserializeObject(File.ReadAllText("models/Fulcnix_exceedspawn.zox")); - //model.Parse(worldUpdate, 8286883, 8344394, 200); - //model = JsonConvert.DeserializeObject(File.ReadAllText("models/Aster_Tavern2.zox")); - //model.Parse(worldUpdate, 8287010, 8344432, 200); - //model = JsonConvert.DeserializeObject(File.ReadAllText("models/Aster_Tavern1.zox")); - //model.Parse(worldUpdate, 8286919, 8344315, 212); - //model = JsonConvert.DeserializeObject(File.ReadAllText("models/arena/aster_arena.zox")); - //model.Parse(worldUpdate, 8286775, 8344392, 207); - //model = JsonConvert.DeserializeObject(File.ReadAllText("models/michael_project1.zox")); - //model.Parse(worldUpdate, 8286898, 8344375, 213); - //model = JsonConvert.DeserializeObject(File.ReadAllText("models/arena/fulcnix_hall.zox")); - //model.Parse(worldUpdate, 8286885, 8344505, 208); - //model = JsonConvert.DeserializeObject(File.ReadAllText("models/arena/fulcnix_hall.zox")); - //model.Parse(worldUpdate, 8286885, 8344629, 208); - //model = JsonConvert.DeserializeObject(File.ReadAllText("models/Tiecz_MountainArena.zox")); - //model.Parse(worldUpdate, 8286885, 8344759, 208); - ////8397006, 8396937, 127 //near spawn - //model = JsonConvert.DeserializeObject(File.ReadAllText("models/Aster_CloudyDay11.zox")); - //model.Parse(worldUpdate, 8286770, 8344262, 207); - //model = JsonConvert.DeserializeObject(File.ReadAllText("models/Aster_CloudyDay12.zox")); - //model.Parse(worldUpdate, 8286770, 8344136, 207); - //model = JsonConvert.DeserializeObject(File.ReadAllText("models/Aster_CloudyDay13.zox")); - //model.Parse(worldUpdate, 8286770, 8344010, 207); - //model = JsonConvert.DeserializeObject(File.ReadAllText("models/Aster_CloudyDay14.zox")); - //model.Parse(worldUpdate, 8286770, 8344010, 333); - //model = JsonConvert.DeserializeObject(File.ReadAllText("models/Aster_CloudyDay01.zox")); - //model.Parse(worldUpdate, 8286644, 8344010, 333); - //model = JsonConvert.DeserializeObject(File.ReadAllText("models/Aster_CloudyDay02.zox")); - //model.Parse(worldUpdate, 8286118, 8344010, 333); - //model = JsonConvert.DeserializeObject(File.ReadAllText("models/Aster_CloudyDay03.zox")); - //model.Parse(worldUpdate, 8285992, 8344010, 333); - //model = JsonConvert.DeserializeObject(File.ReadAllText("models/Aster_CloudyDay04.zox")); - //model.Parse(worldUpdate, 8285992, 8344136, 333); - //model = JsonConvert.DeserializeObject(File.ReadAllText("models/Aster_CloudyDay05.zox")); - //model.Parse(worldUpdate, 8285992, 8344262, 333); - //model = JsonConvert.DeserializeObject(File.ReadAllText("models/Aster_CloudyDay06.zox")); - //model.Parse(worldUpdate, 8286118, 8344262, 333); - //model = JsonConvert.DeserializeObject(File.ReadAllText("models/Aster_CloudyDay07.zox")); - //model.Parse(worldUpdate, 8286118, 8344136, 333); - //model = JsonConvert.DeserializeObject(File.ReadAllText("models/Aster_CloudyDay08.zox")); - //model.Parse(worldUpdate, 8286244, 8344136, 333); - //model = JsonConvert.DeserializeObject(File.ReadAllText("models/Aster_CloudyDay09.zox")); - //model.Parse(worldUpdate, 8286244, 8344262, 333); - //model = JsonConvert.DeserializeObject(File.ReadAllText("models/Aster_CloudyDay10.zox")); - //model.Parse(worldUpdate, 8286770, 8344262, 333); - #endregion + userDatabase = new UserDatabase(); + userDatabase.Database.Migrate(); //Ensure database exists udpClient = new UdpClient(new IPEndPoint(IPAddress.Any, port)); new Thread(new ThreadStart(ListenUDP)).Start(); @@ -138,10 +68,10 @@ private static void ListenUDP() { } } - private static void SendUDP(byte[] data, Player target) { + public static void SendUDP(byte[] data, Player target) { udpClient.Send(data, data.Length, target.RemoteEndPoint); } - private static void BroadcastUDP(byte[] data, Player toSkip = null) { + public static void BroadcastUDP(byte[] data, Player toSkip = null) { foreach (var player in players) { if (player != toSkip) { SendUDP(data, player); @@ -186,7 +116,7 @@ private static void ProcessPacket(byte packetID, Player source) { authResponse = AuthResponse.AccountAlreadyActive; } else { - authResponse = Database.AuthUser(username, password, (int)source.IP.Address, source.MAC); + authResponse = userDatabase.AuthUser(username, password, (int)source.IP.Address, source.MAC); } source.writer.Write((byte)ServerPacketID.Login); source.writer.Write((byte)authResponse); @@ -222,7 +152,7 @@ private static void ProcessPacket(byte packetID, Player source) { registerResponse = RegisterResponse.InvalidInput; } else { - registerResponse = Database.RegisterUser(username, email, password); + registerResponse = userDatabase.RegisterUser(username, email, password); } source.writer.Write((byte)ServerPacketID.Register); source.writer.Write((byte)registerResponse); @@ -297,28 +227,6 @@ private static void ProcessDatagram(byte[] datagram, Player source) { #region specialMove var specialMove = new SpecialMove(datagram); SpecialMoveUsed(specialMove, source); - switch (specialMove.Id) { - case SpecialMoveID.Taunt: - target = players.FirstOrDefault(p => p.entity.guid == specialMove.Guid); - if (target != null) { - specialMove.Guid = (ushort)source.entity.guid; - SendUDP(specialMove.data, target); - } - break; - case SpecialMoveID.SmokeBomb: - BroadcastUDP(specialMove.data, source); - break; - case SpecialMoveID.CursedArrow: - case SpecialMoveID.ArrowRain: - case SpecialMoveID.Shrapnel: - case SpecialMoveID.IceWave: - case SpecialMoveID.Confusion: - case SpecialMoveID.ShadowStep: - BroadcastUDP(specialMove.data); - break; - default: - break; - } break; #endregion case DatagramID.HolePunch: From bfd71e29894854e12182c0f42293b4f7135efd90 Mon Sep 17 00:00:00 2001 From: LastExceed Date: Fri, 12 Oct 2018 23:35:20 +0200 Subject: [PATCH 03/18] add extensions intialization --- Server/Server.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Server/Server.cs b/Server/Server.cs index 91e275a..e0f4e35 100644 --- a/Server/Server.cs +++ b/Server/Server.cs @@ -34,6 +34,8 @@ public static void Start(int port) { tcpListener = new TcpListener(IPAddress.Any, port); tcpListener.Start(); new Thread(new ThreadStart(ListenTCP)).Start(); + + Extensions.Extensions.Init(); Log.PrintLn("loading completed"); } From 7a7c3a3966ccdc2dd63ccbfe9a918ebd155621ac Mon Sep 17 00:00:00 2001 From: LastExceed Date: Sat, 13 Oct 2018 00:30:17 +0200 Subject: [PATCH 04/18] check if eventhandlers are null before raising them --- Server/Server.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Server/Server.cs b/Server/Server.cs index e0f4e35..84b8a94 100644 --- a/Server/Server.cs +++ b/Server/Server.cs @@ -174,7 +174,7 @@ private static void ProcessDatagram(byte[] datagram, Player source) { case DatagramID.DynamicUpdate: #region entityUpdate var entityUpdate = new EntityUpdate(datagram); - EntityUpdated(entityUpdate, source); + EntityUpdated?.Invoke(entityUpdate, source); entityUpdate.Merge(source.entity); BroadcastUDP(entityUpdate.CreateDatagram(), source); break; @@ -182,7 +182,7 @@ private static void ProcessDatagram(byte[] datagram, Player source) { case DatagramID.Attack: #region attack var attack = new Attack(datagram); - EntityAttacked(attack, source); + EntityAttacked?.Invoke(attack, source); source.lastTarget = attack.Target; var target = players.FirstOrDefault(p => p.entity?.guid == attack.Target); if (target != null) SendUDP(attack.data, target); @@ -191,21 +191,21 @@ private static void ProcessDatagram(byte[] datagram, Player source) { case DatagramID.Projectile: #region Projectile var projectile = new Projectile(datagram); - ProjectileCreated(projectile, source); + ProjectileCreated?.Invoke(projectile, source); BroadcastUDP(projectile.data, source); //pass to all players except source break; #endregion case DatagramID.Proc: #region proc var proc = new Proc(datagram); - PassiveProcced(proc, source); + PassiveProcced?.Invoke(proc, source); BroadcastUDP(proc.data, source); //pass to all players except source break; #endregion case DatagramID.Chat: #region chat var chat = new Chat(datagram); - ChatMessageReceived(chat.Text, source); + ChatMessageReceived?.Invoke(chat.Text, source); Log.Print(dynamicEntities[chat.Sender].name + ": ", ConsoleColor.Cyan); Log.PrintLn(chat.Text, ConsoleColor.White, false); BroadcastUDP(chat.data, null); //pass to all players @@ -214,21 +214,21 @@ private static void ProcessDatagram(byte[] datagram, Player source) { case DatagramID.Interaction: #region interaction var interaction = new Interaction(datagram); - EntityInteracted(interaction, source); + EntityInteracted?.Invoke(interaction, source); BroadcastUDP(interaction.data, source); //pass to all players except source break; #endregion case DatagramID.RemoveDynamicEntity: #region removeDynamicEntity var remove = new RemoveDynamicEntity(datagram); - EntityRemoved(remove, source); + EntityRemoved?.Invoke(remove, source); RemovePlayerEntity(source, true); break; #endregion case DatagramID.SpecialMove: #region specialMove var specialMove = new SpecialMove(datagram); - SpecialMoveUsed(specialMove, source); + SpecialMoveUsed?.Invoke(specialMove, source); break; #endregion case DatagramID.HolePunch: From c79b6e1708287970e66652efa43035e75467d78e Mon Sep 17 00:00:00 2001 From: LastExceed Date: Sat, 13 Oct 2018 01:34:00 +0200 Subject: [PATCH 05/18] add damage reduction --- Server/Extensions/Balancing.cs | 19 +++++++++++++++++++ Server/Extensions/Extensions.cs | 1 + Server/Extensions/Pvp.cs | 2 -- 3 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 Server/Extensions/Balancing.cs diff --git a/Server/Extensions/Balancing.cs b/Server/Extensions/Balancing.cs new file mode 100644 index 0000000..629a215 --- /dev/null +++ b/Server/Extensions/Balancing.cs @@ -0,0 +1,19 @@ +using Resources; +using Resources.Datagram; + +namespace Server.Extensions { + public static class Balancing { + public static void Init() { + Server.EntityAttacked += CutDmgInHalf; + } + + private static void CutDmgInHalf(Attack datagram, Player player) { + if (datagram.Damage < 0) { + datagram.Damage *= 0.5f; //dmg + } + else { + datagram.Damage *= 0.333333f; //heal + } + } + } +} diff --git a/Server/Extensions/Extensions.cs b/Server/Extensions/Extensions.cs index f15bad9..c14a3c6 100644 --- a/Server/Extensions/Extensions.cs +++ b/Server/Extensions/Extensions.cs @@ -9,6 +9,7 @@ public static void Init() { Pvp.Init(); ChatCommands.Init(); SpecialMoves.Init(); + Balancing.Init(); } } } diff --git a/Server/Extensions/Pvp.cs b/Server/Extensions/Pvp.cs index 77f7440..94cb147 100644 --- a/Server/Extensions/Pvp.cs +++ b/Server/Extensions/Pvp.cs @@ -12,8 +12,6 @@ public static void Init() { private static void EnableFriendlyFireFlag(EntityUpdate entityUpdate, Player player) { entityUpdate.entityFlags |= 1 << 5; - - } } } From a6ece99eecd7a448aeea01b7b23eafc7b04e110f Mon Sep 17 00:00:00 2001 From: LastExceed Date: Sat, 13 Oct 2018 01:53:39 +0200 Subject: [PATCH 06/18] switch heal and dmg reduction multipliers --- Server/Extensions/Balancing.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Server/Extensions/Balancing.cs b/Server/Extensions/Balancing.cs index 629a215..f8800a5 100644 --- a/Server/Extensions/Balancing.cs +++ b/Server/Extensions/Balancing.cs @@ -7,12 +7,12 @@ public static void Init() { Server.EntityAttacked += CutDmgInHalf; } - private static void CutDmgInHalf(Attack datagram, Player player) { - if (datagram.Damage < 0) { - datagram.Damage *= 0.5f; //dmg + private static void CutDmgInHalf(Attack attack, Player player) { + if (attack.Damage > 0) { + attack.Damage *= 0.5f; //dmg } else { - datagram.Damage *= 0.333333f; //heal + attack.Damage *= 0.333333f; //heal } } } From 2762492a67b377604877fcb2a18bc7ffdb9ae9f8 Mon Sep 17 00:00:00 2001 From: LastExceed Date: Sat, 13 Oct 2018 02:19:22 +0200 Subject: [PATCH 07/18] switch heal and dmg reduction multipliers --- Server/Extensions/Balancing.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Server/Extensions/Balancing.cs b/Server/Extensions/Balancing.cs index f8800a5..f196d78 100644 --- a/Server/Extensions/Balancing.cs +++ b/Server/Extensions/Balancing.cs @@ -14,6 +14,9 @@ private static void CutDmgInHalf(Attack attack, Player player) { else { attack.Damage *= 0.333333f; //heal } + if (attack.Target == player.entity.guid) {//players can't damage themselves. this prevents double self heals since selfheal is already applied locally + attack.Damage = 0; + } } } } From 8916fdcf32770478057c27af18431656df6f996d Mon Sep 17 00:00:00 2001 From: LastExceed Date: Sun, 14 Oct 2018 14:29:06 +0200 Subject: [PATCH 08/18] add dmgReductionByShield --- Server/Extensions/Balancing.cs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/Server/Extensions/Balancing.cs b/Server/Extensions/Balancing.cs index f196d78..f70ee1d 100644 --- a/Server/Extensions/Balancing.cs +++ b/Server/Extensions/Balancing.cs @@ -11,9 +11,21 @@ private static void CutDmgInHalf(Attack attack, Player player) { if (attack.Damage > 0) { attack.Damage *= 0.5f; //dmg } - else { - attack.Damage *= 0.333333f; //heal + //else { + // attack.Damage *= 0.333333f; //heal + //} + var target = Server.dynamicEntities[attack.Target]; + var dmgReductionByShield = 0f; + if (target.equipment[(int)Equipment.LeftWeapon].subtype == (byte)ItemSubtypeWeapon.Shield) { + dmgReductionByShield += 0.25f; } + if (target.equipment[(int)Equipment.RightWeapon].subtype == (byte)ItemSubtypeWeapon.Shield) { + dmgReductionByShield += 0.25f; + } + if (attack.Damage > 0) { + attack.Damage *= 1 - dmgReductionByShield; + } + Log.PrintLn(player.entity.name + " " + attack.Target + " " + attack.Damage + " " + attack.Critical, System.ConsoleColor.Magenta); if (attack.Target == player.entity.guid) {//players can't damage themselves. this prevents double self heals since selfheal is already applied locally attack.Damage = 0; } From 8ec16033b8bd0516624bc7a620f3028373ec00d0 Mon Sep 17 00:00:00 2001 From: LastExceed Date: Mon, 15 Oct 2018 11:31:57 +0200 Subject: [PATCH 09/18] move ZoxModel to resources --- {Server/Addon => Resources}/ZoxModel.cs | 2 +- Server/Server.cs | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) rename {Server/Addon => Resources}/ZoxModel.cs (98%) diff --git a/Server/Addon/ZoxModel.cs b/Resources/ZoxModel.cs similarity index 98% rename from Server/Addon/ZoxModel.cs rename to Resources/ZoxModel.cs index b2c3f28..ed311ea 100644 --- a/Server/Addon/ZoxModel.cs +++ b/Resources/ZoxModel.cs @@ -3,7 +3,7 @@ using Resources.Utilities; using Resources.Packet; -namespace Server.Addon { +namespace Resources { class ZoxModel { public string Creator { get; set; } public byte Height { get; set; } diff --git a/Server/Server.cs b/Server/Server.cs index 84b8a94..85d8a8b 100644 --- a/Server/Server.cs +++ b/Server/Server.cs @@ -5,8 +5,6 @@ using System.Net; using System.Net.Sockets; using System.IO; - -using Server.Addon; using Server.Database; using Microsoft.EntityFrameworkCore; @@ -14,7 +12,6 @@ using Resources; using Resources.Datagram; using Resources.Packet; -using Resources.Utilities; namespace Server { public static partial class Server { From 3fc570bd21f5ea75cd1c85c15129c5770c9e0a66 Mon Sep 17 00:00:00 2001 From: LastExceed Date: Mon, 15 Oct 2018 11:43:19 +0200 Subject: [PATCH 10/18] rename Server class to ServerCore to prevent identical named class in a namespace --- Bridge/Bridge.csproj | 2 +- Bridge/{BridgeTCPUDP.cs => BridgeCore.cs} | 2 +- Bridge/FormMain.cs | 10 +++--- Bridge/FormMap.cs | 2 +- Bridge/FormRegister.cs | 32 +++++++++---------- Bridge/KeyboardHook.cs | 6 ++-- Server/Extensions/AntiCheat.cs | 4 +-- Server/Extensions/Balancing.cs | 4 +-- Server/Extensions/ChatCommands.cs | 24 +++++++------- Server/Extensions/Pvp.cs | 2 +- Server/Extensions/SpecialMoves.cs | 10 +++--- Server/Extensions/Tombstones.cs | 8 ++--- Server/Program.cs | 2 +- Server/{Server.cs => ServerCore.cs} | 2 +- ...{Server_Events.cs => ServerCore_Events.cs} | 2 +- 15 files changed, 56 insertions(+), 56 deletions(-) rename Bridge/{BridgeTCPUDP.cs => BridgeCore.cs} (99%) rename Server/{Server.cs => ServerCore.cs} (99%) rename Server/{Server_Events.cs => ServerCore_Events.cs} (97%) diff --git a/Bridge/Bridge.csproj b/Bridge/Bridge.csproj index 1ccf748..f9a563b 100644 --- a/Bridge/Bridge.csproj +++ b/Bridge/Bridge.csproj @@ -112,7 +112,7 @@ - + FormChat.cs diff --git a/Bridge/BridgeTCPUDP.cs b/Bridge/BridgeCore.cs similarity index 99% rename from Bridge/BridgeTCPUDP.cs rename to Bridge/BridgeCore.cs index f6ff3a1..dce5298 100644 --- a/Bridge/BridgeTCPUDP.cs +++ b/Bridge/BridgeCore.cs @@ -15,7 +15,7 @@ using Resources.Datagram; namespace Bridge { - static class BridgeTCPUDP { + static class BridgeCore { public static UdpClient udpToServer; public static TcpClient tcpToServer, tcpToClient; public static TcpListener tcpListener = new TcpListener(IPAddress.Parse("127.0.0.1"), 12345); //hardcoded because client port can't be changed diff --git a/Bridge/FormMain.cs b/Bridge/FormMain.cs index f0d29c4..7c31963 100644 --- a/Bridge/FormMain.cs +++ b/Bridge/FormMain.cs @@ -22,10 +22,10 @@ private void FormMain_Shown(object sender, EventArgs e) { chat.Show(); chat.Top = this.Top; chat.Left = Left + Width; - BridgeTCPUDP.form = this; + BridgeCore.form = this; CwRam.formMain = this; - new Thread(BridgeTCPUDP.ListenFromClientTCP).Start(); - new Thread(BridgeTCPUDP.Connect).Start(); + new Thread(BridgeCore.ListenFromClientTCP).Start(); + new Thread(BridgeCore.Connect).Start(); keyboardHook = new KeyboardHook(); } private void timerSearchProcess_Tick(object sender, EventArgs e) { @@ -39,7 +39,7 @@ private void timerSearchProcess_Tick(object sender, EventArgs e) { } else { CwRam.RemoveFog(); - if (BridgeTCPUDP.status == Resources.BridgeStatus.Playing) CwRam.SetName(linkLabelUser.Text); + if (BridgeCore.status == Resources.BridgeStatus.Playing) CwRam.SetName(linkLabelUser.Text); } } else { @@ -108,7 +108,7 @@ private void buttonLoginRegister_Click(object sender, EventArgs e) { } private void contextMenuStripUser_ItemClicked(object sender, ToolStripItemClickedEventArgs e) { - BridgeTCPUDP.Logout(); + BridgeCore.Logout(); OnLogout(); } public void OnLogout() { diff --git a/Bridge/FormMap.cs b/Bridge/FormMap.cs index 4ebc3ae..2b66665 100644 --- a/Bridge/FormMap.cs +++ b/Bridge/FormMap.cs @@ -13,7 +13,7 @@ public FormMap() { private void Refreshtimer_Tick(object sender, EventArgs e) { Controls.Clear(); playercollection.Clear(); - foreach (var entity in BridgeTCPUDP.dynamicEntities.Values.ToList()) { + foreach (var entity in BridgeCore.dynamicEntities.Values.ToList()) { if (entity.hostility == Resources.Hostility.Player) { Label playerlabel = new Label { Left = (int)entity.position.x / 0x10000, diff --git a/Bridge/FormRegister.cs b/Bridge/FormRegister.cs index aaff13a..6ca0d7f 100644 --- a/Bridge/FormRegister.cs +++ b/Bridge/FormRegister.cs @@ -41,7 +41,7 @@ private void textBoxEmail_TextChanged(object sender, EventArgs e) { private void buttonRegister_Click(object sender, EventArgs e) { buttonRegister.Enabled = false; - BridgeTCPUDP.Register(textBoxUsername.Text, textBoxEmail.Text, textBoxPassword.Text); + BridgeCore.Register(textBoxUsername.Text, textBoxEmail.Text, textBoxPassword.Text); } private void buttonCreate_Click(object sender, EventArgs e) { @@ -77,39 +77,39 @@ private void buttonLogin_Click(object sender, EventArgs e) { textBoxUsername.ReadOnly = true; textBoxEmail.ReadOnly = true; textBoxPassword.ReadOnly = true; - BridgeTCPUDP.Login(textBoxUsername.Text, textBoxPassword.Text); + BridgeCore.Login(textBoxUsername.Text, textBoxPassword.Text); } public void OnLoginResponse(AuthResponse authResponse) { switch (authResponse) { case AuthResponse.Success: - BridgeTCPUDP.form.Log("success\n", Color.Green); - BridgeTCPUDP.form.buttonLoginRegister.Visible = false; - BridgeTCPUDP.form.linkLabelUser.Text = textBoxUsername.Text; - BridgeTCPUDP.form.linkLabelUser.Visible = true; - BridgeTCPUDP.form.buttonClan.Enabled = true; - BridgeTCPUDP.form.buttonClan.Visible = false; - BridgeTCPUDP.form.linkLabelClan.Text = "Prisoners of Irreality"; - BridgeTCPUDP.form.linkLabelClan.Visible = true; + BridgeCore.form.Log("success\n", Color.Green); + BridgeCore.form.buttonLoginRegister.Visible = false; + BridgeCore.form.linkLabelUser.Text = textBoxUsername.Text; + BridgeCore.form.linkLabelUser.Visible = true; + BridgeCore.form.buttonClan.Enabled = true; + BridgeCore.form.buttonClan.Visible = false; + BridgeCore.form.linkLabelClan.Text = "Prisoners of Irreality"; + BridgeCore.form.linkLabelClan.Visible = true; this.Close(); break; case AuthResponse.UnknownUser: - BridgeTCPUDP.form.Log("username does not exist\n", Color.Red); + BridgeCore.form.Log("username does not exist\n", Color.Red); goto default; case AuthResponse.WrongPassword: - BridgeTCPUDP.form.Log("wrong password\n", Color.Red); + BridgeCore.form.Log("wrong password\n", Color.Red); goto default; case AuthResponse.Banned: - BridgeTCPUDP.form.Log("you are banned\n", Color.Red); + BridgeCore.form.Log("you are banned\n", Color.Red); goto default; case AuthResponse.AccountAlreadyActive: - BridgeTCPUDP.form.Log("account already in use\n", Color.Red); + BridgeCore.form.Log("account already in use\n", Color.Red); goto default; case AuthResponse.Unverified: - BridgeTCPUDP.form.Log("unverified (this shouldnt happen)\n", Color.Red); + BridgeCore.form.Log("unverified (this shouldnt happen)\n", Color.Red); goto default; case AuthResponse.UserAlreadyLoggedIn: - BridgeTCPUDP.form.Log("you are already logged in (this shouldn't happen)\n", Color.Red); + BridgeCore.form.Log("you are already logged in (this shouldn't happen)\n", Color.Red); goto default; default: buttonLogin.Enabled = true; diff --git a/Bridge/KeyboardHook.cs b/Bridge/KeyboardHook.cs index 7d3fcdb..5b67069 100644 --- a/Bridge/KeyboardHook.cs +++ b/Bridge/KeyboardHook.cs @@ -100,13 +100,13 @@ private void OnKey(Keys key, bool isDown) { if (!isDown) return;//temp fix to prevent activation on release switch (key) { case Keys.D4: - BridgeTCPUDP.OnHotkey(Resources.HotkeyID.CtrlSpace); + BridgeCore.OnHotkey(Resources.HotkeyID.CtrlSpace); break; case Keys.D5: - BridgeTCPUDP.OnHotkey(Resources.HotkeyID.SpecialMove2); + BridgeCore.OnHotkey(Resources.HotkeyID.SpecialMove2); break; case Keys.D0: - BridgeTCPUDP.OnHotkey(Resources.HotkeyID.TeleportToTown); + BridgeCore.OnHotkey(Resources.HotkeyID.TeleportToTown); break; default: break; diff --git a/Server/Extensions/AntiCheat.cs b/Server/Extensions/AntiCheat.cs index 4684778..a09b08e 100644 --- a/Server/Extensions/AntiCheat.cs +++ b/Server/Extensions/AntiCheat.cs @@ -7,13 +7,13 @@ namespace Server.Extensions { public static class AntiCheat { public static void Init() { - Server.EntityUpdated += That; + ServerCore.EntityUpdated += That; } private static void That(EntityUpdate entityUpdate, Player player) { string ACmessage = Inspect(entityUpdate, player.entity); if (ACmessage != null) { - Server.Kick(player, ACmessage); + ServerCore.Kick(player, ACmessage); } } diff --git a/Server/Extensions/Balancing.cs b/Server/Extensions/Balancing.cs index f70ee1d..11a01be 100644 --- a/Server/Extensions/Balancing.cs +++ b/Server/Extensions/Balancing.cs @@ -4,7 +4,7 @@ namespace Server.Extensions { public static class Balancing { public static void Init() { - Server.EntityAttacked += CutDmgInHalf; + ServerCore.EntityAttacked += CutDmgInHalf; } private static void CutDmgInHalf(Attack attack, Player player) { @@ -14,7 +14,7 @@ private static void CutDmgInHalf(Attack attack, Player player) { //else { // attack.Damage *= 0.333333f; //heal //} - var target = Server.dynamicEntities[attack.Target]; + var target = ServerCore.dynamicEntities[attack.Target]; var dmgReductionByShield = 0f; if (target.equipment[(int)Equipment.LeftWeapon].subtype == (byte)ItemSubtypeWeapon.Shield) { dmgReductionByShield += 0.25f; diff --git a/Server/Extensions/ChatCommands.cs b/Server/Extensions/ChatCommands.cs index 65adc21..56fab56 100644 --- a/Server/Extensions/ChatCommands.cs +++ b/Server/Extensions/ChatCommands.cs @@ -9,7 +9,7 @@ namespace Server.Extensions { public static class ChatCommands { public static void Init() { - Server.ChatMessageReceived += ParseAsCommand; + ServerCore.ChatMessageReceived += ParseAsCommand; } private static void ParseAsCommand(string message, Player source) { @@ -24,16 +24,16 @@ private static void ParseAsCommand(string message, Player source) { case "ban": #region ban if (source.entity.name != "BLACKROCK") { - Server.Notify(source, "no permission"); + ServerCore.Notify(source, "no permission"); break; } if (parameters.Length == 1) { - Server.Notify(source, string.Format("usage example: /kick blackrock")); + ServerCore.Notify(source, string.Format("usage example: /kick blackrock")); break; } - var target = Server.players.FirstOrDefault(x => x.entity.name.Contains(parameters[1])); + var target = ServerCore.players.FirstOrDefault(x => x.entity.name.Contains(parameters[1])); if (target == null) { - Server.Notify(source, "invalid target"); + ServerCore.Notify(source, "invalid target"); break; }; var reason = "no reason specified"; @@ -41,15 +41,15 @@ private static void ParseAsCommand(string message, Player source) { reason = parameters[2]; } if (command == "kick") { - Server.Kick(target, reason); + ServerCore.Kick(target, reason); break; } target.writer.Write((byte)ServerPacketID.BTFO); target.writer.Write(reason); if (command == "ban") { - Server.userDatabase.BanUser(target.entity.name, (int)target.IP.Address, target.MAC, reason); + ServerCore.userDatabase.BanUser(target.entity.name, (int)target.IP.Address, target.MAC, reason); } - Server.RemovePlayerEntity(target, false); + ServerCore.RemovePlayerEntity(target, false); break; #endregion case "bleeding": @@ -58,24 +58,24 @@ private static void ParseAsCommand(string message, Player source) { case "time": #region time if (parameters.Length == 1) { - Server.Notify(source, string.Format("usage example: /time 12:00")); + ServerCore.Notify(source, string.Format("usage example: /time 12:00")); break; } var clock = parameters[1].Split(":"); if (clock.Length < 2 || !int.TryParse(clock[0], out int hour) || !int.TryParse(clock[1], out int minute)) { - Server.Notify(source, string.Format("invalid syntax")); + ServerCore.Notify(source, string.Format("invalid syntax")); break; } var inGameTime = new InGameTime() { Milliseconds = (hour * 60 + minute) * 60000, }; - Server.SendUDP(inGameTime.data, source); + ServerCore.SendUDP(inGameTime.data, source); break; #endregion default: - Server.Notify(source, string.Format("unknown command '{0}'", parameters[0])); + ServerCore.Notify(source, string.Format("unknown command '{0}'", parameters[0])); break; } } diff --git a/Server/Extensions/Pvp.cs b/Server/Extensions/Pvp.cs index 94cb147..fe9a664 100644 --- a/Server/Extensions/Pvp.cs +++ b/Server/Extensions/Pvp.cs @@ -7,7 +7,7 @@ namespace Server.Extensions { public static class Pvp { public static void Init() { - Server.EntityUpdated += EnableFriendlyFireFlag; + ServerCore.EntityUpdated += EnableFriendlyFireFlag; } private static void EnableFriendlyFireFlag(EntityUpdate entityUpdate, Player player) { diff --git a/Server/Extensions/SpecialMoves.cs b/Server/Extensions/SpecialMoves.cs index f12481c..b57e9de 100644 --- a/Server/Extensions/SpecialMoves.cs +++ b/Server/Extensions/SpecialMoves.cs @@ -9,20 +9,20 @@ namespace Server.Extensions { public static class SpecialMoves { public static void Init() { - Server.SpecialMoveUsed += OnSpecialMove; + ServerCore.SpecialMoveUsed += OnSpecialMove; } private static void OnSpecialMove(SpecialMove specialMove, Player source) { switch (specialMove.Id) { case SpecialMoveID.Taunt: - var target = Server.players.FirstOrDefault(p => p.entity.guid == specialMove.Guid); + var target = ServerCore.players.FirstOrDefault(p => p.entity.guid == specialMove.Guid); if (target != null) { specialMove.Guid = (ushort)source.entity.guid; - Server.SendUDP(specialMove.data, target); + ServerCore.SendUDP(specialMove.data, target); } break; case SpecialMoveID.SmokeBomb: - Server.BroadcastUDP(specialMove.data, source); + ServerCore.BroadcastUDP(specialMove.data, source); break; case SpecialMoveID.CursedArrow: case SpecialMoveID.ArrowRain: @@ -30,7 +30,7 @@ private static void OnSpecialMove(SpecialMove specialMove, Player source) { case SpecialMoveID.IceWave: case SpecialMoveID.Confusion: case SpecialMoveID.ShadowStep: - Server.BroadcastUDP(specialMove.data); + ServerCore.BroadcastUDP(specialMove.data); break; default: break; diff --git a/Server/Extensions/Tombstones.cs b/Server/Extensions/Tombstones.cs index 6b6d664..bb7bad5 100644 --- a/Server/Extensions/Tombstones.cs +++ b/Server/Extensions/Tombstones.cs @@ -9,13 +9,13 @@ namespace Server.Extensions { public static class Tombstones { public static void Init() { - Server.EntityUpdated += SpawnTomb; + ServerCore.EntityUpdated += SpawnTomb; } private static void SpawnTomb(EntityUpdate entityUpdate, Player player) { if (entityUpdate.HP <= 0 && (player.entity.HP > 0 || player.entity.HP == null)) { var tombstone = new EntityUpdate() { - guid = Server.AssignGuid(), + guid = ServerCore.AssignGuid(), position = entityUpdate.position ?? player.entity.position, hostility = Hostility.Neutral, entityType = EntityType.None, @@ -32,13 +32,13 @@ private static void SpawnTomb(EntityUpdate entityUpdate, Player player) { name = "tombstone" }; player.tomb = (ushort)tombstone.guid; - Server.BroadcastUDP(tombstone.CreateDatagram()); + ServerCore.BroadcastUDP(tombstone.CreateDatagram()); } else if (player.entity.HP <= 0 && entityUpdate.HP > 0 && player.tomb != null) { var rde = new RemoveDynamicEntity() { Guid = (ushort)player.tomb, }; - Server.BroadcastUDP(rde.data); + ServerCore.BroadcastUDP(rde.data); } } } diff --git a/Server/Program.cs b/Server/Program.cs index e4ee40f..2596c96 100644 --- a/Server/Program.cs +++ b/Server/Program.cs @@ -3,7 +3,7 @@ namespace Server { class Program { static void Main(string[] args) { - Server.Start(12346); + ServerCore.Start(12346); while (true) { Console.ReadLine(); } diff --git a/Server/Server.cs b/Server/ServerCore.cs similarity index 99% rename from Server/Server.cs rename to Server/ServerCore.cs index 85d8a8b..98b9cba 100644 --- a/Server/Server.cs +++ b/Server/ServerCore.cs @@ -14,7 +14,7 @@ using Resources.Packet; namespace Server { - public static partial class Server { + public static partial class ServerCore { public static UdpClient udpClient; public static TcpListener tcpListener; public static List players = new List(); diff --git a/Server/Server_Events.cs b/Server/ServerCore_Events.cs similarity index 97% rename from Server/Server_Events.cs rename to Server/ServerCore_Events.cs index e474318..f79930e 100644 --- a/Server/Server_Events.cs +++ b/Server/ServerCore_Events.cs @@ -15,7 +15,7 @@ namespace Server { public delegate void EntityRemovedEventHandler(RemoveDynamicEntity datagram, Player source); public delegate void SpecialMoveUsedEventHandler(SpecialMove datagram, Player source); - public static partial class Server { + public static partial class ServerCore { public static event EntityUpdatedEventHandler EntityUpdated; public static event EntityAttackedEventHandler EntityAttacked; public static event ProjectileCreatedEventHandler ProjectileCreated; From 4090abab05e2596029bf27f4a26f36e885ae0bab Mon Sep 17 00:00:00 2001 From: LastExceed Date: Tue, 16 Oct 2018 14:17:18 +0200 Subject: [PATCH 11/18] add events in bridge --- Bridge/Bridge.csproj | 5 + Bridge/BridgeCore.cs | 553 ++--------------------- Bridge/BridgeCore_Events.cs | 57 +++ Bridge/Extensions/ExtensionsCore.cs | 15 + Bridge/Extensions/Logging.cs | 57 +++ Bridge/Extensions/NameSubjectToChange.cs | 167 +++++++ Bridge/Extensions/SpecialMoves.cs | 375 +++++++++++++++ Bridge/FormMain.cs | 8 +- Bridge/KeyboardHook.cs | 21 +- Resources/Config.cs | 2 +- Resources/CubeworldNetworking | 2 +- 11 files changed, 731 insertions(+), 531 deletions(-) create mode 100644 Bridge/BridgeCore_Events.cs create mode 100644 Bridge/Extensions/ExtensionsCore.cs create mode 100644 Bridge/Extensions/Logging.cs create mode 100644 Bridge/Extensions/NameSubjectToChange.cs create mode 100644 Bridge/Extensions/SpecialMoves.cs diff --git a/Bridge/Bridge.csproj b/Bridge/Bridge.csproj index f9a563b..63f1953 100644 --- a/Bridge/Bridge.csproj +++ b/Bridge/Bridge.csproj @@ -71,7 +71,12 @@ + + + + + Form diff --git a/Bridge/BridgeCore.cs b/Bridge/BridgeCore.cs index dce5298..61f917b 100644 --- a/Bridge/BridgeCore.cs +++ b/Bridge/BridgeCore.cs @@ -10,12 +10,11 @@ using System.Net.NetworkInformation; using Resources; -using Resources.Utilities; using Resources.Packet; using Resources.Datagram; namespace Bridge { - static class BridgeCore { + public static partial class BridgeCore { public static UdpClient udpToServer; public static TcpClient tcpToServer, tcpToClient; public static TcpListener tcpListener = new TcpListener(IPAddress.Parse("127.0.0.1"), 12345); //hardcoded because client port can't be changed @@ -25,7 +24,6 @@ static class BridgeCore { public static int mapseed; public static FormMain form; public static Dictionary dynamicEntities = new Dictionary(); - public static ushort lastTarget; public static Mutex outgoingMutex = new Mutex(); public static BridgeStatus status = BridgeStatus.Offline; @@ -117,12 +115,11 @@ public static void ListenFromClientTCP() { } while (true) { tcpToClient = tcpListener.AcceptTcpClient(); - form.Log("client connected\n", Color.Green); + ClientConnected?.Invoke(); tcpToClient.ReceiveTimeout = 500; tcpToClient.SendTimeout = 500; - tcpToClient.NoDelay = true; - Stream stream = tcpToClient.GetStream(); + var stream = tcpToClient.GetStream(); creader = new BinaryReader(stream); cwriter = new BinaryWriter(stream); @@ -131,6 +128,7 @@ public static void ListenFromClientTCP() { version = 42069, }); form.Log("client rejected\n", Color.Red); + ClientDisconnected?.Invoke(); continue; } status = BridgeStatus.Playing; @@ -156,8 +154,7 @@ public static void ListenFromClientTCP() { break; } dynamicEntities.Remove(guid); - form.Log("client disconnected\n", Color.Red); - RefreshPlayerlist(); + ClientDisconnected?.Invoke(); } } private static void ListenFromServerTCP() { @@ -191,30 +188,22 @@ private static void ProcessDatagram(byte[] datagram) { case DatagramID.DynamicUpdate: #region entityUpdate var entityUpdate = new EntityUpdate(datagram); + EntityUpdateReceived?.Invoke(entityUpdate); if (status == BridgeStatus.Playing) { - if (entityUpdate.guid == guid) { - CwRam.Teleport(entityUpdate.position); - break; - } SendToClient(entityUpdate); } - if (dynamicEntities.ContainsKey(entityUpdate.guid)) { entityUpdate.Merge(dynamicEntities[entityUpdate.guid]); } else { dynamicEntities.Add(entityUpdate.guid, entityUpdate); } - - if (entityUpdate.name != null) { - RefreshPlayerlist(); - } break; #endregion case DatagramID.Attack: #region attack var attack = new Attack(datagram); - CwRam.Knockback(attack.Direction); + AttackReceived?.Invoke(attack); var hit = new Hit() { target = attack.Target, damage = attack.Damage, @@ -233,7 +222,7 @@ private static void ProcessDatagram(byte[] datagram) { case DatagramID.Projectile: #region Projectile var projectile = new Projectile(datagram); - + ProjectileReceived?.Invoke(projectile); var shoot = new Shoot() { attacker = projectile.Source, position = projectile.Position, @@ -256,22 +245,7 @@ private static void ProcessDatagram(byte[] datagram) { case DatagramID.Proc: #region proc var proc = new Proc(datagram); - if (proc.Type == ProcType.Poison && proc.Target == guid) { - var su = new ServerUpdate(); - su.hits.Add(new Hit() { - damage = proc.Modifier, - target = guid, - position = dynamicEntities[guid].position, - }); - bool tick() { - bool f = status == BridgeStatus.Playing && dynamicEntities[guid].HP > 0; - if (f) { - SendToClient(su); - } - return !f; - } - Tools.DoLater(tick, 500, 7); - } + PassiveProcReceived?.Invoke(proc); var passiveProc = new PassiveProc() { target = proc.Target, type = proc.Type, @@ -285,33 +259,32 @@ bool tick() { case DatagramID.Chat: #region chat var chat = new Chat(datagram); - var chatMessage = new ChatMessage() { - sender = chat.Sender, - message = chat.Text - }; - if (status == BridgeStatus.Playing) SendToClient(chatMessage); - if (chat.Sender == 0) { - form.Log(chat.Text + "\n", Color.Magenta); - } - else { - form.Log(dynamicEntities[chat.Sender].name + ": ", Color.Cyan); - form.Log(chat.Text + "\n", Color.White); + ChatMessageReceived?.Invoke(chat); + if (status == BridgeStatus.Playing) { + var chatMessage = new ChatMessage() { + sender = chat.Sender, + message = chat.Text + }; + SendToClient(chatMessage); } break; #endregion case DatagramID.Time: #region time - var igt = new InGameTime(datagram); - - var time = new Time() { - time = igt.Milliseconds - }; - if (status == BridgeStatus.Playing) SendToClient(time); + var inGameTime = new InGameTime(datagram); + InGameTimeReceived?.Invoke(inGameTime); + if (status == BridgeStatus.Playing) { + var time = new Time() { + time = inGameTime.Milliseconds + }; + SendToClient(time); + } break; #endregion case DatagramID.Interaction: #region interaction var interaction = new Interaction(datagram); + InteractionReceived?.Invoke(interaction); var entityAction = new EntityAction() { chunkX = interaction.ChunkX, chunkY = interaction.ChunkY, @@ -324,7 +297,7 @@ bool tick() { case DatagramID.StaticUpdate: #region staticUpdate var staticUpdate = new StaticUpdate(datagram); - + StaticUpdateReceived?.Invoke(staticUpdate); var staticEntity = new ServerUpdate.StaticEntity() { chunkX = (int)(staticUpdate.Position.x / (65536 * 256)), chunkY = (int)(staticUpdate.Position.y / (65536 * 256)), @@ -348,7 +321,7 @@ bool tick() { case DatagramID.Particle: #region particle var particleDatagram = new Particle(datagram); - + ParticleReceived?.Invoke(particleDatagram); var particleSubPacket = new ServerUpdate.Particle() { position = particleDatagram.Position, velocity = particleDatagram.Velocity, @@ -364,142 +337,28 @@ bool tick() { spread = particleDatagram.Spread }; serverUpdate.particles.Add(particleSubPacket); + writeServerUpdate = true; break; #endregion case DatagramID.RemoveDynamicEntity: #region RemoveDynamicEntity var rde = new RemoveDynamicEntity(datagram); + DynamicEntityRemoved?.Invoke(rde); entityUpdate = new EntityUpdate() { guid = rde.Guid, hostility = (Hostility)255, //workaround for DC because i dont like packet2 HP = 0 }; - if (status == BridgeStatus.Playing) SendToClient(entityUpdate); + if (status == BridgeStatus.Playing) { + SendToClient(entityUpdate); + } dynamicEntities.Remove(rde.Guid); - RefreshPlayerlist(); break; #endregion case DatagramID.SpecialMove: #region speicalMove var specialMove = new SpecialMove(datagram); - switch (specialMove.Id) { - case SpecialMoveID.Taunt: - if (dynamicEntities.ContainsKey(specialMove.Guid)) { - if (status == BridgeStatus.Playing) { - CwRam.Teleport(dynamicEntities[specialMove.Guid].position); - CwRam.Freeze(5000); - } - } - break; - case SpecialMoveID.CursedArrow: - break; - case SpecialMoveID.ArrowRain: - break; - case SpecialMoveID.Shrapnel: - var su = new ServerUpdate(); - var blood_hit = new Hit() { - damage = 5f, - target = specialMove.Guid, - }; - su.hits.Add(blood_hit); - var blood_particles = new ServerUpdate.Particle() { - count = 10, - spread = 2f, - type = ParticleType.Normal, - size = 0.1f, - velocity = new FloatVector() { - z = 1f, - }, - color = new FloatVector() { - x = 1f, - y = 0f, - z = 0f - }, - alpha = 1f, - }; - su.particles.Add(blood_particles); - bool tick() { - bool f = status == BridgeStatus.Playing && dynamicEntities[specialMove.Guid].HP > 0; - if (f) { - blood_hit.position = blood_particles.position = dynamicEntities[specialMove.Guid].position; - SendToClient(su); - } - return !f; - } - Tools.DoLater(tick, 50, 100); - break; - case SpecialMoveID.SmokeBomb: - serverUpdate.particles.Add(new ServerUpdate.Particle() { - count = 1000, - spread = 5f, - type = ParticleType.NoGravity, - size = 5f, - velocity = new Resources.Utilities.FloatVector(), - color = new Resources.Utilities.FloatVector() { - x = 1f, - y = 1f, - z = 1f - }, - alpha = 1f, - position = dynamicEntities[specialMove.Guid].position - }); - writeServerUpdate = true; - break; - case SpecialMoveID.IceWave: - if (specialMove.Guid != guid) {//distance small enough - CwRam.Freeze(3000); - } - serverUpdate.particles.Add(new ServerUpdate.Particle() { - count = 100, - spread = 4f, - type = ParticleType.NoGravity, - size = 0.3f, - velocity = new FloatVector(), - color = new FloatVector() { - x = 0f, - y = 1f, - z = 1f - }, - alpha = 1f, - position = dynamicEntities[specialMove.Guid].position - }); - serverUpdate.particles.Add(new ServerUpdate.Particle() { - count = 100, - spread = 10f, - type = ParticleType.NoGravity, - size = 0.1f, - velocity = new FloatVector(), - color = new FloatVector() { - x = 1f, - y = 1f, - z = 1f - }, - alpha = 1f, - position = dynamicEntities[specialMove.Guid].position - }); - serverUpdate.particles.Add(new ServerUpdate.Particle() { - count = 100, - spread = 2f, - type = ParticleType.NoGravity, - size = 0.7f, - velocity = new FloatVector(), - color = new FloatVector() { - x = 0f, - y = 0f, - z = 1f - }, - alpha = 1f, - position = dynamicEntities[specialMove.Guid].position - }); - writeServerUpdate = true; - break; - case SpecialMoveID.Confusion: - break; - case SpecialMoveID.ShadowStep: - break; - default: - break; - } + SpecialMoveReceived?.Invoke(specialMove); break; #endregion default: @@ -513,6 +372,7 @@ private static void ProcessClientPacket(int packetID) { case PacketID.EntityUpdate: #region entityUpdate var entityUpdate = new EntityUpdate(creader); + EntityUpdateSent?.Invoke(entityUpdate); if (dynamicEntities.ContainsKey(entityUpdate.guid)) { entityUpdate.Filter(dynamicEntities[entityUpdate.guid]); entityUpdate.Merge(dynamicEntities[entityUpdate.guid]); @@ -520,9 +380,6 @@ private static void ProcessClientPacket(int packetID) { else { dynamicEntities.Add(entityUpdate.guid, entityUpdate); } - if (entityUpdate.name != null) { - RefreshPlayerlist(); - } if (!entityUpdate.IsEmpty) { SendUDP(entityUpdate.CreateDatagram()); } @@ -530,60 +387,14 @@ private static void ProcessClientPacket(int packetID) { #endregion case PacketID.EntityAction: #region entity action - EntityAction entityAction = new EntityAction(creader); - switch (entityAction.type) { - case ActionType.Talk: - #region Talk - break; - #endregion - case ActionType.StaticInteraction: - #region StaticInteraction - ChatMessage x = new ChatMessage() { - message = "You can't use this, your hands are too small.", - sender = 0 - }; - SendToClient(x); - break; - #endregion - case ActionType.PickUp: - #region PickUp - break; - #endregion - case ActionType.Drop: //send item back to dropper because dropping is disabled to prevent chatspam - #region Drop - if (form.radioButtonDestroy.Checked) { - SendToClient(new ChatMessage() { - message = "item destroyed", - sender = 0, - }); - } - else { - var serverUpdate = new ServerUpdate(); - var pickup = new ServerUpdate.Pickup() { - guid = guid, - item = entityAction.item - }; - serverUpdate.pickups.Add(pickup); - if (form.radioButtonDuplicate.Checked) { - serverUpdate.pickups.Add(pickup); - } - SendToClient(serverUpdate); - } - break; - #endregion - case ActionType.CallPet: - #region CallPet - break; - #endregion - default: - //unknown type - break; - } + var entityAction = new EntityAction(creader); + EntityActionSent?.Invoke(entityAction); break; #endregion case PacketID.Hit: #region hit var hit = new Hit(creader); + HitSent?.Invoke(hit); var attack = new Attack() { Target = (ushort)hit.target, Damage = hit.damage, @@ -595,57 +406,12 @@ private static void ProcessClientPacket(int packetID) { Critical = hit.critical }; SendUDP(attack.data); - lastTarget = attack.Target; break; #endregion case PacketID.PassiveProc: #region passiveProc var passiveProc = new PassiveProc(creader); - switch (passiveProc.type) { - case ProcType.Bulwalk: - SendToClient(new ChatMessage() { - message = string.Format("bulwalk: {0}% dmg reduction", 1.0f - passiveProc.modifier), - sender = 0, - }); - break; - case ProcType.WarFrenzy: - CwRam.PlayerEntity.BossBuff = true; - bool DisableBossBuff() { - bool f = status == BridgeStatus.Playing && dynamicEntities[guid].HP > 0; - if (f) { - CwRam.PlayerEntity.BossBuff = false; - } - return !f; - } - Tools.DoLater(DisableBossBuff, passiveProc.duration, 1); - break; - case ProcType.Camouflage: - break; - case ProcType.Poison: - break; - case ProcType.UnknownA: - break; - case ProcType.ManaShield: - SendToClient(new ChatMessage() { - message = string.Format("manashield: {0}", passiveProc.modifier), - sender = 0, - }); - break; - case ProcType.UnknownB: - break; - case ProcType.UnknownC: - break; - case ProcType.FireSpark: - break; - case ProcType.Intuition: - break; - case ProcType.Elusiveness: - break; - case ProcType.Swiftness: - break; - default: - break; - } + PassiveProcSent?.Invoke(passiveProc); var proc = new Proc() { Target = (ushort)passiveProc.target, Type = passiveProc.type, @@ -658,6 +424,7 @@ bool DisableBossBuff() { case PacketID.Shoot: #region shoot var shoot = new Shoot(creader); + ShotSent?.Invoke(shoot); var projectile = new Projectile() { Position = shoot.position, Velocity = shoot.velocity, @@ -672,26 +439,7 @@ bool DisableBossBuff() { case PacketID.Chat: #region chat var chatMessage = new ChatMessage(creader); - if (chatMessage.message.ToLower() == @"/plane") { - Console.Beep(); - var serverUpdate = new ServerUpdate() { - blockDeltas = new Vox("model.vox").Parse(), - }; - foreach (var block in serverUpdate.blockDeltas) { - block.position.x += 0x802080;//(int)(dynamicEntities[guid].position.x / 0x10000);//8286946; - block.position.y += 0x802080;//(int)(dynamicEntities[guid].position.y / 0x10000);//8344456; - block.position.z += 150;// (int)(dynamicEntities[guid].position.z / 0x10000);//220; - } - SendToClient(serverUpdate); - } - if (chatMessage.message.ToLower() == @"/spawn") { - CwRam.Teleport(new LongVector() { - x = 0x8020800000, - y = 0x8020800000, - z = 0, - }); - break; - } + ChatMessageSent?.Invoke(chatMessage); var chat = new Chat() { Sender = guid,//client doesn't send this Text = chatMessage.message @@ -702,16 +450,19 @@ bool DisableBossBuff() { case PacketID.Chunk: #region chunk var chunk = new Chunk(creader); + ChunkDiscovered?.Invoke(chunk); break; #endregion case PacketID.Sector: #region sector var sector = new Sector(creader); + SectorDiscovered?.Invoke(sector); break; #endregion case PacketID.Version: #region version var version = new ProtocolVersion(creader); + VersionSent?.Invoke(version); if (version.version != 3) { version.version = 3; SendToClient(version); @@ -802,224 +553,10 @@ private static void ProcessServerPacket(int packetID) { } } - public static void RefreshPlayerlist() { - form.Invoke((Action)form.listBoxPlayers.Items.Clear); - foreach (var dynamicEntity in dynamicEntities.Values.ToList()) { - if (dynamicEntity.hostility == Hostility.Player) { - form.Invoke(new Action(() => form.listBoxPlayers.Items.Add(dynamicEntity.name))); - } - } - } - - public static void OnHotkey(HotkeyID hotkey) { - if (CwRam.AnyInterfaceOpen) return; - if (hotkey == HotkeyID.TeleportToTown) { - CwRam.SetMode(Mode.Teleport_To_City, 0); - return; - } - var notification = new ChatMessage() { - sender = 0, - }; - bool spec = dynamicEntities[guid].specialization == 1; - switch (dynamicEntities[guid].entityClass) { - case EntityClass.Rogue when spec: - #region ninja - if (hotkey == HotkeyID.CtrlSpace) { - #region dash - notification.message = "using [dash]"; - CwRam.SetMode(Mode.Spin_Run, 0); - #endregion - } - else { - #region blink - notification.message = "using [blink]"; - if (dynamicEntities.ContainsKey(lastTarget)) { - CwRam.Teleport(dynamicEntities[lastTarget].position); - } - #endregion - } - break; - #endregion - case EntityClass.Rogue: - #region assassin - if (hotkey == HotkeyID.CtrlSpace) { - #region confusion - notification.message = "TODO: [confusion]"; - var specialMove = new SpecialMove() { - Guid = guid, - Id = SpecialMoveID.Confusion, - }; - SendUDP(specialMove.data); - #endregion - } - else { - #region shadow step - notification.message = "TOD: [shadow step]"; - var specialMove = new SpecialMove() { - Guid = guid, - Id = SpecialMoveID.ShadowStep, - }; - SendUDP(specialMove.data); - #endregion - } - break; - #endregion - case EntityClass.Warrior when spec: - #region guardian - if (hotkey == HotkeyID.CtrlSpace) { - #region taunt - notification.message = "using [taunt]"; - var specialMove = new SpecialMove() { - Guid = lastTarget, - Id = SpecialMoveID.Taunt, - }; - SendUDP(specialMove.data); - #endregion - } - else { - #region steel wall - notification.message = "using [steel wall]"; - CwRam.SetMode(Mode.Boss_Skill_Block, 0); - #endregion - } - break; - #endregion - case EntityClass.Warrior: - #region berserk - if (hotkey == HotkeyID.CtrlSpace) { - #region boulder toss - notification.message = "using [boulder toss]"; - CwRam.SetMode(Mode.Boulder_Toss, 0); - #endregion - } - else { - #region earth shatter - notification.message = "using [earth shatter]"; - CwRam.SetMode(Mode.Earth_Shatter, 0); - #endregion - } - break; - #endregion - case EntityClass.Mage when spec: - #region watermage - if (hotkey == HotkeyID.CtrlSpace) { - #region splash - notification.message = "using [splash]"; - CwRam.SetMode(Mode.Splash, 0); - #endregion - } - else { - #region ice wave - notification.message = "using [ice wave]"; - var specialMove = new SpecialMove() { - Guid = guid, - Id = SpecialMoveID.IceWave, - }; - SendUDP(specialMove.data); - #endregion - } - break; - #endregion - case EntityClass.Mage: - #region firemage - if (hotkey == HotkeyID.CtrlSpace) { - #region lava - notification.message = "using [lava]"; - CwRam.SetMode(Mode.Lava, 0); - #endregion - } - else { - #region beam - notification.message = "using [fire ray]"; - CwRam.SetMode(Mode.FireRay, 0); - #endregion - } - break; - #endregion - case EntityClass.Ranger when spec: - #region scout - if (hotkey == HotkeyID.CtrlSpace) { - #region shrapnel - notification.message = "using [shrapnel] bleeding test"; - var specialMove = new SpecialMove() { - Guid = guid, - Id = SpecialMoveID.Shrapnel, - }; - SendUDP(specialMove.data); - #endregion - } - else { - #region smoke bomb - notification.message = "using [smoke bomb]"; - var specialMove = new SpecialMove() { - Guid = guid, - Id = SpecialMoveID.SmokeBomb, - }; - SendUDP(specialMove.data); - - var fakeSmoke = new ServerUpdate(); - fakeSmoke.particles.Add(new ServerUpdate.Particle() { - count = 1000, - spread = 5f, - type = ParticleType.NoGravity, - size = 0.3f, - velocity = new Resources.Utilities.FloatVector(), - color = new Resources.Utilities.FloatVector() { - x = 1f, - y = 1f, - z = 1f - }, - alpha = 1f, - position = dynamicEntities[specialMove.Guid].position - }); - SendToClient(fakeSmoke); - #endregion - } - break; - #endregion - case EntityClass.Ranger: - #region sniper - if (hotkey == HotkeyID.CtrlSpace) { - #region cursed arrow - //TODO - notification.message = "TODO: [cursed arrow]"; - #endregion - } - else { - #region arrow rain - //TODO - notification.message = "TODO: [arrow rain]"; - //const int rainSize = 7; - //for (int x = 0; x < rainSize; x++) { - // for (int y = 0; y < rainSize; y++) { - // var projectile = new Projectile() { - // Scale = 1f, - // Type = ProjectileType.Arrow, - // Source = guid, - // Velocity = new FloatVector() { x = 0, y = 0, z = -1f }, - // Position = new LongVector() { - // x = 0x8020800000,//dynamicEntities[guid].position.x + (long)((dynamicEntities[guid].rayHit.x + x - rainSize / 2) * 0x10000), - // y = 0x8020800000,//dynamicEntities[guid].position.y + (long)((dynamicEntities[guid].rayHit.y + y - rainSize / 2) * 0x10000), - // z = 0x01000000,//dynamicEntities[guid].position.z + (long)((dynamicEntities[guid].rayHit.z + 10) * 0x10000), - // } - // }; - // SendUDP(projectile.data); - // ProcessDatagram(projectile.data); - // } - //} - #endregion - } - break; - #endregion - } - CwRam.memory.WriteInt(CwRam.EntityStart + 0x1164, 3);//mana cubes - SendToClient(notification); - } - - private static void SendUDP(byte[] data) { + public static void SendUDP(byte[] data) { udpToServer.Send(data, data.Length); } - private static void SendToClient(Packet packet) { + public static void SendToClient(Packet packet) { outgoingMutex.WaitOne(); try { packet.Write(cwriter); diff --git a/Bridge/BridgeCore_Events.cs b/Bridge/BridgeCore_Events.cs new file mode 100644 index 0000000..b4c452a --- /dev/null +++ b/Bridge/BridgeCore_Events.cs @@ -0,0 +1,57 @@ +using Resources.Datagram; +using Resources.Packet; +using System; + +namespace Bridge { + public delegate void EntityUpdateSentEventHandler(EntityUpdate entityUpdate); + public delegate void EntityActionSentEventHandler(EntityAction entityAction); + public delegate void HitSentHandler(Hit hit); + public delegate void PassiveProcSentEventHandler(PassiveProc passiveProc); + public delegate void ShotSentHandler(Shoot shoot); + public delegate void ChatMessageSentEventHandler(ChatMessage chatMessage); + public delegate void ChunkDiscoveredEventHandler(Chunk chunk); + public delegate void SectorDiscoveredEventHandler(Sector sector); + public delegate void VersionSentEventHandler(ProtocolVersion protocolVersion); + + public delegate void EntityUpdateReceivedEventHandler(EntityUpdate entityUpdate); + public delegate void AttackReceivedEventHandler(Attack attack); + public delegate void ProjectileReceivedEventHandler(Projectile projectile); + public delegate void PassiveProcReceivedEventHandler(Proc proc); + public delegate void ChatMessageReceivedEventHandler(Chat chat); + public delegate void InGameTimeReceivedEventHandler(InGameTime inGameTime); + public delegate void InteractionReceivedEventHandler(Interaction interaction); + public delegate void StaticUpdateReceivedEventHandler(StaticUpdate staticUpdate); + public delegate void ParticleReceivedEventHandler(Particle particle); + public delegate void DynamicEntityRemovedEventHandler(RemoveDynamicEntity removeDynamicEntity); + public delegate void SpecialMoveReceiveddEventHandler(SpecialMove specialMove); + + public delegate void ClientConnectedEventHandler(); + public delegate void ClientDisconnectedEventHandler(); + + public static partial class BridgeCore { + public static event EntityUpdateSentEventHandler EntityUpdateSent; + public static event EntityActionSentEventHandler EntityActionSent; + public static event HitSentHandler HitSent; + public static event PassiveProcSentEventHandler PassiveProcSent; + public static event ShotSentHandler ShotSent; + public static event ChatMessageSentEventHandler ChatMessageSent; + public static event ChunkDiscoveredEventHandler ChunkDiscovered; + public static event SectorDiscoveredEventHandler SectorDiscovered; + public static event VersionSentEventHandler VersionSent; + + public static event EntityUpdateReceivedEventHandler EntityUpdateReceived; + public static event AttackReceivedEventHandler AttackReceived; + public static event ProjectileReceivedEventHandler ProjectileReceived; + public static event PassiveProcReceivedEventHandler PassiveProcReceived; + public static event ChatMessageReceivedEventHandler ChatMessageReceived; + public static event InGameTimeReceivedEventHandler InGameTimeReceived; + public static event InteractionReceivedEventHandler InteractionReceived; + public static event StaticUpdateReceivedEventHandler StaticUpdateReceived; + public static event ParticleReceivedEventHandler ParticleReceived; + public static event DynamicEntityRemovedEventHandler DynamicEntityRemoved; + public static event SpecialMoveReceiveddEventHandler SpecialMoveReceived; + + public static event ClientConnectedEventHandler ClientConnected; + public static event ClientDisconnectedEventHandler ClientDisconnected; + } +} diff --git a/Bridge/Extensions/ExtensionsCore.cs b/Bridge/Extensions/ExtensionsCore.cs new file mode 100644 index 0000000..db7fda9 --- /dev/null +++ b/Bridge/Extensions/ExtensionsCore.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Bridge.Extensions { + public static class ExtensionsCore { + public static void Init() { + Logging.Init(); + NameSubjectToChange.Init(); + SpecialMoves.Init(); + } + } +} diff --git a/Bridge/Extensions/Logging.cs b/Bridge/Extensions/Logging.cs new file mode 100644 index 0000000..ed91b3e --- /dev/null +++ b/Bridge/Extensions/Logging.cs @@ -0,0 +1,57 @@ +using Resources; +using Resources.Datagram; +using Resources.Packet; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Bridge.Extensions { + public static class Logging { + public static void Init() { + BridgeCore.ChatMessageReceived += ChatLog; + BridgeCore.ClientConnected += LogConnect; + BridgeCore.ClientDisconnected += LogDisconnect; + + BridgeCore.EntityUpdateReceived += CheckForNewName; + BridgeCore.EntityUpdateSent += CheckForNewName; + BridgeCore.DynamicEntityRemoved += RemoveNameFromList; + BridgeCore.ClientDisconnected += RefreshPlayerlist; + } + + private static void ChatLog(Chat chat) { + if (chat.Sender == 0) { + BridgeCore.form.Log(chat.Text + "\n", Color.Magenta); + } + else { + BridgeCore.form.Log(BridgeCore.dynamicEntities[chat.Sender].name + ": ", Color.Cyan); + BridgeCore.form.Log(chat.Text + "\n", Color.White); + } + } + private static void LogConnect() { + BridgeCore.form.Log("client connected\n", Color.Green); + } + private static void LogDisconnect() { + BridgeCore.form.Log("client disconnected\n", Color.Red); + } + + private static void CheckForNewName(EntityUpdate entityUpdate) { + if (entityUpdate.name != null) { + RefreshPlayerlist(); + } + } + private static void RemoveNameFromList(RemoveDynamicEntity rde) { + RefreshPlayerlist(); + } + private static void RefreshPlayerlist() { + BridgeCore.form.Invoke((Action)BridgeCore.form.listBoxPlayers.Items.Clear); + foreach (var dynamicEntity in BridgeCore.dynamicEntities.Values.ToList()) { + if (dynamicEntity.hostility == Hostility.Player) { + BridgeCore.form.Invoke(new Action(() => BridgeCore.form.listBoxPlayers.Items.Add(dynamicEntity.name))); + } + } + } + } +} diff --git a/Bridge/Extensions/NameSubjectToChange.cs b/Bridge/Extensions/NameSubjectToChange.cs new file mode 100644 index 0000000..daef5f1 --- /dev/null +++ b/Bridge/Extensions/NameSubjectToChange.cs @@ -0,0 +1,167 @@ +using Resources; +using Resources.Datagram; +using Resources.Packet; +using Resources.Utilities; +using System; +using System.Drawing; +using System.Linq; + +namespace Bridge.Extensions { + public static class NameSubjectToChange { + public static void Init() { + BridgeCore.EntityUpdateReceived += Teleport; + BridgeCore.AttackReceived += Knockback; + BridgeCore.PassiveProcReceived += Poison; + BridgeCore.EntityActionSent += HandleEntityAction; + } + + private static void Teleport(EntityUpdate entityUpdate) { + if (BridgeCore.status == BridgeStatus.Playing) { + if (entityUpdate.guid == BridgeCore.guid) { + CwRam.Teleport(entityUpdate.position); + //todo: prevent packet from being sent to client + } + } + } + private static void Knockback(Attack attack) { + CwRam.Knockback(attack.Direction); + } + private static void Poison(Proc proc) { + if (proc.Type == ProcType.Poison && proc.Target == BridgeCore.guid) { + var su = new ServerUpdate(); + su.hits.Add(new Hit() { + damage = proc.Modifier, + target = BridgeCore.guid, + position = BridgeCore.dynamicEntities[BridgeCore.guid].position, + }); + bool tick() { + bool f = BridgeCore.status == BridgeStatus.Playing && BridgeCore.dynamicEntities[BridgeCore.guid].HP > 0; + if (f) { + BridgeCore.SendToClient(su); + } + return !f; + } + Tools.DoLater(tick, 500, 7); + } + } + + private static void HandleEntityAction(EntityAction entityAction) { + switch (entityAction.type) { + case ActionType.Talk: + #region Talk + break; + #endregion + case ActionType.StaticInteraction: + #region StaticInteraction + ChatMessage x = new ChatMessage() { + message = "static interation is disabled", + sender = 0 + }; + BridgeCore.SendToClient(x); + break; + #endregion + case ActionType.PickUp: + #region PickUp + break; + #endregion + case ActionType.Drop: //send item back to dropper because dropping is disabled to prevent chatspam + #region Drop + if (BridgeCore.form.radioButtonDestroy.Checked) { + BridgeCore.SendToClient(new ChatMessage() { + message = "item destroyed", + sender = 0, + }); + } + else { + var serverUpdate = new ServerUpdate(); + var pickup = new ServerUpdate.Pickup() { + guid = BridgeCore.guid, + item = entityAction.item + }; + serverUpdate.pickups.Add(pickup); + if (BridgeCore.form.radioButtonDuplicate.Checked) { + serverUpdate.pickups.Add(pickup); + } + BridgeCore.SendToClient(serverUpdate); + } + break; + #endregion + case ActionType.CallPet: + #region CallPet + break; + #endregion + default: + //unknown type + break; + } + } + private static void HandlePassiveProc(PassiveProc passiveProc) { + switch (passiveProc.type) { + case ProcType.Bulwalk: + BridgeCore.SendToClient(new ChatMessage() { + message = string.Format("bulwalk: {0}% dmg reduction", 1.0f - passiveProc.modifier), + sender = 0, + }); + break; + case ProcType.WarFrenzy: + CwRam.PlayerEntity.BossBuff = true; + bool DisableBossBuff() { + bool f = BridgeCore.status == BridgeStatus.Playing && BridgeCore.dynamicEntities[BridgeCore.guid].HP > 0; + if (f) { + CwRam.PlayerEntity.BossBuff = false; + } + return !f; + } + Tools.DoLater(DisableBossBuff, passiveProc.duration, 1); + break; + case ProcType.Camouflage: + break; + case ProcType.Poison: + break; + case ProcType.UnknownA: + break; + case ProcType.ManaShield: + BridgeCore.SendToClient(new ChatMessage() { + message = string.Format("manashield: {0}", passiveProc.modifier), + sender = 0, + }); + break; + case ProcType.UnknownB: + break; + case ProcType.UnknownC: + break; + case ProcType.FireSpark: + break; + case ProcType.Intuition: + break; + case ProcType.Elusiveness: + break; + case ProcType.Swiftness: + break; + default: + break; + } + } + private static void ClientSideChatCommands(ChatMessage chatMessage) { + if (chatMessage.message.ToLower() == @"/plane") { + Console.Beep(); + var serverUpdate = new ServerUpdate() { + blockDeltas = new Vox("model.vox").Parse(), + }; + foreach (var block in serverUpdate.blockDeltas) { + block.position.x += 0x802080;//(int)(dynamicEntities[guid].position.x / 0x10000);//8286946; + block.position.y += 0x802080;//(int)(dynamicEntities[guid].position.y / 0x10000);//8344456; + block.position.z += 150;// (int)(dynamicEntities[guid].position.z / 0x10000);//220; + } + BridgeCore.SendToClient(serverUpdate); + } + if (chatMessage.message.ToLower() == @"/spawn") { + CwRam.Teleport(new LongVector() { + x = 0x8020800000, + y = 0x8020800000, + z = 0, + }); + } + } + } +} diff --git a/Bridge/Extensions/SpecialMoves.cs b/Bridge/Extensions/SpecialMoves.cs new file mode 100644 index 0000000..0da06c8 --- /dev/null +++ b/Bridge/Extensions/SpecialMoves.cs @@ -0,0 +1,375 @@ +using Resources; +using Resources.Datagram; +using Resources.Packet; +using Resources.Utilities; +using System.Windows.Forms; + +namespace Bridge.Extensions { + public static class SpecialMoves { + private static ushort lastTarget; + + public static void Init() { + BridgeCore.HitSent += RememberLastTarget; + BridgeCore.SpecialMoveReceived += HandleSpecialMoves; + BridgeCore.ClientConnected += EnableHotkeys; + BridgeCore.ClientDisconnected += DisableHotkeys; + } + + private static void RememberLastTarget(Hit hit) { + lastTarget = (ushort)hit.target; + } + private static void HandleSpecialMoves(SpecialMove specialMove) { + switch (specialMove.Id) { + case SpecialMoveID.Taunt: + if (BridgeCore.dynamicEntities.ContainsKey(specialMove.Guid)) { + if (BridgeCore.status == BridgeStatus.Playing) { + CwRam.Teleport(BridgeCore.dynamicEntities[specialMove.Guid].position); + CwRam.Freeze(5000); + } + } + break; + case SpecialMoveID.CursedArrow: + break; + case SpecialMoveID.ArrowRain: + break; + case SpecialMoveID.Shrapnel: + var su = new ServerUpdate(); + var blood_hit = new Hit() { + damage = 5f, + target = specialMove.Guid, + }; + su.hits.Add(blood_hit); + var blood_particles = new ServerUpdate.Particle() { + count = 10, + spread = 2f, + type = ParticleType.Normal, + size = 0.1f, + velocity = new FloatVector() { + z = 1f, + }, + color = new FloatVector() { + x = 1f, + y = 0f, + z = 0f + }, + alpha = 1f, + }; + su.particles.Add(blood_particles); + bool tick() { + bool f = BridgeCore.status == BridgeStatus.Playing && BridgeCore.dynamicEntities[specialMove.Guid].HP > 0; + if (f) { + blood_hit.position = blood_particles.position = BridgeCore.dynamicEntities[specialMove.Guid].position; + BridgeCore.SendToClient(su); + } + return !f; + } + Tools.DoLater(tick, 50, 100); + break; + case SpecialMoveID.SmokeBomb: + var serverUpdate = new ServerUpdate(); + serverUpdate.particles.Add(new ServerUpdate.Particle() { + count = 1000, + spread = 5f, + type = ParticleType.NoGravity, + size = 5f, + velocity = new FloatVector(), + color = new FloatVector() { + x = 1f, + y = 1f, + z = 1f + }, + alpha = 1f, + position = BridgeCore.dynamicEntities[specialMove.Guid].position + }); + if (BridgeCore.status == BridgeStatus.Playing) { + BridgeCore.SendToClient(serverUpdate); + } + break; + case SpecialMoveID.IceWave: + if (specialMove.Guid != BridgeCore.guid) {//distance small enough + CwRam.Freeze(3000); + } + serverUpdate = new ServerUpdate(); + serverUpdate.particles.Add(new ServerUpdate.Particle() { + count = 100, + spread = 4f, + type = ParticleType.NoGravity, + size = 0.3f, + velocity = new FloatVector(), + color = new FloatVector() { + x = 0f, + y = 1f, + z = 1f + }, + alpha = 1f, + position = BridgeCore.dynamicEntities[specialMove.Guid].position + }); + serverUpdate.particles.Add(new ServerUpdate.Particle() { + count = 100, + spread = 10f, + type = ParticleType.NoGravity, + size = 0.1f, + velocity = new FloatVector(), + color = new FloatVector() { + x = 1f, + y = 1f, + z = 1f + }, + alpha = 1f, + position = BridgeCore.dynamicEntities[specialMove.Guid].position + }); + serverUpdate.particles.Add(new ServerUpdate.Particle() { + count = 100, + spread = 2f, + type = ParticleType.NoGravity, + size = 0.7f, + velocity = new FloatVector(), + color = new FloatVector() { + x = 0f, + y = 0f, + z = 1f + }, + alpha = 1f, + position = BridgeCore.dynamicEntities[specialMove.Guid].position + }); + if (BridgeCore.status == BridgeStatus.Playing) { + BridgeCore.SendToClient(serverUpdate); + } + break; + case SpecialMoveID.Confusion: + break; + case SpecialMoveID.ShadowStep: + break; + default: + break; + } + } + + private static void EnableHotkeys() { + BridgeCore.form.keyboardHook.KeyboardChanged += OnKeyboardChanged; + } + private static void DisableHotkeys() { + BridgeCore.form.keyboardHook.KeyboardChanged -= OnKeyboardChanged; + } + private static void OnKeyboardChanged(Keys key, bool isDown) { + switch (key) { + case Keys.D4 when isDown: + OnHotkey(HotkeyID.CtrlSpace); + break; + case Keys.D5 when isDown: + OnHotkey(HotkeyID.SpecialMove2); + break; + case Keys.D0 when isDown: + OnHotkey(HotkeyID.TeleportToTown); + break; + default: + break; + } + } + private static void OnHotkey(HotkeyID hotkey) { + if (CwRam.AnyInterfaceOpen) return; + + if (hotkey == HotkeyID.TeleportToTown) { + CwRam.SetMode(Mode.Teleport_To_City, 0); + return; + } + var notification = new ChatMessage() { + sender = 0, + }; + bool spec = BridgeCore.dynamicEntities[BridgeCore.guid].specialization == 1; + switch (BridgeCore.dynamicEntities[BridgeCore.guid].entityClass) { + case EntityClass.Rogue when spec: + #region ninja + if (hotkey == HotkeyID.CtrlSpace) { + #region dash + notification.message = "using [dash]"; + CwRam.SetMode(Mode.Spin_Run, 0); + #endregion + } + else { + #region blink + notification.message = "using [blink]"; + if (BridgeCore.dynamicEntities.ContainsKey(lastTarget)) { + CwRam.Teleport(BridgeCore.dynamicEntities[lastTarget].position); + } + #endregion + } + break; + #endregion + case EntityClass.Rogue: + #region assassin + if (hotkey == HotkeyID.CtrlSpace) { + #region confusion + notification.message = "TODO: [confusion]"; + var specialMove = new SpecialMove() { + Guid = BridgeCore.guid, + Id = SpecialMoveID.Confusion, + }; + BridgeCore.SendUDP(specialMove.data); + #endregion + } + else { + #region shadow step + notification.message = "TOD: [shadow step]"; + var specialMove = new SpecialMove() { + Guid = BridgeCore.guid, + Id = SpecialMoveID.ShadowStep, + }; + BridgeCore.SendUDP(specialMove.data); + #endregion + } + break; + #endregion + case EntityClass.Warrior when spec: + #region guardian + if (hotkey == HotkeyID.CtrlSpace) { + #region taunt + notification.message = "using [taunt]"; + var specialMove = new SpecialMove() { + Guid = lastTarget, + Id = SpecialMoveID.Taunt, + }; + BridgeCore.SendUDP(specialMove.data); + #endregion + } + else { + #region steel wall + notification.message = "using [steel wall]"; + CwRam.SetMode(Mode.Boss_Skill_Block, 0); + #endregion + } + break; + #endregion + case EntityClass.Warrior: + #region berserk + if (hotkey == HotkeyID.CtrlSpace) { + #region boulder toss + notification.message = "using [boulder toss]"; + CwRam.SetMode(Mode.Boulder_Toss, 0); + #endregion + } + else { + #region earth shatter + notification.message = "using [earth shatter]"; + CwRam.SetMode(Mode.Earth_Shatter, 0); + #endregion + } + break; + #endregion + case EntityClass.Mage when spec: + #region watermage + if (hotkey == HotkeyID.CtrlSpace) { + #region splash + notification.message = "using [splash]"; + CwRam.SetMode(Mode.Splash, 0); + #endregion + } + else { + #region ice wave + notification.message = "using [ice wave]"; + var specialMove = new SpecialMove() { + Guid = BridgeCore.guid, + Id = SpecialMoveID.IceWave, + }; + BridgeCore.SendUDP(specialMove.data); + #endregion + } + break; + #endregion + case EntityClass.Mage: + #region firemage + if (hotkey == HotkeyID.CtrlSpace) { + #region lava + notification.message = "using [lava]"; + CwRam.SetMode(Mode.Lava, 0); + #endregion + } + else { + #region beam + notification.message = "using [fire ray]"; + CwRam.SetMode(Mode.FireRay, 0); + #endregion + } + break; + #endregion + case EntityClass.Ranger when spec: + #region scout + if (hotkey == HotkeyID.CtrlSpace) { + #region shrapnel + notification.message = "using [shrapnel] bleeding test"; + var specialMove = new SpecialMove() { + Guid = BridgeCore.guid, + Id = SpecialMoveID.Shrapnel, + }; + BridgeCore.SendUDP(specialMove.data); + #endregion + } + else { + #region smoke bomb + notification.message = "using [smoke bomb]"; + var specialMove = new SpecialMove() { + Guid = BridgeCore.guid, + Id = SpecialMoveID.SmokeBomb, + }; + BridgeCore.SendUDP(specialMove.data); + + var fakeSmoke = new ServerUpdate(); + fakeSmoke.particles.Add(new ServerUpdate.Particle() { + count = 1000, + spread = 5f, + type = ParticleType.NoGravity, + size = 0.3f, + velocity = new Resources.Utilities.FloatVector(), + color = new Resources.Utilities.FloatVector() { + x = 1f, + y = 1f, + z = 1f + }, + alpha = 1f, + position = BridgeCore.dynamicEntities[specialMove.Guid].position + }); + BridgeCore.SendToClient(fakeSmoke); + #endregion + } + break; + #endregion + case EntityClass.Ranger: + #region sniper + if (hotkey == HotkeyID.CtrlSpace) { + #region cursed arrow + //TODO + notification.message = "TODO: [cursed arrow]"; + #endregion + } + else { + #region arrow rain + //TODO + notification.message = "TODO: [arrow rain]"; + //const int rainSize = 7; + //for (int x = 0; x < rainSize; x++) { + // for (int y = 0; y < rainSize; y++) { + // var projectile = new Projectile() { + // Scale = 1f, + // Type = ProjectileType.Arrow, + // Source = guid, + // Velocity = new FloatVector() { x = 0, y = 0, z = -1f }, + // Position = new LongVector() { + // x = 0x8020800000,//dynamicEntities[guid].position.x + (long)((dynamicEntities[guid].rayHit.x + x - rainSize / 2) * 0x10000), + // y = 0x8020800000,//dynamicEntities[guid].position.y + (long)((dynamicEntities[guid].rayHit.y + y - rainSize / 2) * 0x10000), + // z = 0x01000000,//dynamicEntities[guid].position.z + (long)((dynamicEntities[guid].rayHit.z + 10) * 0x10000), + // } + // }; + // SendUDP(projectile.data); + // ProcessDatagram(projectile.data); + // } + //} + #endregion + } + break; + #endregion + } + CwRam.memory.WriteInt(CwRam.EntityStart + 0x1164, 3);//mana cubes + BridgeCore.SendToClient(notification); + } + } +} diff --git a/Bridge/FormMain.cs b/Bridge/FormMain.cs index 7c31963..f2f611d 100644 --- a/Bridge/FormMain.cs +++ b/Bridge/FormMain.cs @@ -1,4 +1,5 @@ -using ReadWriteProcessMemory; +using Bridge.Extensions; +using ReadWriteProcessMemory; using System; using System.Diagnostics; using System.Drawing; @@ -12,8 +13,8 @@ public partial class FormMain : Form { public FormRegister register = new FormRegister(); public FormChat chat = new FormChat(); public FormRankings rankings = new FormRankings(); + public KeyboardHook keyboardHook; private bool processAttached = false; - private KeyboardHook keyboardHook; public FormMain(string[]args) { InitializeComponent(); @@ -24,9 +25,10 @@ private void FormMain_Shown(object sender, EventArgs e) { chat.Left = Left + Width; BridgeCore.form = this; CwRam.formMain = this; + keyboardHook = new KeyboardHook(); new Thread(BridgeCore.ListenFromClientTCP).Start(); new Thread(BridgeCore.Connect).Start(); - keyboardHook = new KeyboardHook(); + ExtensionsCore.Init(); } private void timerSearchProcess_Tick(object sender, EventArgs e) { if (processAttached) { diff --git a/Bridge/KeyboardHook.cs b/Bridge/KeyboardHook.cs index 5b67069..c7b4d9c 100644 --- a/Bridge/KeyboardHook.cs +++ b/Bridge/KeyboardHook.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Runtime.InteropServices; -using System.Text; using System.Threading.Tasks; using System.Windows.Forms; @@ -92,25 +90,12 @@ private int KeybHookProc(int Code, int W, int L) { private Dictionary keyboardState = new Dictionary(); private void OnKey(Keys key, bool isDown) { if (GetForegroundWindow() != CwRam.memory.process.MainWindowHandle) return; - if (!keyboardState.ContainsKey(key)) keyboardState.Add(key, !isDown); if (keyboardState[key] == isDown) return; keyboardState[key] = isDown; - - if (!isDown) return;//temp fix to prevent activation on release - switch (key) { - case Keys.D4: - BridgeCore.OnHotkey(Resources.HotkeyID.CtrlSpace); - break; - case Keys.D5: - BridgeCore.OnHotkey(Resources.HotkeyID.SpecialMove2); - break; - case Keys.D0: - BridgeCore.OnHotkey(Resources.HotkeyID.TeleportToTown); - break; - default: - break; - } + KeyboardChanged?.Invoke(key, isDown); } + public delegate void KeyboardChangedEventHandler(Keys key, bool isDown); + public event KeyboardChangedEventHandler KeyboardChanged; } } diff --git a/Resources/Config.cs b/Resources/Config.cs index 3bc30fb..eb03c47 100644 --- a/Resources/Config.cs +++ b/Resources/Config.cs @@ -2,7 +2,7 @@ static public class Config { public const int mapseed = 8710; //hardcoded for now public const int bridgeVersion = 16; - public const string serverIP = "pb97.ddns.net";//temp + public const string serverIP = "localhost";//temp public const int serverPort = 12346; } } diff --git a/Resources/CubeworldNetworking b/Resources/CubeworldNetworking index b24405c..5323adb 160000 --- a/Resources/CubeworldNetworking +++ b/Resources/CubeworldNetworking @@ -1 +1 @@ -Subproject commit b24405c0d42a1384d3cce28cae56d7858fb568c5 +Subproject commit 5323adb8735c2b78d27fd2add8f4df54addbf546 From 33b28599c2d569a07558d9a1baf795067ca0cc2d Mon Sep 17 00:00:00 2001 From: LastExceed Date: Thu, 18 Oct 2018 11:39:21 +0200 Subject: [PATCH 12/18] fix possible server crash from enumeration changed --- Server/ServerCore.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Server/ServerCore.cs b/Server/ServerCore.cs index 98b9cba..657a172 100644 --- a/Server/ServerCore.cs +++ b/Server/ServerCore.cs @@ -71,7 +71,7 @@ public static void SendUDP(byte[] data, Player target) { udpClient.Send(data, data.Length, target.RemoteEndPoint); } public static void BroadcastUDP(byte[] data, Player toSkip = null) { - foreach (var player in players) { + foreach (var player in players.ToList()) { if (player != toSkip) { SendUDP(data, player); } From 4020c9d35dc5699ad2fba5012d8e84a20e93b2bb Mon Sep 17 00:00:00 2001 From: BuildTools Date: Sat, 13 Oct 2018 11:52:50 +0200 Subject: [PATCH 13/18] First Implementation of Plugins System with Arena and Duel --- Server/Plugins/Arena/ArenaConfig.cs | 6 + Server/Plugins/Arena/ArenaCore.cs | 24 ++ Server/Plugins/Arena/Commands.cs | 234 ++++++++++++++++++ .../Plugins/Arena/Database/ArenaDatabase.cs | 173 +++++++++++++ Server/Plugins/Arena/Database/ArenaEntity.cs | 43 ++++ .../Migrations/ArenaDatabaseModelSnapshot.cs | 44 ++++ .../arena_initialCreate.Designer.cs | 45 ++++ .../Arena/Migrations/arena_initialCreate.cs | 35 +++ Server/Plugins/Arena/Resources/Enum.cs | 28 +++ Server/Plugins/Duel/Commands.cs | 156 ++++++++++++ Server/Plugins/Duel/DuelConfig.cs | 11 + Server/Plugins/Duel/DuelCore.cs | 21 ++ Server/Plugins/Duel/DuelSystem.cs | 197 +++++++++++++++ Server/Plugins/Duel/PlayerDuel.cs | 17 ++ Server/Plugins/Plugin.cs | 20 ++ Server/Plugins/PluginsConfig.cs | 13 + Server/Plugins/PluginsCore.cs | 34 +++ Server/Server.csproj | 4 + Server/ServerCore.cs | 7 +- 19 files changed, 1109 insertions(+), 3 deletions(-) create mode 100644 Server/Plugins/Arena/ArenaConfig.cs create mode 100644 Server/Plugins/Arena/ArenaCore.cs create mode 100644 Server/Plugins/Arena/Commands.cs create mode 100644 Server/Plugins/Arena/Database/ArenaDatabase.cs create mode 100644 Server/Plugins/Arena/Database/ArenaEntity.cs create mode 100644 Server/Plugins/Arena/Migrations/ArenaDatabaseModelSnapshot.cs create mode 100644 Server/Plugins/Arena/Migrations/arena_initialCreate.Designer.cs create mode 100644 Server/Plugins/Arena/Migrations/arena_initialCreate.cs create mode 100644 Server/Plugins/Arena/Resources/Enum.cs create mode 100644 Server/Plugins/Duel/Commands.cs create mode 100644 Server/Plugins/Duel/DuelConfig.cs create mode 100644 Server/Plugins/Duel/DuelCore.cs create mode 100644 Server/Plugins/Duel/DuelSystem.cs create mode 100644 Server/Plugins/Duel/PlayerDuel.cs create mode 100644 Server/Plugins/Plugin.cs create mode 100644 Server/Plugins/PluginsConfig.cs create mode 100644 Server/Plugins/PluginsCore.cs diff --git a/Server/Plugins/Arena/ArenaConfig.cs b/Server/Plugins/Arena/ArenaConfig.cs new file mode 100644 index 0000000..1e09cf7 --- /dev/null +++ b/Server/Plugins/Arena/ArenaConfig.cs @@ -0,0 +1,6 @@ +namespace Server.Plugins.Arena +{ + static public class ArenaConfig + { + } +} diff --git a/Server/Plugins/Arena/ArenaCore.cs b/Server/Plugins/Arena/ArenaCore.cs new file mode 100644 index 0000000..e05cbaf --- /dev/null +++ b/Server/Plugins/Arena/ArenaCore.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Microsoft.EntityFrameworkCore; +using Server.Plugins.Arena.Database; + +namespace Server.Plugins.Arena +{ + class ArenaCore : Plugin + { + public static ArenaDatabase ArenaDatabase; + public ArenaCore() + { + ArenaDatabase = new ArenaDatabase(); + ArenaDatabase.Database.Migrate(); + Commands.Init(ArenaDatabase,this); + pluginName = "Arena"; + } + public override Boolean hasCommands() + { + return true; + } + } +} diff --git a/Server/Plugins/Arena/Commands.cs b/Server/Plugins/Arena/Commands.cs new file mode 100644 index 0000000..819676f --- /dev/null +++ b/Server/Plugins/Arena/Commands.cs @@ -0,0 +1,234 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Resources; +using Server.Plugins.Arena.Database; +using Server.Plugins.Arena.Resources; + +namespace Server.Plugins.Arena +{ + class Commands + { + public static ArenaDatabase ArenaDatabase; + public static Plugin pluginRef; + public static void Init(ArenaDatabase arenaDatabase,Plugin plugin) + { + Server.ChatMessageReceived += ParseAsCommand; + ArenaDatabase = arenaDatabase; + pluginRef = plugin; + } + private static void ParseAsCommand(string message, Player source) + { + if (!message.StartsWith("/"+pluginRef.getName())) + { + return; + } + else if(message.Length == 1 + pluginRef.getName().Length) + { + Server.Notify(source, string.Format("Type /"+pluginRef.getName()+" help for further informations about this command")); + return; + } + var parameters = message.Substring(2+pluginRef.getName().Length).Split(" "); + foreach (var item in parameters) + { + Console.WriteLine(item.ToString()); + } + var command = parameters[0].ToLower(); + ArenaResponse response = ArenaResponse.Null; + long[] currentPos = new long[3]; + switch (command) + { + case "setup": + #region setup + if (source.entity.name != "BLACKROCK" && source.entity.name != "BLIZZY") + { + Server.Notify(source, "[Arena] no permission"); + break; + } + string arenaName = null; + if (parameters.Length == 3) + { + arenaName = parameters[2].ToLower(); + } + response = ArenaDatabase.launchSetupArena(arenaName); + if (response == ArenaResponse.SetupLaunched) + { + Server.Notify(source, String.Format("[Arena] The Setup Arena has been initialized !")); + } + else if (response == ArenaResponse.SetupAlreadyLaunched) + { + Server.Notify(source, String.Format("[Arena] The Setup Arena has already been initialized.")); + } + break; + #endregion + /*case "list": + #region arena-list + ArenaDatabase.listArena(); + break; + #endregion + */ + case "set": + #region setup-set + if (source.entity.name != "BLACKROCK" && source.entity.name != "BLIZZY") + { + Server.Notify(source, "[Arena] no permission"); + break; + } + if (parameters.Length == 3) + { + currentPos = new long[3] + { + source.entity.position.x, + source.entity.position.y, + source.entity.position.z + }; + switch (parameters[2].ToLower()) + { + case "player1": + response = ArenaDatabase.setPositionSetupArena(currentPos, ArenaPositionName.player1); + break; + case "player2": + response = ArenaDatabase.setPositionSetupArena(currentPos, ArenaPositionName.player2); + break; + case "spectator": + response = ArenaDatabase.setPositionSetupArena(currentPos, ArenaPositionName.spectator); + break; + default: + Server.Notify(source, String.Format("Syntax : /arena set player1|player2|spectator")); + break; + } + if (response == ArenaResponse.SetupPositionSet) + { + Server.Notify(source, String.Format("[Arena] Parameters {0} has been successfully updated", parameters[2].ToLower())); + } + else if (response == ArenaResponse.SetupEmpty) + { + Server.Notify(source, String.Format("[Arena] The Setup Arena hasn't been initialized")); + } + } + else + { + Server.Notify(source, String.Format("Syntax : /arena set player1|player2|spectator")); + } + break; + #endregion + case "name": + #region setup-name + if (source.entity.name != "BLACKROCK" && source.entity.name != "BLIZZY") + { + Server.Notify(source, "[Arena] no permission"); + break; + } + if (parameters.Length == 3) + { + response = ArenaDatabase.setNameArena(parameters[2].ToLower()); + if (response == ArenaResponse.SetupNameSet) + { + Server.Notify(source, String.Format("[Arena] The Setup Arena's name has been changed !")); + } + else if (response == ArenaResponse.SetupEmpty) + { + Server.Notify(source, String.Format("[Arena] The Setup Arena hasn't been initialized")); + } + } + else + { + Server.Notify(source, String.Format("Syntax : /arena name [newName]")); + } + break; + #endregion + case "create": + #region arena-create + if (source.entity.name != "BLACKROCK" && source.entity.name != "BLIZZY") + { + Server.Notify(source, "[Arena] no permission"); + break; + } + response = ArenaDatabase.SaveDuelArena(); + if (response == ArenaResponse.ArenaCreated) + { + Server.Notify(source, string.Format("[Arena] Arena has been successfully saved and is operational !")); + } + else if (response == ArenaResponse.SetupIncomplete) + { + Server.Notify(source, string.Format("[Arena] Setup Arena is incomplete !")); + } + else if (response == ArenaResponse.SetupEmpty) + { + Server.Notify(source, String.Format("[Arena] The Setup Arena hasn't been initialized")); + } + break; + #endregion + case "delete": + #region arena-delete + if (source.entity.name != "BLACKROCK" && source.entity.name != "BLIZZY") + { + Server.Notify(source, "[Arena] no permission"); + break; + } + if (parameters.Length == 3) + { + bool isId = int.TryParse(parameters[2].ToLower(), out int n); + if (isId) + { + var id = Int32.Parse(parameters[2].ToLower()); + response = ArenaDatabase.RemoveDuelArena((uint)id); + } + else + { + response = ArenaDatabase.RemoveDuelArena(parameters[2].ToLower()); + } + switch (response) + { + case ArenaResponse.ArenaDeleted: + Server.Notify(source, string.Format("[Arena] Arena deleted !")); + break; + case ArenaResponse.ArenaNotFound: + Server.Notify(source, string.Format("[Arena] Invalid id or arena's name")); + break; + } + } + else + { + Server.Notify(source, string.Format("Syntax : /duel arena-delete [id] or /duel arena-delete [name] ")); + } + break; + #endregion + case "reset": + #region reset + if (source.entity.name != "BLACKROCK" && source.entity.name != "BLIZZY") + { + Server.Notify(source, "[Arena] no permission"); + break; + } + response = ArenaDatabase.ResetArena(); + if (response == ArenaResponse.ArenaReset) + { + Server.Notify(source, string.Format("[Arena] Arena's list reseted !")); + } + #endregion + break; + case "help": + #region arena-help + if (source.entity.name != "BLACKROCK" && source.entity.name != "BLIZZY") + { + Server.Notify(source, string.Format("/arena setup")); + Server.Notify(source, string.Format("/arena set player1|player2|spectator")); + Server.Notify(source, string.Format("/arena name [newName]")); + Server.Notify(source, string.Format("/arena create")); + Server.Notify(source, string.Format("/arena delete [ArenaId] or /arena delete [Name]")); + } + Server.Notify(source, string.Format("/arena list")); + break; + #endregion + default: + if (PluginsCore.pluginsWithCommands.Last().getName() == pluginRef.getName()) + { + Server.Notify(source, string.Format("unknown command '{0}'", parameters[0])); + } + break; + } + } + } +} diff --git a/Server/Plugins/Arena/Database/ArenaDatabase.cs b/Server/Plugins/Arena/Database/ArenaDatabase.cs new file mode 100644 index 0000000..52bf8d4 --- /dev/null +++ b/Server/Plugins/Arena/Database/ArenaDatabase.cs @@ -0,0 +1,173 @@ +using Microsoft.EntityFrameworkCore; +using Server.Plugins.Arena.Resources; +using Resources; +using System.Linq; +using System.IO; +using System; + +namespace Server.Plugins.Arena.Database +{ + public class ArenaDatabase : DbContext + { + const string dbFileName = "dbArena.sqlite"; + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + optionsBuilder.UseSqlite($"Data Source={dbFileName}"); + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + { + var arenas = modelBuilder.Entity(); + arenas.HasKey(x => x.Id); + arenas.Property(x => x.Name).IsRequired(); + } + } + public DbSet Arenas { get; set; } + public ArenaEntity setupArena; + public ArenaEntity FindArena(uint id = 0) + { + var arena = Arenas.SingleOrDefault(x => x.ArenaId == id); + return arena; + } + public ArenaEntity FetchRandomArena() + { + int range = Arenas.Count(); + Random rnd = new Random(); + int id = rnd.Next(0, range); + var arena = Arenas.SingleOrDefault(x => x.ArenaId == id); + return arena; + } + public ArenaResponse ResetArena() + { + Arenas.RemoveRange(Arenas.ToList()); + SaveChanges(); + return ArenaResponse.ArenaReset; + } + public ArenaResponse launchSetupArena(string name = null) + { + if (setupArena == null) + { + if (name == null) + { + name = "arena" + Arenas.Count().ToString(); + } + setupArena = new ArenaEntity((uint)Arenas.Count(), name); + return ArenaResponse.SetupLaunched; + } + return ArenaResponse.SetupAlreadyLaunched; + } + public ArenaResponse setNameArena(string arenaName = null) + { + if (setupArena != null) + { + if (arenaName == null) + { + arenaName = "arena" + Arenas.Count().ToString(); + } + setupArena.Name = arenaName; + return ArenaResponse.SetupNameSet; + } + return ArenaResponse.SetupEmpty; + } + public ArenaResponse setPositionSetupArena(long[] position, ArenaPositionName arenaPositionName) + { + if (setupArena != null) + { + switch (arenaPositionName) + { + case ArenaPositionName.player1: + setupArena.SpawnPosition1 = encodePosition(position); + break; + case ArenaPositionName.player2: + setupArena.SpawnPosition2 = encodePosition(position); + break; + case ArenaPositionName.spectator: + setupArena.SpawnPosition3 = encodePosition(position); + break; + } + return ArenaResponse.SetupPositionSet; + } + return ArenaResponse.SetupEmpty; + } + public ArenaResponse SaveDuelArena() + { + if (setupArena == null) + { + return ArenaResponse.SetupEmpty; + } + if (isValid(setupArena)) + { + Arenas.Add(setupArena); + SaveChanges(); + setupArena = null; + return ArenaResponse.ArenaCreated; + } + return ArenaResponse.SetupIncomplete; + } + + public ArenaResponse RemoveDuelArena(uint id = 0) + { + var arena = Arenas.SingleOrDefault(x => x.ArenaId == id); + if (arena == null) + { + return ArenaResponse.ArenaNotFound; + } + Arenas.Remove(arena); + SaveChanges(); + + return ArenaResponse.ArenaDeleted; + } + public ArenaResponse RemoveDuelArena(string name = null) + { + var arena = Arenas.SingleOrDefault(x => x.Name == name); + if (arena == null) + { + return ArenaResponse.ArenaNotFound; + } + Arenas.Remove(arena); + SaveChanges(); + return ArenaResponse.ArenaDeleted; + } + public void listArena() + { + var arenas = Arenas.ToList(); + foreach (ArenaEntity arena in arenas) + { + //Console.WriteLine(String.Format("Arena {0} : Name -> {1} , X -> {2}, Y -> {3}, Z -> {4}", arena.ArenaId, arena.Name, arena.X, arena.Y, arena.Z)); + } + } + public Boolean isValid(ArenaEntity arena) + { + if (arena.Name != null && arena.SpawnPosition1 != null && arena.SpawnPosition2 != null && arena.SpawnPosition3 != null) + { + if (arena.ArenaId == 0 && Arenas.Count() > 0) + { + return false; + } + else + { + return true; + } + } + return false; + } + public static byte[] encodePosition(long[] position) + { + byte[] encodedPosition = new byte[8 * position.Length]; + Array.Copy(BitConverter.GetBytes(position[0]), 0, encodedPosition, 0, 8); + Array.Copy(BitConverter.GetBytes(position[1]), 0, encodedPosition, 8, 8); + Array.Copy(BitConverter.GetBytes(position[2]), 0, encodedPosition, 16, 8); + return encodedPosition; + } + public static long[] decodePosition(byte[] encodedPosition) + { + long[] decodedPosition = new long[3]; + decodedPosition[0] = BitConverter.ToInt64(encodedPosition, 0); + decodedPosition[1] = BitConverter.ToInt64(encodedPosition, 8); + decodedPosition[2] = BitConverter.ToInt64(encodedPosition, 16); + return decodedPosition; + } + } +} diff --git a/Server/Plugins/Arena/Database/ArenaEntity.cs b/Server/Plugins/Arena/Database/ArenaEntity.cs new file mode 100644 index 0000000..5e3def3 --- /dev/null +++ b/Server/Plugins/Arena/Database/ArenaEntity.cs @@ -0,0 +1,43 @@ +using Server.Plugins.Arena.Resources; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Server.Plugins.Arena.Database +{ + public class ArenaEntity + { + public uint Id { get; set; } + public uint ArenaId { get; set; } + public string Name { get; set; } + public byte[] SpawnPosition1 { get; set; } + public byte[] SpawnPosition2 { get; set; } + public byte[] SpawnPosition3 { get; set; } + + public ArenaEntity() + { + } + public ArenaEntity(uint ArenaId, string Name) + { + this.ArenaId = ArenaId; + this.Name = Name; + } + public long[] getPosition(ArenaPositionName arenaPositionName) + { + var position = ArenaDatabase.decodePosition(SpawnPosition1); + switch (arenaPositionName) + { + case ArenaPositionName.player1: + position = ArenaDatabase.decodePosition(SpawnPosition1); + break; + case ArenaPositionName.player2: + position = ArenaDatabase.decodePosition(SpawnPosition2); + break; + case ArenaPositionName.spectator: + position = ArenaDatabase.decodePosition(SpawnPosition3); + break; + } + return position; + } + } +} diff --git a/Server/Plugins/Arena/Migrations/ArenaDatabaseModelSnapshot.cs b/Server/Plugins/Arena/Migrations/ArenaDatabaseModelSnapshot.cs new file mode 100644 index 0000000..e7255a8 --- /dev/null +++ b/Server/Plugins/Arena/Migrations/ArenaDatabaseModelSnapshot.cs @@ -0,0 +1,44 @@ +// +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage; +using Server.Database; +using Server.Plugins.Arena.Database; +using System; + +namespace Server.Plugins.Arena.Migrations +{ + [DbContext(typeof(ArenaDatabase))] + partial class ArenaDatabaseModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.0.2-rtm-10011"); + + modelBuilder.Entity("Server.Database.ArenaEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Name") + .IsRequired(); + + b.Property("SpawnPosition1"); + + b.Property("SpawnPosition2"); + + b.Property("SpawnPosition3"); + + b.HasKey("Id"); + + b.ToTable("Arenas"); + }); + +#pragma warning restore 612, 618 + } + } +} diff --git a/Server/Plugins/Arena/Migrations/arena_initialCreate.Designer.cs b/Server/Plugins/Arena/Migrations/arena_initialCreate.Designer.cs new file mode 100644 index 0000000..37e502e --- /dev/null +++ b/Server/Plugins/Arena/Migrations/arena_initialCreate.Designer.cs @@ -0,0 +1,45 @@ +// +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage; +using Server.Database; +using System; +using Server.Plugins.Arena.Database; +namespace Server.Plugins.Arena.Migrations +{ + [DbContext(typeof(ArenaDatabase))] + [Migration("Arena_initialCreate")] + partial class initialArenaCreate + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.0.2-rtm-10011"); + + modelBuilder.Entity("Server.Database.ArenaEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ArenaId"); + + b.Property("Name") + .IsRequired(); + + b.Property("SpawnPosition1"); + + b.Property("SpawnPosition2"); + + b.Property("SpawnPosition3"); + + b.HasKey("Id"); + + b.ToTable("Arenas"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Server/Plugins/Arena/Migrations/arena_initialCreate.cs b/Server/Plugins/Arena/Migrations/arena_initialCreate.cs new file mode 100644 index 0000000..fb86047 --- /dev/null +++ b/Server/Plugins/Arena/Migrations/arena_initialCreate.cs @@ -0,0 +1,35 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using System; +using System.Collections.Generic; + +namespace Server.Plugins.Arena.Migrations +{ + public partial class initialArenaCreate : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Arenas", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + ArenaId = table.Column(nullable: false), + Name = table.Column(nullable: false), + SpawnPosition1 = table.Column(nullable: false), // Spawn position of Player 1 + SpawnPosition2 = table.Column(nullable: false), // Spawn position of Player 2 + SpawnPosition3 = table.Column(nullable: false) // Spawn position of Spectator + }, + constraints: table => + { + table.PrimaryKey("PK_Arenas", x => x.Id); + }); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Arenas"); + } + } +} diff --git a/Server/Plugins/Arena/Resources/Enum.cs b/Server/Plugins/Arena/Resources/Enum.cs new file mode 100644 index 0000000..4881771 --- /dev/null +++ b/Server/Plugins/Arena/Resources/Enum.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Server.Plugins.Arena.Resources +{ + public enum ArenaResponse : byte + { + Null, + SetupLaunched, + SetupAlreadyLaunched, + SetupEmpty, + SetupNameSet, + SetupPositionSet, + SetupIncomplete, + ArenaCreated, + ArenaDeleted, + ArenaNotFound, + ArenaListEmpty, + ArenaReset + } + public enum ArenaPositionName : byte + { + player1, + player2, + spectator + } +} diff --git a/Server/Plugins/Duel/Commands.cs b/Server/Plugins/Duel/Commands.cs new file mode 100644 index 0000000..f66db37 --- /dev/null +++ b/Server/Plugins/Duel/Commands.cs @@ -0,0 +1,156 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using Resources; +namespace Server.Plugins.Duel +{ + class Commands + { + public static Plugin pluginRef; + public static void Init(Plugin plugin) + { + Server.ChatMessageReceived += ParseAsCommand; + pluginRef = plugin; + } + private static void ParseAsCommand(string message, Player sourceTemp) + { + PlayerDuel target; + PlayerDuel source = DuelCore.players.FirstOrDefault(x => x.entity.guid == sourceTemp.entity.guid); + DuelSystem duelFinder; + if (!message.StartsWith("/duel")) + { + return; + } + var parameters = message.Substring(1 + pluginRef.getName().Length).Split(" "); + var command = parameters[0].ToLower(); + switch (command) + { + case "help": + #region help + Server.Notify(source, string.Format("/duel start [player2]")); + Server.Notify(source, string.Format("/duel accept")); + Server.Notify(source, string.Format("/duel refuse")); + Server.Notify(source, string.Format("/duel spectate [playerName]")); + Server.Notify(source, string.Format("/duel stop")); + break; + #endregion + case "stop": + #region stop + Console.WriteLine(DuelCore.duels.Count()); + duelFinder = DuelCore.duels.LastOrDefault(x => x.player1.entity.name.Contains(source.entity.name) || x.player2.entity.name.Contains(source.entity.name)); + if (duelFinder != null) + { + duelFinder.Stop(); + Console.WriteLine(DuelCore.duels.Count()); + } + else + { + Server.Notify(source, "[Duel] No duel ongoing"); + } + break; + #endregion + case "start": + #region start + if (parameters.Length == 3) + { + target = DuelCore.players.FirstOrDefault(x => x.entity.name.Contains(parameters[2])); + if (target == null) + { + Server.Notify(source, "[Duel] invalid target"); + break; + } + else if (target == source && source.entity.name != "BLIZZY") + { + Server.Notify(source, "[Duel] Unfortunatly, you can't duel yourself"); + break; + } + else if (source.Duel == true) + { + Server.Notify(source, "[Duel] You're already involved in a duel"); + break; + } + else if (target.Duel == true) + { + Server.Notify(source, "[Duel] The target is already involved in a duel"); + break; + } + Server.Notify(target, string.Format("[Duel] {0} wants to duel you ! /duel accept or /duel refuse", source.entity.name)); + var duel = new DuelSystem(source, target, DateTimeOffset.UtcNow.ToUnixTimeSeconds()); + DuelCore.duels.Add(duel); + Console.WriteLine(String.Format("{0} ask a duel with {1}, Total Duel ongoing : {2}", source.entity.name, target.entity.name, DuelCore.duels.Count())); + new Thread(() => duel.RunDuel()).Start(); + } + else + { + Server.Notify(source, string.Format("Syntax : /duel start [player2]")); + } + break; + #endregion + case "accept": + #region accept + duelFinder = DuelCore.duels.LastOrDefault(x => x.player2.entity.name.Contains(source.entity.name)); + if (duelFinder != null && source.Duel == null) + { + duelFinder.AcceptDuel(); + } + else if (source.Duel == true) + { + Server.Notify(source, string.Format("[Duel] Duel already ongoing")); + } + else + { + Server.Notify(source, string.Format("[Duel] No duel request found")); + } + break; + #endregion + case "refuse": + #region refuse + duelFinder = DuelCore.duels.LastOrDefault(x => x.player2.entity.name.Contains(source.entity.name)); + if (duelFinder != null && source.Duel == null) + { + duelFinder.RefuseDuel(); + } + else if (source.Duel == true) + { + Server.Notify(source, string.Format("[Duel] Duel already ongoing")); + } + else + { + Server.Notify(source, string.Format("[Duel] No duel request found")); + } + break; + #endregion + case "spectate": + #region spectate + if (parameters.Length == 3) + { + var name = parameters[2]; + duelFinder = DuelCore.duels.LastOrDefault(x => x.player1.entity.name.Contains(name) || x.player2.entity.name.Contains(name)); + if (duelFinder != null && source.Duel == null) + { + duelFinder.Spectate(source); + Server.Notify(source, string.Format("[Duel] You are spectating the duel of {0} !", name)); + } + else + { + Server.Notify(source, string.Format("[Duel] Invalid Target")); + } + } + else + { + Server.Notify(source, string.Format("Syntax: /duel spectate [playerName]")); + } + #endregion + break; + default: + if (PluginsCore.pluginsWithCommands.Last().getName() == pluginRef.getName()) + { + Server.Notify(source, string.Format("Type /duel help for more information")); + } + break; + } + } + } +} diff --git a/Server/Plugins/Duel/DuelConfig.cs b/Server/Plugins/Duel/DuelConfig.cs new file mode 100644 index 0000000..b91b0a8 --- /dev/null +++ b/Server/Plugins/Duel/DuelConfig.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Server.Plugins.Duel +{ + static public class DuelConfig + { + public const int maxRequestTime = 30; + } +} diff --git a/Server/Plugins/Duel/DuelCore.cs b/Server/Plugins/Duel/DuelCore.cs new file mode 100644 index 0000000..7d94d87 --- /dev/null +++ b/Server/Plugins/Duel/DuelCore.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Server.Plugins.Duel +{ + class DuelCore : Plugin + { + public static volatile List duels = new List(); + public static List players = new List(); + public DuelCore() + { + Commands.Init(this); + pluginName = "Duel"; + } + public override Boolean hasCommands() + { + return true; + } + } +} diff --git a/Server/Plugins/Duel/DuelSystem.cs b/Server/Plugins/Duel/DuelSystem.cs new file mode 100644 index 0000000..d4c6fef --- /dev/null +++ b/Server/Plugins/Duel/DuelSystem.cs @@ -0,0 +1,197 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Resources; +using System.Threading.Tasks; +using Server.Plugins.Arena.Database; + +namespace Server.Plugins.Duel +{ + class DuelSystem + { + private volatile Boolean ongoing; // status of the duel + private volatile Boolean stop; // Token for stopping duel/thread + public Player winner; + public ArenaEntity arena; + private List Spectators; + public ArenaDatabase ArenaDatabase; + public Player player1; + private long[] storedPos1; // initial player1 position + private float? storedHp1; // initial player1 position + public Player player2; + private long[] storedPos2; // initial player2 position + private float? storedHp2; // initial player2 position + private volatile int request_state;// 0 waiting | 1 accepted | 2 refused + private long requestInitialTime; + private Boolean WaitingResponse() + { + #region waitingResponse + while (DateTimeOffset.UtcNow.ToUnixTimeSeconds() < this.requestInitialTime + DuelConfig.maxRequestTime && this.request_state == 0 && stop == false) + { + System.Threading.Thread.Sleep(1000); + } + if (stop == true) + { + return false; + } + switch (this.request_state) + { + case 1: + NotifyPlayers("[Duel] Duel is starting"); + this.ongoing = true; + break; + case 2: + Server.Notify(this.player1, string.Format("[Duel] {0} refused the duel", this.player2.entity.name)); + break; + default: + Server.Notify(this.player1, string.Format("[Duel] {0} didn't respond within the 30s limit", this.player2.entity.name)); + break; + } + return ongoing; + #endregion + } + public DuelSystem(Player player1, Player player2, long requestInitialTime) + { + #region createDuel + this.ongoing = false; + this.player1 = player1; + this.player2 = player2; + this.requestInitialTime = requestInitialTime; + this.ArenaDatabase = new ArenaDatabase(); + this.Spectators = new List(); + #endregion + } + public void PickArena() + { + #region PickArena + this.arena = ArenaDatabase.FetchRandomArena(); + if (this.arena == null) + { + NotifyPlayers("[Duel] An error occured : the arena's list is empty"); + this.stop = true; + } + #endregion + } + public void SetPlayersState() + { + #region setPlayersState + this.storedPos1 = new long[]{ + this.player1.entity.position.x, + this.player1.entity.position.y, + this.player1.entity.position.z, + }; + this.storedPos2 = new long[]{ + this.player2.entity.position.x, + this.player2.entity.position.y, + this.player2.entity.position.z, + }; + this.storedHp1 = this.player1.entity.HP; + this.storedHp2 = this.player2.entity.HP; + // this.player1.Duel = true; + // this.player2.Duel = true; + // Server.TeleportPlayer(this.arena.getPosition(ArenaPositionName.player1), this.player1); + // Server.TeleportPlayer(this.arena.getPosition(ArenaPositionName.player2), this.player2); + #endregion + } + public void LaunchPreparingTime() + { + #region launchPreparingTime + // player1.PreparingTime = true; + // player2.PreparingTime = true; + this.player1.entity.hostility = Hostility.Neutral; + this.player2.entity.hostility = Hostility.Neutral; + NotifyPlayers("[Duel] Duel is starting in 10sd"); + System.Threading.Thread.Sleep(10000); + // Server.setHostility(Hostility.Player, this.player1); + this.player1.entity.hostility = Hostility.Player; + this.player2.entity.hostility = Hostility.Player; + // player1.PreparingTime = null; + // player2.PreparingTime = null; + NotifyPlayers("[Duel] Go !"); + #endregion + } + public void RestorePlayersState() + { + #region restorePlayerState + // Server.setHp(this.storedHp1, this.player1); + // Server.setHp(this.storedHp2, this.player2); + // Server.TeleportPlayer(this.storedPos1, this.player1); + // Server.TeleportPlayer(this.storedPos2, this.player2); + // this.player1.Duel = null; + // this.player2.Duel = null; + #endregion + } + private void ManageDuel() + { + #region ManageDuel + PickArena(); + if (this.arena != null) + { + SetPlayersState(); + LaunchPreparingTime(); + } + while (this.ongoing == true && this.stop == false) + { + if (this.player1.entity.HP <= 0 || this.player2.entity.HP <= 0) + { + this.winner = this.player1.entity.HP <= 0 ? this.player2 : this.player1; + this.ongoing = false; + } + System.Threading.Thread.Sleep(1000); + } + if (this.stop == false) + { + NotifyPlayers(String.Format("[Duel] {0} won this duel", this.winner.entity.name)); + RestorePlayersState(); + } + else + { + if (this.arena != null) + { + RestorePlayersState(); + } + } + DuelCore.duels.Remove(this); + #endregion + } + public void Stop() + { + #region stop + NotifyPlayers(String.Format("[Duel] The duel is cancelled")); + this.stop = true; + #endregion + } + public void AcceptDuel() + { + this.request_state = 1; + } + public void RefuseDuel() + { + this.request_state = 2; + } + public void Spectate(Player player) + { + // Server.TeleportPlayer(this.arena.getPosition(ArenaPositionName.spectator), player); + this.Spectators.Add(player); + } + public void NotifyPlayers(string message) + { + Server.Notify(this.player1, message); + Server.Notify(this.player2, message); + } + public void RunDuel() + { + #region runDuel + Boolean player2Accepted = WaitingResponse(); + if (player2Accepted) + { + ManageDuel(); + } + else + { + DuelCore.duels.Remove(this); + } + #endregion + } + } +} diff --git a/Server/Plugins/Duel/PlayerDuel.cs b/Server/Plugins/Duel/PlayerDuel.cs new file mode 100644 index 0000000..0b5f293 --- /dev/null +++ b/Server/Plugins/Duel/PlayerDuel.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Net.Sockets; +using System.Text; +using Resources; + +namespace Server.Plugins.Duel +{ + class PlayerDuel : Player + { + public bool? Duel; + public bool? PreparingTime; + public PlayerDuel(TcpClient tcpClient) : base(tcpClient) + { + } + } +} diff --git a/Server/Plugins/Plugin.cs b/Server/Plugins/Plugin.cs new file mode 100644 index 0000000..931efe8 --- /dev/null +++ b/Server/Plugins/Plugin.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Server.Plugins +{ + public class Plugin + { + protected String pluginName; + public virtual Boolean hasCommands() + { + Console.WriteLine("test"); + return false; + } + public String getName() + { + return pluginName; + } + } +} diff --git a/Server/Plugins/PluginsConfig.cs b/Server/Plugins/PluginsConfig.cs new file mode 100644 index 0000000..cac786b --- /dev/null +++ b/Server/Plugins/PluginsConfig.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; + +namespace Server.Plugins +{ + class PluginsConfig + { + public static List pluginsName = new List{ + "Duel", + "Arena" + }; + } +} diff --git a/Server/Plugins/PluginsCore.cs b/Server/Plugins/PluginsCore.cs new file mode 100644 index 0000000..7590429 --- /dev/null +++ b/Server/Plugins/PluginsCore.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Text; +namespace Server.Plugins +{ + public static class PluginsCore + { + public static List pluginsList; + public static List pluginsWithCommands; + public static void Init() + { + pluginsList = new List(); + pluginsWithCommands = new List(); + foreach (String pluginName in PluginsConfig.pluginsName) + { + var pluginPath = Type.GetType("Server.Plugins." + pluginName + "." + pluginName + "Core"); + if (pluginPath != null) + { + var plugin = (Plugin)Activator.CreateInstance(pluginPath); + if (plugin.hasCommands()) + { + pluginsWithCommands.Add(plugin); + } + Log.PrintLn("Plugin \"" + pluginName + "\" has been successfully initialized !", ConsoleColor.Green); + pluginsList.Add(plugin); + } + else + { + Log.PrintLn("Plugin \""+pluginName+"\" cannot be found !", ConsoleColor.Red); + } + } + } + } +} diff --git a/Server/Server.csproj b/Server/Server.csproj index 25b0da1..42f01ea 100644 --- a/Server/Server.csproj +++ b/Server/Server.csproj @@ -22,4 +22,8 @@ + + + + diff --git a/Server/ServerCore.cs b/Server/ServerCore.cs index 657a172..569f651 100644 --- a/Server/ServerCore.cs +++ b/Server/ServerCore.cs @@ -12,7 +12,9 @@ using Resources; using Resources.Datagram; using Resources.Packet; - +using Resources.Utilities; +using Server.Plugins; +using Server.Extensions; namespace Server { public static partial class ServerCore { public static UdpClient udpClient; @@ -20,12 +22,10 @@ public static partial class ServerCore { public static List players = new List(); public static Dictionary dynamicEntities = new Dictionary(); public static UserDatabase userDatabase; - public static void Start(int port) { Log.PrintLn("server starting..."); userDatabase = new UserDatabase(); userDatabase.Database.Migrate(); //Ensure database exists - udpClient = new UdpClient(new IPEndPoint(IPAddress.Any, port)); new Thread(new ThreadStart(ListenUDP)).Start(); tcpListener = new TcpListener(IPAddress.Any, port); @@ -33,6 +33,7 @@ public static void Start(int port) { new Thread(new ThreadStart(ListenTCP)).Start(); Extensions.Extensions.Init(); + PluginsCore.Init(); Log.PrintLn("loading completed"); } From 6bac35f6fa1e68e40254cd94c06b2afc4416b373 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Sun, 14 Oct 2018 15:16:42 +0200 Subject: [PATCH 14/18] Implementation of plugin System part 2 --- Server/Plugins/Arena/ArenaConfig.cs | 1 + Server/Plugins/Arena/ArenaCore.cs | 4 +- Server/Plugins/Arena/Commands.cs | 132 +++++++++--------- .../Arena/Resources/CommandsMessages.cs | 46 ++++++ Server/Plugins/Duel/Commands.cs | 23 +-- Server/Plugins/Duel/DuelCore.cs | 2 +- Server/Plugins/{Plugin.cs => PluginBase.cs} | 3 +- Server/Plugins/PluginsCore.cs | 10 +- 8 files changed, 140 insertions(+), 81 deletions(-) create mode 100644 Server/Plugins/Arena/Resources/CommandsMessages.cs rename Server/Plugins/{Plugin.cs => PluginBase.cs} (83%) diff --git a/Server/Plugins/Arena/ArenaConfig.cs b/Server/Plugins/Arena/ArenaConfig.cs index 1e09cf7..dc42d1f 100644 --- a/Server/Plugins/Arena/ArenaConfig.cs +++ b/Server/Plugins/Arena/ArenaConfig.cs @@ -2,5 +2,6 @@ { static public class ArenaConfig { + public static string pluginName = "Arena"; } } diff --git a/Server/Plugins/Arena/ArenaCore.cs b/Server/Plugins/Arena/ArenaCore.cs index e05cbaf..d8b9008 100644 --- a/Server/Plugins/Arena/ArenaCore.cs +++ b/Server/Plugins/Arena/ArenaCore.cs @@ -6,7 +6,7 @@ namespace Server.Plugins.Arena { - class ArenaCore : Plugin + class ArenaCore : PluginBase { public static ArenaDatabase ArenaDatabase; public ArenaCore() @@ -14,7 +14,7 @@ public ArenaCore() ArenaDatabase = new ArenaDatabase(); ArenaDatabase.Database.Migrate(); Commands.Init(ArenaDatabase,this); - pluginName = "Arena"; + pluginName = ArenaConfig.pluginName; } public override Boolean hasCommands() { diff --git a/Server/Plugins/Arena/Commands.cs b/Server/Plugins/Arena/Commands.cs index 819676f..fc99638 100644 --- a/Server/Plugins/Arena/Commands.cs +++ b/Server/Plugins/Arena/Commands.cs @@ -11,8 +11,8 @@ namespace Server.Plugins.Arena class Commands { public static ArenaDatabase ArenaDatabase; - public static Plugin pluginRef; - public static void Init(ArenaDatabase arenaDatabase,Plugin plugin) + public static PluginBase pluginRef; + public static void Init(ArenaDatabase arenaDatabase, PluginBase plugin) { Server.ChatMessageReceived += ParseAsCommand; ArenaDatabase = arenaDatabase; @@ -20,70 +20,69 @@ public static void Init(ArenaDatabase arenaDatabase,Plugin plugin) } private static void ParseAsCommand(string message, Player source) { - if (!message.StartsWith("/"+pluginRef.getName())) + message = message.ToLower(); + if (!message.StartsWith("/" + pluginRef.getName().ToLower())) { + if (PluginsCore.pluginsWithCommands.Last().getName() == pluginRef.getName()) + { + Server.Notify(source, string.Format("unknown command")); + } return; } - else if(message.Length == 1 + pluginRef.getName().Length) + if (message.Length == 1 + pluginRef.getName().Length) { - Server.Notify(source, string.Format("Type /"+pluginRef.getName()+" help for further informations about this command")); + Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.baseSyntax)); return; } - var parameters = message.Substring(2+pluginRef.getName().Length).Split(" "); - foreach (var item in parameters) - { - Console.WriteLine(item.ToString()); - } - var command = parameters[0].ToLower(); + var parameters = message.Substring(2 + pluginRef.getName().Length).Split(" "); ArenaResponse response = ArenaResponse.Null; long[] currentPos = new long[3]; - switch (command) + switch (parameters[0]) { case "setup": #region setup if (source.entity.name != "BLACKROCK" && source.entity.name != "BLIZZY") { - Server.Notify(source, "[Arena] no permission"); + Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.baseNoPermission)); break; } string arenaName = null; - if (parameters.Length == 3) + if (parameters.Length == 2) + { + arenaName = parameters[1]; + } + else if(parameters.Length > 2) { - arenaName = parameters[2].ToLower(); + Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.setupSyntax)); + break; } response = ArenaDatabase.launchSetupArena(arenaName); if (response == ArenaResponse.SetupLaunched) { - Server.Notify(source, String.Format("[Arena] The Setup Arena has been initialized !")); + Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.setupInitialized)); } else if (response == ArenaResponse.SetupAlreadyLaunched) { - Server.Notify(source, String.Format("[Arena] The Setup Arena has already been initialized.")); + Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.setupAlreadyInitialized)); } break; #endregion - /*case "list": - #region arena-list - ArenaDatabase.listArena(); - break; - #endregion - */ case "set": #region setup-set if (source.entity.name != "BLACKROCK" && source.entity.name != "BLIZZY") { - Server.Notify(source, "[Arena] no permission"); + Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.baseNoPermission)); break; } - if (parameters.Length == 3) + if (parameters.Length == 2) { currentPos = new long[3] { - source.entity.position.x, - source.entity.position.y, - source.entity.position.z + source.entity.position.x, + source.entity.position.y, + source.entity.position.z }; - switch (parameters[2].ToLower()) + switch (parameters[1]) { case "player1": response = ArenaDatabase.setPositionSetupArena(currentPos, ArenaPositionName.player1); @@ -95,21 +94,21 @@ private static void ParseAsCommand(string message, Player source) response = ArenaDatabase.setPositionSetupArena(currentPos, ArenaPositionName.spectator); break; default: - Server.Notify(source, String.Format("Syntax : /arena set player1|player2|spectator")); + Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.setSyntax)); break; } if (response == ArenaResponse.SetupPositionSet) { - Server.Notify(source, String.Format("[Arena] Parameters {0} has been successfully updated", parameters[2].ToLower())); + Server.Notify(source, CommandsMessages.getMessage(String.Format(CommandsMessages.setPositionSuccess, parameters[1]))); } else if (response == ArenaResponse.SetupEmpty) { - Server.Notify(source, String.Format("[Arena] The Setup Arena hasn't been initialized")); + Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.baseSetupNotInitialized)); } } else { - Server.Notify(source, String.Format("Syntax : /arena set player1|player2|spectator")); + Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.setSyntax)); } break; #endregion @@ -117,24 +116,24 @@ private static void ParseAsCommand(string message, Player source) #region setup-name if (source.entity.name != "BLACKROCK" && source.entity.name != "BLIZZY") { - Server.Notify(source, "[Arena] no permission"); + Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.baseNoPermission)); break; } - if (parameters.Length == 3) + if (parameters.Length == 2) { - response = ArenaDatabase.setNameArena(parameters[2].ToLower()); + response = ArenaDatabase.setNameArena(parameters[1]); if (response == ArenaResponse.SetupNameSet) { - Server.Notify(source, String.Format("[Arena] The Setup Arena's name has been changed !")); + Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.nameChangeSuccess)); } else if (response == ArenaResponse.SetupEmpty) { - Server.Notify(source, String.Format("[Arena] The Setup Arena hasn't been initialized")); + Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.baseSetupNotInitialized)); } } else { - Server.Notify(source, String.Format("Syntax : /arena name [newName]")); + Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.createSyntax)); } break; #endregion @@ -142,21 +141,26 @@ private static void ParseAsCommand(string message, Player source) #region arena-create if (source.entity.name != "BLACKROCK" && source.entity.name != "BLIZZY") { - Server.Notify(source, "[Arena] no permission"); + Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.baseNoPermission)); + break; + } + if(parameters.Length > 1) + { + Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.createSyntax)); break; } response = ArenaDatabase.SaveDuelArena(); if (response == ArenaResponse.ArenaCreated) { - Server.Notify(source, string.Format("[Arena] Arena has been successfully saved and is operational !")); + Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.createSuccess)); } else if (response == ArenaResponse.SetupIncomplete) { - Server.Notify(source, string.Format("[Arena] Setup Arena is incomplete !")); + Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.createIncomplete)); } else if (response == ArenaResponse.SetupEmpty) { - Server.Notify(source, String.Format("[Arena] The Setup Arena hasn't been initialized")); + Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.baseSetupNotInitialized)); } break; #endregion @@ -164,34 +168,34 @@ private static void ParseAsCommand(string message, Player source) #region arena-delete if (source.entity.name != "BLACKROCK" && source.entity.name != "BLIZZY") { - Server.Notify(source, "[Arena] no permission"); + Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.baseNoPermission)); break; } - if (parameters.Length == 3) + if (parameters.Length == 2) { - bool isId = int.TryParse(parameters[2].ToLower(), out int n); + bool isId = int.TryParse(parameters[1], out int n); if (isId) { - var id = Int32.Parse(parameters[2].ToLower()); + var id = Int32.Parse(parameters[1]); response = ArenaDatabase.RemoveDuelArena((uint)id); } else { - response = ArenaDatabase.RemoveDuelArena(parameters[2].ToLower()); + response = ArenaDatabase.RemoveDuelArena(parameters[1]); } switch (response) { case ArenaResponse.ArenaDeleted: - Server.Notify(source, string.Format("[Arena] Arena deleted !")); + Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.deleteSuccess)); break; case ArenaResponse.ArenaNotFound: - Server.Notify(source, string.Format("[Arena] Invalid id or arena's name")); + Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.deleteNotFound)); break; } } else { - Server.Notify(source, string.Format("Syntax : /duel arena-delete [id] or /duel arena-delete [name] ")); + Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.deleteSyntax)); } break; #endregion @@ -199,13 +203,18 @@ private static void ParseAsCommand(string message, Player source) #region reset if (source.entity.name != "BLACKROCK" && source.entity.name != "BLIZZY") { - Server.Notify(source, "[Arena] no permission"); + Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.baseNoPermission)); + break; + } + if(parameters.Length > 1) + { + Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.resetSyntax)); break; } response = ArenaDatabase.ResetArena(); if (response == ArenaResponse.ArenaReset) { - Server.Notify(source, string.Format("[Arena] Arena's list reseted !")); + Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.resetSuccess)); } #endregion break; @@ -213,20 +222,17 @@ private static void ParseAsCommand(string message, Player source) #region arena-help if (source.entity.name != "BLACKROCK" && source.entity.name != "BLIZZY") { - Server.Notify(source, string.Format("/arena setup")); - Server.Notify(source, string.Format("/arena set player1|player2|spectator")); - Server.Notify(source, string.Format("/arena name [newName]")); - Server.Notify(source, string.Format("/arena create")); - Server.Notify(source, string.Format("/arena delete [ArenaId] or /arena delete [Name]")); + Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.setupSyntax)); + Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.setSyntax)); + Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.nameSyntax)); + Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.createSyntax)); + Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.deleteSyntax)); + Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.resetSyntax)); } - Server.Notify(source, string.Format("/arena list")); break; #endregion default: - if (PluginsCore.pluginsWithCommands.Last().getName() == pluginRef.getName()) - { - Server.Notify(source, string.Format("unknown command '{0}'", parameters[0])); - } + Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.baseSyntax)); break; } } diff --git a/Server/Plugins/Arena/Resources/CommandsMessages.cs b/Server/Plugins/Arena/Resources/CommandsMessages.cs new file mode 100644 index 0000000..ce77715 --- /dev/null +++ b/Server/Plugins/Arena/Resources/CommandsMessages.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Server.Plugins.Arena.Resources +{ + static class CommandsMessages + { + // Base Command + public static readonly string baseSyntax = "Type '/arena help' for further informations about this plugin"; + public static readonly string baseNoPermission = "You don't have sufficient permission for this command"; + public static readonly string baseSetupNotInitialized = "The Setup Arena hasn't been initialized"; + + // Setup + public static readonly string setupSyntax = "Syntax: /arena setup"; + public static readonly string setupInitialized = "The Setup Arena has been initialized !"; + public static readonly string setupAlreadyInitialized = "The Setup Arena has already been initialized."; + + // Set + public static readonly string setSyntax = "Syntax : /arena set player1|player2|spectator"; + public static readonly string setPositionSuccess = "Parameters {0} has been successfully updated"; + + // Name + public static readonly string nameSyntax = "Syntax : /arena name [newName]"; + public static readonly string nameChangeSuccess = "The Setup Arena's name has been changed !"; + + // Create + public static readonly string createSyntax = "Syntax : /arena create"; + public static readonly string createSuccess = "Arena has been successfully saved and is operational !"; + public static readonly string createIncomplete = "Setup Arena is incomplete !"; + + // Delete + public static readonly string deleteSyntax = "Syntax : /duel arena-delete [id] or /duel arena-delete [name] "; + public static readonly string deleteSuccess = " Arena deleted !"; + public static readonly string deleteNotFound = "Invalid id or arena's name"; + + // Reset + public static readonly string resetSyntax= "Syntax : /arena reset"; + public static readonly string resetSuccess = "Arena's list reset !"; + + public static string getMessage(String message) + { + return String.Format("[{0}] " + message, ArenaConfig.pluginName); + } + } +} diff --git a/Server/Plugins/Duel/Commands.cs b/Server/Plugins/Duel/Commands.cs index f66db37..4d8a9a8 100644 --- a/Server/Plugins/Duel/Commands.cs +++ b/Server/Plugins/Duel/Commands.cs @@ -8,8 +8,8 @@ namespace Server.Plugins.Duel { class Commands { - public static Plugin pluginRef; - public static void Init(Plugin plugin) + public static PluginBase pluginRef; + public static void Init(PluginBase plugin) { Server.ChatMessageReceived += ParseAsCommand; pluginRef = plugin; @@ -19,11 +19,21 @@ private static void ParseAsCommand(string message, Player sourceTemp) PlayerDuel target; PlayerDuel source = DuelCore.players.FirstOrDefault(x => x.entity.guid == sourceTemp.entity.guid); DuelSystem duelFinder; - if (!message.StartsWith("/duel")) + message = message.ToLower(); + if (!message.StartsWith("/" + pluginRef.getName().ToLower())) { + if (PluginsCore.pluginsWithCommands.Last().getName() == pluginRef.getName()) + { + Server.Notify(source, string.Format("unknown command")); + } return; } - var parameters = message.Substring(1 + pluginRef.getName().Length).Split(" "); + if (message.Length == 1 + pluginRef.getName().Length) + { + Server.Notify(source, string.Format("Type /" + pluginRef.getName() + " help for further informations about this command")); + return; + } + var parameters = message.Substring(2 + pluginRef.getName().Length).Split(" "); var command = parameters[0].ToLower(); switch (command) { @@ -145,10 +155,7 @@ private static void ParseAsCommand(string message, Player sourceTemp) #endregion break; default: - if (PluginsCore.pluginsWithCommands.Last().getName() == pluginRef.getName()) - { - Server.Notify(source, string.Format("Type /duel help for more information")); - } + Server.Notify(source, string.Format("Type /duel help for more information")); break; } } diff --git a/Server/Plugins/Duel/DuelCore.cs b/Server/Plugins/Duel/DuelCore.cs index 7d94d87..d6e191b 100644 --- a/Server/Plugins/Duel/DuelCore.cs +++ b/Server/Plugins/Duel/DuelCore.cs @@ -4,7 +4,7 @@ namespace Server.Plugins.Duel { - class DuelCore : Plugin + class DuelCore : PluginBase { public static volatile List duels = new List(); public static List players = new List(); diff --git a/Server/Plugins/Plugin.cs b/Server/Plugins/PluginBase.cs similarity index 83% rename from Server/Plugins/Plugin.cs rename to Server/Plugins/PluginBase.cs index 931efe8..8160537 100644 --- a/Server/Plugins/Plugin.cs +++ b/Server/Plugins/PluginBase.cs @@ -4,12 +4,11 @@ namespace Server.Plugins { - public class Plugin + public class PluginBase { protected String pluginName; public virtual Boolean hasCommands() { - Console.WriteLine("test"); return false; } public String getName() diff --git a/Server/Plugins/PluginsCore.cs b/Server/Plugins/PluginsCore.cs index 7590429..3e6ff9e 100644 --- a/Server/Plugins/PluginsCore.cs +++ b/Server/Plugins/PluginsCore.cs @@ -5,18 +5,18 @@ namespace Server.Plugins { public static class PluginsCore { - public static List pluginsList; - public static List pluginsWithCommands; + public static List pluginsList; + public static List pluginsWithCommands; public static void Init() { - pluginsList = new List(); - pluginsWithCommands = new List(); + pluginsList = new List(); + pluginsWithCommands = new List(); foreach (String pluginName in PluginsConfig.pluginsName) { var pluginPath = Type.GetType("Server.Plugins." + pluginName + "." + pluginName + "Core"); if (pluginPath != null) { - var plugin = (Plugin)Activator.CreateInstance(pluginPath); + var plugin = (PluginBase)Activator.CreateInstance(pluginPath); if (plugin.hasCommands()) { pluginsWithCommands.Add(plugin); From 87cf2fd2f0b93fe0720813b6c4bd7dc1fc19d21a Mon Sep 17 00:00:00 2001 From: BuildTools Date: Mon, 15 Oct 2018 12:16:31 +0200 Subject: [PATCH 15/18] Rewrite of Chat system to be more plugin's friendly --- Server/Extensions/ChatCommands.cs | 17 +++---- Server/Extensions/ChatManager.cs | 47 +++++++++++++++++++ Server/Extensions/Extensions.cs | 2 +- Server/Plugins/Arena/ArenaCore.cs | 5 ++ Server/Plugins/Arena/Commands.cs | 32 ++++++------- .../Arena/Resources/CommandsMessages.cs | 1 - Server/Plugins/CommandsMessage.cs | 16 +++++++ Server/Plugins/Duel/Commands.cs | 15 ++---- Server/Plugins/PluginBase.cs | 7 ++- Server/ServerCore.cs | 5 +- Server/ServerCore_Events.cs | 2 +- 11 files changed, 102 insertions(+), 47 deletions(-) create mode 100644 Server/Extensions/ChatManager.cs create mode 100644 Server/Plugins/CommandsMessage.cs diff --git a/Server/Extensions/ChatCommands.cs b/Server/Extensions/ChatCommands.cs index 56fab56..a58e3b9 100644 --- a/Server/Extensions/ChatCommands.cs +++ b/Server/Extensions/ChatCommands.cs @@ -1,21 +1,16 @@ using Resources; using Resources.Datagram; using Resources.Packet; +using Server.Plugins; using System; using System.Collections.Generic; using System.Linq; using System.Text; +namespace Server.Extensions { namespace Server.Extensions { public static class ChatCommands { - public static void Init() { - ServerCore.ChatMessageReceived += ParseAsCommand; - } - - private static void ParseAsCommand(string message, Player source) { - if (!message.StartsWith("/")) { - return; - } + public static Boolean ParseAsCommand(string message, Player source) { var parameters = message.Substring(1).Split(" "); var command = parameters[0].ToLower(); switch (command) { @@ -31,7 +26,7 @@ private static void ParseAsCommand(string message, Player source) { ServerCore.Notify(source, string.Format("usage example: /kick blackrock")); break; } - var target = ServerCore.players.FirstOrDefault(x => x.entity.name.Contains(parameters[1])); + var target = Server.players.FirstOrDefault(x => x.entity.name.Contains(parameters[1])); if (target == null) { ServerCore.Notify(source, "invalid target"); break; @@ -75,9 +70,9 @@ private static void ParseAsCommand(string message, Player source) { break; #endregion default: - ServerCore.Notify(source, string.Format("unknown command '{0}'", parameters[0])); - break; + return false; } + return true; } } } diff --git a/Server/Extensions/ChatManager.cs b/Server/Extensions/ChatManager.cs new file mode 100644 index 0000000..a061cfe --- /dev/null +++ b/Server/Extensions/ChatManager.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Resources; +using Resources.Datagram; +using Server.Plugins; + +namespace Server.Extensions +{ + class ChatManager + { + public static void Init() + { + Server.ChatMessageReceived += analyzeMessage; + } + private static void analyzeMessage(Chat chat, Player source) + { + var message = chat.Text; + Log.Print(Server.dynamicEntities[chat.Sender].name + ": ", ConsoleColor.Cyan); + Log.PrintLn(chat.Text, ConsoleColor.White, false); + if (!message.StartsWith("/")) + { + Server.BroadcastUDP(chat.data, null); //pass to all players + return; + } + Boolean CommandFound; + CommandFound = ChatCommands.ParseAsCommand(message, source); + if (!CommandFound) + { + foreach (PluginBase plugin in PluginsCore.pluginsWithCommands) + { + CommandFound = plugin.analyzeCommand(message, source); + if (CommandFound == true) + { + break; + } + } + if (!CommandFound) + { + var commandName = message.Substring(1).Split(" ")[0]; + Server.Notify(source, CommandsMessage.getMessage(String.Format(CommandsMessage.baseUnknowCommand, commandName))); + } + } + } + } +} diff --git a/Server/Extensions/Extensions.cs b/Server/Extensions/Extensions.cs index c14a3c6..4183dfb 100644 --- a/Server/Extensions/Extensions.cs +++ b/Server/Extensions/Extensions.cs @@ -7,7 +7,7 @@ public static class Extensions { public static void Init() { AntiCheat.Init(); Pvp.Init(); - ChatCommands.Init(); + ChatManager.Init(); SpecialMoves.Init(); Balancing.Init(); } diff --git a/Server/Plugins/Arena/ArenaCore.cs b/Server/Plugins/Arena/ArenaCore.cs index d8b9008..d3cca0c 100644 --- a/Server/Plugins/Arena/ArenaCore.cs +++ b/Server/Plugins/Arena/ArenaCore.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Text; using Microsoft.EntityFrameworkCore; +using Resources; using Server.Plugins.Arena.Database; namespace Server.Plugins.Arena @@ -20,5 +21,9 @@ public override Boolean hasCommands() { return true; } + public override Boolean analyzeCommand(string message,Player source) + { + return Commands.ParseAsCommand(message, source); + } } } diff --git a/Server/Plugins/Arena/Commands.cs b/Server/Plugins/Arena/Commands.cs index fc99638..9dd09c3 100644 --- a/Server/Plugins/Arena/Commands.cs +++ b/Server/Plugins/Arena/Commands.cs @@ -5,7 +5,7 @@ using Resources; using Server.Plugins.Arena.Database; using Server.Plugins.Arena.Resources; - +using CommandsBaseMessages = Server.Plugins.CommandsMessage; namespace Server.Plugins.Arena { class Commands @@ -14,25 +14,21 @@ class Commands public static PluginBase pluginRef; public static void Init(ArenaDatabase arenaDatabase, PluginBase plugin) { - Server.ChatMessageReceived += ParseAsCommand; ArenaDatabase = arenaDatabase; pluginRef = plugin; } - private static void ParseAsCommand(string message, Player source) + public static Boolean ParseAsCommand(string message, Player source) { message = message.ToLower(); - if (!message.StartsWith("/" + pluginRef.getName().ToLower())) + var commandName = message.Substring(1).Split(" ")[0]; + if (!(commandName == pluginRef.getName().ToLower())) { - if (PluginsCore.pluginsWithCommands.Last().getName() == pluginRef.getName()) - { - Server.Notify(source, string.Format("unknown command")); - } - return; + return false; } if (message.Length == 1 + pluginRef.getName().Length) { Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.baseSyntax)); - return; + return true; } var parameters = message.Substring(2 + pluginRef.getName().Length).Split(" "); ArenaResponse response = ArenaResponse.Null; @@ -43,7 +39,7 @@ private static void ParseAsCommand(string message, Player source) #region setup if (source.entity.name != "BLACKROCK" && source.entity.name != "BLIZZY") { - Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.baseNoPermission)); + Server.Notify(source, CommandsMessages.getMessage(CommandsBaseMessages.baseNoPermission)); break; } string arenaName = null; @@ -71,7 +67,7 @@ private static void ParseAsCommand(string message, Player source) #region setup-set if (source.entity.name != "BLACKROCK" && source.entity.name != "BLIZZY") { - Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.baseNoPermission)); + Server.Notify(source, CommandsMessages.getMessage(CommandsBaseMessages.baseNoPermission)); break; } if (parameters.Length == 2) @@ -116,7 +112,7 @@ private static void ParseAsCommand(string message, Player source) #region setup-name if (source.entity.name != "BLACKROCK" && source.entity.name != "BLIZZY") { - Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.baseNoPermission)); + Server.Notify(source, CommandsMessages.getMessage(CommandsBaseMessages.baseNoPermission)); break; } if (parameters.Length == 2) @@ -141,7 +137,7 @@ private static void ParseAsCommand(string message, Player source) #region arena-create if (source.entity.name != "BLACKROCK" && source.entity.name != "BLIZZY") { - Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.baseNoPermission)); + Server.Notify(source, CommandsMessages.getMessage(CommandsBaseMessages.baseNoPermission)); break; } if(parameters.Length > 1) @@ -168,7 +164,7 @@ private static void ParseAsCommand(string message, Player source) #region arena-delete if (source.entity.name != "BLACKROCK" && source.entity.name != "BLIZZY") { - Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.baseNoPermission)); + Server.Notify(source, CommandsMessages.getMessage(CommandsBaseMessages.baseNoPermission)); break; } if (parameters.Length == 2) @@ -203,7 +199,7 @@ private static void ParseAsCommand(string message, Player source) #region reset if (source.entity.name != "BLACKROCK" && source.entity.name != "BLIZZY") { - Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.baseNoPermission)); + Server.Notify(source, CommandsMessages.getMessage(CommandsBaseMessages.baseNoPermission)); break; } if(parameters.Length > 1) @@ -232,9 +228,9 @@ private static void ParseAsCommand(string message, Player source) break; #endregion default: - Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.baseSyntax)); - break; + return false; } + return true; } } } diff --git a/Server/Plugins/Arena/Resources/CommandsMessages.cs b/Server/Plugins/Arena/Resources/CommandsMessages.cs index ce77715..5b1f08e 100644 --- a/Server/Plugins/Arena/Resources/CommandsMessages.cs +++ b/Server/Plugins/Arena/Resources/CommandsMessages.cs @@ -8,7 +8,6 @@ static class CommandsMessages { // Base Command public static readonly string baseSyntax = "Type '/arena help' for further informations about this plugin"; - public static readonly string baseNoPermission = "You don't have sufficient permission for this command"; public static readonly string baseSetupNotInitialized = "The Setup Arena hasn't been initialized"; // Setup diff --git a/Server/Plugins/CommandsMessage.cs b/Server/Plugins/CommandsMessage.cs new file mode 100644 index 0000000..799130e --- /dev/null +++ b/Server/Plugins/CommandsMessage.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Server.Plugins +{ + class CommandsMessage + { + public static readonly string baseUnknowCommand = "Unknown command : '{0}'"; + public static readonly string baseNoPermission = "You don't have sufficient permission for this command"; + public static string getMessage(String message) + { + return String.Format("[{0}] " + message, "Server"); + } + } +} diff --git a/Server/Plugins/Duel/Commands.cs b/Server/Plugins/Duel/Commands.cs index 4d8a9a8..00fa000 100644 --- a/Server/Plugins/Duel/Commands.cs +++ b/Server/Plugins/Duel/Commands.cs @@ -11,10 +11,9 @@ class Commands public static PluginBase pluginRef; public static void Init(PluginBase plugin) { - Server.ChatMessageReceived += ParseAsCommand; pluginRef = plugin; } - private static void ParseAsCommand(string message, Player sourceTemp) + private static Boolean ParseAsCommand(string message, Player sourceTemp) { PlayerDuel target; PlayerDuel source = DuelCore.players.FirstOrDefault(x => x.entity.guid == sourceTemp.entity.guid); @@ -22,16 +21,12 @@ private static void ParseAsCommand(string message, Player sourceTemp) message = message.ToLower(); if (!message.StartsWith("/" + pluginRef.getName().ToLower())) { - if (PluginsCore.pluginsWithCommands.Last().getName() == pluginRef.getName()) - { - Server.Notify(source, string.Format("unknown command")); - } - return; + return false; } if (message.Length == 1 + pluginRef.getName().Length) { Server.Notify(source, string.Format("Type /" + pluginRef.getName() + " help for further informations about this command")); - return; + return true; } var parameters = message.Substring(2 + pluginRef.getName().Length).Split(" "); var command = parameters[0].ToLower(); @@ -155,9 +150,9 @@ private static void ParseAsCommand(string message, Player sourceTemp) #endregion break; default: - Server.Notify(source, string.Format("Type /duel help for more information")); - break; + return false; } + return true; } } } diff --git a/Server/Plugins/PluginBase.cs b/Server/Plugins/PluginBase.cs index 8160537..0dda59b 100644 --- a/Server/Plugins/PluginBase.cs +++ b/Server/Plugins/PluginBase.cs @@ -1,4 +1,5 @@ -using System; +using Resources; +using System; using System.Collections.Generic; using System.Text; @@ -15,5 +16,9 @@ public String getName() { return pluginName; } + public virtual Boolean analyzeCommand(string message, Player source) + { + return false; + } } } diff --git a/Server/ServerCore.cs b/Server/ServerCore.cs index 569f651..47b1386 100644 --- a/Server/ServerCore.cs +++ b/Server/ServerCore.cs @@ -203,10 +203,7 @@ private static void ProcessDatagram(byte[] datagram, Player source) { case DatagramID.Chat: #region chat var chat = new Chat(datagram); - ChatMessageReceived?.Invoke(chat.Text, source); - Log.Print(dynamicEntities[chat.Sender].name + ": ", ConsoleColor.Cyan); - Log.PrintLn(chat.Text, ConsoleColor.White, false); - BroadcastUDP(chat.data, null); //pass to all players + ChatMessageReceived?.Invoke(chat, source); break; #endregion case DatagramID.Interaction: diff --git a/Server/ServerCore_Events.cs b/Server/ServerCore_Events.cs index f79930e..c1fad0b 100644 --- a/Server/ServerCore_Events.cs +++ b/Server/ServerCore_Events.cs @@ -10,7 +10,7 @@ namespace Server { public delegate void EntityAttackedEventHandler(Attack datagram, Player source); public delegate void ProjectileCreatedEventHandler(Projectile datagram, Player source); public delegate void PassiveProccedEventHandler(Proc datagram, Player source); - public delegate void ChatMessageReceivedEventHandler(string message, Player source); + public delegate void ChatMessageReceivedEventHandler(Chat message, Player source); public delegate void EntityInteractedEventHandler(Interaction datagram, Player source); public delegate void EntityRemovedEventHandler(RemoveDynamicEntity datagram, Player source); public delegate void SpecialMoveUsedEventHandler(SpecialMove datagram, Player source); From 22e091b380d4cfba8e817e9ada1ab6a899c79aa5 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Mon, 15 Oct 2018 22:02:43 +0200 Subject: [PATCH 16/18] Some structural changes --- Server/Extensions/ChatManager.cs | 2 +- Server/Plugins/Arena/ArenaConfig.cs | 2 +- Server/Plugins/Arena/Commands.cs | 3 +- ...andsMessage.cs => CommandsBaseMessages.cs} | 2 +- Server/Plugins/Duel/Commands.cs | 57 +++++++++---------- Server/Plugins/Duel/DuelConfig.cs | 1 + .../Duel/Resources/CommandsMessages.cs | 36 ++++++++++++ .../Duel/{ => Resources}/PlayerDuel.cs | 0 .../Plugins/Duel/{ => Scripts}/DuelSystem.cs | 0 9 files changed, 69 insertions(+), 34 deletions(-) rename Server/Plugins/{CommandsMessage.cs => CommandsBaseMessages.cs} (93%) create mode 100644 Server/Plugins/Duel/Resources/CommandsMessages.cs rename Server/Plugins/Duel/{ => Resources}/PlayerDuel.cs (100%) rename Server/Plugins/Duel/{ => Scripts}/DuelSystem.cs (100%) diff --git a/Server/Extensions/ChatManager.cs b/Server/Extensions/ChatManager.cs index a061cfe..fb429b2 100644 --- a/Server/Extensions/ChatManager.cs +++ b/Server/Extensions/ChatManager.cs @@ -39,7 +39,7 @@ private static void analyzeMessage(Chat chat, Player source) if (!CommandFound) { var commandName = message.Substring(1).Split(" ")[0]; - Server.Notify(source, CommandsMessage.getMessage(String.Format(CommandsMessage.baseUnknowCommand, commandName))); + Server.Notify(source, CommandsBaseMessages.getMessage(String.Format(CommandsBaseMessages.baseUnknowCommand, commandName))); } } } diff --git a/Server/Plugins/Arena/ArenaConfig.cs b/Server/Plugins/Arena/ArenaConfig.cs index dc42d1f..d9a215b 100644 --- a/Server/Plugins/Arena/ArenaConfig.cs +++ b/Server/Plugins/Arena/ArenaConfig.cs @@ -2,6 +2,6 @@ { static public class ArenaConfig { - public static string pluginName = "Arena"; + public const string pluginName = "Arena"; } } diff --git a/Server/Plugins/Arena/Commands.cs b/Server/Plugins/Arena/Commands.cs index 9dd09c3..d3b23d5 100644 --- a/Server/Plugins/Arena/Commands.cs +++ b/Server/Plugins/Arena/Commands.cs @@ -5,7 +5,6 @@ using Resources; using Server.Plugins.Arena.Database; using Server.Plugins.Arena.Resources; -using CommandsBaseMessages = Server.Plugins.CommandsMessage; namespace Server.Plugins.Arena { class Commands @@ -95,7 +94,7 @@ public static Boolean ParseAsCommand(string message, Player source) } if (response == ArenaResponse.SetupPositionSet) { - Server.Notify(source, CommandsMessages.getMessage(String.Format(CommandsMessages.setPositionSuccess, parameters[1]))); + Server.Notify(source, CommandsMessages.getMessage(string.Format(CommandsMessages.setPositionSuccess, parameters[1]))); } else if (response == ArenaResponse.SetupEmpty) { diff --git a/Server/Plugins/CommandsMessage.cs b/Server/Plugins/CommandsBaseMessages.cs similarity index 93% rename from Server/Plugins/CommandsMessage.cs rename to Server/Plugins/CommandsBaseMessages.cs index 799130e..ab707a9 100644 --- a/Server/Plugins/CommandsMessage.cs +++ b/Server/Plugins/CommandsBaseMessages.cs @@ -4,7 +4,7 @@ namespace Server.Plugins { - class CommandsMessage + class CommandsBaseMessages { public static readonly string baseUnknowCommand = "Unknown command : '{0}'"; public static readonly string baseNoPermission = "You don't have sufficient permission for this command"; diff --git a/Server/Plugins/Duel/Commands.cs b/Server/Plugins/Duel/Commands.cs index 00fa000..f06e3c5 100644 --- a/Server/Plugins/Duel/Commands.cs +++ b/Server/Plugins/Duel/Commands.cs @@ -4,6 +4,8 @@ using System.Text; using System.Threading; using Resources; +using Server.Plugins.Duel.Resources; +using CommandsBaseMessages = Server.Plugins.CommandsBaseMessages; namespace Server.Plugins.Duel { class Commands @@ -19,40 +21,38 @@ private static Boolean ParseAsCommand(string message, Player sourceTemp) PlayerDuel source = DuelCore.players.FirstOrDefault(x => x.entity.guid == sourceTemp.entity.guid); DuelSystem duelFinder; message = message.ToLower(); - if (!message.StartsWith("/" + pluginRef.getName().ToLower())) + var commandName = message.Substring(1).Split(" ")[0]; + if (!(commandName == pluginRef.getName().ToLower())) { return false; } if (message.Length == 1 + pluginRef.getName().Length) { - Server.Notify(source, string.Format("Type /" + pluginRef.getName() + " help for further informations about this command")); + Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.baseSyntax)); return true; } var parameters = message.Substring(2 + pluginRef.getName().Length).Split(" "); - var command = parameters[0].ToLower(); - switch (command) + switch (parameters[0]) { case "help": #region help - Server.Notify(source, string.Format("/duel start [player2]")); - Server.Notify(source, string.Format("/duel accept")); - Server.Notify(source, string.Format("/duel refuse")); - Server.Notify(source, string.Format("/duel spectate [playerName]")); - Server.Notify(source, string.Format("/duel stop")); + Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.startSyntax)); + Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.acceptSyntax)); + Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.refuseSyntax)); + Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.stopSyntax)); + Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.spectateSyntax)); break; #endregion case "stop": #region stop - Console.WriteLine(DuelCore.duels.Count()); duelFinder = DuelCore.duels.LastOrDefault(x => x.player1.entity.name.Contains(source.entity.name) || x.player2.entity.name.Contains(source.entity.name)); if (duelFinder != null) { duelFinder.Stop(); - Console.WriteLine(DuelCore.duels.Count()); } else { - Server.Notify(source, "[Duel] No duel ongoing"); + Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.baseNoDuelRequestFound)); } break; #endregion @@ -60,36 +60,35 @@ private static Boolean ParseAsCommand(string message, Player sourceTemp) #region start if (parameters.Length == 3) { - target = DuelCore.players.FirstOrDefault(x => x.entity.name.Contains(parameters[2])); + target = DuelCore.players.FirstOrDefault(x => x.entity.name.Contains(parameters[1])); if (target == null) { - Server.Notify(source, "[Duel] invalid target"); + Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.baseInvalidTarget)); break; } else if (target == source && source.entity.name != "BLIZZY") { - Server.Notify(source, "[Duel] Unfortunatly, you can't duel yourself"); + Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.startSelfError)); break; } else if (source.Duel == true) { - Server.Notify(source, "[Duel] You're already involved in a duel"); + Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.baseAlreadyDueling)); break; } else if (target.Duel == true) { - Server.Notify(source, "[Duel] The target is already involved in a duel"); + Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.startTargetAlreadyDueling)); break; } - Server.Notify(target, string.Format("[Duel] {0} wants to duel you ! /duel accept or /duel refuse", source.entity.name)); + Server.Notify(source, CommandsMessages.getMessage(String.Format(CommandsMessages.startAcceptMessage,source.entity.name))); var duel = new DuelSystem(source, target, DateTimeOffset.UtcNow.ToUnixTimeSeconds()); DuelCore.duels.Add(duel); - Console.WriteLine(String.Format("{0} ask a duel with {1}, Total Duel ongoing : {2}", source.entity.name, target.entity.name, DuelCore.duels.Count())); new Thread(() => duel.RunDuel()).Start(); } else { - Server.Notify(source, string.Format("Syntax : /duel start [player2]")); + Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.startSyntax)); } break; #endregion @@ -102,11 +101,11 @@ private static Boolean ParseAsCommand(string message, Player sourceTemp) } else if (source.Duel == true) { - Server.Notify(source, string.Format("[Duel] Duel already ongoing")); + Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.baseAlreadyDueling)); } else { - Server.Notify(source, string.Format("[Duel] No duel request found")); + Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.baseNoDuelRequestFound)); } break; #endregion @@ -119,33 +118,33 @@ private static Boolean ParseAsCommand(string message, Player sourceTemp) } else if (source.Duel == true) { - Server.Notify(source, string.Format("[Duel] Duel already ongoing")); + Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.baseAlreadyDueling)); } else { - Server.Notify(source, string.Format("[Duel] No duel request found")); + Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.baseNoDuelRequestFound)); } break; #endregion case "spectate": #region spectate - if (parameters.Length == 3) + if (parameters.Length == 2) { - var name = parameters[2]; + var name = parameters[1]; duelFinder = DuelCore.duels.LastOrDefault(x => x.player1.entity.name.Contains(name) || x.player2.entity.name.Contains(name)); if (duelFinder != null && source.Duel == null) { duelFinder.Spectate(source); - Server.Notify(source, string.Format("[Duel] You are spectating the duel of {0} !", name)); + Server.Notify(source, CommandsMessages.getMessage(String.Format(CommandsMessages.spectateSuccess, name))); } else { - Server.Notify(source, string.Format("[Duel] Invalid Target")); + Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.baseInvalidTarget)); } } else { - Server.Notify(source, string.Format("Syntax: /duel spectate [playerName]")); + Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.spectateSyntax)); } #endregion break; diff --git a/Server/Plugins/Duel/DuelConfig.cs b/Server/Plugins/Duel/DuelConfig.cs index b91b0a8..e31f281 100644 --- a/Server/Plugins/Duel/DuelConfig.cs +++ b/Server/Plugins/Duel/DuelConfig.cs @@ -6,6 +6,7 @@ namespace Server.Plugins.Duel { static public class DuelConfig { + public const string pluginName = "Duel"; public const int maxRequestTime = 30; } } diff --git a/Server/Plugins/Duel/Resources/CommandsMessages.cs b/Server/Plugins/Duel/Resources/CommandsMessages.cs new file mode 100644 index 0000000..ffd2f51 --- /dev/null +++ b/Server/Plugins/Duel/Resources/CommandsMessages.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Server.Plugins.Duel.Resources +{ + static class CommandsMessages + { + // Base Command + public static readonly string baseSyntax = "Type '/duel help' for further informations about this plugin"; + public static readonly string baseInvalidTarget = "Invalid target"; + public static readonly string baseAlreadyDueling = "You're already involved in a duel"; + public static readonly string baseNoDuelRequestFound = "No duel request found"; + // Start + public static readonly string startSyntax = "Syntax : /duel start [player2]"; + public static readonly string startSelfError = "Unfortunatly, you can't duel yourself"; + public static readonly string startTargetAlreadyDueling = "The target is already involved in a duel"; + public static readonly string startAcceptMessage = "{0} wants to duel you ! /duel accept or /duel refuse"; + + // Duel Accept + public static readonly string acceptSyntax = "Syntax : /duel accept"; + // Duel Refuse + public static readonly string refuseSyntax = "Syntax : /duel refuse"; + + // Duel Stop + public static readonly string stopSyntax = "Syntax : /duel stop"; + // Spectate + public static readonly string spectateSyntax = "Syntax : /duel spectate [player]"; + public static readonly string spectateSuccess = "You are spectating the duel of {0} !"; + + public static string getMessage(String message) + { + return String.Format("[{0}] " + message, DuelConfig.pluginName); + } + } +} diff --git a/Server/Plugins/Duel/PlayerDuel.cs b/Server/Plugins/Duel/Resources/PlayerDuel.cs similarity index 100% rename from Server/Plugins/Duel/PlayerDuel.cs rename to Server/Plugins/Duel/Resources/PlayerDuel.cs diff --git a/Server/Plugins/Duel/DuelSystem.cs b/Server/Plugins/Duel/Scripts/DuelSystem.cs similarity index 100% rename from Server/Plugins/Duel/DuelSystem.cs rename to Server/Plugins/Duel/Scripts/DuelSystem.cs From fde6f7e3ab41e947759c55600435c566d672e8b3 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Sat, 20 Oct 2018 17:16:21 +0200 Subject: [PATCH 17/18] Cleaning the code and improve some mechanics --- Resources/CubeworldNetworking | 2 +- Server/Extensions/ChatManager.cs | 47 -------- Server/Extensions/Extensions.cs | 1 - Server/Plugins/Arena/ArenaConfig.cs | 8 +- Server/Plugins/Arena/ArenaCore.cs | 14 ++- .../Plugins/Arena/{ => Resources}/Commands.cs | 102 +++++++++--------- Server/Plugins/BaseServer/BaseServerConfig.cs | 7 ++ Server/Plugins/BaseServer/BaseServerCore.cs | 25 +++++ .../BaseServer/Resources/Commands.cs} | 54 ++++++---- .../Plugins/BaseServer/Scripts/ChatManager.cs | 39 +++++++ Server/Plugins/CommandsBase.cs | 20 ++++ Server/Plugins/Duel/DuelConfig.cs | 4 + Server/Plugins/Duel/DuelCore.cs | 17 ++- .../Plugins/Duel/{ => Resources}/Commands.cs | 65 ++++++----- Server/Plugins/Duel/Scripts/DuelSystem.cs | 16 +-- Server/Plugins/PluginBase.cs | 7 +- Server/Plugins/PluginsConfig.cs | 1 + Server/Plugins/PluginsCore.cs | 17 ++- 18 files changed, 272 insertions(+), 174 deletions(-) delete mode 100644 Server/Extensions/ChatManager.cs rename Server/Plugins/Arena/{ => Resources}/Commands.cs (57%) create mode 100644 Server/Plugins/BaseServer/BaseServerConfig.cs create mode 100644 Server/Plugins/BaseServer/BaseServerCore.cs rename Server/{Extensions/ChatCommands.cs => Plugins/BaseServer/Resources/Commands.cs} (67%) create mode 100644 Server/Plugins/BaseServer/Scripts/ChatManager.cs create mode 100644 Server/Plugins/CommandsBase.cs rename Server/Plugins/Duel/{ => Resources}/Commands.cs (53%) diff --git a/Resources/CubeworldNetworking b/Resources/CubeworldNetworking index 5323adb..b24405c 160000 --- a/Resources/CubeworldNetworking +++ b/Resources/CubeworldNetworking @@ -1 +1 @@ -Subproject commit 5323adb8735c2b78d27fd2add8f4df54addbf546 +Subproject commit b24405c0d42a1384d3cce28cae56d7858fb568c5 diff --git a/Server/Extensions/ChatManager.cs b/Server/Extensions/ChatManager.cs deleted file mode 100644 index fb429b2..0000000 --- a/Server/Extensions/ChatManager.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Resources; -using Resources.Datagram; -using Server.Plugins; - -namespace Server.Extensions -{ - class ChatManager - { - public static void Init() - { - Server.ChatMessageReceived += analyzeMessage; - } - private static void analyzeMessage(Chat chat, Player source) - { - var message = chat.Text; - Log.Print(Server.dynamicEntities[chat.Sender].name + ": ", ConsoleColor.Cyan); - Log.PrintLn(chat.Text, ConsoleColor.White, false); - if (!message.StartsWith("/")) - { - Server.BroadcastUDP(chat.data, null); //pass to all players - return; - } - Boolean CommandFound; - CommandFound = ChatCommands.ParseAsCommand(message, source); - if (!CommandFound) - { - foreach (PluginBase plugin in PluginsCore.pluginsWithCommands) - { - CommandFound = plugin.analyzeCommand(message, source); - if (CommandFound == true) - { - break; - } - } - if (!CommandFound) - { - var commandName = message.Substring(1).Split(" ")[0]; - Server.Notify(source, CommandsBaseMessages.getMessage(String.Format(CommandsBaseMessages.baseUnknowCommand, commandName))); - } - } - } - } -} diff --git a/Server/Extensions/Extensions.cs b/Server/Extensions/Extensions.cs index 4183dfb..a2368de 100644 --- a/Server/Extensions/Extensions.cs +++ b/Server/Extensions/Extensions.cs @@ -7,7 +7,6 @@ public static class Extensions { public static void Init() { AntiCheat.Init(); Pvp.Init(); - ChatManager.Init(); SpecialMoves.Init(); Balancing.Init(); } diff --git a/Server/Plugins/Arena/ArenaConfig.cs b/Server/Plugins/Arena/ArenaConfig.cs index d9a215b..9ae0861 100644 --- a/Server/Plugins/Arena/ArenaConfig.cs +++ b/Server/Plugins/Arena/ArenaConfig.cs @@ -1,7 +1,13 @@ -namespace Server.Plugins.Arena +using System; +using System.Collections.Generic; + +namespace Server.Plugins.Arena { static public class ArenaConfig { public const string pluginName = "Arena"; + public static List pluginDependencies = new List{ + "BaseServer" + }; } } diff --git a/Server/Plugins/Arena/ArenaCore.cs b/Server/Plugins/Arena/ArenaCore.cs index d3cca0c..8791145 100644 --- a/Server/Plugins/Arena/ArenaCore.cs +++ b/Server/Plugins/Arena/ArenaCore.cs @@ -4,26 +4,32 @@ using Microsoft.EntityFrameworkCore; using Resources; using Server.Plugins.Arena.Database; +using Server.Plugins.Arena.Resources; namespace Server.Plugins.Arena { class ArenaCore : PluginBase { - public static ArenaDatabase ArenaDatabase; + public ArenaDatabase ArenaDatabase; + CommandsBase command; public ArenaCore() { ArenaDatabase = new ArenaDatabase(); ArenaDatabase.Database.Migrate(); - Commands.Init(ArenaDatabase,this); + command = new Commands(this); pluginName = ArenaConfig.pluginName; } public override Boolean hasCommands() { return true; } - public override Boolean analyzeCommand(string message,Player source) + public override Boolean analyzeCommand(string message, Player source) { - return Commands.ParseAsCommand(message, source); + return command.ParseAsCommand(message, source); + } + public override List checkDependencies() + { + return ArenaConfig.pluginDependencies; } } } diff --git a/Server/Plugins/Arena/Commands.cs b/Server/Plugins/Arena/Resources/Commands.cs similarity index 57% rename from Server/Plugins/Arena/Commands.cs rename to Server/Plugins/Arena/Resources/Commands.cs index d3b23d5..d8db78e 100644 --- a/Server/Plugins/Arena/Commands.cs +++ b/Server/Plugins/Arena/Resources/Commands.cs @@ -5,18 +5,14 @@ using Resources; using Server.Plugins.Arena.Database; using Server.Plugins.Arena.Resources; -namespace Server.Plugins.Arena +namespace Server.Plugins.Arena.Resources { - class Commands + class Commands : CommandsBase { - public static ArenaDatabase ArenaDatabase; - public static PluginBase pluginRef; - public static void Init(ArenaDatabase arenaDatabase, PluginBase plugin) + public Commands(PluginBase plugin) : base(plugin) { - ArenaDatabase = arenaDatabase; - pluginRef = plugin; } - public static Boolean ParseAsCommand(string message, Player source) + public override Boolean ParseAsCommand(string message, Player source) { message = message.ToLower(); var commandName = message.Substring(1).Split(" ")[0]; @@ -26,7 +22,7 @@ public static Boolean ParseAsCommand(string message, Player source) } if (message.Length == 1 + pluginRef.getName().Length) { - Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.baseSyntax)); + ServerCore.Notify(source, CommandsMessages.getMessage(CommandsMessages.baseSyntax)); return true; } var parameters = message.Substring(2 + pluginRef.getName().Length).Split(" "); @@ -38,7 +34,7 @@ public static Boolean ParseAsCommand(string message, Player source) #region setup if (source.entity.name != "BLACKROCK" && source.entity.name != "BLIZZY") { - Server.Notify(source, CommandsMessages.getMessage(CommandsBaseMessages.baseNoPermission)); + ServerCore.Notify(source, CommandsMessages.getMessage(CommandsBaseMessages.baseNoPermission)); break; } string arenaName = null; @@ -46,19 +42,19 @@ public static Boolean ParseAsCommand(string message, Player source) { arenaName = parameters[1]; } - else if(parameters.Length > 2) + else if (parameters.Length > 2) { - Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.setupSyntax)); + ServerCore.Notify(source, CommandsMessages.getMessage(CommandsMessages.setupSyntax)); break; } - response = ArenaDatabase.launchSetupArena(arenaName); + response = ((ArenaCore)pluginRef).ArenaDatabase.launchSetupArena(arenaName); if (response == ArenaResponse.SetupLaunched) { - Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.setupInitialized)); + ServerCore.Notify(source, CommandsMessages.getMessage(CommandsMessages.setupInitialized)); } else if (response == ArenaResponse.SetupAlreadyLaunched) { - Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.setupAlreadyInitialized)); + ServerCore.Notify(source, CommandsMessages.getMessage(CommandsMessages.setupAlreadyInitialized)); } break; #endregion @@ -66,7 +62,7 @@ public static Boolean ParseAsCommand(string message, Player source) #region setup-set if (source.entity.name != "BLACKROCK" && source.entity.name != "BLIZZY") { - Server.Notify(source, CommandsMessages.getMessage(CommandsBaseMessages.baseNoPermission)); + ServerCore.Notify(source, CommandsMessages.getMessage(CommandsBaseMessages.baseNoPermission)); break; } if (parameters.Length == 2) @@ -80,30 +76,30 @@ public static Boolean ParseAsCommand(string message, Player source) switch (parameters[1]) { case "player1": - response = ArenaDatabase.setPositionSetupArena(currentPos, ArenaPositionName.player1); + response = ((ArenaCore)pluginRef).ArenaDatabase.setPositionSetupArena(currentPos, ArenaPositionName.player1); break; case "player2": - response = ArenaDatabase.setPositionSetupArena(currentPos, ArenaPositionName.player2); + response = ((ArenaCore)pluginRef).ArenaDatabase.setPositionSetupArena(currentPos, ArenaPositionName.player2); break; case "spectator": - response = ArenaDatabase.setPositionSetupArena(currentPos, ArenaPositionName.spectator); + response = ((ArenaCore)pluginRef).ArenaDatabase.setPositionSetupArena(currentPos, ArenaPositionName.spectator); break; default: - Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.setSyntax)); + ServerCore.Notify(source, CommandsMessages.getMessage(CommandsMessages.setSyntax)); break; } if (response == ArenaResponse.SetupPositionSet) { - Server.Notify(source, CommandsMessages.getMessage(string.Format(CommandsMessages.setPositionSuccess, parameters[1]))); + ServerCore.Notify(source, CommandsMessages.getMessage(string.Format(CommandsMessages.setPositionSuccess, parameters[1]))); } else if (response == ArenaResponse.SetupEmpty) { - Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.baseSetupNotInitialized)); + ServerCore.Notify(source, CommandsMessages.getMessage(CommandsMessages.baseSetupNotInitialized)); } } else { - Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.setSyntax)); + ServerCore.Notify(source, CommandsMessages.getMessage(CommandsMessages.setSyntax)); } break; #endregion @@ -111,24 +107,24 @@ public static Boolean ParseAsCommand(string message, Player source) #region setup-name if (source.entity.name != "BLACKROCK" && source.entity.name != "BLIZZY") { - Server.Notify(source, CommandsMessages.getMessage(CommandsBaseMessages.baseNoPermission)); + ServerCore.Notify(source, CommandsMessages.getMessage(CommandsBaseMessages.baseNoPermission)); break; } if (parameters.Length == 2) { - response = ArenaDatabase.setNameArena(parameters[1]); + response = ((ArenaCore)pluginRef).ArenaDatabase.setNameArena(parameters[1]); if (response == ArenaResponse.SetupNameSet) { - Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.nameChangeSuccess)); + ServerCore.Notify(source, CommandsMessages.getMessage(CommandsMessages.nameChangeSuccess)); } else if (response == ArenaResponse.SetupEmpty) { - Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.baseSetupNotInitialized)); + ServerCore.Notify(source, CommandsMessages.getMessage(CommandsMessages.baseSetupNotInitialized)); } } else { - Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.createSyntax)); + ServerCore.Notify(source, CommandsMessages.getMessage(CommandsMessages.createSyntax)); } break; #endregion @@ -136,26 +132,26 @@ public static Boolean ParseAsCommand(string message, Player source) #region arena-create if (source.entity.name != "BLACKROCK" && source.entity.name != "BLIZZY") { - Server.Notify(source, CommandsMessages.getMessage(CommandsBaseMessages.baseNoPermission)); + ServerCore.Notify(source, CommandsMessages.getMessage(CommandsBaseMessages.baseNoPermission)); break; } - if(parameters.Length > 1) + if (parameters.Length > 1) { - Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.createSyntax)); + ServerCore.Notify(source, CommandsMessages.getMessage(CommandsMessages.createSyntax)); break; } - response = ArenaDatabase.SaveDuelArena(); + response = ((ArenaCore)pluginRef).ArenaDatabase.SaveDuelArena(); if (response == ArenaResponse.ArenaCreated) { - Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.createSuccess)); + ServerCore.Notify(source, CommandsMessages.getMessage(CommandsMessages.createSuccess)); } else if (response == ArenaResponse.SetupIncomplete) { - Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.createIncomplete)); + ServerCore.Notify(source, CommandsMessages.getMessage(CommandsMessages.createIncomplete)); } else if (response == ArenaResponse.SetupEmpty) { - Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.baseSetupNotInitialized)); + ServerCore.Notify(source, CommandsMessages.getMessage(CommandsMessages.baseSetupNotInitialized)); } break; #endregion @@ -163,7 +159,7 @@ public static Boolean ParseAsCommand(string message, Player source) #region arena-delete if (source.entity.name != "BLACKROCK" && source.entity.name != "BLIZZY") { - Server.Notify(source, CommandsMessages.getMessage(CommandsBaseMessages.baseNoPermission)); + ServerCore.Notify(source, CommandsMessages.getMessage(CommandsBaseMessages.baseNoPermission)); break; } if (parameters.Length == 2) @@ -172,25 +168,25 @@ public static Boolean ParseAsCommand(string message, Player source) if (isId) { var id = Int32.Parse(parameters[1]); - response = ArenaDatabase.RemoveDuelArena((uint)id); + response = ((ArenaCore)pluginRef).ArenaDatabase.RemoveDuelArena((uint)id); } else { - response = ArenaDatabase.RemoveDuelArena(parameters[1]); + response = ((ArenaCore)pluginRef).ArenaDatabase.RemoveDuelArena(parameters[1]); } switch (response) { case ArenaResponse.ArenaDeleted: - Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.deleteSuccess)); + ServerCore.Notify(source, CommandsMessages.getMessage(CommandsMessages.deleteSuccess)); break; case ArenaResponse.ArenaNotFound: - Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.deleteNotFound)); + ServerCore.Notify(source, CommandsMessages.getMessage(CommandsMessages.deleteNotFound)); break; } } else { - Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.deleteSyntax)); + ServerCore.Notify(source, CommandsMessages.getMessage(CommandsMessages.deleteSyntax)); } break; #endregion @@ -198,18 +194,18 @@ public static Boolean ParseAsCommand(string message, Player source) #region reset if (source.entity.name != "BLACKROCK" && source.entity.name != "BLIZZY") { - Server.Notify(source, CommandsMessages.getMessage(CommandsBaseMessages.baseNoPermission)); + ServerCore.Notify(source, CommandsMessages.getMessage(CommandsBaseMessages.baseNoPermission)); break; } - if(parameters.Length > 1) + if (parameters.Length > 1) { - Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.resetSyntax)); + ServerCore.Notify(source, CommandsMessages.getMessage(CommandsMessages.resetSyntax)); break; } - response = ArenaDatabase.ResetArena(); + response = ((ArenaCore)pluginRef).ArenaDatabase.ResetArena(); if (response == ArenaResponse.ArenaReset) { - Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.resetSuccess)); + ServerCore.Notify(source, CommandsMessages.getMessage(CommandsMessages.resetSuccess)); } #endregion break; @@ -217,13 +213,15 @@ public static Boolean ParseAsCommand(string message, Player source) #region arena-help if (source.entity.name != "BLACKROCK" && source.entity.name != "BLIZZY") { - Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.setupSyntax)); - Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.setSyntax)); - Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.nameSyntax)); - Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.createSyntax)); - Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.deleteSyntax)); - Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.resetSyntax)); + ServerCore.Notify(source, CommandsMessages.getMessage(CommandsBaseMessages.baseNoPermission)); + break; } + ServerCore.Notify(source, CommandsMessages.getMessage(CommandsMessages.setupSyntax)); + ServerCore.Notify(source, CommandsMessages.getMessage(CommandsMessages.setSyntax)); + ServerCore.Notify(source, CommandsMessages.getMessage(CommandsMessages.nameSyntax)); + ServerCore.Notify(source, CommandsMessages.getMessage(CommandsMessages.createSyntax)); + ServerCore.Notify(source, CommandsMessages.getMessage(CommandsMessages.deleteSyntax)); + ServerCore.Notify(source, CommandsMessages.getMessage(CommandsMessages.resetSyntax)); break; #endregion default: diff --git a/Server/Plugins/BaseServer/BaseServerConfig.cs b/Server/Plugins/BaseServer/BaseServerConfig.cs new file mode 100644 index 0000000..8e1393d --- /dev/null +++ b/Server/Plugins/BaseServer/BaseServerConfig.cs @@ -0,0 +1,7 @@ +namespace Server.Plugins.BaseServer +{ + static public class BaseServerConfig + { + public const string pluginName = "BaseServer"; + } +} diff --git a/Server/Plugins/BaseServer/BaseServerCore.cs b/Server/Plugins/BaseServer/BaseServerCore.cs new file mode 100644 index 0000000..a7a68b5 --- /dev/null +++ b/Server/Plugins/BaseServer/BaseServerCore.cs @@ -0,0 +1,25 @@ +using System; +using Resources; +using Server.Plugins.BaseServer.Resources; +using Server.Plugins.BaseServer.Scripts; +namespace Server.Plugins.BaseServer +{ + class BaseServerCore : PluginBase + { + CommandsBase command; + public BaseServerCore() + { + command = new Commands(this); + ChatManager chatManager = new ChatManager(); + pluginName = BaseServerConfig.pluginName; + } + public override Boolean hasCommands() + { + return true; + } + public override Boolean analyzeCommand(string message,Player source) + { + return command.ParseAsCommand(message, source); + } + } +} diff --git a/Server/Extensions/ChatCommands.cs b/Server/Plugins/BaseServer/Resources/Commands.cs similarity index 67% rename from Server/Extensions/ChatCommands.cs rename to Server/Plugins/BaseServer/Resources/Commands.cs index a58e3b9..7965c68 100644 --- a/Server/Extensions/ChatCommands.cs +++ b/Server/Plugins/BaseServer/Resources/Commands.cs @@ -1,69 +1,81 @@ -using Resources; -using Resources.Datagram; -using Resources.Packet; -using Server.Plugins; -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Text; +using Resources; +using Resources.Datagram; -namespace Server.Extensions { -namespace Server.Extensions { - public static class ChatCommands { - public static Boolean ParseAsCommand(string message, Player source) { +namespace Server.Plugins.BaseServer.Resources +{ + class Commands : CommandsBase + { + public Commands(PluginBase plugin) : base(plugin) + { + } + public override Boolean ParseAsCommand(string message, Player source) + { var parameters = message.Substring(1).Split(" "); var command = parameters[0].ToLower(); - switch (command) { + switch (command) + { case "kick": case "btfo": case "ban": #region ban - if (source.entity.name != "BLACKROCK") { + if (source.entity.name != "BLACKROCK") + { ServerCore.Notify(source, "no permission"); break; } - if (parameters.Length == 1) { + if (parameters.Length == 1) + { ServerCore.Notify(source, string.Format("usage example: /kick blackrock")); break; } - var target = Server.players.FirstOrDefault(x => x.entity.name.Contains(parameters[1])); - if (target == null) { + var target = ServerCore.players.FirstOrDefault(x => x.entity.name.Contains(parameters[1])); + if (target == null) + { ServerCore.Notify(source, "invalid target"); break; }; var reason = "no reason specified"; - if (parameters.Length > 2) { + if (parameters.Length > 2) + { reason = parameters[2]; } - if (command == "kick") { + if (command == "kick") + { ServerCore.Kick(target, reason); break; } target.writer.Write((byte)ServerPacketID.BTFO); target.writer.Write(reason); - if (command == "ban") { + if (command == "ban") + { ServerCore.userDatabase.BanUser(target.entity.name, (int)target.IP.Address, target.MAC, reason); } ServerCore.RemovePlayerEntity(target, false); break; #endregion case "bleeding": - break; case "time": #region time - if (parameters.Length == 1) { + if (parameters.Length == 1) + { ServerCore.Notify(source, string.Format("usage example: /time 12:00")); break; } var clock = parameters[1].Split(":"); if (clock.Length < 2 || !int.TryParse(clock[0], out int hour) || - !int.TryParse(clock[1], out int minute)) { + !int.TryParse(clock[1], out int minute)) + { ServerCore.Notify(source, string.Format("invalid syntax")); break; } - var inGameTime = new InGameTime() { + var inGameTime = new InGameTime() + { Milliseconds = (hour * 60 + minute) * 60000, }; ServerCore.SendUDP(inGameTime.data, source); diff --git a/Server/Plugins/BaseServer/Scripts/ChatManager.cs b/Server/Plugins/BaseServer/Scripts/ChatManager.cs new file mode 100644 index 0000000..cf522e1 --- /dev/null +++ b/Server/Plugins/BaseServer/Scripts/ChatManager.cs @@ -0,0 +1,39 @@ +using System; +using Resources; +using Resources.Datagram; + +namespace Server.Plugins.BaseServer.Scripts +{ + public class ChatManager + { + public ChatManager() + { + ServerCore.ChatMessageReceived += analyzeMessage; + } + private static void analyzeMessage(Chat chat, Player source) + { + var message = chat.Text; + Log.Print(ServerCore.dynamicEntities[chat.Sender].name + ": ", ConsoleColor.Cyan); + Log.PrintLn(chat.Text, ConsoleColor.White, false); + if (!message.StartsWith("/")) + { + ServerCore.BroadcastUDP(chat.data, null); //pass to all players + return; + } + Boolean CommandFound = false; + foreach (PluginBase plugin in PluginsCore.pluginsWithCommands) + { + CommandFound = plugin.analyzeCommand(message, source); + if (CommandFound == true) + { + break; + } + } + if (!CommandFound) + { + var commandName = message.Substring(1).Split(" ")[0]; + ServerCore.Notify(source, CommandsBaseMessages.getMessage(String.Format(CommandsBaseMessages.baseUnknowCommand, commandName))); + } + } + } +} diff --git a/Server/Plugins/CommandsBase.cs b/Server/Plugins/CommandsBase.cs new file mode 100644 index 0000000..1b13f11 --- /dev/null +++ b/Server/Plugins/CommandsBase.cs @@ -0,0 +1,20 @@ +using Resources; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Server.Plugins +{ + abstract class CommandsBase + { + public PluginBase pluginRef; + protected CommandsBase(PluginBase plugin) + { + pluginRef = plugin; + } + public virtual Boolean ParseAsCommand(string message,Player source) + { + return false; + } + } +} diff --git a/Server/Plugins/Duel/DuelConfig.cs b/Server/Plugins/Duel/DuelConfig.cs index e31f281..7c1dc4b 100644 --- a/Server/Plugins/Duel/DuelConfig.cs +++ b/Server/Plugins/Duel/DuelConfig.cs @@ -7,6 +7,10 @@ namespace Server.Plugins.Duel static public class DuelConfig { public const string pluginName = "Duel"; + public static List pluginDependencies = new List{ + "BaseServer", + "Arena" + }; public const int maxRequestTime = 30; } } diff --git a/Server/Plugins/Duel/DuelCore.cs b/Server/Plugins/Duel/DuelCore.cs index d6e191b..f928b2f 100644 --- a/Server/Plugins/Duel/DuelCore.cs +++ b/Server/Plugins/Duel/DuelCore.cs @@ -1,21 +1,30 @@ using System; using System.Collections.Generic; -using System.Text; +using Resources; namespace Server.Plugins.Duel { class DuelCore : PluginBase { - public static volatile List duels = new List(); - public static List players = new List(); + public volatile List duels = new List(); + public List players = new List(); + CommandsBase command; public DuelCore() { - Commands.Init(this); + command = new Commands(this); pluginName = "Duel"; } public override Boolean hasCommands() { return true; } + public override Boolean analyzeCommand(string message, Player source) + { + return command.ParseAsCommand(message, source); + } + public override List checkDependencies() + { + return DuelConfig.pluginDependencies; + } } } diff --git a/Server/Plugins/Duel/Commands.cs b/Server/Plugins/Duel/Resources/Commands.cs similarity index 53% rename from Server/Plugins/Duel/Commands.cs rename to Server/Plugins/Duel/Resources/Commands.cs index f06e3c5..035653c 100644 --- a/Server/Plugins/Duel/Commands.cs +++ b/Server/Plugins/Duel/Resources/Commands.cs @@ -8,17 +8,16 @@ using CommandsBaseMessages = Server.Plugins.CommandsBaseMessages; namespace Server.Plugins.Duel { - class Commands + class Commands : CommandsBase { - public static PluginBase pluginRef; - public static void Init(PluginBase plugin) + + public Commands(PluginBase plugin) : base(plugin) { - pluginRef = plugin; } - private static Boolean ParseAsCommand(string message, Player sourceTemp) + public override Boolean ParseAsCommand(string message, Player sourceTemp) { PlayerDuel target; - PlayerDuel source = DuelCore.players.FirstOrDefault(x => x.entity.guid == sourceTemp.entity.guid); + PlayerDuel source = ((DuelCore)pluginRef).players.FirstOrDefault(x => x.entity.guid == sourceTemp.entity.guid); DuelSystem duelFinder; message = message.ToLower(); var commandName = message.Substring(1).Split(" ")[0]; @@ -28,7 +27,7 @@ private static Boolean ParseAsCommand(string message, Player sourceTemp) } if (message.Length == 1 + pluginRef.getName().Length) { - Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.baseSyntax)); + ServerCore.Notify(source, CommandsMessages.getMessage(CommandsMessages.baseSyntax)); return true; } var parameters = message.Substring(2 + pluginRef.getName().Length).Split(" "); @@ -36,23 +35,23 @@ private static Boolean ParseAsCommand(string message, Player sourceTemp) { case "help": #region help - Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.startSyntax)); - Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.acceptSyntax)); - Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.refuseSyntax)); - Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.stopSyntax)); - Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.spectateSyntax)); + ServerCore.Notify(source, CommandsMessages.getMessage(CommandsMessages.startSyntax)); + ServerCore.Notify(source, CommandsMessages.getMessage(CommandsMessages.acceptSyntax)); + ServerCore.Notify(source, CommandsMessages.getMessage(CommandsMessages.refuseSyntax)); + ServerCore.Notify(source, CommandsMessages.getMessage(CommandsMessages.stopSyntax)); + ServerCore.Notify(source, CommandsMessages.getMessage(CommandsMessages.spectateSyntax)); break; #endregion case "stop": #region stop - duelFinder = DuelCore.duels.LastOrDefault(x => x.player1.entity.name.Contains(source.entity.name) || x.player2.entity.name.Contains(source.entity.name)); + duelFinder = ((DuelCore)pluginRef).duels.LastOrDefault(x => x.player1.entity.name.Contains(source.entity.name) || x.player2.entity.name.Contains(source.entity.name)); if (duelFinder != null) { duelFinder.Stop(); } else { - Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.baseNoDuelRequestFound)); + ServerCore.Notify(source, CommandsMessages.getMessage(CommandsMessages.baseNoDuelRequestFound)); } break; #endregion @@ -60,69 +59,69 @@ private static Boolean ParseAsCommand(string message, Player sourceTemp) #region start if (parameters.Length == 3) { - target = DuelCore.players.FirstOrDefault(x => x.entity.name.Contains(parameters[1])); + target = ((DuelCore)pluginRef).players.FirstOrDefault(x => x.entity.name.Contains(parameters[1])); if (target == null) { - Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.baseInvalidTarget)); + ServerCore.Notify(source, CommandsMessages.getMessage(CommandsMessages.baseInvalidTarget)); break; } else if (target == source && source.entity.name != "BLIZZY") { - Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.startSelfError)); + ServerCore.Notify(source, CommandsMessages.getMessage(CommandsMessages.startSelfError)); break; } else if (source.Duel == true) { - Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.baseAlreadyDueling)); + ServerCore.Notify(source, CommandsMessages.getMessage(CommandsMessages.baseAlreadyDueling)); break; } else if (target.Duel == true) { - Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.startTargetAlreadyDueling)); + ServerCore.Notify(source, CommandsMessages.getMessage(CommandsMessages.startTargetAlreadyDueling)); break; } - Server.Notify(source, CommandsMessages.getMessage(String.Format(CommandsMessages.startAcceptMessage,source.entity.name))); - var duel = new DuelSystem(source, target, DateTimeOffset.UtcNow.ToUnixTimeSeconds()); - DuelCore.duels.Add(duel); + ServerCore.Notify(source, CommandsMessages.getMessage(String.Format(CommandsMessages.startAcceptMessage,source.entity.name))); + var duel = new DuelSystem(pluginRef,source, target, DateTimeOffset.UtcNow.ToUnixTimeSeconds()); + ((DuelCore)pluginRef).duels.Add(duel); new Thread(() => duel.RunDuel()).Start(); } else { - Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.startSyntax)); + ServerCore.Notify(source, CommandsMessages.getMessage(CommandsMessages.startSyntax)); } break; #endregion case "accept": #region accept - duelFinder = DuelCore.duels.LastOrDefault(x => x.player2.entity.name.Contains(source.entity.name)); + duelFinder = ((DuelCore)pluginRef).duels.LastOrDefault(x => x.player2.entity.name.Contains(source.entity.name)); if (duelFinder != null && source.Duel == null) { duelFinder.AcceptDuel(); } else if (source.Duel == true) { - Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.baseAlreadyDueling)); + ServerCore.Notify(source, CommandsMessages.getMessage(CommandsMessages.baseAlreadyDueling)); } else { - Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.baseNoDuelRequestFound)); + ServerCore.Notify(source, CommandsMessages.getMessage(CommandsMessages.baseNoDuelRequestFound)); } break; #endregion case "refuse": #region refuse - duelFinder = DuelCore.duels.LastOrDefault(x => x.player2.entity.name.Contains(source.entity.name)); + duelFinder = ((DuelCore)pluginRef).duels.LastOrDefault(x => x.player2.entity.name.Contains(source.entity.name)); if (duelFinder != null && source.Duel == null) { duelFinder.RefuseDuel(); } else if (source.Duel == true) { - Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.baseAlreadyDueling)); + ServerCore.Notify(source, CommandsMessages.getMessage(CommandsMessages.baseAlreadyDueling)); } else { - Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.baseNoDuelRequestFound)); + ServerCore.Notify(source, CommandsMessages.getMessage(CommandsMessages.baseNoDuelRequestFound)); } break; #endregion @@ -131,20 +130,20 @@ private static Boolean ParseAsCommand(string message, Player sourceTemp) if (parameters.Length == 2) { var name = parameters[1]; - duelFinder = DuelCore.duels.LastOrDefault(x => x.player1.entity.name.Contains(name) || x.player2.entity.name.Contains(name)); + duelFinder = ((DuelCore)pluginRef).duels.LastOrDefault(x => x.player1.entity.name.Contains(name) || x.player2.entity.name.Contains(name)); if (duelFinder != null && source.Duel == null) { duelFinder.Spectate(source); - Server.Notify(source, CommandsMessages.getMessage(String.Format(CommandsMessages.spectateSuccess, name))); + ServerCore.Notify(source, CommandsMessages.getMessage(String.Format(CommandsMessages.spectateSuccess, name))); } else { - Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.baseInvalidTarget)); + ServerCore.Notify(source, CommandsMessages.getMessage(CommandsMessages.baseInvalidTarget)); } } else { - Server.Notify(source, CommandsMessages.getMessage(CommandsMessages.spectateSyntax)); + ServerCore.Notify(source, CommandsMessages.getMessage(CommandsMessages.spectateSyntax)); } #endregion break; diff --git a/Server/Plugins/Duel/Scripts/DuelSystem.cs b/Server/Plugins/Duel/Scripts/DuelSystem.cs index d4c6fef..2e6abc7 100644 --- a/Server/Plugins/Duel/Scripts/DuelSystem.cs +++ b/Server/Plugins/Duel/Scripts/DuelSystem.cs @@ -9,6 +9,7 @@ namespace Server.Plugins.Duel { class DuelSystem { + private PluginBase pluginRef; private volatile Boolean ongoing; // status of the duel private volatile Boolean stop; // Token for stopping duel/thread public Player winner; @@ -41,18 +42,19 @@ private Boolean WaitingResponse() this.ongoing = true; break; case 2: - Server.Notify(this.player1, string.Format("[Duel] {0} refused the duel", this.player2.entity.name)); + ServerCore.Notify(this.player1, string.Format("[Duel] {0} refused the duel", this.player2.entity.name)); break; default: - Server.Notify(this.player1, string.Format("[Duel] {0} didn't respond within the 30s limit", this.player2.entity.name)); + ServerCore.Notify(this.player1, string.Format("[Duel] {0} didn't respond within the 30s limit", this.player2.entity.name)); break; } return ongoing; #endregion } - public DuelSystem(Player player1, Player player2, long requestInitialTime) + public DuelSystem(PluginBase pluginRef,Player player1, Player player2, long requestInitialTime) { #region createDuel + this.pluginRef = pluginRef; this.ongoing = false; this.player1 = player1; this.player2 = player2; @@ -151,7 +153,7 @@ private void ManageDuel() RestorePlayersState(); } } - DuelCore.duels.Remove(this); + ((DuelCore)pluginRef).duels.Remove(this); #endregion } public void Stop() @@ -176,8 +178,8 @@ public void Spectate(Player player) } public void NotifyPlayers(string message) { - Server.Notify(this.player1, message); - Server.Notify(this.player2, message); + ServerCore.Notify(this.player1, message); + ServerCore.Notify(this.player2, message); } public void RunDuel() { @@ -189,7 +191,7 @@ public void RunDuel() } else { - DuelCore.duels.Remove(this); + ((DuelCore)pluginRef).duels.Remove(this); } #endregion } diff --git a/Server/Plugins/PluginBase.cs b/Server/Plugins/PluginBase.cs index 0dda59b..4183eb3 100644 --- a/Server/Plugins/PluginBase.cs +++ b/Server/Plugins/PluginBase.cs @@ -7,7 +7,7 @@ namespace Server.Plugins { public class PluginBase { - protected String pluginName; + public String pluginName; public virtual Boolean hasCommands() { return false; @@ -20,5 +20,10 @@ public virtual Boolean analyzeCommand(string message, Player source) { return false; } + public virtual List checkDependencies() + { + var depencies = new List(); + return depencies; + } } } diff --git a/Server/Plugins/PluginsConfig.cs b/Server/Plugins/PluginsConfig.cs index cac786b..6146aec 100644 --- a/Server/Plugins/PluginsConfig.cs +++ b/Server/Plugins/PluginsConfig.cs @@ -6,6 +6,7 @@ namespace Server.Plugins class PluginsConfig { public static List pluginsName = new List{ + "BaseServer", "Duel", "Arena" }; diff --git a/Server/Plugins/PluginsCore.cs b/Server/Plugins/PluginsCore.cs index 3e6ff9e..bf7c541 100644 --- a/Server/Plugins/PluginsCore.cs +++ b/Server/Plugins/PluginsCore.cs @@ -1,12 +1,14 @@ using System; using System.Collections.Generic; using System.Text; +using System.Linq; namespace Server.Plugins { public static class PluginsCore { public static List pluginsList; public static List pluginsWithCommands; + public static List DependenciesList; public static void Init() { pluginsList = new List(); @@ -21,12 +23,23 @@ public static void Init() { pluginsWithCommands.Add(plugin); } - Log.PrintLn("Plugin \"" + pluginName + "\" has been successfully initialized !", ConsoleColor.Green); + Log.PrintLn(String.Format("Plugin '{0}' has been successfully initialized !",pluginName), ConsoleColor.Green); pluginsList.Add(plugin); } else { - Log.PrintLn("Plugin \""+pluginName+"\" cannot be found !", ConsoleColor.Red); + Log.PrintLn(String.Format("Plugin '{0}' cannot be found !", pluginName), ConsoleColor.Red); + } + } + foreach(PluginBase plugin in pluginsList) + { + var dependencies = plugin.checkDependencies(); + foreach(string dependency in dependencies) + { + if(!pluginsList.Select(p => p.pluginName).Contains(dependency)) + { + Log.PrintLn(String.Format("Plugin '{0}' require the initialization of plugin '{1}' !", plugin.pluginName,dependency), ConsoleColor.Red); + } } } } From a33ca2cdc9b4a8a96e0c79b0edbd656962a3ceaf Mon Sep 17 00:00:00 2001 From: BuildTools Date: Sat, 20 Oct 2018 18:16:32 +0200 Subject: [PATCH 18/18] Implement Base game mechanics --- Server/Extensions/ChatMessage.cs | 25 +++++++++++++++++++++++++ Server/Extensions/Extensions.cs | 1 + Server/Plugins/PluginsCore.cs | 6 ++++++ Server/ServerCore_Events.cs | 2 +- 4 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 Server/Extensions/ChatMessage.cs diff --git a/Server/Extensions/ChatMessage.cs b/Server/Extensions/ChatMessage.cs new file mode 100644 index 0000000..5dcfb31 --- /dev/null +++ b/Server/Extensions/ChatMessage.cs @@ -0,0 +1,25 @@ +using Resources; +using Resources.Datagram; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Server.Extensions +{ + public static class ChatMessage + { + public static void Init() + { + ServerCore.ChatMessageReceived += BroadcastMessage; + } + public static void Desactivate() + { + ServerCore.ChatMessageReceived -= BroadcastMessage; + } + private static void BroadcastMessage(Chat chat, Player source) + { + ServerCore.BroadcastUDP(chat.data, null); + } + + } +} diff --git a/Server/Extensions/Extensions.cs b/Server/Extensions/Extensions.cs index a2368de..141f95e 100644 --- a/Server/Extensions/Extensions.cs +++ b/Server/Extensions/Extensions.cs @@ -7,6 +7,7 @@ public static class Extensions { public static void Init() { AntiCheat.Init(); Pvp.Init(); + ChatMessage.Init(); SpecialMoves.Init(); Balancing.Init(); } diff --git a/Server/Plugins/PluginsCore.cs b/Server/Plugins/PluginsCore.cs index bf7c541..bf4f625 100644 --- a/Server/Plugins/PluginsCore.cs +++ b/Server/Plugins/PluginsCore.cs @@ -2,6 +2,8 @@ using System.Collections.Generic; using System.Text; using System.Linq; +using Server.Extensions; + namespace Server.Plugins { public static class PluginsCore @@ -42,6 +44,10 @@ public static void Init() } } } + if(pluginsWithCommands.Count > 0) + { + ChatMessage.Desactivate(); + } } } } diff --git a/Server/ServerCore_Events.cs b/Server/ServerCore_Events.cs index c1fad0b..033a71d 100644 --- a/Server/ServerCore_Events.cs +++ b/Server/ServerCore_Events.cs @@ -10,7 +10,7 @@ namespace Server { public delegate void EntityAttackedEventHandler(Attack datagram, Player source); public delegate void ProjectileCreatedEventHandler(Projectile datagram, Player source); public delegate void PassiveProccedEventHandler(Proc datagram, Player source); - public delegate void ChatMessageReceivedEventHandler(Chat message, Player source); + public delegate void ChatMessageReceivedEventHandler(Chat chat, Player source); public delegate void EntityInteractedEventHandler(Interaction datagram, Player source); public delegate void EntityRemovedEventHandler(RemoveDynamicEntity datagram, Player source); public delegate void SpecialMoveUsedEventHandler(SpecialMove datagram, Player source);