Attempt at implementing versioned block registry
All checks were successful
Build & Test / nix-build (push) Successful in 1m47s
All checks were successful
Build & Test / nix-build (push) Successful in 1m47s
This commit is contained in:
parent
e8f0e1b4c0
commit
4a387ff296
@ -31,18 +31,7 @@ defmodule Amethyst.Application do
|
|||||||
child_spec: DynamicSupervisor.child_spec([]),
|
child_spec: DynamicSupervisor.child_spec([]),
|
||||||
name: Amethyst.GameMetaSupervisor
|
name: Amethyst.GameMetaSupervisor
|
||||||
},
|
},
|
||||||
{PartitionSupervisor,
|
{Registry, keys: :unique, name: Amethyst.BlockStateRegistry},
|
||||||
child_spec: Amethyst.BlockRegistry.child_spec(%{}),
|
|
||||||
name: Amethyst.BlockRegistry},
|
|
||||||
Supervisor.child_spec(
|
|
||||||
{Task, fn ->
|
|
||||||
# TODO: not this
|
|
||||||
Amethyst.DataGenerator.generate_and_populate_data(
|
|
||||||
:latest,
|
|
||||||
"/tmp/server.jar",
|
|
||||||
"/tmp/amethyst-generated")
|
|
||||||
end},
|
|
||||||
id: Amethyst.DataGenerator)
|
|
||||||
]
|
]
|
||||||
|
|
||||||
children = case Application.fetch_env!(:amethyst, :port) do
|
children = case Application.fetch_env!(:amethyst, :port) do
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
# You should have received a copy of the GNU Affero General Public License
|
# 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/>.
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
defmodule Amethyst.BlockRegistry do
|
defmodule Amethyst.BlockStates do
|
||||||
use GenServer
|
use GenServer
|
||||||
@moduledoc """
|
@moduledoc """
|
||||||
GenServer which can be populated with block states and their corresponding IDs.
|
GenServer which can be populated with block states and their corresponding IDs.
|
||||||
@ -22,8 +22,8 @@ defmodule Amethyst.BlockRegistry do
|
|||||||
"""
|
"""
|
||||||
require Logger
|
require Logger
|
||||||
|
|
||||||
def start_link(map) do
|
def start_link(map, name) do
|
||||||
GenServer.start_link(__MODULE__, map)
|
GenServer.start_link(__MODULE__, map, name: name)
|
||||||
end
|
end
|
||||||
|
|
||||||
def init(map) do
|
def init(map) do
|
||||||
@ -52,22 +52,48 @@ defmodule Amethyst.BlockRegistry do
|
|||||||
Adds a block state to the registry.
|
Adds a block state to the registry.
|
||||||
|
|
||||||
## Parameters
|
## Parameters
|
||||||
|
- `version` - The Minecraft version
|
||||||
- `id` - The block identifier
|
- `id` - The block identifier
|
||||||
- `bs` - The block state
|
- `bs` - The block state
|
||||||
- `bsi` - The block state ID
|
- `bsi` - The block state ID
|
||||||
"""
|
"""
|
||||||
@spec add(String.t(), map(), integer()) :: :ok
|
@spec add(String.t(), String.t(), map(), integer()) :: :ok
|
||||||
def add(id, bs, bsi) do
|
def add(version, id, bs, bsi) do
|
||||||
GenServer.cast({:via, PartitionSupervisor, {__MODULE__, id}}, {:add, id, bs, bsi})
|
ps = {:via, Registry, {Amethyst.BlockStateRegistry, version}}
|
||||||
|
GenServer.cast({:via, PartitionSupervisor, {ps, id}}, {:add, id, bs, bsi})
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Gets the block state ID for a given block identifier and block state.
|
Gets the block state ID for a given block identifier and block state.
|
||||||
|
If no data is known for this version, errors. Prefer using `try_get/3`
|
||||||
|
if you can wait for the data to be loaded.
|
||||||
|
- `version` - The Minecraft version
|
||||||
- `id` - The block identifier
|
- `id` - The block identifier
|
||||||
- `bs` - The block state, nil if the block has no states
|
- `bs` - The block state, nil if the block has no states
|
||||||
"""
|
"""
|
||||||
@spec get(String.t(), map() | nil) :: integer() | nil
|
@spec get(String.t(), String.t(), map() | nil) :: integer() | nil
|
||||||
def get(id, bs \\ %{}) do
|
def get(version, id, bs \\ %{}) do
|
||||||
GenServer.call({:via, PartitionSupervisor, {__MODULE__, id}}, {:get, id, bs})
|
ps = {:via, Registry, {Amethyst.BlockStateRegistry, version}}
|
||||||
|
GenServer.call({:via, PartitionSupervisor, {ps, id}}, {:get, id, bs})
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Tries to get the block state ID for a given block identifier and block state.
|
||||||
|
If no data is known for this version, it will block until the data is loaded.
|
||||||
|
- `version` - The Minecraft version
|
||||||
|
- `id` - The block identifier
|
||||||
|
- `bs` - The block state, nil if the block has no states
|
||||||
|
"""
|
||||||
|
@spec try_get(String.t(), String.t(), map() | nil) :: integer() | nil
|
||||||
|
def try_get(version, id, bs \\ %{}) do
|
||||||
|
case Registry.lookup(Amethyst.BlockStateRegistry, version) do
|
||||||
|
[{_pid, _}] ->
|
||||||
|
ps = {:via, Registry, {Amethyst.BlockStateRegistry, version}}
|
||||||
|
GenServer.call({:via, PartitionSupervisor, {ps, id}}, {:get, id, bs})
|
||||||
|
[] ->
|
||||||
|
Logger.warning("BlockStateRegistry doesn't exist for version #{version}, generating it now!")
|
||||||
|
Amethyst.DataGenerator.generate_and_populate_data(version, "/tmp/minecraft_server_#{version}.jar", "/tmp/minecraft_data_#{version}")
|
||||||
|
try_get(version, id, bs)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
@ -75,8 +75,8 @@ defmodule Amethyst.DataGenerator do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec populate_blockregistry(String.t()) :: :ok | {:error, term}
|
@spec populate_blockstates(String.t(), String.t()) :: :ok | {:error, term}
|
||||||
def populate_blockregistry(data_path) do
|
def populate_blockstates(data_path, version) do
|
||||||
block_file = Path.join([data_path, "reports", "blocks.json"])
|
block_file = Path.join([data_path, "reports", "blocks.json"])
|
||||||
case File.read(block_file) do
|
case File.read(block_file) do
|
||||||
{:ok, data} ->
|
{:ok, data} ->
|
||||||
@ -84,8 +84,8 @@ defmodule Amethyst.DataGenerator do
|
|||||||
{:ok, blocks} ->
|
{:ok, blocks} ->
|
||||||
Enum.each(blocks, fn {id, %{"states" => states}} ->
|
Enum.each(blocks, fn {id, %{"states" => states}} ->
|
||||||
Enum.each(states, fn
|
Enum.each(states, fn
|
||||||
%{"id" => bsi, "properties" => props} -> Amethyst.BlockRegistry.add(id, props, bsi)
|
%{"id" => bsi, "properties" => props} -> Amethyst.BlockStates.add(version, id, props, bsi)
|
||||||
%{"id" => bsi, "default" => true} -> Amethyst.BlockRegistry.add(id, %{}, bsi)
|
%{"id" => bsi, "default" => true} -> Amethyst.BlockStates.add(version, id, %{}, bsi)
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
:ok
|
:ok
|
||||||
@ -95,15 +95,25 @@ defmodule Amethyst.DataGenerator do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp create_blockregistry(version) do
|
||||||
|
# TODO: unsupervised
|
||||||
|
Amethyst.BlockStates.start_link(%{}, {:via, Registry, {Amethyst.BlockStateRegistry, version}})
|
||||||
|
end
|
||||||
|
|
||||||
@spec generate_and_populate_data(String.t() | :latest, String.t(), String.t(), String.t() | nil) :: :ok | {:error, term}
|
@spec generate_and_populate_data(String.t() | :latest, String.t(), String.t(), String.t() | nil) :: :ok | {:error, term}
|
||||||
def generate_and_populate_data(version, jar_path, data_dir, java_bin \\ "java") do
|
def generate_and_populate_data(version, jar_path, data_dir, java_bin \\ "java") do
|
||||||
start_time = Time.utc_now()
|
start_time = Time.utc_now()
|
||||||
|
{:ok, version} = case version do
|
||||||
|
:latest -> get_latest_version()
|
||||||
|
version -> {:ok, version}
|
||||||
|
end
|
||||||
case get_server_jar(version, jar_path) do
|
case get_server_jar(version, jar_path) do
|
||||||
{:ok, jar_path} ->
|
{:ok, jar_path} ->
|
||||||
case generate_data_files(jar_path, data_dir, java_bin) do
|
case generate_data_files(jar_path, data_dir, java_bin) do
|
||||||
{:ok, data_path} ->
|
{:ok, data_path} ->
|
||||||
Logger.info("Finished generating data in #{Time.diff(Time.utc_now(), start_time, :millisecond)}ms")
|
Logger.info("Finished generating data in #{Time.diff(Time.utc_now(), start_time, :millisecond)}ms")
|
||||||
populate_blockregistry(data_path)
|
create_blockregistry(version)
|
||||||
|
populate_blockstates(version, data_path)
|
||||||
Logger.info("Finished generating and populating data in #{Time.diff(Time.utc_now(), start_time, :millisecond)}ms")
|
Logger.info("Finished generating and populating data in #{Time.diff(Time.utc_now(), start_time, :millisecond)}ms")
|
||||||
{:error, code} -> {:error, code}
|
{:error, code} -> {:error, code}
|
||||||
end
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user