118 lines
3.6 KiB
Elixir
118 lines
3.6 KiB
Elixir
# Amethyst - An experimental Minecraft server written in Elixir.
|
|
# Copyright (C) 2024 KodiCraft
|
|
#
|
|
# This program is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU Affero General Public License as
|
|
# published by the Free Software Foundation, either version 3 of the
|
|
# License, or (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU Affero General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU Affero General Public License
|
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
defmodule Amethyst.NBT.Write do
|
|
@moduledoc """
|
|
This module contains the logic for writing NBT data.
|
|
"""
|
|
|
|
def write(name, {type, value}) do
|
|
<<type_id(type)::size(8), payload(:string, name)::binary, payload(type, value)::binary>>
|
|
end
|
|
|
|
def write_net({type, value}) do
|
|
<<type_id(type)::size(8), payload(type, value)::binary>>
|
|
end
|
|
|
|
defp type_id(:end), do: 0
|
|
defp type_id(:byte), do: 1
|
|
defp type_id(:short), do: 2
|
|
defp type_id(:int), do: 3
|
|
defp type_id(:long), do: 4
|
|
defp type_id(:float), do: 5
|
|
defp type_id(:double), do: 6
|
|
defp type_id(:byte_array), do: 7
|
|
defp type_id(:string), do: 8
|
|
defp type_id(:list), do: 9
|
|
defp type_id(:compound), do: 10
|
|
defp type_id(:int_array), do: 11
|
|
defp type_id(:long_array), do: 12
|
|
|
|
defp payload(:byte, value), do: <<value::size(8)-big>>
|
|
defp payload(:short, value), do: <<value::size(16)-big>>
|
|
defp payload(:int, value), do: <<value::size(32)-big>>
|
|
defp payload(:long, value), do: <<value::size(64)-big>>
|
|
defp payload(:float, value), do: <<value::size(32)-float>>
|
|
defp payload(:double, value), do: <<value::size(64)-float>>
|
|
defp payload(:byte_array, values), do: <<length(values)::size(32)-big>> <> Enum.map_join(values, "", &payload(:byte, &1))
|
|
defp payload(:string, value), do: <<byte_size(value)::size(16)-big-unsigned>> <> value
|
|
defp payload(:list, {type, values}), do: <<type_id(type)::size(8)>> <> <<length(values)::size(32)-big>> <> Enum.map_join(values, "", &payload(type, &1))
|
|
defp payload(:compound, values), do: Enum.map_join(values, "", fn {name, {type, value}} -> write(name, {type, value}) end) <> <<0::size(8)>>
|
|
defp payload(:int_array, values), do: <<length(values)::size(32)-big>> <> Enum.map_join(values, "", &payload(:int, &1))
|
|
defp payload(:long_array, values), do: <<length(values)::size(32)-big>> <> Enum.map_join(values, "", &payload(:long, &1))
|
|
|
|
defmacro byte(value) do
|
|
quote do
|
|
{:byte, unquote(value)}
|
|
end
|
|
end
|
|
defmacro short(value) do
|
|
quote do
|
|
{:short, unquote(value)}
|
|
end
|
|
end
|
|
defmacro int(value) do
|
|
quote do
|
|
{:int, unquote(value)}
|
|
end
|
|
end
|
|
defmacro long(value) do
|
|
quote do
|
|
{:long, unquote(value)}
|
|
end
|
|
end
|
|
defmacro float(value) do
|
|
quote do
|
|
{:float, unquote(value)}
|
|
end
|
|
end
|
|
defmacro double(value) do
|
|
quote do
|
|
{:double, unquote(value)}
|
|
end
|
|
end
|
|
defmacro byte_array(values) do
|
|
quote do
|
|
{:byte_array, unquote(values)}
|
|
end
|
|
end
|
|
defmacro string(value) do
|
|
quote do
|
|
{:string, unquote(value)}
|
|
end
|
|
end
|
|
defmacro list(type, values) do
|
|
quote do
|
|
{:list, {unquote(type), unquote(values)}}
|
|
end
|
|
end
|
|
defmacro compound(values) do
|
|
quote do
|
|
{:compound, unquote(values)}
|
|
end
|
|
end
|
|
defmacro int_array(values) do
|
|
quote do
|
|
{:int_array, unquote(values)}
|
|
end
|
|
end
|
|
defmacro long_array(values) do
|
|
quote do
|
|
{:long_array, unquote(values)}
|
|
end
|
|
end
|
|
end
|