83 lines
4.0 KiB
Elixir
83 lines
4.0 KiB
Elixir
# Amethyst - An experimental Minecraft server written in Elixir.
|
|
# Copyright (C) 2024 KodiCraft
|
|
#
|
|
# This program is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU Affero General Public License as
|
|
# published by the Free Software Foundation, either version 3 of the
|
|
# License, or (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU Affero General Public License for more details.
|
|
#
|
|
# 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/>.
|
|
|
|
defmodule Amethyst.API.Game do
|
|
@moduledoc """
|
|
This module includes the interface for defining and registering
|
|
a game with Amethyst.
|
|
"""
|
|
|
|
@doc """
|
|
`instantiate/1` is called when a new instance of your game is created. You may start any additional
|
|
processes you want under the `DynamicSupervisor` 'supervisor' and return a map with the PIDs to those
|
|
processes, known as your references. Other callbacks in your game will receive these references and
|
|
may use them to access and update state.
|
|
"""
|
|
@callback instantiate(supervisor :: pid()) :: {:ok, state_refs :: map()} | {:error, reason :: term}
|
|
@doc """
|
|
`login/3` is called when a new player logs into a game instance.
|
|
You may either :accept or :reject the player for whatever reason, avoid
|
|
rejecting the player in your default game as that will disconnect the player.
|
|
|
|
Note that if no new players can join for any reason, your game should return false from `joinable?/1`.
|
|
|
|
The PID received in 'from' will be the one that calls all callbacks
|
|
caused directly by this player, such as their movement or interactions --
|
|
You can expect that PID to never be used by any other player and that this same
|
|
player will not use another PID until they disconnect from the server.
|
|
|
|
- 'from' is the PID of the player's connection process.
|
|
- 'player_cfg' is a keyword list containing the configuration passed by the game client
|
|
- 'state_refs' are your references (see `instantiate/1`)
|
|
"""
|
|
@callback login(from :: pid(), player_cfg :: keyword(), state_refs :: map()) :: :accept | :reject
|
|
def login(%{:mod => mod, :refs => refs}, player_cfg) do
|
|
mod.login(self(), player_cfg, refs)
|
|
end
|
|
@doc """
|
|
`player_position/3` is called when a player moves. This function is called with the absolute coordinates
|
|
that the player client expects. TODO: Teleport Player API.
|
|
|
|
- 'from' is the PID of the player's connection process (see `login/3`).
|
|
- 'x', 'y' and 'z' are the absolute coordinates that the player wants to move to.
|
|
- `state_refs` are your references (see `instantiate/1`)
|
|
"""
|
|
@callback player_position(from :: pid(), {x :: float(), y :: float(), z :: float()}, state_refs :: map()) :: :ok
|
|
def player_position(%{:mod => mod, :refs => refs}, {x, y, z}) do
|
|
mod.player_position(self(), {x, y, z}, refs)
|
|
end
|
|
@doc """
|
|
`accept_teleport/3` is called when a client accepts a teleportation as sent by the Synchronize Player Position
|
|
packet (TODO: Teleport Player API). This lets you know that the client is now where you expect it to be.
|
|
|
|
- 'from' is the PID of the player's connection process (see `login/3`).
|
|
- 'id' is the teleport ID (TODO: Teleport Player API)
|
|
- 'state_refs' are your references (see `instantiate/1`)
|
|
"""
|
|
@callback accept_teleport(from :: pid(), id :: integer(), state_refs :: map()) :: :ok
|
|
def accept_teleport(%{:mod => mod, :refs => refs}, id) do
|
|
mod.accept_teleport(self(), id, refs)
|
|
end
|
|
@doc """
|
|
Whether or not this game instance can be joined by a new player. This should include basic logic such as
|
|
if joining makes sense, for instance if the game is full or if the game has already started.
|
|
"""
|
|
@callback joinable?(state_refs :: map()) :: boolean()
|
|
def joinable?(%{:mod => mod, :refs => refs}) do
|
|
mod.joinable?(refs)
|
|
end
|
|
end
|