2020-05-09 12:48:02 +02:00

14 KiB

Arena_lib docs

You in a hurry? Skip the theory going to point #2

1. Arenas

It all starts with a table called arena_lib.mods = {}. This table allows arena_lib to be subdivided per mod and it has different parameters, one being arena_lib.mods[yourmod].arenas. Here is where every new arena created gets put.
An arena is a table having as a key an ID and as a value its parameters. They are:

  • name: (string) the name of the arena, declared when creating it
  • sign: (pos) the position of the sign associated with the arena.
  • players: (table) where to store players
  • max_players: (string) default is 4
  • min_players: (string) default is 2. When this value is reached, a queue starts
  • in_queue: (bool) about phases, look at "Arena phases" down below
  • in_loading: (bool)
  • in_game: (bool)
  • in_celebration: (bool)
  • enabled: (bool) by default an arena is disabled, to avoid any unwanted damage

Being arenas stored by ID, they can be easily retrieved by arena_libs.mods[yourmod].arenas[THEARENAID].

There are two ways to know an arena ID: the first is in-game via the two debug utilities:

  • arena_lib.print_arenas(sender, mod): coincise
  • arena_lib.print_arena_info(sender, mod, arena_name): extended with much more information

The second is via code by the function arena_libs.get_arenaID_by_player(p_name).

1.1 Creating and removing arenas

There are two functions for it and they all need to be connected to some command in your mod. The functions are

  • arena_lib.create_arena(sender, mod, arena_name, <min_players>, <max_players>): it doesn't accept duplicates. Sender is a string, fields between < > are optional
  • arena_lib.remove_arena(mod, arena_name): if a game is taking place in it, it won't go through

1.1.1 Storing arenas

Arenas and their settings are stored inside the mod storage. What is not stored are players, their stats and such.
Better said, these kind of parameters are emptied every time the server starts. And not when it ends, because handling situations like crashes is simply not possible.

1.2 Setting up an arena

Two things are needed to have an arena up to go: spawners and signs. There are two functions for that:

  • arena_lib.set_spawner(sender, mod, arena_name, spawner_ID)
  • arena_lib.set_sign(sender, mod, arena_name)

1.2.1 Spawners

arena_lib.set_spawner(sender, arena_name, spawner_ID) creates a spawner where the sender is standing, so be sure to stand where you want the spawn point to be.
spawner_ID is optional and it does make a difference: with it, it overrides an existing spawner (if exists), without it, it creates a new one. Spawners can't exceed the maximum players of an arena and, more specifically, the must be the same number.
I suggest you using ChatCmdBuilder by rubenwardy and connect the set_spawner function to two separate subcommands such as:


local mod = "mymod" --more about this later

