Implement part of chunk sending
All checks were successful
Build & Test / nix-build (pull_request) Successful in 2m31s
Build & Test / nix-build (push) Successful in 2m37s

This commit is contained in:
Kodi Craft 2024-10-01 10:51:08 +02:00
parent c880ea95f3
commit 453daa817b
Signed by: kodi
GPG Key ID: 69D9EED60B242822
2 changed files with 53 additions and 2 deletions

View File

@ -60,6 +60,39 @@ defmodule Amethyst.ConnectionHandler do
{:set_version, newversion} -> {:set_version, newversion} ->
Logger.debug("Switching to version #{newversion} from #{version}") Logger.debug("Switching to version #{newversion} from #{version}")
loop(socket, connstate, newversion, state) 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))
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
send(self(), {:send_packet, %{
packet_type: :set_center_chunk,
chunk_x: elem(cp, 0),
chunk_z: elem(cp, 1)
}})
# Figure out which new chunks are visible
prev_chunks =
if prev_cp == nil do
MapSet.new([])
else
MapSet.new(visible_chunks_from(elem(prev_cp, 0), elem(prev_cp, 1), Map.get(state, :view_distance, 16)))
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)
# Process these chunks, we can process all chunks in parallel
Task.Supervisor.async_stream(state |> Map.get(:game) |> Map.get(:refs) |> Map.get(:task_supervisor),
new_chunks,
fn chunk -> process_chunk(chunk, state) end,
[ordered: false]
) |> Stream.run()
end
loop(socket, connstate, version, state)
{:send_packet, packet} -> {:send_packet, packet} ->
Logger.debug("Sending packet #{inspect(packet)}") Logger.debug("Sending packet #{inspect(packet)}")
send_packet(socket, connstate, packet, version) send_packet(socket, connstate, packet, version)
@ -73,6 +106,23 @@ defmodule Amethyst.ConnectionHandler do
end end
end end
defp chunk_pos(x, z) do
{div(floor(x), 16), div(floor(z), 16)}
end
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 ->
{ix, iz}
end)
end)
end
defp process_chunk(_chunk, _state) do
# TODO: Actually ask the game for the desired chunk then send the packets.
end
defp handle_packet(id, data, connstate, version, state) do defp handle_packet(id, data, connstate, version, state) do
try do try do
packet = connstate.deserialize(id, version, data) packet = connstate.deserialize(id, version, data)

View File

@ -305,9 +305,10 @@ defmodule Amethyst.ConnectionState.Configuration do
}}) }})
send(self(), {:send_packet, Amethyst.ConnectionState.Play.ge_start_waiting_for_level_chunks(767)}) send(self(), {:send_packet, Amethyst.ConnectionState.Play.ge_start_waiting_for_level_chunks(767)})
send(self(), {:send_packet, %{packet_type: :set_center_chunk, send(self(), {:send_packet, %{packet_type: :set_center_chunk,
chunk_x: div(x, 16), chunk_x: div(floor(x), 16),
chunk_y: div(z, 16) chunk_z: div(floor(z), 16)
}}) }})
send(self(), {:set_position, {x, y, z}})
state state
end end
end end