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
|
||||
|
||||
@moduledoc """
|
||||
This module contains functions for writing certain Minecraft data types which are more complex
|
||||
than simple binary data.
|
||||
This module contains functions for writing Minecraft 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)
|
||||
end
|
||||
|
||||
def bool(value) do
|
||||
def bool(value) when is_boolean(value) do
|
||||
case value do
|
||||
true -> <<0x01::8>>
|
||||
false -> <<0x00::8>>
|
||||
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
|
||||
<<value::32-unsigned>> = <<value::32-signed>> # This is a trick to allow the arithmetic shift to act as a logical shift
|
||||
varnum("", value)
|
||||
@ -73,13 +107,12 @@ defmodule Amethyst.Minecraft.Read do
|
||||
import Bitwise
|
||||
|
||||
@moduledoc """
|
||||
This module contains functions for reading Minecraft data. Unlike Amethyst.Minecraft.Write, this
|
||||
includes all supported data types in order to make the interface more consistent.
|
||||
This module contains functions for reading Minecraft data.
|
||||
|
||||
These functions allow you to chain them into eachother, at the end they will produce a list of all the
|
||||
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.
|
||||
|
||||
iex> alias Amethyst.Minecraft.Read
|
||||
@ -87,9 +120,15 @@ defmodule Amethyst.Minecraft.Read do
|
||||
{[true, 999, 64], ""}
|
||||
"""
|
||||
|
||||
@doc """
|
||||
This function structures an input binary to be used by the functions in `Amethyst.Minecraft.Read`.
|
||||
"""
|
||||
def start(binary) do
|
||||
{[], binary, :reversed}
|
||||
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
|
||||
{Enum.reverse(acc), rest}
|
||||
end
|
||||
@ -139,6 +178,9 @@ defmodule Amethyst.Minecraft.Read do
|
||||
{[data | acc], rest, :reversed}
|
||||
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({acc, <<1::1, value::7, rest::binary>>, :reversed}, read, nacc) when read < 5 do
|
||||
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!"
|
||||
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({acc, <<1::1, value::7, rest::binary>>, :reversed}, read, nacc) when read < 10 do
|
||||
varlong({acc, rest, :reversed}, read + 1, nacc + (value <<< (7 * read)))
|
||||
@ -165,10 +210,10 @@ defmodule Amethyst.Minecraft.Read do
|
||||
{[value | acc], rest, :reversed}
|
||||
end
|
||||
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
|
||||
def varlong({_, ""}, _, _) do
|
||||
raise RuntimeError, "Got an incomplete varint!"
|
||||
raise RuntimeError, "Got an incomplete varlong!"
|
||||
end
|
||||
|
||||
def string({acc, data, :reversed}) do
|
||||
|
@ -44,17 +44,17 @@ defmodule Amethyst.Server.Play do
|
||||
reduce_debug, enable_respawn_screen, limited_crafting,
|
||||
dim_type, dim_name, hashed_seed, gamemode, prev_gm,
|
||||
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) <>
|
||||
<<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(max_players) <> Write.varint(view_distance) <> Write.varint(simulation_distance) <> if(reduce_debug, do: <<1::big-8>>, else: <<0::big-8>>) <>
|
||||
if(enable_respawn_screen, do: <<1::big-8>>, else: <<0::big-8>>)
|
||||
if(limited_crafting, do: <<1::big-8>>, else: <<0::big-8>>) <> Write.varint(dim_type) <> Write.string(dim_name) <>
|
||||
hashed_seed <> <<gamemode_id(gamemode)::unsigned-big-8>> <> <<gamemode_id(prev_gm)::signed-big-8>> <>
|
||||
if(is_debug, do: <<1::big-8>>, else: <<0::big-8>>) <> if(is_flat, do: <<1::big-8>>, else: <<0::big-8>>) <>
|
||||
Write.varint(max_players) <> Write.varint(view_distance) <> Write.varint(simulation_distance) <> Write.bool(reduce_debug) <>
|
||||
Write.bool(enable_respawn_screen) <>
|
||||
Write.bool(limited_crafting) <> Write.varint(dim_type) <> Write.string(dim_name) <>
|
||||
hashed_seed <> Write.ubyte(gamemode_id(gamemode)) <> Write.byte(gamemode_id(prev_gm)) <>
|
||||
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))) <>
|
||||
Write.varint(portal_cooldown) <> if(enforce_chat, do: <<1::big-8>>, else: <<0::big-8>>)
|
||||
Write.varint(portal_cooldown) <> Write.bool(enforce_chat)
|
||||
end
|
||||
def serialize(packet) do
|
||||
raise ArgumentError, "Tried serializing unknown packet #{inspect(packet)}"
|
||||
|
@ -51,7 +51,7 @@ defmodule Amethyst.Server.Status do
|
||||
Write.varint(0x00) <> Write.string(data)
|
||||
end
|
||||
def serialize({:ping_response, payload}) do
|
||||
Write.varint(0x01) <> <<payload::64-big-signed>>
|
||||
Write.varint(0x01) <> Write.long(payload)
|
||||
end
|
||||
def serialize(packet) do
|
||||
raise ArgumentError, "Tried serializing unknown packet #{inspect(packet)}"
|
||||
|
Loading…
Reference in New Issue
Block a user