ChatCmdBuilder.new("NAMEOFYOURCOMMAND", function(cmd)

    cmd:sub("setspawn :arena", function(sender, arena)
        arena_lib.set_spawner(sender, mod, arena)
      end)

      cmd:sub("setspawn :arena :spawnID:int", function(sender, arena, spawn_ID)
          arena_lib.set_spawner(sender, mod, arena, spawn_ID)
        end)

   [etc.]

1.2.2 Signs

arena_lib.set_sign(sender, mod, arena_name) gives the player an item to hit a sign with. There must be one and one only sign for arena, and when hit it becomes the access to the arena.

1.2.3 Enabling an arena

When a sign has been set, it won't work. This because an arena must be enabled manually via
arena_lib.enable_arena(sender, mod, arena_ID)
If all the conditions are met, you'll receive a confirmation. If not, you'll receive a reason and the arena will remain disabled. Conditions are:

  • all spawn points set
  • sign placed

Arenas can be disabled too, via
arena_lib.disable_arena(sender, mod, arena_ID)
In order to do that, no game must be taking place in that specific arena.

1.3 Arena phases

An arena comes in 4 phases, each one of them linked to a specific function:

  • waiting phase: it's the queuing process. People hit a sign waiting for other players to play with
  • loading phase: it's the pre-match. By default players get teleported in the arena not being able to do anything but jump
  • fighting phase: the actual game
  • celebration phase: the after-match. By default people stroll around for the arena knowing who won, waiting to be teleported

The 4 functions, intertwined with the previously mentioned phases are:

  • arena_lib.load_arena(mod, arena_ID): between the waiting and the loading phase. Called when the queue timer reaches 0, it teleports people inside.
  • arena_lib.start_arena(mod_ref, arena): between the loading and the fighting phase. Called when the loading phase timer reaches 0.
  • arena_lib.load_celebration(mod, arena, winner_name): between the fighting and the celebration phase. Called when the winning conditions are met.
  • arena_lib.end_arena(mod_ref, mod, arena): at the very end of the celebration phase. It teleports people outside the arena

Overriding these functions is not recommended. Instead, there are 4 respective callbacks made specifically to customize the behaviour of the formers, sharing (almost) the same variables. They are called after the function they're associated with and by default they are empty, so feel free to override them. They are on_load, on_start, on_celebration and on_end, and they are explained later in 2.2.

2. Configuration

Still a TL;DR? Check out the example file

First of all download the mod and put it in your mods folder.

Then, you need to initialise the mod for each mod you want to feature arena_lib in, inside the init.lua via:

arena_lib.initialize("yourmod")

Be careful: the string you put inside the round brackets will be how arena_lib stores your mod inside its memory and what it needs in order to understand you're referring to that specific mod (that's why almost every function contains "mod" as a parameter). You'll need it when calling for commands.

To customise your mod, you can then call arena_lib.settings, specifying the mod name as follows:

arena_lib.settings("mymod", {
  --whatever parameter, such as
  -- prefix = "[mymode] ",
})

The parameters are:

  • prefix: what's gonna appear in most of the lines printed by your mod. Default is [arena_lib]
  • hub_spawn_point: where players will be teleported when a match in your mod ends. Default is { x = 0, y = 20, z = 0 }
  • join_while_in_progress: whether the minigame allows to join an ongoing match. Default is false
  • show_nametags: whether to show the players nametags while in game. Default is false
  • show_minimap: whether to allow players to use the builtin minimap function. Default is false
  • queue_waiting_time: the time to wait before the loading phase starts. It gets triggered when the minimium amount of players has been reached to start the queue. Default is 5
  • load_time: the time between the loading state and the start of the match. Default is 3
  • celebration_time: the time between the celebration state and the end of the match. Default is 3
  • immunity_time: the duration of the immunity right after respawning. Default is 3
  • immunity_slot: the slot whereto put the immunity item. Default is 9 (the first slot of the inventory minus the hotbar)
  • properties: explained down below
  • temp_properties: same
  • player_properties: same

On the contrary, to customise the global spawn point of your hub, meaning where to spawn players when they join the server, you need to edit the line
local hub_spawn_point = { x = 0, y = 20, z = 0}
in api.lua, inside the arena_lib folder.

2.1 Commands

You need to connect the functions of the library with your mod in order to use them. The best way is with commands and again I suggest you the ChatCmdBuilder by rubenwardy. This is what I came up with in my Quake minigame, which relies on arena_lib. As you can see, I declared a local mod = "quake" at the beginning, because it's how I stored my mod inside the library.

2.2 Callbacks

