Fix bugs in sending paletted chunks
This commit is contained in:
parent
288ead3e9b
commit
b40fee3c3c
@ -61,13 +61,12 @@ defmodule Amethyst.ConnectionHandler do
|
||||
Logger.debug("Switching to version #{newversion} from #{version}")
|
||||
loop(socket, connstate, newversion, state)
|
||||
{:set_position, position} ->
|
||||
Logger.debug("Updating client position to #{inspect(position)}")
|
||||
prev_position = Map.get(state, :position)
|
||||
state = Map.put(state, :position, position)
|
||||
# If there was no prev position, we consider that we
|
||||
# definitely moved
|
||||
prev_cp = if prev_position == nil do nil else chunk_pos(elem(prev_position, 0), elem(prev_position, 1)) end
|
||||
cp = chunk_pos(elem(position, 0), elem(position, 1))
|
||||
prev_cp = if prev_position == nil do nil else chunk_pos(elem(prev_position, 0), elem(prev_position, 2)) end
|
||||
cp = chunk_pos(elem(position, 0), elem(position, 2))
|
||||
if prev_cp != cp do
|
||||
Logger.debug("Client entered new chunk #{inspect(cp)}")
|
||||
# We changed chunk borders, update center chunk and begin sending new chunks
|
||||
@ -85,6 +84,7 @@ defmodule Amethyst.ConnectionHandler do
|
||||
end
|
||||
chunks = MapSet.new(visible_chunks_from(elem(cp, 0), elem(cp, 1), Map.get(state, :view_distance, 16)))
|
||||
new_chunks = MapSet.difference(chunks, prev_chunks)
|
||||
Logger.debug("Sending #{MapSet.size(new_chunks)} chunks...")
|
||||
# We can process all chunks in parallel
|
||||
me = self()
|
||||
ts = state |> Map.get(:game) |> Map.get(:refs) |> Map.get(:task_supervisor)
|
||||
@ -110,13 +110,13 @@ defmodule Amethyst.ConnectionHandler do
|
||||
end
|
||||
|
||||
defp chunk_pos(x, z) do
|
||||
{div(floor(x), 16), div(floor(z), 16)}
|
||||
{floor(round(x) / 16.0), floor(round(z) / 16.0)}
|
||||
end
|
||||
|
||||
# x, z here is chunk position
|
||||
defp visible_chunks_from(x, z, view_distance) do
|
||||
{cx, cz} = chunk_pos(x, z)
|
||||
(cx - view_distance - 3 .. cx + view_distance + 3) |> Enum.flat_map(fn ix ->
|
||||
(cz - view_distance - 3 .. cz + view_distance + 3) |> Enum.map(fn iz ->
|
||||
(x - view_distance - 3 .. x + view_distance + 3) |> Enum.flat_map(fn ix ->
|
||||
(z - view_distance - 3 .. z + view_distance + 3) |> Enum.map(fn iz ->
|
||||
{ix, iz}
|
||||
end)
|
||||
end)
|
||||
@ -154,15 +154,18 @@ defmodule Amethyst.ConnectionHandler do
|
||||
bpe = max(min_bpe, 4)
|
||||
palette = MapSet.to_list(unique_blocks) |>
|
||||
Enum.with_index() |>
|
||||
Map.new(fn {i, v} -> {v, i} end)
|
||||
Map.new(fn {i, v} -> {i, v} end)
|
||||
Logger.debug("Using palette #{inspect(palette)}")
|
||||
paletted_blocks = blocks |>
|
||||
Enum.map(&(Map.get(palette, &1)))
|
||||
Logger.debug("Paletted blocks: #{inspect(paletted_blocks)}")
|
||||
paletted_data = long_aligned_bit_string_reduce(paletted_blocks, bpe)
|
||||
Logger.debug("Paletted data: #{inspect(paletted_data)}")
|
||||
|
||||
Write.ubyte(bpe) <>
|
||||
Write.varint(map_size(palette)) <>
|
||||
Enum.reduce(0..(map_size(palette)-1), "", fn i, acc ->
|
||||
acc <> Write.varint(Map.get(palette, i))
|
||||
Enum.reduce(palette, "", fn {_k, v}, acc ->
|
||||
acc <> Write.varint(v)
|
||||
end) <>
|
||||
Write.varint(floor(bit_size(paletted_data) / 64)) <>
|
||||
paletted_data
|
||||
@ -197,9 +200,9 @@ defmodule Amethyst.ConnectionHandler do
|
||||
|
||||
defp long_aligned_bit_string_reduce(values, bpe) do
|
||||
values |> Enum.reduce(<<>>, fn value, acc ->
|
||||
next = <<acc::bitstring, value::size(bpe)-big>>
|
||||
next = <<acc::bitstring, value::big-size(bpe)>>
|
||||
# man i hope they dont suddenly change the size of a long
|
||||
if rem(bit_size(next), 64) + bpe < 64 do
|
||||
if rem(bit_size(next), 64) + bpe > 64 do
|
||||
# gotta pad it
|
||||
<<next::bitstring, 0::big-size(64 - rem(bit_size(next), 64))>>
|
||||
else
|
||||
|
@ -208,7 +208,7 @@ defmodule Amethyst.ConnectionState.Play do
|
||||
def handle(%{packet_type: :set_player_on_ground, on_ground: _}, 767, _state) do
|
||||
:ok # Again, don't trust the client for something we can compute
|
||||
end
|
||||
def handle(%{packet_type: :player_command, eid: _eid, action_id: aid, jump_boost: _horse_jump}, 767, state) do
|
||||
def handle(%{packet_type: :player_command, eid: _eid, action_id: aid, jump_boost: _horse_jump}, 767, _state) do
|
||||
# TODO: Actually handle these events
|
||||
case aid do
|
||||
0 -> # Start sneaking
|
||||
@ -243,7 +243,6 @@ defmodule Amethyst.ConnectionState.Play do
|
||||
def keepalive_loop(player) do
|
||||
Process.link(player) # Is it fine to do this on loop?
|
||||
<<id::32>> = :rand.bytes(4)
|
||||
Logger.debug("Sending keepalive...")
|
||||
send(player, {:send_packet, %{packet_type: :keep_alive, id: id}})
|
||||
receive do
|
||||
{:respond, ^id} ->
|
||||
|
@ -12,19 +12,20 @@ defmodule Example.Game do
|
||||
def login(from, cfg, refs) do
|
||||
Logger.info("Player logged in from #{inspect(from)}: #{inspect(cfg)}")
|
||||
Logger.info("The refs for this game are #{inspect(refs)}")
|
||||
{:accept, {0.0, 10.0, 0.0}, {0.0, 0.0}}
|
||||
{:accept, {0.0, 270.0, 0.0}, {0.0, 0.0}}
|
||||
end
|
||||
|
||||
@impl true
|
||||
@spec player_position(any(), {any(), any(), any()}, any()) :: :ok
|
||||
def player_position(from, {x, y, z}, _refs) do
|
||||
Logger.info("Player at #{inspect(from)} moved to #{x}, #{y}, #{z}")
|
||||
# Logger.info("Player at #{inspect(from)} moved to #{x}, #{y}, #{z}")
|
||||
send(from, {:set_position, {x, y, z}})
|
||||
:ok
|
||||
end
|
||||
|
||||
@impl true
|
||||
def player_rotation(from, {yaw, pitch}, _refs) do
|
||||
Logger.info("Player at #{inspect(from)} rotated to #{yaw}, #{pitch}")
|
||||
def player_rotation(_from, {_yaw, _pitch}, _refs) do
|
||||
# Logger.info("Player at #{inspect(from)} rotated to #{yaw}, #{pitch}")
|
||||
:ok
|
||||
end
|
||||
|
||||
@ -40,18 +41,18 @@ defmodule Example.Game do
|
||||
end
|
||||
|
||||
@impl true
|
||||
def chunk(_from, {_x, _z}, _state_refs) do
|
||||
# Logger.info("Player at #{inspect(from)} wants to know chunk #{x}, #{z}")
|
||||
def chunk(_from, {_cx, _cz}, _state_refs) do
|
||||
# Logger.info("Player at #{inspect(from)} wants to know chunk #{cx}, #{cz}")
|
||||
(0..255) |> Enum.map(fn y ->
|
||||
if y < 5 do
|
||||
(0..15) |> Enum.map(fn _z ->
|
||||
(0..15) |> Enum.map(fn _x -> 1 end)
|
||||
end)
|
||||
(0..15) |> Enum.map(fn z ->
|
||||
(0..15) |> Enum.map(fn x ->
|
||||
if y <= x + z do
|
||||
3
|
||||
else
|
||||
(0..15) |> Enum.map(fn _z ->
|
||||
(0..15) |> Enum.map(fn _x -> 1 end)
|
||||
end)
|
||||
0
|
||||
end
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user