kimi gone wild
This commit is contained in:
282
lib/odinsea/channel/handler/alliance.ex
Normal file
282
lib/odinsea/channel/handler/alliance.ex
Normal file
@@ -0,0 +1,282 @@
|
||||
defmodule Odinsea.Channel.Handler.Alliance do
|
||||
@moduledoc """
|
||||
Handles Guild Alliance operations.
|
||||
|
||||
Ported from: src/handling/channel/handler/AllianceHandler.java
|
||||
|
||||
Guild alliances allow multiple guilds to:
|
||||
- Share a common chat channel
|
||||
- Display alliance information
|
||||
- Coordinate activities
|
||||
|
||||
## Operations
|
||||
- 1: Load alliance info
|
||||
- 2: Leave alliance
|
||||
- 3: Invite guild to alliance
|
||||
- 4: Accept alliance invitation
|
||||
- 6: Expel guild from alliance
|
||||
- 7: Change alliance leader
|
||||
- 8: Update alliance titles (ranks)
|
||||
- 9: Change member guild rank
|
||||
- 10: Update alliance notice
|
||||
- 22: Deny alliance invitation
|
||||
|
||||
## Main Handlers
|
||||
- handle_alliance/2 - All alliance operations
|
||||
- handle_deny_invite/2 - Deny alliance invitation
|
||||
"""
|
||||
|
||||
require Logger
|
||||
|
||||
alias Odinsea.Net.Packet.In
|
||||
alias Odinsea.Game.Character
|
||||
alias Odinsea.World.Guild
|
||||
alias Odinsea.Channel.Packets
|
||||
|
||||
# ============================================================================
|
||||
# Alliance Operations
|
||||
# ============================================================================
|
||||
|
||||
@doc """
|
||||
Handles all alliance operations (CP_ALLIANCE_OPERATION / 0xBA).
|
||||
|
||||
Reference: AllianceHandler.HandleAlliance()
|
||||
"""
|
||||
def handle_alliance(packet, client_pid, denied \\ false) do
|
||||
case Character.get_state_by_client(client_pid) do
|
||||
{:ok, character_id, char_state} ->
|
||||
guild_id = char_state.guild_id
|
||||
|
||||
# Check if in guild
|
||||
if guild_id <= 0 do
|
||||
send(client_pid, {:send_packet, Packets.enable_actions()})
|
||||
:ok
|
||||
else
|
||||
# Get guild info
|
||||
# guild = World.Guild.get_guild(guild_id)
|
||||
|
||||
op = In.decode_byte(packet)
|
||||
|
||||
# Handle deny separately
|
||||
if op == 22 do
|
||||
handle_deny_invite(client_pid, character_id, char_state, guild_id)
|
||||
else
|
||||
handle_alliance_op(op, packet, client_pid, character_id, char_state, guild_id)
|
||||
end
|
||||
end
|
||||
|
||||
{:error, reason} ->
|
||||
Logger.warn("Failed to handle alliance: #{inspect(reason)}")
|
||||
end
|
||||
end
|
||||
|
||||
# ============================================================================
|
||||
# Individual Operations
|
||||
# ============================================================================
|
||||
|
||||
# Operation 1: Load alliance info
|
||||
defp handle_alliance_op(1, _packet, client_pid, character_id, char_state, guild_id) do
|
||||
alliance_id = char_state.alliance_id
|
||||
|
||||
if alliance_id > 0 do
|
||||
# TODO: Get alliance info from World.Alliance
|
||||
# packets = World.Alliance.get_alliance_info(alliance_id, false)
|
||||
# Enum.each(packets, fn packet -> send(client_pid, {:send_packet, packet}) end)
|
||||
|
||||
Logger.debug("Alliance load: alliance #{alliance_id}, character #{character_id}")
|
||||
end
|
||||
|
||||
:ok
|
||||
end
|
||||
|
||||
# Operation 2: Leave alliance / Operation 6: Expel guild
|
||||
defp handle_alliance_op(op, packet, client_pid, character_id, char_state, guild_id)
|
||||
when op in [2, 6] do
|
||||
alliance_id = char_state.alliance_id
|
||||
guild_rank = char_state.guild_rank
|
||||
|
||||
# Get target guild ID
|
||||
target_guild_id = if op == 6 and byte_size(packet.data) >= 4 do
|
||||
In.decode_int(packet)
|
||||
else
|
||||
guild_id
|
||||
end
|
||||
|
||||
# Permission check: alliance rank <= 2, or own guild
|
||||
if guild_rank <= 2 or target_guild_id == guild_id do
|
||||
# TODO: Remove guild from alliance
|
||||
# World.Alliance.remove_guild_from_alliance(alliance_id, target_guild_id, target_guild_id != guild_id)
|
||||
|
||||
Logger.debug("Alliance remove: guild #{target_guild_id} from alliance #{alliance_id}, character #{character_id}")
|
||||
end
|
||||
|
||||
:ok
|
||||
end
|
||||
|
||||
# Operation 3: Invite guild to alliance
|
||||
defp handle_alliance_op(3, packet, client_pid, character_id, char_state, guild_id) do
|
||||
alliance_id = char_state.alliance_id
|
||||
alliance_rank = char_state.alliance_rank
|
||||
|
||||
# Get guild leader name to invite
|
||||
target_leader_name = In.decode_string(packet)
|
||||
|
||||
# Only alliance leader (rank 1) can invite
|
||||
if alliance_rank == 1 do
|
||||
# TODO: Get target guild leader ID
|
||||
# target_leader_id = World.Guild.get_guild_leader(target_leader_name)
|
||||
|
||||
# TODO: Get target character
|
||||
# target_char = ChannelServer.get_player_storage().get_character_by_id(target_leader_id)
|
||||
|
||||
# TODO: Check if can invite
|
||||
# if World.Alliance.can_invite(alliance_id) do
|
||||
# # Send invite
|
||||
# target_char.client.send_packet(Packets.alliance_invite(alliance_name, character_id))
|
||||
# World.Guild.set_invited_id(target_char.guild_id, alliance_id)
|
||||
# end
|
||||
|
||||
Logger.debug("Alliance invite: to leader #{target_leader_name}, alliance #{alliance_id}, character #{character_id}")
|
||||
end
|
||||
|
||||
:ok
|
||||
end
|
||||
|
||||
# Operation 4: Accept alliance invitation
|
||||
defp handle_alliance_op(4, _packet, client_pid, character_id, char_state, guild_id) do
|
||||
# Get invited alliance ID
|
||||
# invited_alliance_id = World.Guild.get_invited_id(guild_id)
|
||||
|
||||
# if invited_alliance_id > 0 do
|
||||
# # Add guild to alliance
|
||||
# success = World.Alliance.add_guild_to_alliance(invited_alliance_id, guild_id)
|
||||
# if not success do
|
||||
# # Send error message
|
||||
# end
|
||||
#
|
||||
# # Clear invited ID
|
||||
# World.Guild.set_invited_id(guild_id, 0)
|
||||
# end
|
||||
|
||||
Logger.debug("Alliance accept: guild #{guild_id}, character #{character_id}")
|
||||
:ok
|
||||
end
|
||||
|
||||
# Operation 7: Change alliance leader
|
||||
defp handle_alliance_op(7, packet, client_pid, character_id, char_state, guild_id) do
|
||||
alliance_id = char_state.alliance_id
|
||||
alliance_rank = char_state.alliance_rank
|
||||
|
||||
# Only alliance leader can change leader
|
||||
if alliance_rank == 1 do
|
||||
new_leader_id = In.decode_int(packet)
|
||||
|
||||
# TODO: Change alliance leader
|
||||
# World.Alliance.change_alliance_leader(alliance_id, new_leader_id)
|
||||
|
||||
Logger.debug("Alliance leader change: to #{new_leader_id}, alliance #{alliance_id}, character #{character_id}")
|
||||
end
|
||||
|
||||
:ok
|
||||
end
|
||||
|
||||
# Operation 8: Update alliance titles/ranks
|
||||
defp handle_alliance_op(8, packet, client_pid, character_id, char_state, guild_id) do
|
||||
alliance_id = char_state.alliance_id
|
||||
alliance_rank = char_state.alliance_rank
|
||||
|
||||
# Only alliance leader can update titles
|
||||
if alliance_rank == 1 do
|
||||
# Read 5 rank titles
|
||||
ranks = Enum.map(1..5, fn _ -> In.decode_string(packet) end)
|
||||
|
||||
# TODO: Update alliance ranks
|
||||
# World.Alliance.update_alliance_ranks(alliance_id, ranks)
|
||||
|
||||
Logger.debug("Alliance ranks update: alliance #{alliance_id}, character #{character_id}")
|
||||
end
|
||||
|
||||
:ok
|
||||
end
|
||||
|
||||
# Operation 9: Change member guild rank
|
||||
defp handle_alliance_op(9, packet, client_pid, character_id, char_state, guild_id) do
|
||||
alliance_id = char_state.alliance_id
|
||||
alliance_rank = char_state.alliance_rank
|
||||
|
||||
# Alliance rank <= 2 can change ranks
|
||||
if alliance_rank <= 2 do
|
||||
target_guild_id = In.decode_int(packet)
|
||||
new_rank = In.decode_byte(packet)
|
||||
|
||||
# TODO: Change guild rank in alliance
|
||||
# World.Alliance.change_alliance_rank(alliance_id, target_guild_id, new_rank)
|
||||
|
||||
Logger.debug("Alliance rank change: guild #{target_guild_id} to rank #{new_rank}, alliance #{alliance_id}, character #{character_id}")
|
||||
end
|
||||
|
||||
:ok
|
||||
end
|
||||
|
||||
# Operation 10: Update alliance notice
|
||||
defp handle_alliance_op(10, packet, client_pid, character_id, char_state, guild_id) do
|
||||
alliance_id = char_state.alliance_id
|
||||
alliance_rank = char_state.alliance_rank
|
||||
|
||||
# Alliance rank <= 2 can update notice
|
||||
if alliance_rank <= 2 do
|
||||
notice = In.decode_string(packet)
|
||||
|
||||
# Check notice length (max 100)
|
||||
if String.length(notice) <= 100 do
|
||||
# TODO: Update alliance notice
|
||||
# World.Alliance.update_alliance_notice(alliance_id, notice)
|
||||
|
||||
Logger.debug("Alliance notice update: alliance #{alliance_id}, character #{character_id}")
|
||||
end
|
||||
end
|
||||
|
||||
:ok
|
||||
end
|
||||
|
||||
# Unknown operation
|
||||
defp handle_alliance_op(op, _packet, _client_pid, character_id, _char_state, guild_id) do
|
||||
Logger.warning("Unknown alliance operation #{op} from character #{character_id}, guild #{guild_id}")
|
||||
:ok
|
||||
end
|
||||
|
||||
# ============================================================================
|
||||
# Deny Invite Handler
|
||||
# ============================================================================
|
||||
|
||||
@doc """
|
||||
Handles deny alliance invitation (CP_DENY_ALLIANCE_REQUEST / 0xBB).
|
||||
|
||||
Also called when op == 22 in alliance operation.
|
||||
|
||||
Reference: AllianceHandler.DenyInvite()
|
||||
"""
|
||||
def handle_deny_invite(client_pid, character_id, char_state, guild_id) do
|
||||
# Get invited alliance ID
|
||||
# invited_alliance_id = World.Guild.get_invited_id(guild_id)
|
||||
|
||||
# if invited_alliance_id > 0 do
|
||||
# # Get alliance leader
|
||||
# leader_id = World.Alliance.get_alliance_leader(invited_alliance_id)
|
||||
#
|
||||
# if leader_id > 0 do
|
||||
# # Notify leader of rejection
|
||||
# leader = ChannelServer.get_player_storage().get_character_by_id(leader_id)
|
||||
# if leader do
|
||||
# leader.drop_message(5, "#{guild.name} Guild has rejected the Guild Union invitation.")
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # Clear invited ID
|
||||
# World.Guild.set_invited_id(guild_id, 0)
|
||||
# end
|
||||
|
||||
Logger.debug("Alliance invite denied: guild #{guild_id}, character #{character_id}")
|
||||
:ok
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user