Flattened writing interface
All checks were successful
Build & Test / nix-build (push) Successful in 1m12s
All checks were successful
Build & Test / nix-build (push) Successful in 1m12s
This commit is contained in:
parent
8e57427c99
commit
9f9526f5de
63
lib/data.ex
63
lib/data.ex
@ -18,21 +18,55 @@ defmodule Amethyst.Minecraft.Write do
|
|||||||
import Bitwise
|
import Bitwise
|
||||||
|
|
||||||
@moduledoc """
|
@moduledoc """
|
||||||
This module contains functions for writing certain Minecraft data types which are more complex
|
This module contains functions for writing Minecraft data.
|
||||||
than simple binary data.
|
|
||||||
|
Each function in this module takes in an input of the proper type and returns a binary
|
||||||
|
of the encoded data.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def uuid(uuid) do
|
def uuid(uuid) when is_binary(uuid) do
|
||||||
UUID.string_to_binary!(uuid)
|
UUID.string_to_binary!(uuid)
|
||||||
end
|
end
|
||||||
|
|
||||||
def bool(value) do
|
def bool(value) when is_boolean(value) do
|
||||||
case value do
|
case value do
|
||||||
true -> <<0x01::8>>
|
true -> <<0x01::8>>
|
||||||
false -> <<0x00::8>>
|
false -> <<0x00::8>>
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def byte(value) when value in -128..127 do
|
||||||
|
<<value::8-signed-big>>
|
||||||
|
end
|
||||||
|
|
||||||
|
def ubyte(value) when value in 0..255 do
|
||||||
|
<<value::8-unsigned-big>>
|
||||||
|
end
|
||||||
|
|
||||||
|
def short(value) when value in -32_768..32_767 do
|
||||||
|
<<value::16-signed-big>>
|
||||||
|
end
|
||||||
|
|
||||||
|
def ushort(value) when value in 0..65_535 do
|
||||||
|
<<value::16-unsigned-big>>
|
||||||
|
end
|
||||||
|
|
||||||
|
def int(value) when value in -2_147_483_648..2_147_483_647 do
|
||||||
|
<<value::32-signed-big>>
|
||||||
|
end
|
||||||
|
|
||||||
|
def long(value) when value in -9_223_372_036_854_775_808..9_223_372_036_854_775_807 do
|
||||||
|
<<value::64-signed-big>>
|
||||||
|
end
|
||||||
|
|
||||||
|
def float(value) when is_number(value) do
|
||||||
|
<<value::32-float>>
|
||||||
|
end
|
||||||
|
|
||||||
|
def double(value) when is_number(value) do
|
||||||
|
<<value::64-float>>
|
||||||
|
end
|
||||||
|
|
||||||
def varint(value) when value in -2_147_483_648..2_147_483_647 do
|
def varint(value) when value in -2_147_483_648..2_147_483_647 do
|
||||||
<<value::32-unsigned>> = <<value::32-signed>> # This is a trick to allow the arithmetic shift to act as a logical shift
|
<<value::32-unsigned>> = <<value::32-signed>> # This is a trick to allow the arithmetic shift to act as a logical shift
|
||||||
varnum("", value)
|
varnum("", value)
|
||||||
@ -73,13 +107,12 @@ defmodule Amethyst.Minecraft.Read do
|
|||||||
import Bitwise
|
import Bitwise
|
||||||
|
|
||||||
@moduledoc """
|
@moduledoc """
|
||||||
This module contains functions for reading Minecraft data. Unlike Amethyst.Minecraft.Write, this
|
This module contains functions for reading Minecraft data.
|
||||||
includes all supported data types in order to make the interface more consistent.
|
|
||||||
|
|
||||||
These functions allow you to chain them into eachother, at the end they will produce a list of all the
|
These functions allow you to chain them into eachother, at the end they will produce a list of all the
|
||||||
values they have read.
|
values they have read.
|
||||||
|
|
||||||
You may use the helper function Amethyst.Minecraft.Read.start/1 to start the chain with a binary buffer.
|
You may use the helper function `Amethyst.Minecraft.Read.start/1` to start the chain with a binary buffer.
|
||||||
The return value of the chain is a tuple containing the list of values and the remaining binary buffer.
|
The return value of the chain is a tuple containing the list of values and the remaining binary buffer.
|
||||||
|
|
||||||
iex> alias Amethyst.Minecraft.Read
|
iex> alias Amethyst.Minecraft.Read
|
||||||
@ -87,9 +120,15 @@ defmodule Amethyst.Minecraft.Read do
|
|||||||
{[true, 999, 64], ""}
|
{[true, 999, 64], ""}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
This function structures an input binary to be used by the functions in `Amethyst.Minecraft.Read`.
|
||||||
|
"""
|
||||||
def start(binary) do
|
def start(binary) do
|
||||||
{[], binary, :reversed}
|
{[], binary, :reversed}
|
||||||
end
|
end
|
||||||
|
@doc """
|
||||||
|
This function structures the result of the functions in `Amethyst.Minecraft.Read` to be used in the same order they were read.
|
||||||
|
"""
|
||||||
def stop({acc, rest, :reversed}) do
|
def stop({acc, rest, :reversed}) do
|
||||||
{Enum.reverse(acc), rest}
|
{Enum.reverse(acc), rest}
|
||||||
end
|
end
|
||||||
@ -139,6 +178,9 @@ defmodule Amethyst.Minecraft.Read do
|
|||||||
{[data | acc], rest, :reversed}
|
{[data | acc], rest, :reversed}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Reads a varint. `read` tracks the number of bytes read and `nacc` tracks the number being read.
|
||||||
|
"""
|
||||||
def varint(tuple, read \\ 0, nacc \\ 0)
|
def varint(tuple, read \\ 0, nacc \\ 0)
|
||||||
def varint({acc, <<1::1, value::7, rest::binary>>, :reversed}, read, nacc) when read < 5 do
|
def varint({acc, <<1::1, value::7, rest::binary>>, :reversed}, read, nacc) when read < 5 do
|
||||||
varint({acc, rest, :reversed}, read + 1, nacc + (value <<< (7 * read)))
|
varint({acc, rest, :reversed}, read + 1, nacc + (value <<< (7 * read)))
|
||||||
@ -155,6 +197,9 @@ defmodule Amethyst.Minecraft.Read do
|
|||||||
raise RuntimeError, "Got an incomplete varint!"
|
raise RuntimeError, "Got an incomplete varint!"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Reads a varlong. `read` tracks the number of bytes read and `nacc` tracks the number being read.
|
||||||
|
"""
|
||||||
def varlong(tuple, read \\ 0, nacc \\ 0)
|
def varlong(tuple, read \\ 0, nacc \\ 0)
|
||||||
def varlong({acc, <<1::1, value::7, rest::binary>>, :reversed}, read, nacc) when read < 10 do
|
def varlong({acc, <<1::1, value::7, rest::binary>>, :reversed}, read, nacc) when read < 10 do
|
||||||
varlong({acc, rest, :reversed}, read + 1, nacc + (value <<< (7 * read)))
|
varlong({acc, rest, :reversed}, read + 1, nacc + (value <<< (7 * read)))
|
||||||
@ -165,10 +210,10 @@ defmodule Amethyst.Minecraft.Read do
|
|||||||
{[value | acc], rest, :reversed}
|
{[value | acc], rest, :reversed}
|
||||||
end
|
end
|
||||||
def varlong(_, read, _) when read >= 10 do
|
def varlong(_, read, _) when read >= 10 do
|
||||||
raise RuntimeError, "Got a varint which is too big!"
|
raise RuntimeError, "Got a varlong which is too big!"
|
||||||
end
|
end
|
||||||
def varlong({_, ""}, _, _) do
|
def varlong({_, ""}, _, _) do
|
||||||
raise RuntimeError, "Got an incomplete varint!"
|
raise RuntimeError, "Got an incomplete varlong!"
|
||||||
end
|
end
|
||||||
|
|
||||||
def string({acc, data, :reversed}) do
|
def string({acc, data, :reversed}) do
|
||||||
|
@ -44,17 +44,17 @@ defmodule Amethyst.Server.Play do
|
|||||||
reduce_debug, enable_respawn_screen, limited_crafting,
|
reduce_debug, enable_respawn_screen, limited_crafting,
|
||||||
dim_type, dim_name, hashed_seed, gamemode, prev_gm,
|
dim_type, dim_name, hashed_seed, gamemode, prev_gm,
|
||||||
is_debug, is_flat, death_loc, portal_cooldown, enforce_chat}) do
|
is_debug, is_flat, death_loc, portal_cooldown, enforce_chat}) do
|
||||||
# TODO: this singlehandedly made me regret not making the write API better, please rework :(
|
# TODO: This is a big unreadable slab of serialization, it needs a proper rework at some point
|
||||||
Write.varint(0x2B) <>
|
Write.varint(0x2B) <>
|
||||||
<<eid::big-signed-32>> <> if(hardcore, do: <<1::big-8>>, else: <<0::big-8>>) <>
|
Write.int(eid) <> Write.bool(hardcore) <>
|
||||||
Write.varint(length(dimensions)) <> Enum.reduce(dimensions, "", fn dim, acc -> acc <> Write.string(dim) end) <>
|
Write.varint(length(dimensions)) <> Enum.reduce(dimensions, "", fn dim, acc -> acc <> Write.string(dim) end) <>
|
||||||
Write.varint(max_players) <> Write.varint(view_distance) <> Write.varint(simulation_distance) <> if(reduce_debug, do: <<1::big-8>>, else: <<0::big-8>>) <>
|
Write.varint(max_players) <> Write.varint(view_distance) <> Write.varint(simulation_distance) <> Write.bool(reduce_debug) <>
|
||||||
if(enable_respawn_screen, do: <<1::big-8>>, else: <<0::big-8>>)
|
Write.bool(enable_respawn_screen) <>
|
||||||
if(limited_crafting, do: <<1::big-8>>, else: <<0::big-8>>) <> Write.varint(dim_type) <> Write.string(dim_name) <>
|
Write.bool(limited_crafting) <> Write.varint(dim_type) <> Write.string(dim_name) <>
|
||||||
hashed_seed <> <<gamemode_id(gamemode)::unsigned-big-8>> <> <<gamemode_id(prev_gm)::signed-big-8>> <>
|
hashed_seed <> Write.ubyte(gamemode_id(gamemode)) <> Write.byte(gamemode_id(prev_gm)) <>
|
||||||
if(is_debug, do: <<1::big-8>>, else: <<0::big-8>>) <> if(is_flat, do: <<1::big-8>>, else: <<0::big-8>>) <>
|
Write.bool(is_debug) <> Write.bool(is_flat) <>
|
||||||
if(death_loc == nil, do: <<0::big-8>>, else: <<1::big-8>> <> Write.string(elem(death_loc, 0)) <> Write.position(elem(death_loc, 1))) <>
|
if(death_loc == nil, do: <<0::big-8>>, else: <<1::big-8>> <> Write.string(elem(death_loc, 0)) <> Write.position(elem(death_loc, 1))) <>
|
||||||
Write.varint(portal_cooldown) <> if(enforce_chat, do: <<1::big-8>>, else: <<0::big-8>>)
|
Write.varint(portal_cooldown) <> Write.bool(enforce_chat)
|
||||||
end
|
end
|
||||||
def serialize(packet) do
|
def serialize(packet) do
|
||||||
raise ArgumentError, "Tried serializing unknown packet #{inspect(packet)}"
|
raise ArgumentError, "Tried serializing unknown packet #{inspect(packet)}"
|
||||||
|
@ -51,7 +51,7 @@ defmodule Amethyst.Server.Status do
|
|||||||
Write.varint(0x00) <> Write.string(data)
|
Write.varint(0x00) <> Write.string(data)
|
||||||
end
|
end
|
||||||
def serialize({:ping_response, payload}) do
|
def serialize({:ping_response, payload}) do
|
||||||
Write.varint(0x01) <> <<payload::64-big-signed>>
|
Write.varint(0x01) <> Write.long(payload)
|
||||||
end
|
end
|
||||||
def serialize(packet) do
|
def serialize(packet) do
|
||||||
raise ArgumentError, "Tried serializing unknown packet #{inspect(packet)}"
|
raise ArgumentError, "Tried serializing unknown packet #{inspect(packet)}"
|
||||||
|
Loading…
Reference in New Issue
Block a user