Skip to content

Statistic Operation

Kamil Więczaszek edited this page Jun 5, 2023 · 10 revisions

Statistic interface

Info

Statistic interface is the root for all the statistics. It is a generic interface of <T extends Number> which simply means the T can only be a number. Statistic are counted automaticly and manually during the game. The user can define how and when they are counted.

Usage

Declaration

The .statistic package contains a subpackage .common which contains six predefined statistic interfaces of all six primitive numeric types. Those are ment to be implemented to create a statistic as the concept is to make one class per one. There is also an abstract class LockableStatistic that adds an ability to lock whole statistic, thus making it irresponsive for any value change operation.

Statistic declaration using IntStatistic interface:

import dev.kavu.gameapi.statistic.common.IntStatistic;

import java.util.HashSet;
import java.util.Set;

public class MyStatistic implements IntStatistic {
    
    @Override
    public Integer getDefault() {
        return 0;
    }

    @Override
    public Set<Trigger<?>> getTriggers() {
        return new HashSet<>(); // No triggers
    }
}

Statistic declaration using IntStatistic interface:

import dev.kavu.gameapi.statistic.LockableStatistic

import java.util.HashSet;
import java.util.Set;

public final class MyLockableStatistic extends LockableStatistic<Integer> {

    @Override
    public Integer getDefault() {
        return 0;
    }

    @Override
    public Set<Trigger<?>> getTriggers() {
        return new HashSet<>();
    }
}

Automatication

Statistics can be easily automaticated by using triggers. Those are specified in returned Set by Statistic.getTriggers() function.

Trigger

Info

Statistics are automaticly counted using Trigger objects. Triggers are triggered when the particular event is called, and react with given response. Also, the StatisticTriggerEvent event is called when any trigger is triggered.

Usage

Triggers are created via constructor, where the monitored event is specified by its class. Before this event is catched it can be validated using the validator.

Example player death trigger:

@Override
public Set<Trigger<?>> getTriggers() {
    Set<Trigger<?>> triggers = new HashSet<>();
    // Trigger initialization
    Trigger<PlayerDeathEvent> playerDeathTrigger = 
        new Trigger<>(PlayerDeathEvent.class, playerDeathEvent -> playerDeathEvent.getEntity().getUniqueId());

    triggers.add(playerDeathTrigger);
    return triggers;
}

@Condition

Info

The exact condition when the triggers can be triggered can be specified using @Condition annotation. Boolean functions in the Statistic object annotated with this annotation will be run and if the final result is true, the trigger will be triggered.

Annotated function must fulfill the following conditions:

  1. The annotated function has to return the boolean
  2. It can accept no arguments, or one of UUID type. The passed UUID object will be the member that the trigger was triggered for.

Usage

The @Condition annotation has two properties:

  • .negate - determines if the result should be negated; default false
  • .alternate - determines if the condition should be treated as an alternative one; default false

Note: If any of the proper (not alternative) condition fails, whole test fails. Then any alternative condition that returns true, if specified, will make the test pass.

The usage of @Condition annotation can be seen in the LockableStatistic class declaration:

package dev.kavu.gameapi.statistic;

import java.util.HashMap;
import java.util.UUID;

public abstract class LockableStatistic<T extends Number> implements Statistic<T>{

    private boolean locked;

    private final HashMap<UUID, Boolean> locks = new HashMap<>();

    public void setLocked(boolean locked) {
        this.locked = locked;
    }

    public void setLocked(UUID member, boolean locked){
        locks.replace(member, locked);
    }

    @Condition(negate = true)
    public boolean isLocked() {
        return locked;
    }

    @Condition(negate = true)
    public boolean isLocked(UUID member) {
        return locks.getOrDefault(member, true);
    }
}

RegisteredStatistic

Info

Registering a statistic means creating a RegisteredStatistic object with a use of particular Statistic object. It is the way to actually make statistic work. Every RegisteredStatistic has a map of members expressed by UUID associated with the value of same type as the generic parameter of Statistic object.

Usage

Registration

Registration happens by the GameManager object, that stores all RegisteredStatistic objects. Note that there can be only one statistic registered per one class. Ex. two objects of MyStatistic class cannot be registered.

MyStatistic object registration:

gameManager.registerStatistic(new MyStatistic());

Statistic can also be obtained using GameManager.getRegisteredStatistic() function by passing the statistic class:

// Getting RegisteredStatistic object by class
RegisteredStatistic<Integer> regStat = gameManager.getRegisteredStatistic(new MyStatistic(), this);

// Retrieving the statistic from RegisteredStatistic object
MyStatistic myStatistic = (MyStatistic) regStat.getStatistic();

Storage and value modifying

Every RegisteredStatisti stores a map of members as UUID objects associated with values of type same as the generic of parent Statistic object. Those can be modified using following functions:

  • .exec - executes the function for every member
  • .execFor - executes the function for specified member if present

Note: The Function<T, T> accepts the current value and returns new to be assigned.

The value change can also be achieved by calling RegisteredStatistic.trigger(UUID) function. It is a manual trigger that can be called any time. Although, it will not give any default response, but will call the StatisticTriggerEvent with an event field set to null.

Every predeclared statistic interfaces have declared static increment and decrement methods for each type. The increment of the value for a specific member of integer statistic will look like this:

// Getting RegisteredStatistic object by class
RegisteredStatistic<Integer> intStatistic = gameManager.getRegisteredStatistic(new MyStatistic(), this);

// Adding a member
UUID member = UUID.random();
intStatistic.addMember(member); // Member is automaticly given the default value of the parent Statistic

// Incrementing the value
intStatistic.execFor(member, IntStatistic::increment);

Technical info

  • Java version: 8
  • Build: Maven
  • Minecraft version: 1.8.8+
  • License: Apache 2.0

⚠️ Repository in development state. ⚠️

Clone this wiki locally