151 lines
4.1 KiB
Elixir
151 lines
4.1 KiB
Elixir
defmodule Odinsea.Admin.Handler do
|
|
@moduledoc """
|
|
Main admin command handler.
|
|
Ported from Java handling.admin.AdminHandler
|
|
|
|
Parses chat messages starting with '!' as admin commands
|
|
and routes them to the appropriate command implementation.
|
|
"""
|
|
|
|
require Logger
|
|
|
|
alias Odinsea.Admin.Commands
|
|
alias Odinsea.Channel.Packets
|
|
|
|
@doc """
|
|
Parses and executes an admin command from chat message.
|
|
|
|
Commands start with '!' followed by the command name and arguments.
|
|
Example: "!warp PlayerName 100000000"
|
|
|
|
Returns:
|
|
- {:ok, result_message} - Command executed successfully
|
|
- {:error, reason} - Command failed
|
|
- :not_command - Message is not an admin command
|
|
"""
|
|
def handle_command(message, client_state) when is_binary(message) do
|
|
# Check if message is a command (starts with !)
|
|
if String.starts_with?(message, "!") do
|
|
parse_and_execute(message, client_state)
|
|
else
|
|
:not_command
|
|
end
|
|
end
|
|
|
|
@doc """
|
|
Parses command string and executes.
|
|
"""
|
|
def parse_and_execute(message, client_state) do
|
|
# Remove leading '!' and split into command and arguments
|
|
command_str = String.slice(message, 1..-1//-1)
|
|
parts = String.split(command_str)
|
|
|
|
case parts do
|
|
[] ->
|
|
{:error, "Empty command"}
|
|
|
|
[command | args] ->
|
|
command = String.downcase(command)
|
|
|
|
char_id = if client_state.character_id, do: client_state.character_id, else: "unknown"
|
|
Logger.info("Admin command from #{char_id}: #{command} #{inspect(args)}")
|
|
|
|
# Get admin state (character info with GM level)
|
|
admin_state = build_admin_state(client_state)
|
|
|
|
case Commands.execute(command, args, admin_state) do
|
|
{:ok, result} ->
|
|
# Send success message back to admin
|
|
notify_admin(client_state, result)
|
|
{:ok, result}
|
|
|
|
{:error, reason} ->
|
|
# Send error message back to admin
|
|
notify_admin(client_state, "Error: #{reason}")
|
|
{:error, reason}
|
|
end
|
|
end
|
|
end
|
|
|
|
@doc """
|
|
Checks if a message is an admin command.
|
|
"""
|
|
def admin_command?(message) do
|
|
String.starts_with?(message, "!")
|
|
end
|
|
|
|
@doc """
|
|
Gets the command name from a message (for logging).
|
|
"""
|
|
def extract_command_name(message) do
|
|
case String.split(message) do
|
|
[first | _] -> String.downcase(String.trim_leading(first, "!"))
|
|
_ -> "unknown"
|
|
end
|
|
end
|
|
|
|
@doc """
|
|
Sends help information to the admin.
|
|
"""
|
|
def send_help(client_state) do
|
|
commands = Commands.list_commands()
|
|
|
|
help_text = [
|
|
"=== Admin Commands ===",
|
|
""
|
|
| Enum.map(commands, fn {cmd, args, desc} ->
|
|
"!#{cmd} #{args} - #{desc}"
|
|
end)
|
|
]
|
|
|> Enum.join("\n")
|
|
|
|
notify_admin(client_state, help_text)
|
|
end
|
|
|
|
# ============================================================================
|
|
# Private Functions
|
|
# ============================================================================
|
|
|
|
defp build_admin_state(client_state) do
|
|
# Get character information including GM level
|
|
gm_level = get_gm_level(client_state)
|
|
|
|
%{
|
|
character_id: client_state.character_id,
|
|
channel_id: client_state.channel_id,
|
|
gm_level: gm_level,
|
|
client_pid: self()
|
|
}
|
|
end
|
|
|
|
defp get_gm_level(client_state) do
|
|
# Try to get GM level from character
|
|
case client_state.character_id do
|
|
nil -> 0
|
|
character_id ->
|
|
# In a full implementation, this would query the character state
|
|
# For now, use a default or check player storage
|
|
case Odinsea.Channel.Players.get_player(character_id) do
|
|
nil -> 0
|
|
player_data -> Map.get(player_data, :gm, 0)
|
|
end
|
|
end
|
|
end
|
|
|
|
defp notify_admin(client_state, message) do
|
|
case client_state.character_id do
|
|
nil ->
|
|
:ok
|
|
character_id ->
|
|
case Odinsea.Channel.Players.get_player(character_id) do
|
|
nil -> :ok
|
|
%{client_pid: pid} when is_pid(pid) ->
|
|
packet = Packets.drop_message(5, message)
|
|
send(pid, {:send_packet, packet})
|
|
:ok
|
|
_ -> :ok
|
|
end
|
|
end
|
|
end
|
|
end
|