To customise your mod even more, there are a few empty callbacks you can use. They are:

  • arena_lib.on_load(mod, function(arena) (we saw these 4 earlier)
  • arena_lib.on_start(mod, function(arena))
  • arena_lib.on_celebration(mod, function(arena, winner_name)
  • arena_lib.on_end(mod, function(arena, players))
  • arena_lib.on_join(mod, function(p_name, arena)): called when a player joins an ongoing match
  • arena_lib.on_death(mod, function(arena, p_name, reason)): called when a player dies

Beware: there is a default behaviour already for each one of these situations: for instance when a player dies, its deaths increase by 1. These callbacks exist just in case you want to add some extra behaviour to arena_lib's.

So for instance, if we want to add an object in the first slot when a player joins the pre-match, we can simply do:

arena_lib.on_load("mymod", function(arena)

  local item = ItemStack("default:dirt")

  for pl_name, stats in pairs(arena.players) do
    pl_name:get_inventory():set_stack("main", 1, item)
  end

end)

2.3 Additional properties

Let's say you want to add a kill leader parameter. Arena_lib doesn't provide specific parameters, as its role is to be generic. Instead, you can create your own kill leader parameter by using the three tables properties, temp_properties and player_properties. The last one is for players, while the others are for the arena.

2.3.1 Arenas properties

The difference between properties and temp_properties is that the former will be stored by the the mod so that when the server reboots it'll still be there, while the latter won't and it's reset every time a match ends. So in our case, we don't want the kill leader to be stored outside the arena, thus we go to our arena_lib.settings and write

arena_lib.settings("mymod", {
  --whatever stuff we already have
  temp_properties = {
    kill_leader = " "
  }
}

and then we can easily access the kill_leader field whenever we want from every arena we have, via theactualarena.kill_leader, like when creating a function that returns the kill leader of a given arena.

Beware: you DO need to initialise your properties (whatever type) or it'll return an error

2.3.1.1 Updating properties for old arenas

If you decide to add a new property (temporary or not) to your mod but you had created a few arenas already, you need to update them manually by calling
arena_lib.update_properties("mymod")
right after arena_lib.settings. This has to be done manually because it'd be quite heavy to run a check on hypotetically very long strings whenever the server goes online for each mod relying on arena_lib. So just add it, run the server, shut it down when it's done loading, remove the call and then you're good to go.

2.3.2 Players properties

These are a particular type of temporary properties, as they're attached to every player in the arena. Let's say you now want to keep track of how many kills a player does in a streak without dying. You just need to create a killstreak parameter, declaring it like so

arena_lib.settings("mymod", {
  --stuff
  temp_properties = {
    kill_leader = " "
  },
  player_properties = {
    killstreak = 0
  }
}

Now you can easily access the killstreak parameter by retrieving the player inside an arena. Also, don't forget to reset it when a player dies via the on_death callback we saw earlier:

arena_lib.on_death("mymod", function(arena, p_name, reason)
  arena.players[p_name].killstreak = 0
end)

Check out this example for a full configuration file

2.4 Utils

There are also some other functions which might turn useful. They are:

  • arena_lib.is_player_in_queue(p_name, <mod>): returns a boolean. If a mod is specified, returns true only if it's inside a queue of that specific mod.
  • arena_lib.is_player_in_arena(p_name, <mod>): returns a boolean. Same as above.
  • arena_lib.remove_player_from_arena(p_name, is_eliminated): if is_eliminated is not specified, other players will see that the player has left the match. If it is (true), the message will say the player has been eliminated. The latter comes in handy for games like Murder or TNT Run
  • arena_lib.send_message_players_in_arena(arena, msg): send a message to all the players in that specific arena
  • arena_lib.immunity(player): grants immunity to the specified player. It lasts till the immunity_time declared in arena_lib.settings

3. Collaborating

Something's wrong? Feel free to:

  • open an issue
  • submit a merge request. In this case, PLEASE, do follow milestones. I won't merge features for milestones that are different from the upcoming one (if it's declared)
  • contact me on the Minetest Forum

I'd really appreciate it :)

4. About the author(s)

I'm Zughy (Marco), a professional Italian pixel artist who fights for FOSS and digital ethics. If this library spared you a lot of time and you want to support me somehow, please consider donating on LiberaPay directly to my educational Italian project (because not everyone speaks English and Italian media don't talk about these topics much). Also, this project wouldn't have been possible if it hadn't been for some friends who helped me testing through: SonoMichele, _Zaizen_ and Xx_Crazyminer_xX