Files
odinsea-elixir/lib/odinsea/game/movement.ex

147 lines
4.7 KiB
Elixir

defmodule Odinsea.Game.Movement do
@moduledoc """
Movement parsing and validation for players, mobs, pets, summons, and dragons.
Ported from Java MovementParse.java.
Movement types (kind):
- 1: Player
- 2: Mob
- 3: Pet
- 4: Summon
- 5: Dragon
This is a SIMPLIFIED implementation for now. The full Java version has complex
parsing for different movement command types. We'll expand this as needed.
"""
require Logger
alias Odinsea.Net.Packet.In
alias Odinsea.Game.Character.Position
@doc """
Parses movement data from a packet.
Returns {:ok, movements} or {:error, reason}.
For now, this returns a simplified structure. The full implementation
would parse all movement fragment types.
"""
def parse_movement(packet, _kind) do
num_commands = In.decode_byte(packet)
# For now, just skip through the movement data and extract final position
# TODO: Implement full movement parsing with all command types
case extract_final_position(packet, num_commands) do
{:ok, position} ->
{:ok, %{num_commands: num_commands, final_position: position}}
:error ->
{:error, :invalid_movement}
end
end
@doc """
Updates an entity's position from movement data.
"""
def update_position(_movements, character_id) do
# TODO: Implement position update logic
# For now, just return ok
Logger.debug("Update position for character #{character_id}")
:ok
end
# ============================================================================
# Private Functions
# ============================================================================
# Extract the final position from movement data
# This is a TEMPORARY simplification - we just read through the movement
# commands and try to extract the last absolute position
defp extract_final_position(packet, num_commands) do
try do
final_pos = parse_commands(packet, num_commands, nil)
{:ok, final_pos || %{x: 0, y: 0, stance: 0, foothold: 0}}
rescue
_ ->
:error
end
end
defp parse_commands(_packet, 0, last_position) do
last_position
end
defp parse_commands(packet, remaining, last_position) do
command = In.decode_byte(packet)
new_position =
case command do
# Absolute movement commands - extract position
cmd when cmd in [0, 37, 38, 39, 40, 41, 42] ->
x = In.decode_short(packet)
y = In.decode_short(packet)
_xwobble = In.decode_short(packet)
_ywobble = In.decode_short(packet)
_unk = In.decode_short(packet)
_xoffset = In.decode_short(packet)
_yoffset = In.decode_short(packet)
stance = In.decode_byte(packet)
_duration = In.decode_short(packet)
%{x: x, y: y, stance: stance, foothold: 0}
# Relative movement - skip for now
cmd when cmd in [1, 2, 33, 34, 36] ->
_xmod = In.decode_short(packet)
_ymod = In.decode_short(packet)
_stance = In.decode_byte(packet)
_duration = In.decode_short(packet)
last_position
# Teleport movement
cmd when cmd in [3, 4, 8, 100, 101] ->
x = In.decode_short(packet)
y = In.decode_short(packet)
_xwobble = In.decode_short(packet)
_ywobble = In.decode_short(packet)
stance = In.decode_byte(packet)
%{x: x, y: y, stance: stance, foothold: 0}
# Chair movement
cmd when cmd in [9, 12] ->
x = In.decode_short(packet)
y = In.decode_short(packet)
_unk = In.decode_short(packet)
stance = In.decode_byte(packet)
_duration = In.decode_short(packet)
%{x: x, y: y, stance: stance, foothold: 0}
# Aran combat step
cmd when cmd in [21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 35] ->
_stance = In.decode_byte(packet)
_unk = In.decode_short(packet)
last_position
# Jump down
cmd when cmd in [13, 14] ->
# Simplified - just skip the data
x = In.decode_short(packet)
y = In.decode_short(packet)
_xwobble = In.decode_short(packet)
_ywobble = In.decode_short(packet)
_unk = In.decode_short(packet)
_fh = In.decode_short(packet)
_xoffset = In.decode_short(packet)
_yoffset = In.decode_short(packet)
stance = In.decode_byte(packet)
_duration = In.decode_short(packet)
%{x: x, y: y, stance: stance, foothold: 0}
# Unknown/unhandled - log and skip
_ ->
Logger.warning("Unhandled movement command: #{command}")
last_position
end
parse_commands(packet, remaining - 1, new_position || last_position)
end
end