Begin implementing :set_player_position packet in Play
Some checks failed
Build & Test / nix-build (push) Failing after 17s

This commit is contained in:
Kodi Craft 2024-08-19 00:53:34 +02:00
parent c7d3b139fe
commit ec7119251c
Signed by: kodi
GPG Key ID: 69D9EED60B242822
2 changed files with 55 additions and 3 deletions

View File

@ -20,7 +20,8 @@ defmodule Amethyst.API.Game do
a game with Amethyst.
"""
@callback instantiate() :: {:ok, new_state :: term} | {:error, reason :: term}
@callback login(connection_process :: pid(), player_cfg :: keyword(), state :: term) :: {:ok, new_state :: term} | {:refuse, new_state :: term}
@callback login(from :: pid(), player_cfg :: keyword(), state :: term) :: {:ok, new_state :: term} | {:refuse, new_state :: term}
@callback player_position(from :: pid(), {x :: float(), y :: float(), z :: float()}, state :: term) :: {{x :: float(), y :: float(), z :: float()}, state :: term}
defmacro __using__(opts) do
meta = Keyword.get(opts, :meta, [])
@ -54,6 +55,12 @@ defmodule Amethyst.API.Game do
send(caller, :refuse)
loop(mod, state)
end
{:player_position, caller, pos} ->
case mod.player_position(caller, pos, state) do
{pos, state} ->
send(caller, pos)
loop(mod, state)
end
end
end
@ -64,4 +71,12 @@ defmodule Amethyst.API.Game do
:refuse -> :refuse
end
end
@spec player_position(atom() | pid() | port() | reference() | {atom(), atom()}, {float(), float(), float()}) :: {float(), float(), float()}
def player_position(pid, pos) do
send(pid, {:player_position, self(), pos})
receive do
pos -> pos
end
end
end

View File

@ -35,6 +35,26 @@ defmodule Amethyst.Server.Play do
{[channel], data} = Read.start(data) |> Read.string |> Read.stop
{:serverbound_plugin_message, channel, data}
end
@impl true
def deserialize(0x1A, data) do
{[x, feet_y, z, on_ground], ""} = Read.start(data) |> Read.double |> Read.double |> Read.double |> Read.bool |> Read.stop
{:set_player_position, x, feet_y, z, on_ground}
end
@impl true
def deserialize(0x1B, data) do
{[x, feet_y, z, yaw, pitch, on_ground], ""} = Read.start(data) |> Read.double |> Read.double |> Read.double |> Read.float |> Read.float |> Read.bool |> Read.stop
{:set_position_position_and_rotation, x, feet_y, z, yaw, pitch, on_ground}
end
@impl true
def deserialize(0x1C, data) do
{[yaw, pitch, on_ground], ""} = Read.start(data) |> Read.float |> Read.float |> Read.bool |> Read.stop()
{:set_player_rotation, yaw, pitch, on_ground}
end
@impl true
def deserialize(0x1D, data) do
{[on_ground], ""} = Read.start(data) |> Read.bool |> Read.stop()
{:set_player_on_ground, on_ground}
end
def deserialize(type, _) do
raise RuntimeError, "Got unknown packet type #{type}!"
end
@ -80,8 +100,25 @@ defmodule Amethyst.Server.Play do
Logger.debug("Got plugin message #{channel} with data #{inspect(data)}")
{:ok, state}
end
def handle(tuple, _, state) do
Logger.error("Unhandled but known packet #{elem(tuple, 0)}")
def handle({:set_player_position, x, y, z, _on_ground}, _client, state) do
# We do not accept movement packets until we get a :confirm_teleportation
if Keyword.fetch(state, :awaiting_tp_confirm) != :error do
Logger.warning("Got :set_player_position packet while waiting for :confirm_teleportation!")
{:ok, state}
else
game = Keyword.fetch!(state, :game)
{nx, ny, nz} = Amethyst.API.Game.player_position(game, {x, y, z})
# If pos is not very close to the position the client wants, synchronize them
# TODO: Make a general-purpose distance function
dist = :math.sqrt((nx - x)**2 + (ny - y)**2 + (nz - z)**2)
if dist > 0.01 do
# TODO: Implement synchronization
raise "The game wants to resynchronize the player, but I haven't implemented that yet"
end
end
end
def handle(tuple, _, state) do # TODO: These error cases should be somehow moved into some shared area? Maybe even moved out of the modules themselves
Logger.error("Unhandled but known packet #{inspect(tuple)}")
{:unhandled, state}
end