From 29014aa45f2393d9188f8839e836d81a79a39bc3 Mon Sep 17 00:00:00 2001 From: Kodi Craft Date: Tue, 8 Oct 2024 15:34:57 +0200 Subject: [PATCH] Implement receiving chat messages --- apps/amethyst/lib/game.ex | 11 +++++++++++ apps/amethyst/lib/states/macros.ex | 13 +++++++++++++ apps/amethyst/lib/states/play.ex | 8 +++++++- apps/example_game/lib/example/game.ex | 7 +++++++ 4 files changed, 38 insertions(+), 1 deletion(-) diff --git a/apps/amethyst/lib/game.ex b/apps/amethyst/lib/game.ex index 08792ef..df683b8 100644 --- a/apps/amethyst/lib/game.ex +++ b/apps/amethyst/lib/game.ex @@ -88,6 +88,17 @@ defmodule Amethyst.Game do mod.accept_teleport(self(), id, refs) end @doc """ + `chat/3` is called when a player sends a chat message. Note that it is not how slash commands should be handled. + + - 'from' is the PID of the player's connection process (see `login/3`). + - 'message' is the chat message sent by the player. + - `state_refs` are your references (see `instantiate/1`) + """ + @callback chat(from :: pid(), message :: binary(), state_refs :: map()) :: :ok + def chat(%{:mod => mod, :refs => refs}, message) do + mod.chat(self(), message, refs) + end + @doc """ The terrain of a specific chunk column. This is automatically used to load chunks for a player. For now, this data must be formatted as a 3D list, indexed as [y][z][x]. diff --git a/apps/amethyst/lib/states/macros.ex b/apps/amethyst/lib/states/macros.ex index c96abb9..fdeb172 100644 --- a/apps/amethyst/lib/states/macros.ex +++ b/apps/amethyst/lib/states/macros.ex @@ -14,6 +14,8 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . +# TODO!!!: REDO THIS WHOLE THING AGAIN IT'S A MESS + defmodule Amethyst.ConnectionState.Macros do @moduledoc """ Useful macros for defining packets. @@ -56,6 +58,13 @@ defmodule Amethyst.ConnectionState.Macros do else {[nil | acc], rest, :reversed} end + {:optional, {:raw, length}} -> + {[exists], rest} = Read.start(rest) |> Read.bool() |> Read.stop() + if exists do + Read.raw({acc, rest, :reversed}, length) + else + {[nil | acc], rest, :reversed} + end {:optional, t} -> {[exists], rest} = Read.start(rest) |> Read.bool() |> Read.stop() if exists do @@ -63,6 +72,10 @@ defmodule Amethyst.ConnectionState.Macros do else {[nil | acc], rest, :reversed} end + {:fixed_bitset, length} -> + Read.fixed_bitset({acc, rest, :reversed}, length) + {:raw, length} -> + Read.raw({acc, rest, :reversed}, length) {:array, signature} -> {[count], rest} = Read.start(rest) |> Read.varint() |> Read.stop() if count == 0 do diff --git a/apps/amethyst/lib/states/play.ex b/apps/amethyst/lib/states/play.ex index 4d576eb..297cc65 100644 --- a/apps/amethyst/lib/states/play.ex +++ b/apps/amethyst/lib/states/play.ex @@ -161,7 +161,7 @@ defmodule Amethyst.ConnectionState.Play do message: :string, timestamp: :long, salt: :long, - signature: {:optional, :byte_array}, + signature: {:optional, {:raw, 256}}, message_count: :varint, acknowledged: {:fixed_bitset, 20} ] @@ -241,6 +241,12 @@ defmodule Amethyst.ConnectionState.Play do end end + def handle(%{packet_type: :chat_message, message: msg, timestamp: _, salt: _, signature: _, message_count: _, acknowledged: _}, 767, state) do + # We will never support message signing + state |> Map.get(:game) |> Amethyst.Game.chat(msg) + :ok + end + def handle(%{packet_type: :keep_alive, id: id}, 767, state) do ka = state |> Map.get(:keepalive) send(ka, {:respond, id}) diff --git a/apps/example_game/lib/example/game.ex b/apps/example_game/lib/example/game.ex index e727907..b71f404 100644 --- a/apps/example_game/lib/example/game.ex +++ b/apps/example_game/lib/example/game.ex @@ -39,11 +39,18 @@ defmodule Example.Game do :ok end + @impl true + def chat(from, message, _state_refs) do + Logger.info("Player at #{inspect(from)} said: #{inspect(message)}") + :ok + end + @impl true def joinable?(_refs) do true end + @impl true def chunk(_from, {cx, cz}, _state_refs) do # Logger.info("Player at #{inspect(from)} wants to know chunk #{cx}, #{cz}")