diff --git a/apps/amethyst/lib/data.ex b/apps/amethyst/lib/data.ex index 204d2a6..4410e14 100644 --- a/apps/amethyst/lib/data.ex +++ b/apps/amethyst/lib/data.ex @@ -142,7 +142,7 @@ defmodule Amethyst.Minecraft.Write do end def bitset(list) do - unaligned = Enum.reduce(list, <<>>, &(if &1 do <<&2::bitstring, 1::1>> else <<&2::bitstring, 0::1>> end)) + unaligned = Enum.reduce(list, <<>>, &(if &1 do <<1::1, &2::bitstring>> else <<0::1, &2::bitstring>> end)) aligned = if rem(bit_size(unaligned), 64) == 0 do unaligned else @@ -150,6 +150,18 @@ defmodule Amethyst.Minecraft.Write do end varint(div(byte_size(aligned), 8)) <> aligned end + def fixed_bitset(list, length) do + unaligned = Enum.reduce(list, <<>>, &(if &1 do <<1::1, &2::bitstring>> else <<0::1, &2::bitstring>> end)) + if bit_size(unaligned) != length do + raise ArgumentError, "Fixed bitset is not the correct length" + end + aligned = if rem(bit_size(unaligned), 64) == 0 do + unaligned + else + <<0::size(64 - rem(bit_size(unaligned), 64)), unaligned::bitstring>> + end + aligned + end end defmodule Amethyst.Minecraft.Read do @@ -282,4 +294,10 @@ defmodule Amethyst.Minecraft.Read do def raw({acc, data, :reversed}) do {[data | acc], "", :reversed} end + def fixed_bitset({acc, data, :reversed}, length) do + bytes = ceil(length / 8) + <> = data + value = :binary.bin_to_list(value, 0, 1) |> Enum.reverse() |> Enum.take(length) |> Enum.map(& &1 != 0) + {[value | acc], rest, :reversed} + end end diff --git a/apps/amethyst/lib/states/play.ex b/apps/amethyst/lib/states/play.ex index 3c95619..4d576eb 100644 --- a/apps/amethyst/lib/states/play.ex +++ b/apps/amethyst/lib/states/play.ex @@ -157,6 +157,14 @@ defmodule Amethyst.ConnectionState.Play do def ge_start_waiting_for_level_chunks(767), do: %{packet_type: :game_event, event: 13, value: 0} Macros.defpacket_serverbound :confirm_teleportation, 0x00, 767, [teleport_id: :varint] + Macros.defpacket_serverbound :chat_message, 0x06, 767, [ + message: :string, + timestamp: :long, + salt: :long, + signature: {:optional, :byte_array}, + message_count: :varint, + acknowledged: {:fixed_bitset, 20} + ] Macros.defpacket_serverbound :serverbound_plugin_message, 0x12, 767, [channel: :string, data: :raw] Macros.defpacket_serverbound :keep_alive, 0x18, 767, [id: :long] Macros.defpacket_serverbound :set_player_position, 0x1A, 767, [