diff --git a/.gitignore b/.gitignore index 8357e32b..cf3c8c9a 100644 --- a/.gitignore +++ b/.gitignore @@ -568,3 +568,5 @@ fabric.properties # End of https://www.gitignore.io/api/rider,csharp,visualstudio .DS_Store + +*.bat diff --git a/Uchu.World/Handlers/Commands/CharacterCommandHandler.cs b/Uchu.World/Handlers/Commands/CharacterCommandHandler.cs index 9d48bf0b..470bcda1 100644 --- a/Uchu.World/Handlers/Commands/CharacterCommandHandler.cs +++ b/Uchu.World/Handlers/Commands/CharacterCommandHandler.cs @@ -8,6 +8,7 @@ using System.Runtime.CompilerServices; using System.Text; using System.Threading.Tasks; +using System.IO; using Uchu.Core; using Uchu.Core.Client; using Uchu.Core.Resources; @@ -86,6 +87,7 @@ public string ChangeCoin(string[] arguments, Player player) { if (arguments.Length != 1) return "coin "; + // We parse this as an int instead of long, due to the max long causing bugs. Currency maxes out at a long. if (!int.TryParse(arguments[0], out var delta) || delta == default) return "Invalid "; player.Currency += delta; @@ -170,7 +172,7 @@ public string Rotation(string[] arguments, Player player) return $"{player.Transform.Rotation}"; } - [CommandHandler(Signature = "smash", Help = "Smash yourself", GameMasterLevel = GameMasterLevel.Admin)] + [CommandHandler(Signature = "smash", Help = "Smash yourself", GameMasterLevel = GameMasterLevel.Player)] public async Task Smash(string[] arguments, Player player) { var animation = "violent"; @@ -517,7 +519,7 @@ public string Stat(string[] arguments, Player player) return $"Successfully set {arguments[0]} to {value}"; } - [CommandHandler(Signature = "pvp", Help = "Change PvP state", GameMasterLevel = GameMasterLevel.Admin)] + [CommandHandler(Signature = "pvp", Help = "Change PvP state", GameMasterLevel = GameMasterLevel.Mythran)] public string Pvp(string[] arguments, Player player) { if (arguments.Length != 1) return "pvp "; @@ -643,28 +645,6 @@ public string Teleport(string[] arguments, Player player) return "tp / "; Vector3 position; - //Quaternion rotation; - - //Logger.Debug($"Current Position: {player.Transform.Position}"); - //position.X = player.Transform.Position.X; - //position.Y = player.Transform.Position.Y + 1000; - //position.Z = player.Transform.Position.Z; - - ////player.Transform.Rotation - - //Logger.Debug($"Teleporting to: {position}"); - - //player.Message(new TeleportMessage - //{ - // Associate = player, - // Position = position - //}); - - - ////player.Teleport(position, player.Transform.Rotation); - //Logger.Debug($"Sent Teleport GM"); - //return $"Going to {position}"; - var relativeX = arguments[0].StartsWith('~'); if (relativeX) arguments[0] = arguments[0].Remove(default, 1); @@ -759,7 +739,7 @@ public string AddComponent(string[] arguments, Player player) return $"Successfully added {type.Name} to {player}"; } - + [CommandHandler(Signature = "testmap", Help = "Transfer to world", GameMasterLevel = GameMasterLevel.Mythran)] public string World(string[] arguments, Player player) { @@ -777,9 +757,9 @@ public string World(string[] arguments, Player player) return $"Can't find world with ID {id}"; } - string WorldName = WorldTable.ZoneName; + var path = Path.Combine(UchuServer.Config.ResourcesConfiguration?.GameResourceFolder, Path.Combine("maps", WorldTable.ZoneName.ToLower())); - if (WorldName.EndsWith(".luz")) + if (File.Exists(path) && WorldTable.LocStatus > 0) { // // We don't want to lock up the server on a world server request, as it may take time. diff --git a/Uchu.World/Handlers/Commands/OperatorCommandHandler.cs b/Uchu.World/Handlers/Commands/OperatorCommandHandler.cs index b217fce3..8f7bf453 100644 --- a/Uchu.World/Handlers/Commands/OperatorCommandHandler.cs +++ b/Uchu.World/Handlers/Commands/OperatorCommandHandler.cs @@ -8,6 +8,7 @@ using Uchu.Core; using Uchu.World.Scripting.Managed; using Uchu.World.Social; +using Microsoft.EntityFrameworkCore; namespace Uchu.World.Handlers.Commands { @@ -236,5 +237,74 @@ public string Target(string[] arguments, Player player) return $"Target: {baseCombatAiComponent.Target}"; } + + /// + /// Executes a command as another player or every player in the session. + /// To execute a command as player "Tracer": /execute Tracer + /// To execute a command as everyone: /execute * + /// + /// + /// + [CommandHandler(Signature = "execute", Help = "Execute a command as another player", GameMasterLevel = GameMasterLevel.Admin)] + public async Task ExecuteAs(string[] arguments, Player executor) + { + if (arguments.Length == default) return "execute "; + + List players = new List(); + if (arguments[0] == "*") + { + foreach (var player in executor.Zone.Players) + { + players.Add(player); + } + } + else + { + // Todo: Fix this throwing an error if no player is found. + var player = executor.Zone.Players.FirstOrDefault(p => p.Name == arguments[0]); + if (player == default) return $"No player named {arguments[0]}"; + players.Add(player); + } + + await using var ctx = new UchuContext(); + var character = await ctx.Characters.Include(c => c.User).FirstAsync( + c => c.Id == executor.Id + ); + + var message = new List(arguments); + message.RemoveAt(0); + + var command = string.Join(" ", message); + + if (!command.StartsWith('/')) + { + command = "/" + command; + } + + if (!SocialHandler.ClientCommands.Contains(command.Split(" ").ElementAt(0)) && command.Split(" ").ElementAt(0) != "/execute" && command.Length > 1) + { + foreach (Player player in players) + { + player.SendChatMessage("You feel a magical power...", PlayerChatChannel.Normal); + var response = await UchuServer.HandleCommandAsync( + command, + player, + (GameMasterLevel)character.User.GameMasterLevel + ); + + if (!string.IsNullOrWhiteSpace(response)) + { + //executor.SendChatMessage($"{player.Name}: {response}", PlayerChatChannel.Normal); + player.SendChatMessage(response, PlayerChatChannel.Normal); + } + } + + return $"Executed \"{command}\" as {players.Count} {(players.Count == 1 ? "person" : "people")}"; + } + else + { + return $"Unable to execute \"{command}\""; + } + } } } \ No newline at end of file diff --git a/Uchu.World/Handlers/SocialHandler.cs b/Uchu.World/Handlers/SocialHandler.cs index a5476637..144c5eaf 100644 --- a/Uchu.World/Handlers/SocialHandler.cs +++ b/Uchu.World/Handlers/SocialHandler.cs @@ -11,7 +11,7 @@ namespace Uchu.World.Handlers { public class SocialHandler : HandlerGroup { - private static string[] ClientCommands = { "/quit", "/exit", "/logoutcharacter", "/camp", "/logoutaccount", "/logout", "/say", "/s", + public static string[] ClientCommands = { "/quit", "/exit", "/logoutcharacter", "/camp", "/logoutaccount", "/logout", "/say", "/s", "/whisper", "/w", "/tell", "/team", "/t", "/location", "/locate", "/loc", "/faq", "/faqs", "/shop", "/store", "/minigames", "/forums", "/thumbsup", "/thumb", "/thumb", "/victory", "/backflip", "/clap", "/cringe", "/cry", "/dance", "/gasp", "/giggle", "/talk", "/salute", "/shrug", "/sigh", "/wave", "/why", "/thanks", "/yes", "/addfriend", "/removefriend", "/addignore", "/removeignore", "/recommendedperfoptions", @@ -40,6 +40,8 @@ public async Task ParseChatMessageHandler(ParseChatMessage message, Player playe if (message.Message.StartsWith('/') && !ClientCommands.Contains(message.Message.Split(" ").ElementAt(0))) { + //Logger.Debug($"message.Message: {message.Message}"); + if (ClientCommands.Contains(message.Message.Split(" ").ElementAt(0))) return; diff --git a/Uchu.World/Objects/Components/ReplicaComponents/CharacterComponent.cs b/Uchu.World/Objects/Components/ReplicaComponents/CharacterComponent.cs index 5c2ca66f..ee5fc494 100644 --- a/Uchu.World/Objects/Components/ReplicaComponents/CharacterComponent.cs +++ b/Uchu.World/Objects/Components/ReplicaComponents/CharacterComponent.cs @@ -137,7 +137,10 @@ private void WritePart4(BitWriter writer) writer.WriteBit(IsPvP); writer.WriteBit(IsGameMaster); - writer.Write(GameMasterLevel); + + //writer.Write(GameMasterLevel); // Original code + //writer.Write((GameMasterLevel != 1 ? GameMasterLevel : 0)); // This broke the component + writer.Write(GameMasterLevel != 1 ? GameMasterLevel : (byte)0); // This casts to the correct type (u8) writer.WriteBit(false); // ??? writer.Write(0); // ??? diff --git a/Uchu.World/Objects/GameObjects/InstancingUtilities.cs b/Uchu.World/Objects/GameObjects/InstancingUtilities.cs index d887fced..f5d67597 100644 --- a/Uchu.World/Objects/GameObjects/InstancingUtilities.cs +++ b/Uchu.World/Objects/GameObjects/InstancingUtilities.cs @@ -126,6 +126,7 @@ public static GameObject InstantiateLoot(Lot lot, Player owner, GameObject sourc public static void InstantiateCurrency(int currency, Player owner, GameObject source, Vector3 spawn) { if (owner is null) return; + if (currency <= 0) return; try { diff --git a/Uchu.World/Packets/GameMessages/Server/TeleportMessage.cs b/Uchu.World/Packets/GameMessages/Server/TeleportMessage.cs index 698c00b6..baa00c08 100644 --- a/Uchu.World/Packets/GameMessages/Server/TeleportMessage.cs +++ b/Uchu.World/Packets/GameMessages/Server/TeleportMessage.cs @@ -23,17 +23,17 @@ public class TeleportMessage : ServerGameMessage public override void SerializeMessage(BitWriter writer) { - writer.WriteBit(NoGravity); writer.WriteBit(IgnoreY); writer.WriteBit(SetRotation); writer.WriteBit(SkipAllChecks); writer.Write(Position); - writer.Write(UseNavMesh); + writer.WriteBit(UseNavMesh); + writer.WriteBit(NoGravity); - writer.WriteBit(true); writer.Write(Rotation); + } } } \ No newline at end of file