mirror of
https://github.com/SimplexDevelopment/FreedomNetworkSuite.git
synced 2024-11-13 04:33:33 +00:00
Documentation, Add BouncyPads
This commit is contained in:
parent
27dafd69e6
commit
1ea106d999
@ -27,11 +27,11 @@ public class Datura extends JavaPlugin
|
||||
|
||||
CommonsBase.getInstance()
|
||||
.getRegistrations()
|
||||
.getServiceRegistry()
|
||||
.getServiceTaskRegistry()
|
||||
.registerService(SubscriptionProvider.syncService(this, locker));
|
||||
CommonsBase.getInstance()
|
||||
.getRegistrations()
|
||||
.getServiceRegistry()
|
||||
.getServiceTaskRegistry()
|
||||
.registerService(SubscriptionProvider.syncService(this, cager));
|
||||
|
||||
Bukkit.getPluginManager()
|
||||
|
@ -45,7 +45,7 @@ public class FreedomUser implements User
|
||||
final Datura datura = CommonsBase.getInstance()
|
||||
.getRegistrations()
|
||||
.getModuleRegistry()
|
||||
.getModule(Datura.class)
|
||||
.getProvider(Datura.class)
|
||||
.getModule();
|
||||
|
||||
UserData data = SimpleUserData.fromSQL(datura.getSQL(), uuid.toString());
|
||||
|
@ -3,40 +3,112 @@ package me.totalfreedom.datura.user;
|
||||
import me.totalfreedom.economy.EconomicEntity;
|
||||
import me.totalfreedom.economy.EconomicEntityData;
|
||||
|
||||
/**
|
||||
* Represents the server's economy holder.
|
||||
* <br>
|
||||
* <br>
|
||||
* This is effectively a Bank object which is meant to represent the server itself,
|
||||
* which can store a balance and perform transactions with other EconomicEntity objects.
|
||||
* <br>
|
||||
* <br>
|
||||
* The server is initially given a maximum balance of {@link Long#MAX_VALUE}, though this can be changed
|
||||
* using the constructor {@link #ServerEconomyHolder(String, long)}. The value that this
|
||||
* bank object holds is persistent, which means that the total economic resources available
|
||||
* are of limited supply.
|
||||
* <br>
|
||||
* <br>
|
||||
* Please be aware, if the server's economy falls below 0,
|
||||
* it will have drastic consequences.
|
||||
*/
|
||||
public class ServerEconomyHolder implements EconomicEntity, EconomicEntityData
|
||||
{
|
||||
private long balance = Long.MAX_VALUE;
|
||||
private final String name;
|
||||
private long balance;
|
||||
|
||||
/**
|
||||
* Constructs a new ServerEconomyHolder with the specified name and a balance of {@link Long#MAX_VALUE}.
|
||||
*
|
||||
* @param name The name of this server economy holder.
|
||||
*/
|
||||
public ServerEconomyHolder(final String name)
|
||||
{
|
||||
this.name = name;
|
||||
this.balance = Long.MAX_VALUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new ServerEconomyHolder with the specified name and balance.
|
||||
*
|
||||
* @param name The name of this server economy holder.
|
||||
* @param balance The balance of this server economy holder.
|
||||
*/
|
||||
public ServerEconomyHolder(final String name, final long balance)
|
||||
{
|
||||
this.name = name;
|
||||
this.balance = balance;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will return this object, as it is both the EconomicEntity and the EconomicEntityData.
|
||||
* This is due to the fact that the server should only ever have one singular concrete representation
|
||||
* of it's economic entity and the respective data.
|
||||
*
|
||||
* @return this object.
|
||||
*/
|
||||
@Override
|
||||
public EconomicEntityData getEconomicData()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The name of this server economy holder.
|
||||
*/
|
||||
@Override
|
||||
public String getName()
|
||||
{
|
||||
return "TotalFreedom-Bank";
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will always return false, as the server should not ever be
|
||||
* prevented from performing transactions.
|
||||
*
|
||||
* @return false
|
||||
*/
|
||||
@Override
|
||||
public boolean areTransactionsFrozen()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The server's current available balance.
|
||||
*/
|
||||
@Override
|
||||
public long getBalance()
|
||||
{
|
||||
return balance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the server's balance to the specified value.
|
||||
*
|
||||
* @param newBalance The new balance to set.
|
||||
*/
|
||||
@Override
|
||||
public void setBalance(final long newBalance)
|
||||
{
|
||||
balance = newBalance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the specified amount to the server's balance.
|
||||
* This method mutates the balance and returns the new balance.
|
||||
*
|
||||
* @param amount The amount to add.
|
||||
* @return The new balance.
|
||||
*/
|
||||
@Override
|
||||
public long addToBalance(final long amount)
|
||||
{
|
||||
@ -44,6 +116,13 @@ public class ServerEconomyHolder implements EconomicEntity, EconomicEntityData
|
||||
return balance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the specified amount from the server's balance.
|
||||
* This method mutates the balance and returns the new balance.
|
||||
*
|
||||
* @param amount The amount to remove.
|
||||
* @return The new balance.
|
||||
*/
|
||||
@Override
|
||||
public long removeFromBalance(final long amount)
|
||||
{
|
||||
|
@ -18,7 +18,7 @@ public class Fossil extends JavaPlugin
|
||||
registration.getModuleRegistry()
|
||||
.addModule(this);
|
||||
|
||||
registration.getServiceRegistry()
|
||||
registration.getServiceTaskRegistry()
|
||||
.registerService(
|
||||
SubscriptionProvider.syncService(this, trailer));
|
||||
}
|
||||
|
@ -0,0 +1,211 @@
|
||||
package me.totalfreedom.fossil.bouncypads;
|
||||
|
||||
import com.google.errorprone.annotations.Immutable;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.SplittableRandom;
|
||||
|
||||
/**
|
||||
* Represents a bouncy pad. Has a velocity and a type.
|
||||
*/
|
||||
@Immutable
|
||||
public class BouncyPad
|
||||
{
|
||||
/**
|
||||
* The velocity of the pad.
|
||||
*/
|
||||
private final double velocity;
|
||||
/**
|
||||
* The type of the pad.
|
||||
*/
|
||||
private final PadType padType;
|
||||
|
||||
/**
|
||||
* Creates a new bouncy pad.
|
||||
*
|
||||
* @param velocity The velocity of the pad.
|
||||
* @param padType The type of the pad.
|
||||
*/
|
||||
public BouncyPad(final double velocity, final PadType padType)
|
||||
{
|
||||
this.velocity = velocity;
|
||||
this.padType = padType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new bouncy pad with a type of {@link PadType#NORMAL}.
|
||||
*
|
||||
* @param velocity The velocity of the pad.
|
||||
*/
|
||||
public BouncyPad(final double velocity)
|
||||
{
|
||||
this(velocity, PadType.NORMAL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new bouncy pad with a velocity of 1.1 and a type of {@link PadType#NORMAL}.
|
||||
*/
|
||||
public BouncyPad()
|
||||
{
|
||||
this(1.0 + 0.1F);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will bounce the player based on the type of the pad.
|
||||
* <p>
|
||||
* The type of the pad, defined by {@link #padType}, will determine how the player is bounced.
|
||||
* <br>
|
||||
* For type {@link PadType#NORMAL}, the player will be bounced if the face is {@link BlockFace#UP}.
|
||||
* <br>
|
||||
* For type {@link PadType#SIDES}, the player will be bounced if the face is not {@link BlockFace#UP} or
|
||||
* {@link BlockFace#DOWN}.
|
||||
* <br>
|
||||
* For type {@link PadType#ALL}, the player will be bounced regardless of the face.
|
||||
* <br>
|
||||
* For type {@link PadType#EXTREME}, the player will be bounced with a velocity based on the formula:
|
||||
* <br>
|
||||
* <span color=#f07a21><code>(((173.31 + 0.5 * velocity) - (31.2 + 0.5 * Math.pow(velocity, 2.0)) + (0.5 *
|
||||
* Math.pow(velocity, 3.0))) - 173.31) / (velocity * (velocity - 1))</code></span>
|
||||
* <br>
|
||||
* For type {@link PadType#SPACE_CADET}, the player will be bounced with a velocity based on the formula:
|
||||
* <br>
|
||||
* <span color=#f07a21><code>Math.round(Math.abs((accel * 100.0) + Math.pow(y, Math.floor(accel)) /
|
||||
* Math.exp(accel)))</code></span>
|
||||
* <br>
|
||||
* where <span color=#f07a21><code>y = Math.abs(random.nextGaussian(12, 5) * 0.5 + 0.5)</code></span> and <span
|
||||
* color=#f07a21><code>accel = Math.sqrt(2 * 9.81 * y)</code></span>
|
||||
* <br>
|
||||
* <br>
|
||||
* <b>NOTE:</b> The velocity of the pad is added with the inverse velocity of the player. The inverse
|
||||
* velocity of the player is acquired by multiplying the velocity of the player by -1.
|
||||
*
|
||||
* @param player The player to bounce.
|
||||
* @param face The face of the block the player is bouncing on.
|
||||
*/
|
||||
public void bouncePad(final Player player, final BlockFace face)
|
||||
{
|
||||
switch (padType)
|
||||
{
|
||||
case NORMAL -> bounceNormal(player, face);
|
||||
case SIDES -> bounceSides(player, face);
|
||||
case ALL -> bounceAll(player, face);
|
||||
case EXTREME -> bounceExtreme(player, face);
|
||||
case SPACE_CADET -> bounceSpaceCadet(player, face);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns a vector based on the following:
|
||||
* <br>
|
||||
* <span color=#f07a21><code>(BlockFace direction + Player velocity * -1) * velocity</code></span>
|
||||
* <br>
|
||||
* <br>
|
||||
* We retrieve a vector representing the direction in which this block face is facing. This is then added with the
|
||||
* inverse velocity of the player, which is the direction and speed in which the player is moving multiplied by -1.
|
||||
* This is then multiplied by the velocity of the pad.
|
||||
*
|
||||
* @param player The moving player
|
||||
* @param face The face of the block the player is bouncing on.
|
||||
* @return A vector representing the direction and speed in which the player should be bounced.
|
||||
*/
|
||||
private Vector getVector(final Player player, final BlockFace face)
|
||||
{
|
||||
return face.getDirection()
|
||||
.add(player.getVelocity()
|
||||
.multiply(-1))
|
||||
.multiply(velocity);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will bounce the player if the face is {@link BlockFace#UP}.
|
||||
*
|
||||
* @param player The player to bounce.
|
||||
* @param face The face of the block the player is bouncing on.
|
||||
*/
|
||||
private void bounceNormal(final Player player, final BlockFace face)
|
||||
{
|
||||
if (!face.equals(BlockFace.UP))
|
||||
return;
|
||||
|
||||
player.setVelocity(getVector(player, face));
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will bounce the player if the face is not {@link BlockFace#UP} or {@link BlockFace#DOWN}.
|
||||
*
|
||||
* @param player The player to bounce.
|
||||
* @param face The face of the block the player is bouncing on.
|
||||
*/
|
||||
private void bounceSides(final Player player, final BlockFace face)
|
||||
{
|
||||
if (face == BlockFace.UP || face == BlockFace.DOWN)
|
||||
return;
|
||||
|
||||
player.setVelocity(getVector(player, face));
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will bounce the player regardless of the face.
|
||||
*
|
||||
* @param player The player to bounce.
|
||||
* @param face The face of the block the player is bouncing on.
|
||||
*/
|
||||
private void bounceAll(final Player player, final BlockFace face)
|
||||
{
|
||||
player.setVelocity(getVector(player, face));
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will bounce the player with a velocity based on the formula:
|
||||
* <br>
|
||||
* <span color=#f07a21><code>(((173.31 + 0.5 * velocity) - (31.2 + 0.5 * Math.pow(velocity, 2.0)) + (0.5 *
|
||||
* Math.pow(velocity, 3.0))) - 173.31) / (velocity * (velocity - 1))</code></span>
|
||||
* <br>
|
||||
* <br>
|
||||
* <b>NOTE:</b> The velocity of the pad is added with the inverse velocity of the player. The inverse
|
||||
* velocity of the player is acquired by multiplying the velocity of the player by -1.
|
||||
*
|
||||
* @param player The player to bounce.
|
||||
* @param face The face of the block the player is bouncing on.
|
||||
*/
|
||||
private void bounceExtreme(final Player player, final BlockFace face)
|
||||
{
|
||||
final double extremeVelocity = (((173.31 + 0.5 * velocity) - (31.2 + 0.5 * Math.pow(velocity, 2.0)) + (0.5 * Math.pow(velocity, 3.0))) - 173.31) / (velocity * (velocity - 1));
|
||||
player.setVelocity(face.getDirection()
|
||||
.add(player.getVelocity()
|
||||
.multiply(-1))
|
||||
.multiply(extremeVelocity * velocity));
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will bounce the player with a velocity based on the formula:
|
||||
* <br>
|
||||
* <span color=#f07a21><code>Math.round(Math.abs((accel * 100.0) + Math.pow(y, Math.floor(accel)) /
|
||||
* Math.exp(accel)))</code></span>
|
||||
* <br>
|
||||
* where <span color=#f07a21><code>y = Math.abs(random.nextGaussian(12, 5) * 0.5 + 0.5)</code></span> and
|
||||
* <span color=#f07a21><code>accel = Math.sqrt(2 * 9.81 * y)</code></span>
|
||||
*
|
||||
* @param player The player to bounce.
|
||||
* @param face The face of the block the player is bouncing on.
|
||||
*/
|
||||
private void bounceSpaceCadet(final Player player, final BlockFace face)
|
||||
{
|
||||
final SplittableRandom random = new SplittableRandom();
|
||||
final double y = Math.abs(random.nextGaussian(12, 5) * 0.5 + 0.5);
|
||||
final double accel = Math.sqrt(2 * 9.81 * y);
|
||||
final double spaceVelocity = Math.round(Math.abs((accel * 100.0) + Math.pow(y, Math.floor(accel)) / Math.exp(accel)));
|
||||
|
||||
final Vector accelVector = new Vector(0, y + accel, 0);
|
||||
final Vector postVector = new Vector(0, spaceVelocity, 0);
|
||||
|
||||
final Vector spaceVector = face.getDirection()
|
||||
.add(player.getVelocity()
|
||||
.multiply(-1))
|
||||
.multiply(accelVector.multiply(postVector));
|
||||
|
||||
player.setVelocity(spaceVector);
|
||||
}
|
||||
}
|
@ -0,0 +1,156 @@
|
||||
package me.totalfreedom.fossil.bouncypads;
|
||||
|
||||
import me.totalfreedom.base.CommonsBase;
|
||||
import me.totalfreedom.fossil.Fossil;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Tag;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerMoveEvent;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Holds all the active pads for each player, and also manages player pad interaction.
|
||||
*/
|
||||
public class PadHolder implements Listener
|
||||
{
|
||||
/**
|
||||
* A map of all the currently active pads, stored by {@link Player} {@link UUID}.
|
||||
*/
|
||||
private final Map<UUID, BouncyPad> pads = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Creates a new pad holder.
|
||||
*/
|
||||
public PadHolder()
|
||||
{
|
||||
Bukkit.getPluginManager().registerEvents(this, CommonsBase
|
||||
.getInstance()
|
||||
.getRegistrations()
|
||||
.getModuleRegistry()
|
||||
.getProvider(Fossil.class)
|
||||
.getModule());
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a pad for the given player. If the player already has a pad stored in the map,
|
||||
* it will be overwritten with the new pad.
|
||||
*
|
||||
* @param player The player to add the pad for.
|
||||
* @param pad The pad to add.
|
||||
*/
|
||||
public void addPad(final Player player, final BouncyPad pad)
|
||||
{
|
||||
this.pads.put(player.getUniqueId(), pad);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the pad for the given player, if the player has one.
|
||||
*
|
||||
* @param player The player to remove the pad for.
|
||||
*/
|
||||
public void removePad(final Player player)
|
||||
{
|
||||
this.pads.remove(player.getUniqueId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the pad for the given player, if the player has one.
|
||||
* If the player has no active pad, this will return null.
|
||||
*
|
||||
* @param player The player to get the pad for.
|
||||
* @return The pad for the given player.
|
||||
*/
|
||||
@Nullable
|
||||
public BouncyPad getPad(final Player player)
|
||||
{
|
||||
return this.pads.get(player.getUniqueId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if there is a pad active for the given player.
|
||||
*
|
||||
* @param player The player to check.
|
||||
* @return True if the player has a pad, false otherwise.
|
||||
*/
|
||||
public boolean hasPad(final Player player)
|
||||
{
|
||||
return this.pads.containsKey(player.getUniqueId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a map of all the currently active pads, stored by {@link Player} {@link UUID}.
|
||||
*
|
||||
* @return A map of all the currently active pads.
|
||||
*/
|
||||
public Map<UUID, BouncyPad> getPads()
|
||||
{
|
||||
return this.pads;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles player pad interaction. This will check the relative block for each acceptible direction, and pass the
|
||||
* resulting block face (if any) to the bounce pad. See {@link BouncyPad#bouncePad(Player, org.bukkit.block.BlockFace)}
|
||||
* for how the resulting block face is processed.
|
||||
*
|
||||
* @param event The event which gets called when a player moves.
|
||||
*/
|
||||
@EventHandler
|
||||
public void onPlayerMove(final PlayerMoveEvent event)
|
||||
{
|
||||
final Player player = event.getPlayer();
|
||||
if (!this.hasPad(player))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
final BouncyPad pad = this.getPad(player);
|
||||
final Location location = player.getLocation();
|
||||
|
||||
final Block xNeg1 = getRelative(location, -1, 0, 0);
|
||||
final Block xPos1 = getRelative(location, 1, 0, 0);
|
||||
final Block zNeg1 = getRelative(location, 0, 0, -1);
|
||||
final Block zPos1 = getRelative(location, 0, 0, 1);
|
||||
final Block yNeg1 = getRelative(location, 0, -1, 0);
|
||||
|
||||
Stream.of(xNeg1, xPos1, zNeg1, zPos1, yNeg1)
|
||||
.filter(this::isWool)
|
||||
.map(block -> block.getFace(location.getBlock()))
|
||||
.findFirst()
|
||||
.ifPresent(face -> pad.bouncePad(player, face));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the relative block at the given location.
|
||||
*
|
||||
* @param location The location to get the relative block from.
|
||||
* @param x The x mod.
|
||||
* @param y The y mod.
|
||||
* @param z The z mod.
|
||||
* @return The relative block.
|
||||
*/
|
||||
private Block getRelative(final Location location, final int x, final int y, final int z)
|
||||
{
|
||||
return location.getBlock().getRelative(x, y, z);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given block is wool.
|
||||
*
|
||||
* @param block The block to check.
|
||||
* @return True if the block is wool, false otherwise.
|
||||
* @see Tag#WOOL
|
||||
*/
|
||||
private boolean isWool(final Block block)
|
||||
{
|
||||
return Tag.WOOL.isTagged(block.getType());
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package me.totalfreedom.fossil.bouncypads;
|
||||
|
||||
import org.bukkit.block.BlockFace;
|
||||
|
||||
/**
|
||||
* Represents a specific type of bouncy pad.
|
||||
*/
|
||||
public enum PadType
|
||||
{
|
||||
/**
|
||||
* A normal pad, which will only bounce the player if the face is {@link BlockFace#UP}.
|
||||
*/
|
||||
NORMAL,
|
||||
/**
|
||||
* A pad which will bounce the player on {@link BlockFace#NORTH}, {@link BlockFace#SOUTH}, {@link BlockFace#EAST}
|
||||
* or {@link BlockFace#WEST}.
|
||||
*/
|
||||
SIDES,
|
||||
/**
|
||||
* A pad which will bounce the player if the face is {@link BlockFace#UP}, {@link BlockFace#NORTH},
|
||||
* {@link BlockFace#EAST}, {@link BlockFace#SOUTH} or {@link BlockFace#WEST}.
|
||||
*/
|
||||
ALL,
|
||||
/**
|
||||
* A pad which will bounce the player with an extreme velocity
|
||||
*/
|
||||
EXTREME,
|
||||
/**
|
||||
* A pad which will send the player to space.
|
||||
*/
|
||||
SPACE_CADET;
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
package me.totalfreedom.fossil.reactions;
|
||||
|
||||
import me.totalfreedom.display.BossBarDisplay;
|
||||
import me.totalfreedom.economy.EconomicEntity;
|
||||
import me.totalfreedom.shop.Reaction;
|
||||
import me.totalfreedom.shop.ReactionType;
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
import net.kyori.adventure.bossbar.BossBar;
|
||||
|
||||
import java.util.SplittableRandom;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* Represents a single chat reaction that can be performed by a player.
|
||||
*/
|
||||
public final class CopyCatReaction extends Reaction
|
||||
{
|
||||
private final long reward;
|
||||
|
||||
public CopyCatReaction(final long reward)
|
||||
{
|
||||
super(ReactionType.COPYCAT);
|
||||
this.reward = reward;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getReward()
|
||||
{
|
||||
return reward;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReact(final Consumer<EconomicEntity> entity)
|
||||
{
|
||||
entity.accept(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void display(final Audience audience)
|
||||
{
|
||||
final BossBar bossBar = BossBarDisplay.builder().setName(getRandomCharacterString())
|
||||
.setProgress(0.0F)
|
||||
.build();
|
||||
}
|
||||
|
||||
public String getRandomCharacterString() {
|
||||
final SplittableRandom random = new SplittableRandom();
|
||||
final StringBuilder sb = new StringBuilder(10);
|
||||
|
||||
final String chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
sb.append(chars.charAt(random.nextInt(chars.length())));
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package me.totalfreedom.api;
|
||||
|
||||
import me.totalfreedom.provider.ContextProvider;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
@ -13,16 +14,40 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Represents an object context. This class is a simple generic type wrapper that can be used to ensure data types. This
|
||||
* class is also used to provide a simple way to map data types.
|
||||
*
|
||||
* @param <T> The type of the context.
|
||||
* @see ContextProvider
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface Context<T>
|
||||
{
|
||||
/**
|
||||
* Maps the context to another context.
|
||||
*
|
||||
* @param mapper The mapper function.
|
||||
* @param <S> The type of the mapped context.
|
||||
* @return The mapped context.
|
||||
*/
|
||||
default <S> Context<S> map(@NotNull final Function<T, S> mapper)
|
||||
{
|
||||
return () -> mapper.apply(get());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the context.
|
||||
*
|
||||
* @return The context.
|
||||
*/
|
||||
T get();
|
||||
|
||||
/**
|
||||
* Gets the context as a string.
|
||||
*
|
||||
* @return The context as a string.
|
||||
*/
|
||||
default @Nullable String asString()
|
||||
{
|
||||
if (get() instanceof String string)
|
||||
@ -34,6 +59,11 @@ public interface Context<T>
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the context as a boolean.
|
||||
*
|
||||
* @return The context as a boolean.
|
||||
*/
|
||||
default @Nullable Boolean asBoolean()
|
||||
{
|
||||
if (get() instanceof Boolean bool)
|
||||
@ -45,6 +75,9 @@ public interface Context<T>
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The context as a {@link Double}.
|
||||
*/
|
||||
default @Nullable Double asDouble()
|
||||
{
|
||||
if (get() instanceof Double doub)
|
||||
@ -56,6 +89,9 @@ public interface Context<T>
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The context as a {@link Integer}.
|
||||
*/
|
||||
default @Nullable Integer asInt()
|
||||
{
|
||||
if (get() instanceof Integer integer)
|
||||
@ -67,6 +103,9 @@ public interface Context<T>
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The context as a {@link Byte}.
|
||||
*/
|
||||
default @Nullable Long asLong()
|
||||
{
|
||||
if (get() instanceof Long longg)
|
||||
@ -78,6 +117,9 @@ public interface Context<T>
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The context as a {@link Float}.
|
||||
*/
|
||||
default @Nullable Float asFloat()
|
||||
{
|
||||
if (get() instanceof Float floatt)
|
||||
@ -89,6 +131,9 @@ public interface Context<T>
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The context as a {@link Player}.
|
||||
*/
|
||||
default @Nullable Player asPlayer()
|
||||
{
|
||||
if (get() instanceof Player player)
|
||||
@ -100,6 +145,9 @@ public interface Context<T>
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The context as a {@link CommandSender}.
|
||||
*/
|
||||
default @Nullable CommandSender asCommandSender()
|
||||
{
|
||||
if (get() instanceof CommandSender commandSender)
|
||||
@ -111,11 +159,19 @@ public interface Context<T>
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the same as calling {@link #get()} and then calling {@link Object#toString()} on the result.
|
||||
*
|
||||
* @return The context as a {@link String} literal.
|
||||
*/
|
||||
default @NotNull String literal()
|
||||
{
|
||||
return get().toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The context as a {@link World}.
|
||||
*/
|
||||
default @Nullable World asWorld()
|
||||
{
|
||||
if (get() instanceof World world)
|
||||
@ -127,6 +183,9 @@ public interface Context<T>
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The context as a {@link Location}.
|
||||
*/
|
||||
default @Nullable Location asLocation()
|
||||
{
|
||||
if (get() instanceof Location location)
|
||||
@ -138,6 +197,9 @@ public interface Context<T>
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The context as a {@link LivingEntity}.
|
||||
*/
|
||||
default @Nullable LivingEntity asLivingEntity()
|
||||
{
|
||||
if (get() instanceof LivingEntity livingEntity)
|
||||
@ -149,6 +211,9 @@ public interface Context<T>
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The context as a {@link Component}.
|
||||
*/
|
||||
default @Nullable Component asComponent()
|
||||
{
|
||||
if (get() instanceof Component component)
|
||||
@ -160,6 +225,9 @@ public interface Context<T>
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The context as a {@link Projectile}.
|
||||
*/
|
||||
default @Nullable Projectile asProjectile()
|
||||
{
|
||||
if (get() instanceof Projectile projectile)
|
||||
@ -171,6 +239,9 @@ public interface Context<T>
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The context as an {@link Action}.
|
||||
*/
|
||||
default @Nullable Action asAction()
|
||||
{
|
||||
if (get() instanceof Action action)
|
||||
@ -182,6 +253,22 @@ public interface Context<T>
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the context as a custom class. This will cast the object to the class if it is an instance of it.
|
||||
* <br>
|
||||
* Typically, Context objects are useful when used to collect unknown data and then cast it to a known type.
|
||||
* <br>
|
||||
* In the case where we know what the data should be but the compiler or the runtime does not, the object is wrapped
|
||||
* in a Context which then exposes multiple methods to get the data as one of the known types.
|
||||
* <p>
|
||||
* For example, if we have a Context<Object> and we already know that the wrapped object should be of type X,
|
||||
* we can use <code>X.class</code> on this method to retrieve the actual object. That is, to say, if there is not
|
||||
* already a predefined method to get the object as the type we want.
|
||||
*
|
||||
* @param clazz
|
||||
* @param <U>
|
||||
* @return
|
||||
*/
|
||||
default <U> @Nullable U asCustom(Class<U> clazz)
|
||||
{
|
||||
if (clazz.isInstance(get()))
|
||||
|
@ -1,7 +1,21 @@
|
||||
package me.totalfreedom.api;
|
||||
|
||||
/**
|
||||
* Interpolates a range of values and returns the results in a {@link Double} array.
|
||||
* <br>
|
||||
* This is a functional interface, to allow for lambda expressions, but also for anonymous custom interpolation
|
||||
* implementations.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface Interpolator
|
||||
{
|
||||
/**
|
||||
* Interpolates a range of values and returns the results in a {@link Double} array.
|
||||
*
|
||||
* @param from The starting value.
|
||||
* @param to The ending value.
|
||||
* @param max The number of values to interpolate.
|
||||
* @return The interpolated values.
|
||||
*/
|
||||
double[] interpolate(final double from, final double to, final int max);
|
||||
}
|
||||
|
@ -1,5 +1,12 @@
|
||||
package me.totalfreedom.api;
|
||||
|
||||
/**
|
||||
* This interface represents a Serializable object.
|
||||
* Objects which require custom serialization and cannot simply override or call
|
||||
* the default {@link Object#toString()} method should implement this interface.
|
||||
*
|
||||
* @param <T> The type of object to serialize
|
||||
*/
|
||||
public interface Serializable<T>
|
||||
{
|
||||
/**
|
||||
@ -11,5 +18,11 @@ public interface Serializable<T>
|
||||
*/
|
||||
String serialize(T object);
|
||||
|
||||
T deserialize(Context<?>... contexts);
|
||||
/**
|
||||
* Deserialize an object from a Serialized string..
|
||||
* @param serializedObject The serialized object
|
||||
* @return The deserialized object
|
||||
*/
|
||||
|
||||
T deserialize(String serializedObject);
|
||||
}
|
||||
|
@ -19,16 +19,25 @@ import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* A replacement for {@link net.kyori.adventure.audience.ForwardingAudience} that allows for audiences to be removed
|
||||
* & added at will. Not thread safe.
|
||||
* A replacement for {@link net.kyori.adventure.audience.ForwardingAudience} that allows for audiences to be removed &
|
||||
* added at will. Not thread safe.
|
||||
* <p>
|
||||
* This is intended for use in toggleable logging systems, for example, potion spy.
|
||||
*/
|
||||
// TODO: Work on thread-safety (or thread-safe alternative)
|
||||
public class MutableAudienceForwarder implements Audience
|
||||
{
|
||||
/**
|
||||
* The audiences that this forwards to.
|
||||
*/
|
||||
private final Set<Audience> audiences = new HashSet<>();
|
||||
|
||||
/**
|
||||
* Creates a new {@link MutableAudienceForwarder} with the given audiences.
|
||||
*
|
||||
* @param audiences The audiences to forward to.
|
||||
* @return The new {@link MutableAudienceForwarder}.
|
||||
*/
|
||||
public static MutableAudienceForwarder from(final Audience... audiences)
|
||||
{
|
||||
final MutableAudienceForwarder audienceForwarder = new MutableAudienceForwarder();
|
||||
@ -41,6 +50,11 @@ public class MutableAudienceForwarder implements Audience
|
||||
return audienceForwarder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an audience to this forwarder.
|
||||
*
|
||||
* @param audience The audience to add.
|
||||
*/
|
||||
public void addAudience(final Audience audience)
|
||||
{
|
||||
if (audiences.contains(audience) || audience == this /* Protect against honest self-referential calls */)
|
||||
@ -51,12 +65,23 @@ public class MutableAudienceForwarder implements Audience
|
||||
audiences.add(audience);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an audience from this forwarder.
|
||||
*
|
||||
* @param audience The audience to remove.
|
||||
* @return Whether the audience was removed.
|
||||
*/
|
||||
public boolean removeAudience(final Audience audience)
|
||||
{
|
||||
return audiences.remove(audience);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Filters the audiences in the stream by the given predicate.
|
||||
*
|
||||
* @param filter a filter that determines if an audience should be included
|
||||
* @return The first Audience found that matches the filter.
|
||||
*/
|
||||
@Override
|
||||
public @NotNull Audience filterAudience(@NotNull final Predicate<? super Audience> filter)
|
||||
{
|
||||
@ -66,52 +91,103 @@ public class MutableAudienceForwarder implements Audience
|
||||
.orElseThrow();
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies a consumer to each audience in the stream.
|
||||
*
|
||||
* @param action the action to apply.
|
||||
*/
|
||||
@Override
|
||||
public void forEachAudience(@NotNull final Consumer<? super Audience> action)
|
||||
{
|
||||
audiences.forEach(action);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a {@link ComponentLike} to every audience within the stream.
|
||||
*
|
||||
* @param message The message to send.
|
||||
* @see Audience#sendMessage(ComponentLike)
|
||||
* @see #forEachAudience(Consumer)
|
||||
*/
|
||||
@Override
|
||||
public void sendMessage(@NotNull final ComponentLike message)
|
||||
{
|
||||
audiences.forEach(a -> a.sendMessage(message));
|
||||
forEachAudience(a -> a.sendMessage(message));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a {@link Component} to every audience within the stream.
|
||||
*
|
||||
* @param message The message to send
|
||||
* @see Audience#sendMessage(Component)
|
||||
* @see #forEachAudience(Consumer)
|
||||
*/
|
||||
@Override
|
||||
public void sendMessage(@NotNull final Component message)
|
||||
{
|
||||
audiences.forEach(a -> a.sendMessage(message));
|
||||
forEachAudience(a -> a.sendMessage(message));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a {@link SignedMessage} to every audience within the stream.
|
||||
*
|
||||
* @param message the component content of the message
|
||||
* @param boundChatType the bound chat type of the message
|
||||
* @see Audience#sendMessage(Component, ChatType.Bound)
|
||||
* @see #forEachAudience(Consumer)
|
||||
*/
|
||||
@Override
|
||||
public void sendMessage(@NotNull final Component message, final ChatType.@NotNull Bound boundChatType)
|
||||
{
|
||||
audiences.forEach(a -> a.sendMessage(message, boundChatType));
|
||||
forEachAudience(a -> a.sendMessage(message, boundChatType));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a {@link SignedMessage} to every audience within the stream.
|
||||
*
|
||||
* @param message the component content of the message
|
||||
* @param boundChatType the bound chat type of the message
|
||||
* @see Audience#sendMessage(ComponentLike, ChatType.Bound)
|
||||
* @see #forEachAudience(Consumer)
|
||||
*/
|
||||
@Override
|
||||
public void sendMessage(@NotNull final ComponentLike message, final ChatType.@NotNull Bound boundChatType)
|
||||
{
|
||||
audiences.forEach(a -> a.sendMessage(message, boundChatType));
|
||||
forEachAudience(a -> a.sendMessage(message, boundChatType));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a {@link SignedMessage} to every audience within the stream.
|
||||
*
|
||||
* @param signedMessage the signed message data to send
|
||||
* @param boundChatType the bound chat type of the message
|
||||
*/
|
||||
@Override
|
||||
public void sendMessage(@NotNull final SignedMessage signedMessage, final ChatType.@NotNull Bound boundChatType)
|
||||
{
|
||||
audiences.forEach(a -> a.sendMessage(signedMessage, boundChatType));
|
||||
forEachAudience(a -> a.sendMessage(signedMessage, boundChatType));
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a signed message from the audiences chat.
|
||||
*
|
||||
* @param signedMessage the message to delete
|
||||
*/
|
||||
@Override
|
||||
public void deleteMessage(@NotNull final SignedMessage signedMessage)
|
||||
{
|
||||
audiences.forEach(a -> a.deleteMessage(signedMessage));
|
||||
forEachAudience(a -> a.deleteMessage(signedMessage));
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a signed message from the audiences chat using the provided chat signature.
|
||||
*
|
||||
* @param signature the signature associated with the message to delete.
|
||||
*/
|
||||
@Override
|
||||
public void deleteMessage(final SignedMessage.@NotNull Signature signature)
|
||||
{
|
||||
audiences.forEach(a -> a.deleteMessage(signature));
|
||||
forEachAudience(a -> a.deleteMessage(signature));
|
||||
}
|
||||
|
||||
// The methods below here will (probably) never be used, however it's good to keep them for completeness' sake.
|
||||
@ -119,127 +195,127 @@ public class MutableAudienceForwarder implements Audience
|
||||
@Override
|
||||
public void sendActionBar(@NotNull final ComponentLike message)
|
||||
{
|
||||
audiences.forEach(a -> a.sendActionBar(message));
|
||||
forEachAudience(a -> a.sendActionBar(message));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendActionBar(@NotNull final Component message)
|
||||
{
|
||||
audiences.forEach(a -> a.sendActionBar(message));
|
||||
forEachAudience(a -> a.sendActionBar(message));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendPlayerListHeader(@NotNull final ComponentLike header)
|
||||
{
|
||||
audiences.forEach(a -> a.sendPlayerListHeader(header));
|
||||
forEachAudience(a -> a.sendPlayerListHeader(header));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendPlayerListHeader(@NotNull final Component header)
|
||||
{
|
||||
audiences.forEach(a -> a.sendPlayerListHeader(header));
|
||||
forEachAudience(a -> a.sendPlayerListHeader(header));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendPlayerListFooter(@NotNull final ComponentLike footer)
|
||||
{
|
||||
audiences.forEach(a -> a.sendPlayerListFooter(footer));
|
||||
forEachAudience(a -> a.sendPlayerListFooter(footer));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendPlayerListFooter(@NotNull final Component footer)
|
||||
{
|
||||
audiences.forEach(a -> a.sendPlayerListFooter(footer));
|
||||
forEachAudience(a -> a.sendPlayerListFooter(footer));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendPlayerListHeaderAndFooter(@NotNull final ComponentLike header, @NotNull final ComponentLike footer)
|
||||
{
|
||||
audiences.forEach(a -> a.sendPlayerListHeaderAndFooter(header, footer));
|
||||
forEachAudience(a -> a.sendPlayerListHeaderAndFooter(header, footer));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendPlayerListHeaderAndFooter(@NotNull final Component header, @NotNull final Component footer)
|
||||
{
|
||||
audiences.forEach(a -> a.sendPlayerListHeaderAndFooter(header, footer));
|
||||
forEachAudience(a -> a.sendPlayerListHeaderAndFooter(header, footer));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showTitle(@NotNull final Title title)
|
||||
{
|
||||
audiences.forEach(a -> a.showTitle(title));
|
||||
forEachAudience(a -> a.showTitle(title));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void sendTitlePart(@NotNull final TitlePart<T> part, @NotNull final T value)
|
||||
{
|
||||
audiences.forEach(a -> a.sendTitlePart(part, value));
|
||||
forEachAudience(a -> a.sendTitlePart(part, value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearTitle()
|
||||
{
|
||||
audiences.forEach(Audience::clearTitle);
|
||||
forEachAudience(Audience::clearTitle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetTitle()
|
||||
{
|
||||
audiences.forEach(Audience::resetTitle);
|
||||
forEachAudience(Audience::resetTitle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showBossBar(@NotNull final BossBar bar)
|
||||
{
|
||||
audiences.forEach(a -> a.showBossBar(bar));
|
||||
forEachAudience(a -> a.showBossBar(bar));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hideBossBar(@NotNull final BossBar bar)
|
||||
{
|
||||
audiences.forEach(a -> a.hideBossBar(bar));
|
||||
forEachAudience(a -> a.hideBossBar(bar));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playSound(@NotNull final Sound sound)
|
||||
{
|
||||
audiences.forEach(a -> a.playSound(sound));
|
||||
forEachAudience(a -> a.playSound(sound));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playSound(@NotNull final Sound sound, final double x, final double y, final double z)
|
||||
{
|
||||
|
||||
audiences.forEach(a -> a.playSound(sound, x, y, z));
|
||||
forEachAudience(a -> a.playSound(sound, x, y, z));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playSound(@NotNull final Sound sound, final Sound.@NotNull Emitter emitter)
|
||||
{
|
||||
audiences.forEach(a -> a.playSound(sound, emitter));
|
||||
forEachAudience(a -> a.playSound(sound, emitter));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopSound(@NotNull final Sound sound)
|
||||
{
|
||||
audiences.forEach(a -> a.stopSound(sound));
|
||||
forEachAudience(a -> a.stopSound(sound));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopSound(@NotNull final SoundStop stop)
|
||||
{
|
||||
audiences.forEach(a -> a.stopSound(stop));
|
||||
forEachAudience(a -> a.stopSound(stop));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void openBook(final Book.@NotNull Builder book)
|
||||
{
|
||||
audiences.forEach(a -> a.openBook(book));
|
||||
forEachAudience(a -> a.openBook(book));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void openBook(@NotNull final Book book)
|
||||
{
|
||||
audiences.forEach(a -> a.openBook(book));
|
||||
forEachAudience(a -> a.openBook(book));
|
||||
}
|
||||
}
|
||||
|
@ -6,12 +6,30 @@ import me.totalfreedom.service.SubscriptionProvider;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
/**
|
||||
* The base class for Patchwork.
|
||||
*/
|
||||
public class CommonsBase extends JavaPlugin
|
||||
{
|
||||
/**
|
||||
* The {@link EventBus} for this plugin.
|
||||
*/
|
||||
private final EventBus eventBus = new EventBus(this);
|
||||
/**
|
||||
* The {@link Registration} object for this plugin.
|
||||
*/
|
||||
private final Registration registration = new Registration();
|
||||
/**
|
||||
* The {@link FreedomExecutor} for this plugin.
|
||||
*/
|
||||
private final FreedomExecutor executor = new FreedomExecutor();
|
||||
|
||||
/**
|
||||
* Provides this plugin instance through a safe static method.
|
||||
* This is effectively the same thing as using {@link JavaPlugin#getPlugin(Class)}
|
||||
*
|
||||
* @return the plugin instance
|
||||
*/
|
||||
public static CommonsBase getInstance()
|
||||
{
|
||||
return JavaPlugin.getPlugin(CommonsBase.class);
|
||||
@ -22,34 +40,51 @@ public class CommonsBase extends JavaPlugin
|
||||
{
|
||||
Bukkit.getScheduler()
|
||||
.runTaskLater(this, () -> getRegistrations()
|
||||
.getServiceRegistry()
|
||||
.stopAllServices(), 1L);
|
||||
.getServiceTaskRegistry()
|
||||
.stopAllServices(), 1L);
|
||||
|
||||
getRegistrations().getServiceRegistry()
|
||||
getRegistrations().getServiceTaskRegistry()
|
||||
.unregisterService(EventBus.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable()
|
||||
{
|
||||
getRegistrations().getServiceRegistry()
|
||||
getRegistrations().getServiceTaskRegistry()
|
||||
.registerService(SubscriptionProvider.asyncService(this, eventBus));
|
||||
getExecutor().getSync()
|
||||
.execute(() -> getRegistrations()
|
||||
.getServiceRegistry()
|
||||
.startAllServices());
|
||||
.getServiceTaskRegistry()
|
||||
.startAllServices());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link FreedomExecutor} for this plugin.
|
||||
*
|
||||
* @return the {@link FreedomExecutor}
|
||||
*/
|
||||
public FreedomExecutor getExecutor()
|
||||
{
|
||||
return executor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get's the Registration object for this plugin. This object contains every registry class for the various features
|
||||
* provided by this plugin.
|
||||
*
|
||||
* @return the Registration object
|
||||
*/
|
||||
public Registration getRegistrations()
|
||||
{
|
||||
return registration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link EventBus} for this plugin. The EventBus is used to register and listen to custom events provided
|
||||
* by Freedom Network Suite.
|
||||
*
|
||||
* @return the {@link EventBus}
|
||||
*/
|
||||
public EventBus getEventBus()
|
||||
{
|
||||
return eventBus;
|
||||
|
@ -7,16 +7,44 @@ import me.totalfreedom.data.ModuleRegistry;
|
||||
import me.totalfreedom.data.ServiceTaskRegistry;
|
||||
import me.totalfreedom.data.UserRegistry;
|
||||
|
||||
/**
|
||||
* This class is a holder for each registry in the data package.
|
||||
* <br>
|
||||
* Registries such as {@link ModuleRegistry} and {@link ServiceTaskRegistry}
|
||||
* can be found as final objects in this class. These registries should only ever be accessed through
|
||||
* the single Registration object in CommonsBase using {@link CommonsBase#getRegistrations()}
|
||||
*/
|
||||
public class Registration
|
||||
{
|
||||
/**
|
||||
* The {@link EventRegistry}
|
||||
*/
|
||||
private final EventRegistry eventRegistry;
|
||||
/**
|
||||
* The {@link UserRegistry}
|
||||
*/
|
||||
private final UserRegistry userRegistry;
|
||||
/**
|
||||
* The {@link ServiceTaskRegistry}
|
||||
*/
|
||||
private final ServiceTaskRegistry serviceTaskRegistry;
|
||||
/**
|
||||
* The {@link ModuleRegistry}
|
||||
*/
|
||||
private final ModuleRegistry moduleRegistry;
|
||||
/**
|
||||
* The {@link GroupRegistry}
|
||||
*/
|
||||
private final GroupRegistry groupRegistry;
|
||||
/**
|
||||
* The {@link ConfigRegistry}
|
||||
*/
|
||||
private final ConfigRegistry configRegistry;
|
||||
|
||||
public Registration()
|
||||
/**
|
||||
* Constructs a new Registration object and initializes all registries.
|
||||
*/
|
||||
Registration()
|
||||
{
|
||||
this.eventRegistry = new EventRegistry();
|
||||
this.userRegistry = new UserRegistry();
|
||||
@ -26,31 +54,49 @@ public class Registration
|
||||
this.configRegistry = new ConfigRegistry();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The {@link ModuleRegistry}
|
||||
*/
|
||||
public ModuleRegistry getModuleRegistry()
|
||||
{
|
||||
return moduleRegistry;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The {@link EventRegistry}
|
||||
*/
|
||||
public EventRegistry getEventRegistry()
|
||||
{
|
||||
return eventRegistry;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The {@link UserRegistry}
|
||||
*/
|
||||
public UserRegistry getUserRegistry()
|
||||
{
|
||||
return userRegistry;
|
||||
}
|
||||
|
||||
public ServiceTaskRegistry getServiceRegistry()
|
||||
/**
|
||||
* @return The {@link ServiceTaskRegistry}
|
||||
*/
|
||||
public ServiceTaskRegistry getServiceTaskRegistry()
|
||||
{
|
||||
return serviceTaskRegistry;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The {@link GroupRegistry}
|
||||
*/
|
||||
public GroupRegistry getGroupRegistry()
|
||||
{
|
||||
return groupRegistry;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The {@link ConfigRegistry}
|
||||
*/
|
||||
public ConfigRegistry getConfigRegistry()
|
||||
{
|
||||
return configRegistry;
|
||||
|
@ -22,7 +22,23 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class BukkitDelegate extends Command implements PluginIdentifiableCommand
|
||||
/**
|
||||
* This class is acts as a delegate between our custom command implementation and the Bukkit API.
|
||||
* <br>
|
||||
* This class is not meant to be used directly, and is only public to allow for the Bukkit API to access it.
|
||||
* As a result, this file will remain undocumented.
|
||||
* <span color=#ff0000>
|
||||
* <br>
|
||||
* This class is not thread-safe.
|
||||
* <br>
|
||||
* This class is not meant to be extended.
|
||||
* <br>
|
||||
* This class is not meant to be instantiated.
|
||||
* <br>
|
||||
* This class is not meant to be used outside Patchwork.
|
||||
* </span>
|
||||
*/
|
||||
public final class BukkitDelegate extends Command implements PluginIdentifiableCommand
|
||||
{
|
||||
private final JavaPlugin plugin;
|
||||
private final Commander command;
|
||||
@ -50,8 +66,8 @@ public class BukkitDelegate extends Command implements PluginIdentifiableCommand
|
||||
|
||||
@Override
|
||||
public boolean execute(@NotNull final CommandSender sender,
|
||||
@NotNull final String commandLabel,
|
||||
@NotNull final String[] args)
|
||||
@NotNull final String commandLabel,
|
||||
@NotNull final String[] args)
|
||||
{
|
||||
if (sender instanceof ConsoleCommandSender && noConsole)
|
||||
{
|
||||
@ -87,8 +103,7 @@ public class BukkitDelegate extends Command implements PluginIdentifiableCommand
|
||||
{
|
||||
command.getBaseMethod()
|
||||
.invoke(command, sender);
|
||||
}
|
||||
catch (Exception ex)
|
||||
} catch (Exception ex)
|
||||
{
|
||||
FreedomLogger.getLogger("Patchwork")
|
||||
.error(ex);
|
||||
@ -101,8 +116,8 @@ public class BukkitDelegate extends Command implements PluginIdentifiableCommand
|
||||
}
|
||||
|
||||
private void processSubCommands(final @NotNull String @NotNull [] args,
|
||||
final CommandSender sender, final ContextProvider provider,
|
||||
final Subcommand node)
|
||||
final CommandSender sender, final ContextProvider provider,
|
||||
final Subcommand node)
|
||||
{
|
||||
final Class<?>[] argTypes = node.args();
|
||||
if (argTypes.length != args.length)
|
||||
@ -126,8 +141,7 @@ public class BukkitDelegate extends Command implements PluginIdentifiableCommand
|
||||
command.getSubcommands()
|
||||
.get(node)
|
||||
.invoke(command, sender, objects);
|
||||
}
|
||||
catch (Exception ex)
|
||||
} catch (Exception ex)
|
||||
{
|
||||
FreedomLogger.getLogger("Patchwork")
|
||||
.error(ex);
|
||||
@ -159,16 +173,16 @@ public class BukkitDelegate extends Command implements PluginIdentifiableCommand
|
||||
.map(World::getName)
|
||||
.toList());
|
||||
case "%number%" -> results.addAll(List.of(
|
||||
"0",
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"4",
|
||||
"5",
|
||||
"6",
|
||||
"7",
|
||||
"8",
|
||||
"9"));
|
||||
"0",
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"4",
|
||||
"5",
|
||||
"6",
|
||||
"7",
|
||||
"8",
|
||||
"9"));
|
||||
case "%location%" -> results.add("world,x,y,z");
|
||||
default -> results.add(p);
|
||||
}
|
||||
|
@ -1,17 +1,39 @@
|
||||
package me.totalfreedom.command;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandMap;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
/**
|
||||
* Handles the registration of commands.
|
||||
* The plugin which initializes this class should be the plugin that is registering the commands.
|
||||
*/
|
||||
public class CommandHandler
|
||||
{
|
||||
/**
|
||||
* The plugin that this command handler is registered to.
|
||||
* <br>
|
||||
* This should be the plugin instance which is trying to register the commands.
|
||||
*/
|
||||
private final JavaPlugin plugin;
|
||||
|
||||
/**
|
||||
* Creates a new command handler.
|
||||
*
|
||||
* @param plugin The plugin that this command handler is registered to.
|
||||
*/
|
||||
public CommandHandler(final JavaPlugin plugin)
|
||||
{
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a command. This method will automatically delegate the command information to the Bukkit API and
|
||||
* register with the {@link CommandMap}.
|
||||
*
|
||||
* @param command The command to register.
|
||||
* @param <T> The type of the command.
|
||||
*/
|
||||
public <T extends Commander> void registerCommand(final T command)
|
||||
{
|
||||
final BukkitDelegate delegate = new BukkitDelegate(command);
|
||||
|
@ -17,15 +17,60 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* This is the base command class which should be extended when creating a new command. Commands must be annotated with
|
||||
* the {@link Info} and {@link Permissive} annotations in order to be properly registered with the
|
||||
* {@link CommandHandler}.
|
||||
* <p>
|
||||
* One single method can be annotated with the {@link Base} annotation to specify that method should be called when the
|
||||
* command is executed without any arguments.
|
||||
* <br>
|
||||
* You are allowed to have as many methods as you want which are annotated with the {@link Subcommand} annotation. These
|
||||
* methods will be called when the command is executed with the specified subcommand.
|
||||
* <br>
|
||||
* You are also allowed to use multiple {@link Completion} annotations per method to define multiple tab completions for
|
||||
* a single subcommand. This would be useful in the case where you would like to include specific completion cases, but
|
||||
* also support basic String completion cases.
|
||||
* <br>
|
||||
* When creating {@link Completion} annotations, you only need to register arguments a single time per class. For more
|
||||
* information, see {@link Subcommand}.
|
||||
*/
|
||||
public abstract class Commander
|
||||
{
|
||||
/**
|
||||
* The plugin which owns this command.
|
||||
*/
|
||||
private final JavaPlugin plugin;
|
||||
/**
|
||||
* The {@link Info} annotation for this command.
|
||||
*/
|
||||
private final Info info;
|
||||
/**
|
||||
* The {@link Permissive} annotation for this command.
|
||||
*/
|
||||
private final Permissive perms;
|
||||
/**
|
||||
* A map of all subcommands and their related methods for this command.
|
||||
*/
|
||||
private final Map<Subcommand, Method> subcommands;
|
||||
/**
|
||||
* A set of all {@link Completion} annotations for this command.
|
||||
*/
|
||||
private final Set<Completion> completions;
|
||||
/**
|
||||
* The method which should be called when the command is executed without any arguments.
|
||||
*/
|
||||
private final Method baseMethod;
|
||||
|
||||
/**
|
||||
* Initializes this command object. The provided {@link JavaPlugin} should be the plugin which contains the
|
||||
* command.
|
||||
* <p>
|
||||
* This constructor will automatically register all subcommands and completions for this command. It will also
|
||||
* automatically infer all required information from the provided {@link Info} and {@link Permissive} annotations.
|
||||
*
|
||||
* @param plugin The plugin which contains this command.
|
||||
*/
|
||||
protected Commander(final @NotNull JavaPlugin plugin)
|
||||
{
|
||||
this.info = this.getClass()
|
||||
@ -44,7 +89,7 @@ public abstract class Commander
|
||||
.filter(m -> m.isAnnotationPresent(Base.class))
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new RuntimeException(
|
||||
"Base annotation present but no method found."));
|
||||
"Base annotation present but no method found."));
|
||||
|
||||
this.baseMethod = method;
|
||||
} else
|
||||
@ -55,14 +100,17 @@ public abstract class Commander
|
||||
registerAnnotations();
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers all subcommands and completions for this command.
|
||||
*/
|
||||
private void registerAnnotations()
|
||||
{
|
||||
Stream.of(this.getClass()
|
||||
.getDeclaredMethods())
|
||||
.filter(method -> method.isAnnotationPresent(Subcommand.class))
|
||||
.forEach(method -> this.subcommands.put(
|
||||
method.getDeclaredAnnotation(Subcommand.class),
|
||||
method));
|
||||
method.getDeclaredAnnotation(Subcommand.class),
|
||||
method));
|
||||
|
||||
List.of(this.getClass()
|
||||
.getDeclaredAnnotationsByType(Completion.class))
|
||||
@ -70,36 +118,66 @@ public abstract class Commander
|
||||
.forEach(completions::add);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the method which should be called when the command is executed without any arguments.
|
||||
* <br>
|
||||
* This method will return null if the command does not have a base method.
|
||||
*
|
||||
* @return The base method for this command, or null if the command does not have a base method.
|
||||
*/
|
||||
@Nullable
|
||||
public Method getBaseMethod()
|
||||
{
|
||||
return baseMethod;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link Info} annotation for this command.
|
||||
* <br>
|
||||
* This method will never return null as this annotation is required for the command to be registered.
|
||||
*
|
||||
* @return The {@link Info} annotation for this command.
|
||||
*/
|
||||
@NotNull
|
||||
Info getInfo()
|
||||
{
|
||||
return this.info;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link Permissive} annotation for this command.
|
||||
* <br>
|
||||
* This method will never return null as this annotation is required for the command to be registered.
|
||||
*
|
||||
* @return The {@link Permissive} annotation for this command.
|
||||
*/
|
||||
@NotNull
|
||||
Permissive getPerms()
|
||||
{
|
||||
return this.perms;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The plugin which owns this command.
|
||||
*/
|
||||
@NotNull
|
||||
public JavaPlugin getPlugin()
|
||||
{
|
||||
return this.plugin;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A map of all subcommands and their related methods for this command.
|
||||
*/
|
||||
@NotNull
|
||||
Map<Subcommand, Method> getSubcommands()
|
||||
{
|
||||
return this.subcommands;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A set of all {@link Completion} annotations for this command.
|
||||
*/
|
||||
@Nullable
|
||||
Set<Completion> getCompletions()
|
||||
{
|
||||
|
@ -6,12 +6,26 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Represents a tab completion for a command.
|
||||
* <p>
|
||||
* This will register at class level, and does not retain method information. As a result, you only need to register the
|
||||
* arguments a single time, and it will always be used in tab completions.
|
||||
*/
|
||||
@Target(ElementType.METHOD)
|
||||
@Repeatable(Completions.class)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Completion
|
||||
{
|
||||
/**
|
||||
* An array of possible arguments for this particular index, represented by {@link #index()}.
|
||||
*
|
||||
* @return An array of possible arguments for tab completion.
|
||||
*/
|
||||
String[] args();
|
||||
|
||||
/**
|
||||
* @return The index in which these arguments should be shown.
|
||||
*/
|
||||
int index();
|
||||
}
|
||||
|
@ -5,9 +5,18 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* A marker interface which represents a holder for multiple {@link Completion} annotations.
|
||||
* <br>
|
||||
* <u>This interface is <span color=#ff0000><b>NOT</b></span> intended for implementation and should
|
||||
* <span color=#ff0000><b>NOT</b></span> be used.</u>
|
||||
*/
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Completions
|
||||
{
|
||||
/**
|
||||
* @return The {@link Completion} annotations.
|
||||
*/
|
||||
Completion[] value();
|
||||
}
|
||||
|
@ -3,14 +3,40 @@ package me.totalfreedom.command.annotation;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
/**
|
||||
* This interface holds the information for each command. This annotation defines the command's name, description,
|
||||
* usage, and aliases. Commands <b><u>must</u></b> have this annotation present to be registered with the handler.
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Info
|
||||
{
|
||||
/**
|
||||
* Technically, this is the only required value you must supply yourself.
|
||||
* However, it is HIGHLY recommended you supply the other optional values as well,
|
||||
* for better customization of your command.
|
||||
*
|
||||
* @return The command's name.
|
||||
*/
|
||||
String name();
|
||||
|
||||
/**
|
||||
* By default, this is set to <u>"This is the default command description."</u>
|
||||
*
|
||||
* @return The command's description.
|
||||
*/
|
||||
String description() default "This is the default command description.";
|
||||
|
||||
/**
|
||||
* By default, this is set to <u>"/<command>"</u>
|
||||
*
|
||||
* @return The command's usage.
|
||||
*/
|
||||
String usage() default "/<command>";
|
||||
|
||||
/**
|
||||
* By default, this returns an empty array.
|
||||
*
|
||||
* @return The command's aliases.
|
||||
*/
|
||||
String[] aliases() default {};
|
||||
}
|
||||
|
@ -3,12 +3,31 @@ package me.totalfreedom.command.annotation;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
/**
|
||||
* This annotation holds the permission information for each command. This annotation defines the command's permission,
|
||||
* whether it is only for players, and the message to send if the sender does not have permission to use the command.
|
||||
* <p>
|
||||
* Classes <u><b>MUST</b></u> have this annotation present to be registered with the handler.
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Permissive
|
||||
{
|
||||
/**
|
||||
* @return The command's permission.
|
||||
*/
|
||||
String perm();
|
||||
|
||||
/**
|
||||
* By default, this is set to <u>false</u>.
|
||||
*
|
||||
* @return True if the command is only for players, false otherwise.
|
||||
*/
|
||||
boolean onlyPlayers() default false;
|
||||
|
||||
/**
|
||||
* By default, this is set to <u>"You do not have permission to use this command."</u>
|
||||
*
|
||||
* @return The message to send if the sender does not have permission to use the command.
|
||||
*/
|
||||
String noPerms() default "You do not have permission to use this command.";
|
||||
}
|
||||
|
@ -1,15 +1,41 @@
|
||||
package me.totalfreedom.command.annotation;
|
||||
|
||||
import me.totalfreedom.command.CommandHandler;
|
||||
import me.totalfreedom.provider.ContextProvider;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* This annotation should be used to mark methods as subcommand methods.
|
||||
* Subcommand methods can have custom arguments (current supported arguments can be found in the {@link ContextProvider}),
|
||||
* and can also have a custom permission. These subcommands can also be annotated with {@link Completions} to provide
|
||||
* tab completions for the subcommand. The subcommand method must be public, and must be in a class that is registered
|
||||
* with the {@link CommandHandler}.
|
||||
* <br>
|
||||
* Tab completions with the {@link Completions} annotation are only supported for subcommands. When registering
|
||||
* completions, you only need to define the completion arguments a single time. If there are other methods which
|
||||
* function as optional additional arguments for the subcommand, the previously registered arguments will still be
|
||||
* present when the user does their tab completion.
|
||||
* <br>
|
||||
* For example, if you have a subcommand method with the arguments {@code (Player, String)}, and another method which
|
||||
* has the arguments {@code (Player, String, String)}, the tab completions for the second method will still have the
|
||||
* {@code Player} and {@code String} arguments registered from the first method. You will only need to provide a
|
||||
* {@link Completion} for the additional 3rd argument.
|
||||
*/
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Subcommand
|
||||
{
|
||||
/**
|
||||
* @return The permission to use when executing this subcommand.
|
||||
*/
|
||||
String permission();
|
||||
|
||||
/**
|
||||
* @return The arguments, as classes, to use when registering this subcommand.
|
||||
*/
|
||||
Class<?>[] args() default {};
|
||||
}
|
||||
|
@ -1,36 +1,132 @@
|
||||
package me.totalfreedom.config;
|
||||
|
||||
import me.totalfreedom.api.Context;
|
||||
import me.totalfreedom.provider.ContextProvider;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Represents a configuration file of any type.
|
||||
*/
|
||||
public interface Configuration
|
||||
{
|
||||
/**
|
||||
* Saves the configuration to the file.
|
||||
*
|
||||
* @throws IOException If the operation cannot be completed.
|
||||
*/
|
||||
void save() throws IOException;
|
||||
|
||||
/**
|
||||
* Loads the configuration from the file.
|
||||
*
|
||||
* @throws IOException If the operation cannot be completed.
|
||||
*/
|
||||
void load() throws IOException;
|
||||
|
||||
/**
|
||||
* @return The name of the file.
|
||||
*/
|
||||
String getFileName();
|
||||
|
||||
/**
|
||||
* @return The actual Configuration {@link File}.
|
||||
*/
|
||||
File getConfigurationFile();
|
||||
|
||||
/**
|
||||
* Gets a String object from the associated path.
|
||||
*
|
||||
* @param path The path to get the String from.
|
||||
* @return The String object.
|
||||
*/
|
||||
String getString(String path);
|
||||
|
||||
/**
|
||||
* Gets a Boolean object from the associated path.
|
||||
*
|
||||
* @param path The path to get the Boolean from.
|
||||
* @return The Boolean object.
|
||||
*/
|
||||
Boolean getBoolean(String path);
|
||||
|
||||
/**
|
||||
* Gets a List object from the associated path. This method will use {@link Context}s and the
|
||||
* {@link ContextProvider} to get the object types in the list. If the objects cannot be inferred, the method will
|
||||
* return a list of generic {@link Object}s.
|
||||
*
|
||||
* @param path The path to get the List from.
|
||||
* @param <T> The type of the objects in the list.
|
||||
* @return The List object.
|
||||
*/
|
||||
<T> List<T> getList(String path);
|
||||
|
||||
/**
|
||||
* Gets a List object from the associated path. The List that is returned will be the String values which are stored
|
||||
* within the configuration file at the given path.
|
||||
*
|
||||
* @param path The path to get the List from.
|
||||
* @return The List object.
|
||||
*/
|
||||
List<String> getStringList(String path);
|
||||
|
||||
/**
|
||||
* Gets an Integer from the associated path.
|
||||
*
|
||||
* @param path The path to get the Integer from.
|
||||
* @return The Integer object.
|
||||
*/
|
||||
Integer getInt(String path);
|
||||
|
||||
/**
|
||||
* Gets a Long from the associated path.
|
||||
*
|
||||
* @param path The path to get the Long from.
|
||||
* @return The Long object.
|
||||
*/
|
||||
Long getLong(String path);
|
||||
|
||||
/**
|
||||
* Gets a Double from the associated path.
|
||||
*
|
||||
* @param path The path to get the Double from.
|
||||
* @return The Double object.
|
||||
*/
|
||||
Double getDouble(String path);
|
||||
|
||||
/**
|
||||
* Sets the value at the given path to the given value.
|
||||
*
|
||||
* @param path The path to set the value at.
|
||||
* @param value The value to set.
|
||||
* @param <T> The type of the value.
|
||||
*/
|
||||
<T> void set(String path, T value);
|
||||
|
||||
<T> T get(String path, Class<T> type);
|
||||
/**
|
||||
* Gets the value at the given path as the given type.
|
||||
* <p>
|
||||
* This method will use {@link Context}s and the {@link ContextProvider} to get the object type. If the object type
|
||||
* cannot be inferred, the method will return a generic {@link Object}.
|
||||
*
|
||||
* @param path The path to get the value from.
|
||||
* @param <T> The type of the value.
|
||||
* @return The value at the given path.
|
||||
*/
|
||||
<T> T get(String path);
|
||||
|
||||
<T> T getOrDefault(String path, Class<T> type, T fallback);
|
||||
/**
|
||||
* Gets the value at the given path as the given type.
|
||||
* <p>
|
||||
* This method will use {@link Context}s and the {@link ContextProvider} to get the object type. If the object type
|
||||
* cannot be inferred, the method will return the given fallback value.
|
||||
*
|
||||
* @param path The path to get the value from.
|
||||
* @param fallback The fallback value to return if the value at the given path is null.
|
||||
* @param <T> The type of the value.
|
||||
* @return The value at the given path.
|
||||
*/
|
||||
<T> T getOrDefault(String path, T fallback);
|
||||
}
|
@ -5,20 +5,40 @@ import me.totalfreedom.config.Configuration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A registry for all the configurations.
|
||||
*/
|
||||
public class ConfigRegistry
|
||||
{
|
||||
/**
|
||||
* A map of all the configurations.
|
||||
*/
|
||||
private final Map<String, Configuration> configurationList = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Registers a configuration.
|
||||
* @param name The name of the configuration.
|
||||
* @param configuration The configuration.
|
||||
*/
|
||||
public void register(final String name, final Configuration configuration)
|
||||
{
|
||||
configurationList.put(name, configuration);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters a configuration.
|
||||
* @param name The name of the configuration.
|
||||
*/
|
||||
public void unregister(final String name)
|
||||
{
|
||||
configurationList.remove(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a configuration.
|
||||
* @param name The name of the configuration.
|
||||
* @return The configuration.
|
||||
*/
|
||||
public Configuration getConfiguration(final String name)
|
||||
{
|
||||
return configurationList.get(name);
|
||||
|
@ -6,25 +6,49 @@ import me.totalfreedom.provider.EventProvider;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A registry for {@link FEvent}s.
|
||||
*/
|
||||
public class EventRegistry
|
||||
{
|
||||
/**
|
||||
* The list of events.
|
||||
*/
|
||||
private final List<FEvent> events;
|
||||
|
||||
/**
|
||||
* Creates a new event registry.
|
||||
*/
|
||||
public EventRegistry()
|
||||
{
|
||||
this.events = new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers an event.
|
||||
* @param event The event to register.
|
||||
*/
|
||||
public void register(final FEvent event)
|
||||
{
|
||||
this.events.add(event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters an event.
|
||||
* @param event The event to unregister.
|
||||
*/
|
||||
public void unregister(final FEvent event)
|
||||
{
|
||||
this.events.remove(event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an {@link EventProvider} for the specified event class which contains the actual {@link FEvent} instance.
|
||||
*
|
||||
* @param clazz The event class.
|
||||
* @return The event provider.
|
||||
* @param <T> The event type.
|
||||
*/
|
||||
public <T extends FEvent> EventProvider<T> getEvent(final Class<T> clazz)
|
||||
{
|
||||
for (final FEvent event : this.events)
|
||||
|
@ -6,25 +6,49 @@ import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A registry for {@link Group}s.
|
||||
*/
|
||||
public class GroupRegistry
|
||||
{
|
||||
/**
|
||||
* The list of groups.
|
||||
*/
|
||||
private final List<Group> groups;
|
||||
|
||||
/**
|
||||
* Creates a new group registry.
|
||||
*/
|
||||
public GroupRegistry()
|
||||
{
|
||||
this.groups = new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a group.
|
||||
* @param group The group to register.
|
||||
* @return {@code true} if the group was registered, {@code false} otherwise.
|
||||
*/
|
||||
public boolean registerGroup(final Group group)
|
||||
{
|
||||
return groups.add(group);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters a group.
|
||||
* @param group The group to unregister.
|
||||
* @return {@code true} if the group was unregistered, {@code false} otherwise.
|
||||
*/
|
||||
public boolean unregisterGroup(final Group group)
|
||||
{
|
||||
return groups.remove(group);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a group by name.
|
||||
* @param name The name of the group.
|
||||
* @return The group, or {@code null} if no group was found.
|
||||
*/
|
||||
public Group getGroup(final String name)
|
||||
{
|
||||
final PlainTextComponentSerializer s = PlainTextComponentSerializer.plainText();
|
||||
@ -39,6 +63,9 @@ public class GroupRegistry
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The list of groups.
|
||||
*/
|
||||
public List<Group> getGroups()
|
||||
{
|
||||
return groups;
|
||||
|
@ -6,15 +6,29 @@ import org.bukkit.plugin.java.JavaPlugin;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A registry for modules.
|
||||
*/
|
||||
public class ModuleRegistry
|
||||
{
|
||||
/**
|
||||
* The list of modules.
|
||||
*/
|
||||
private final List<JavaPlugin> plugins;
|
||||
|
||||
/**
|
||||
* Creates a new module registry.
|
||||
*/
|
||||
public ModuleRegistry()
|
||||
{
|
||||
this.plugins = new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a module to the registry.
|
||||
*
|
||||
* @param plugin The module to add.
|
||||
*/
|
||||
public void addModule(final JavaPlugin plugin)
|
||||
{
|
||||
if (this.plugins.contains(plugin))
|
||||
@ -24,19 +38,30 @@ public class ModuleRegistry
|
||||
this.plugins.add(plugin);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a module from the registry.
|
||||
*
|
||||
* @param plugin The module to remove.
|
||||
*/
|
||||
public void removeModule(final JavaPlugin plugin)
|
||||
{
|
||||
this.plugins.remove(plugin);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends JavaPlugin> ModuleProvider<T> getModule(final Class<T> clazz)
|
||||
/**
|
||||
* Gets a module from the registry wrapped in a {@link ModuleProvider}.
|
||||
*
|
||||
* @param clazz The class of the module.
|
||||
* @param <T> The type of the module.
|
||||
* @return The module.
|
||||
*/
|
||||
public <T extends JavaPlugin> ModuleProvider<T> getProvider(final Class<T> clazz)
|
||||
{
|
||||
for (final JavaPlugin plugin : plugins)
|
||||
{
|
||||
if (clazz.isInstance(plugin))
|
||||
{
|
||||
return () -> (T) plugin;
|
||||
return () -> clazz.cast(plugin);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,39 +7,91 @@ import org.bukkit.entity.Player;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A registry for {@link UserData} objects.
|
||||
*/
|
||||
public class UserRegistry
|
||||
{
|
||||
/**
|
||||
* A map of {@link User} objects to {@link UserData} objects.
|
||||
*/
|
||||
private final Map<User, UserData> userDataMap;
|
||||
|
||||
/**
|
||||
* Creates a new {@link UserRegistry}.
|
||||
*/
|
||||
public UserRegistry()
|
||||
{
|
||||
this.userDataMap = new HashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link UserData} object for the given {@link User}.
|
||||
*
|
||||
* @param user The {@link User} to get the {@link UserData} for.
|
||||
* @return The {@link UserData} object for the given {@link User}.
|
||||
*/
|
||||
public UserData getUserData(final User user)
|
||||
{
|
||||
return userDataMap.get(user);
|
||||
}
|
||||
|
||||
public UserData fromPlayer(final Player player) {
|
||||
/**
|
||||
* Gets the {@link UserData} object for the given {@link Player}.
|
||||
*/
|
||||
public UserData fromPlayer(final Player player)
|
||||
{
|
||||
return userDataMap.entrySet()
|
||||
.stream()
|
||||
.filter(entry -> entry.getKey().getUniqueId().equals(player.getUniqueId()))
|
||||
.filter(entry -> entry.getKey()
|
||||
.getUniqueId()
|
||||
.equals(player.getUniqueId()))
|
||||
.findFirst()
|
||||
.map(Map.Entry::getValue)
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link User} object for the given {@link Player}.
|
||||
*
|
||||
* @param player The {@link Player} to get the {@link User} for.
|
||||
* @return The {@link User} object for the given {@link Player}.
|
||||
*/
|
||||
public User getUser(final Player player)
|
||||
{
|
||||
return userDataMap.entrySet()
|
||||
.stream()
|
||||
.filter(entry -> entry.getKey()
|
||||
.getUniqueId()
|
||||
.equals(player.getUniqueId()))
|
||||
.findFirst()
|
||||
.map(Map.Entry::getKey)
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the given {@link User} and {@link UserData} objects.
|
||||
* @param user The {@link User} to register.
|
||||
* @param userData The {@link UserData} to register.
|
||||
*/
|
||||
public void registerUserData(final User user, final UserData userData)
|
||||
{
|
||||
userDataMap.put(user, userData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters the given {@link User} and {@link UserData} objects.
|
||||
* @param user The {@link User} to unregister.
|
||||
*/
|
||||
public void unregisterUserData(final User user)
|
||||
{
|
||||
userDataMap.remove(user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the map of {@link User} objects to {@link UserData} objects.
|
||||
* @return The map of {@link User} objects to {@link UserData} objects.
|
||||
*/
|
||||
public Map<User, UserData> getUserDataMap()
|
||||
{
|
||||
return userDataMap;
|
||||
|
@ -15,14 +15,34 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Represents a menu that can be opened by a player.
|
||||
*/
|
||||
public abstract class AbstractMenu
|
||||
{
|
||||
/**
|
||||
* A map of all menus by their UUID.
|
||||
*/
|
||||
private static final Map<UUID, AbstractMenu> invByUUID = new HashMap<>();
|
||||
/**
|
||||
* A map of all open menus by the player's UUID.
|
||||
*/
|
||||
private static final Map<UUID, UUID> openInvs = new HashMap<>();
|
||||
private final Map<Integer, ClickAction> actionMap;
|
||||
/**
|
||||
* The displayable that represents this menu.
|
||||
*/
|
||||
private final Displayable displayable;
|
||||
/**
|
||||
* The UUID of the displayable that represents this menu.
|
||||
*/
|
||||
private final UUID displayableUUID;
|
||||
|
||||
/**
|
||||
* Creates a new menu with the specified size.
|
||||
*
|
||||
* @param size The size of the menu.
|
||||
*/
|
||||
protected AbstractMenu(final int size)
|
||||
{
|
||||
actionMap = new HashMap<>();
|
||||
@ -32,26 +52,48 @@ public abstract class AbstractMenu
|
||||
invByUUID.put(getDisplayableUUID(), this);
|
||||
}
|
||||
|
||||
public UUID getDisplayableUUID()
|
||||
{
|
||||
return displayableUUID;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A map of all menus by their UUID.
|
||||
*/
|
||||
public static Map<UUID, AbstractMenu> getInvByUUID()
|
||||
{
|
||||
return invByUUID;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A map of all open menus by the player's UUID.
|
||||
*/
|
||||
public static Map<UUID, UUID> getOpenInvs()
|
||||
{
|
||||
return openInvs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The displayable UUID of this menu.
|
||||
*/
|
||||
public UUID getDisplayableUUID()
|
||||
{
|
||||
return displayableUUID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the item at the specified slot.
|
||||
*
|
||||
* @param slot The slot to set the item at.
|
||||
* @param stack The item to set.
|
||||
*/
|
||||
public void setItem(final int slot, final @NotNull ItemStack stack)
|
||||
{
|
||||
setItem(slot, stack, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the item at the specified slot.
|
||||
*
|
||||
* @param slot The slot to set the item at.
|
||||
* @param stack The item to set.
|
||||
* @param action The action to perform when the item is clicked.
|
||||
*/
|
||||
public void setItem(final int slot, final @NotNull ItemStack stack, final @Nullable ClickAction action)
|
||||
{
|
||||
getDisplayable().setItem(slot, stack);
|
||||
@ -61,17 +103,28 @@ public abstract class AbstractMenu
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The displayable that represents this menu.
|
||||
*/
|
||||
public Displayable getDisplayable()
|
||||
{
|
||||
return displayable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens this menu for the specified player.
|
||||
*
|
||||
* @param player The player to open the menu for.
|
||||
*/
|
||||
public void open(final @NotNull Player player)
|
||||
{
|
||||
player.openInventory(getDisplayable());
|
||||
openInvs.put(player.getUniqueId(), getDisplayableUUID());
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes this menu.
|
||||
*/
|
||||
public void delete()
|
||||
{
|
||||
Bukkit.getOnlinePlayers()
|
||||
@ -87,24 +140,47 @@ public abstract class AbstractMenu
|
||||
invByUUID.remove(getDisplayableUUID());
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes this menu for the specified player.
|
||||
*
|
||||
* @param player The player to close the menu for.
|
||||
*/
|
||||
public void close(final @NotNull Player player)
|
||||
{
|
||||
player.closeInventory();
|
||||
openInvs.remove(player.getUniqueId());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A map of all actions by their slot.
|
||||
*/
|
||||
public Map<Integer, ClickAction> getActions()
|
||||
{
|
||||
return actionMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new item with the specified material and name.
|
||||
*
|
||||
* @param material The material of the item.
|
||||
* @param name The name of the item.
|
||||
* @return The created item.
|
||||
*/
|
||||
public ItemStack newItem(final @NotNull Material material, final @NotNull Component name)
|
||||
{
|
||||
return this.newItem(material, name, new Component[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new item with the specified material, name, and lore.
|
||||
*
|
||||
* @param material The material of the item.
|
||||
* @param name The name of the item.
|
||||
* @param lore The lore of the item.
|
||||
* @return The created item.
|
||||
*/
|
||||
public ItemStack newItem(final @NotNull Material material, final @NotNull Component name,
|
||||
final @NotNull Component... lore)
|
||||
final @NotNull Component... lore)
|
||||
{
|
||||
final ItemStack item = new ItemStack(material, 1);
|
||||
final ItemMeta meta = item.getItemMeta();
|
||||
|
@ -11,65 +11,126 @@ import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* This class is a wrapper for {@link BossBar} objects. It provides some handy methods for changing the boss bar's
|
||||
* properties, displaying the bar to {@link Audience}s, and a {@link BossBarBuilder} to easily create new boss bars.
|
||||
*/
|
||||
public class BossBarDisplay
|
||||
{
|
||||
private BossBar bossBar;
|
||||
|
||||
/**
|
||||
* Creates a new {@link BossBarDisplay} object.
|
||||
*
|
||||
* @param bossBar The {@link BossBar} to wrap.
|
||||
*/
|
||||
public BossBarDisplay(final BossBar bossBar)
|
||||
{
|
||||
this.bossBar = bossBar;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A new {@link BossBarBuilder} object.
|
||||
*/
|
||||
public static BossBarBuilder builder()
|
||||
{
|
||||
return new BossBarBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the boss bar's color.
|
||||
*
|
||||
* @param color The new color.
|
||||
*/
|
||||
public void changeColor(final BossBar.Color color)
|
||||
{
|
||||
this.bossBar.color(color);
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the boss bar's color.
|
||||
*
|
||||
* @param overlay The new overlay.
|
||||
*/
|
||||
public void changeOverlay(final BossBar.Overlay overlay)
|
||||
{
|
||||
this.bossBar.overlay(overlay);
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the boss bar's name using a {@link Component}.
|
||||
*
|
||||
* @param name The new name.
|
||||
*/
|
||||
public void changeName(final Component name)
|
||||
{
|
||||
this.bossBar.name(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the boss bar's name with a String and a {@link TextColor}.
|
||||
*
|
||||
* @param name The new name.
|
||||
* @param color The name color.
|
||||
*/
|
||||
public void changeName(final String name, final TextColor color)
|
||||
{
|
||||
this.bossBar.name(Component.text(name, color));
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the boss bar's name with a String.
|
||||
*
|
||||
* @param name The new name.
|
||||
*/
|
||||
public void changeName(final String name)
|
||||
{
|
||||
this.bossBar.name(Component.text(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows this Boss Bar to the specified {@link Audience}.
|
||||
*
|
||||
* @param audience The {@link Audience} to show the Boss Bar to.
|
||||
*/
|
||||
public void showTo(final Audience audience)
|
||||
{
|
||||
audience.showBossBar(getBossBar());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The {@link BossBar} object that this class wraps.
|
||||
*/
|
||||
public BossBar getBossBar()
|
||||
{
|
||||
return this.bossBar;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link BossBar} object that this class wraps.
|
||||
*
|
||||
* @param bossBar The new {@link BossBar} object.
|
||||
*/
|
||||
public void setBossBar(final BossBar bossBar)
|
||||
{
|
||||
this.bossBar = bossBar;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hides this Boss Bar from the specified {@link Audience}.
|
||||
*
|
||||
* @param audience The {@link Audience} to hide the Boss Bar from.
|
||||
*/
|
||||
public void hideFrom(final Audience audience)
|
||||
{
|
||||
audience.hideBossBar(getBossBar());
|
||||
}
|
||||
|
||||
/**
|
||||
* Increments the Bar's progress by the specified amount. This must be a range from 0 to 100.
|
||||
*
|
||||
* @param progress The new progress.
|
||||
*/
|
||||
public void incrementProgress(final @Range(from = 0, to = 100) float progress)
|
||||
{
|
||||
final float currentProgress = this.bossBar.progress();
|
||||
@ -79,6 +140,11 @@ public class BossBarDisplay
|
||||
else this.bossBar.progress(newProgress);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrements the Bar's progress by the specified amount. This must be a range from 0 to 100.
|
||||
*
|
||||
* @param progress The new progress.
|
||||
*/
|
||||
public void decrementProgress(final @Range(from = 0, to = 100) float progress)
|
||||
{
|
||||
final float currentProgress = this.bossBar.progress();
|
||||
@ -88,40 +154,80 @@ public class BossBarDisplay
|
||||
else this.bossBar.progress(newProgress);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Bar's progress to the maximum amount (full bar).
|
||||
*/
|
||||
public void maximumProgress()
|
||||
{
|
||||
this.bossBar.progress(1.0F);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Bar's progress to half of the maximum amount (half bar).
|
||||
*/
|
||||
public void halfProgress()
|
||||
{
|
||||
this.bossBar.progress(0.5F);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Bar's progress to the minimum amount (empty bar).
|
||||
*/
|
||||
public void minimumProgress()
|
||||
{
|
||||
this.bossBar.progress(0.0F);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows this Boss Bar to the specified {@link ForwardingAudience}.
|
||||
*
|
||||
* @param forwardingAudience The {@link ForwardingAudience} to show the Boss Bar to.
|
||||
*/
|
||||
public void showForwarded(final ForwardingAudience forwardingAudience)
|
||||
{
|
||||
forwardingAudience.showBossBar(getBossBar());
|
||||
}
|
||||
|
||||
/**
|
||||
* Hides this Boss Bar from the specified {@link ForwardingAudience}.
|
||||
*
|
||||
* @param forwardingAudience The {@link ForwardingAudience} to hide the Boss Bar from.
|
||||
*/
|
||||
public void hideForwarded(final ForwardingAudience forwardingAudience)
|
||||
{
|
||||
forwardingAudience.hideBossBar(getBossBar());
|
||||
}
|
||||
|
||||
private static final class BossBarBuilder
|
||||
/**
|
||||
* A Builder class for {@link BossBar} objects.
|
||||
*/
|
||||
public static final class BossBarBuilder
|
||||
{
|
||||
/**
|
||||
* The flags that this Boss Bar will have.
|
||||
*/
|
||||
private final Set<BossBar.Flag> flags = new HashSet<>();
|
||||
/**
|
||||
* The Boss Bar's name.
|
||||
*/
|
||||
private Component name;
|
||||
/**
|
||||
* The Boss Bar's color.
|
||||
*/
|
||||
private BossBar.Color color;
|
||||
/**
|
||||
* The Boss Bar's overlay.
|
||||
*/
|
||||
private BossBar.Overlay overlay;
|
||||
/**
|
||||
* The Boss Bar's progress.
|
||||
*/
|
||||
@Range(from = 0, to = 1)
|
||||
private float progress;
|
||||
|
||||
/**
|
||||
* Initializes this Builder object.
|
||||
*/
|
||||
public BossBarBuilder()
|
||||
{
|
||||
this.name = Component.empty();
|
||||
@ -130,72 +236,134 @@ public class BossBarDisplay
|
||||
this.progress = 0.0F;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of the boss bar.
|
||||
*
|
||||
* @param name The name of the boss bar.
|
||||
* @return The builder.
|
||||
*/
|
||||
public BossBarBuilder setName(final Component name)
|
||||
{
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of the boss bar using a String and a {@link TextColor}.
|
||||
*
|
||||
* @param name The name of the boss bar.
|
||||
* @param color The color of the boss bar.
|
||||
* @return The builder.
|
||||
*/
|
||||
public BossBarBuilder setName(final String name, final TextColor color)
|
||||
{
|
||||
this.name = Component.text(name, color);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of the boss bar using a String.
|
||||
*
|
||||
* @param name The name of the boss bar.
|
||||
* @return The builder.
|
||||
*/
|
||||
public BossBarBuilder setName(final String name)
|
||||
{
|
||||
this.name = Component.text(name);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a flag to the boss bar.
|
||||
* @param flag The flag to add.
|
||||
* @return The builder.
|
||||
*/
|
||||
public BossBarBuilder addFlag(final BossBar.Flag flag)
|
||||
{
|
||||
this.flags.add(flag);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds multiple flags to the boss bar.
|
||||
* @param flags The flags to add.
|
||||
* @return The builder.
|
||||
*/
|
||||
public BossBarBuilder addFlags(final BossBar.Flag... flags)
|
||||
{
|
||||
this.flags.addAll(List.of(flags));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a flag from the boss bar.
|
||||
* @param flag The flag to remove.
|
||||
* @return The builder.
|
||||
*/
|
||||
public BossBarBuilder removeFlag(final BossBar.Flag flag)
|
||||
{
|
||||
this.flags.remove(flag);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes multiple flags from the boss bar.
|
||||
* @param flags The flags to remove.
|
||||
* @return The builder.
|
||||
*/
|
||||
public BossBarBuilder removeFlags(final BossBar.Flag... flags)
|
||||
{
|
||||
this.flags.removeAll(List.of(flags));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all flags from the boss bar.
|
||||
* @return The builder.
|
||||
*/
|
||||
public BossBarBuilder clearFlags()
|
||||
{
|
||||
this.flags.clear();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the color of the boss bar.
|
||||
* @param color The color of the boss bar.
|
||||
* @return The builder.
|
||||
*/
|
||||
public BossBarBuilder setColor(final BossBar.Color color)
|
||||
{
|
||||
this.color = color;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the overlay of the boss bar.
|
||||
* @param overlay The overlay of the boss bar.
|
||||
* @return The builder.
|
||||
*/
|
||||
public BossBarBuilder setOverlay(final BossBar.Overlay overlay)
|
||||
{
|
||||
this.overlay = overlay;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the progress of the boss bar. This must satisfy {@code 0 <= progress <= 100}.
|
||||
* @param progress The progress of the boss bar.
|
||||
* @return The builder.
|
||||
*/
|
||||
public BossBarBuilder setProgress(final @Range(from = 0, to = 100) float progress)
|
||||
{
|
||||
this.progress = progress / 100.0F;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the boss bar.
|
||||
* @return The {@link BossBar}.
|
||||
*/
|
||||
public BossBar build()
|
||||
{
|
||||
return BossBar.bossBar(this.name, this.progress, this.color, this.overlay, this.flags);
|
||||
|
@ -0,0 +1,40 @@
|
||||
package me.totalfreedom.display;
|
||||
|
||||
import me.totalfreedom.service.Task;
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
public class BossBarTimer extends Task
|
||||
{
|
||||
private final BossBarDisplay bossBarDisplay;
|
||||
private final Duration duration;
|
||||
private double seconds = 0;
|
||||
|
||||
public BossBarTimer(final BossBarDisplay bossBarDisplay, final Duration duration)
|
||||
{
|
||||
super("BossBarTimer", -1L, 20L);
|
||||
this.bossBarDisplay = bossBarDisplay;
|
||||
this.duration = duration;
|
||||
bossBarDisplay.minimumProgress();
|
||||
bossBarDisplay.showTo(Bukkit.getServer());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
if (this.isCancelled()) return;
|
||||
|
||||
if (seconds >= duration.getSeconds())
|
||||
{
|
||||
bossBarDisplay.hideFrom(Bukkit.getServer());
|
||||
this.cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
final float percentage = (float) (seconds / duration.getSeconds()) * 100L;
|
||||
bossBarDisplay.incrementProgress(percentage);
|
||||
seconds++;
|
||||
}
|
||||
}
|
@ -2,8 +2,15 @@ package me.totalfreedom.display;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
/**
|
||||
* Represents an action to be performed when a player clicks on an inventory slot in the respective {@link AbstractMenu}.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface ClickAction
|
||||
{
|
||||
/**
|
||||
* Called when a player clicks on an inventory slot in the respective {@link AbstractMenu}.
|
||||
* @param player The player who clicked.
|
||||
*/
|
||||
void onClick(final Player player);
|
||||
}
|
||||
|
@ -15,12 +15,29 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
|
||||
/**
|
||||
* A class that represents an inventory that can be displayed to players. This class also represents the inventory
|
||||
* holder which contains the inventory.
|
||||
*/
|
||||
public final class Displayable implements Inventory, InventoryHolder
|
||||
{
|
||||
|
||||
/**
|
||||
* The size of the inventory. This is always a multiple of 9.
|
||||
*/
|
||||
private final int size;
|
||||
/**
|
||||
* The contents of the inventory.
|
||||
*/
|
||||
private ItemStack[] contents;
|
||||
|
||||
/**
|
||||
* Creates a new Displayable inventory with the given size. You are free to supply any size you want, but it will
|
||||
* always be rounded up to the next multiple of 9. The maximum size allowed is 54. Any number higher than that will
|
||||
* be rounded down to 54.
|
||||
*
|
||||
* @param size The size of the inventory.
|
||||
*/
|
||||
protected Displayable(final int size)
|
||||
{
|
||||
if (size < 1 || size > 54)
|
||||
@ -31,8 +48,8 @@ public final class Displayable implements Inventory, InventoryHolder
|
||||
// If the size is not a multiple of nine, find the difference to the next highest multiple of 9 and make up
|
||||
// the difference.
|
||||
this.size = (size % 9 == 0)
|
||||
? size
|
||||
: size + (9 - size % 9);
|
||||
? size
|
||||
: size + (9 - size % 9);
|
||||
|
||||
this.contents = new ItemStack[size];
|
||||
}
|
||||
@ -82,7 +99,7 @@ public final class Displayable implements Inventory, InventoryHolder
|
||||
|
||||
@Override
|
||||
public @NotNull HashMap<Integer, ItemStack> addItem(final @NotNull ItemStack... items)
|
||||
throws IllegalArgumentException
|
||||
throws IllegalArgumentException
|
||||
{
|
||||
final HashMap<Integer, ItemStack> remainingItems = new HashMap<>();
|
||||
|
||||
@ -121,7 +138,7 @@ public final class Displayable implements Inventory, InventoryHolder
|
||||
|
||||
@Override
|
||||
public @NotNull HashMap<Integer, ItemStack> removeItem(final @NotNull ItemStack... items)
|
||||
throws IllegalArgumentException
|
||||
throws IllegalArgumentException
|
||||
{
|
||||
final HashMap<Integer, ItemStack> removedItems = new HashMap<>();
|
||||
|
||||
@ -154,7 +171,7 @@ public final class Displayable implements Inventory, InventoryHolder
|
||||
if (remainingAmount < item.getAmount())
|
||||
{
|
||||
removedItems.put(removedItems.size(),
|
||||
new ItemStack(item.getType(), item.getAmount() - remainingAmount));
|
||||
new ItemStack(item.getType(), item.getAmount() - remainingAmount));
|
||||
}
|
||||
}
|
||||
|
||||
@ -163,7 +180,7 @@ public final class Displayable implements Inventory, InventoryHolder
|
||||
|
||||
@Override
|
||||
public @NotNull HashMap<Integer, ItemStack> removeItemAnySlot(final @NotNull ItemStack... items)
|
||||
throws IllegalArgumentException
|
||||
throws IllegalArgumentException
|
||||
{
|
||||
return removeItem(items);
|
||||
}
|
||||
@ -294,7 +311,7 @@ public final class Displayable implements Inventory, InventoryHolder
|
||||
|
||||
@Override
|
||||
public @NotNull HashMap<Integer, ? extends ItemStack> all(final @NotNull Material material)
|
||||
throws IllegalArgumentException
|
||||
throws IllegalArgumentException
|
||||
{
|
||||
final HashMap<Integer, ItemStack> matchingItems = new HashMap<>();
|
||||
for (int i = 0; i < size; i++)
|
||||
|
@ -8,14 +8,42 @@ import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.InventoryView;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* A view of a {@link Displayable} inventory.
|
||||
* <p>
|
||||
* This class can be used to display two separate {@link Displayable} objects to the Player.
|
||||
*/
|
||||
public class DisplayableView extends InventoryView
|
||||
{
|
||||
/**
|
||||
* The upper inventory involved in this transaction.
|
||||
*/
|
||||
private final Displayable top;
|
||||
/**
|
||||
* The lower inventory involved in this transaction.
|
||||
*/
|
||||
private final Displayable bottom;
|
||||
/**
|
||||
* The player viewing the inventories involved in this transaction.
|
||||
*/
|
||||
private final Player player;
|
||||
/**
|
||||
* The type of inventory this transaction is for.
|
||||
*/
|
||||
private final InventoryType type;
|
||||
/**
|
||||
* The title of the main inventory involved in this transaction. The main inventory should always be the top
|
||||
* inventory.
|
||||
*/
|
||||
private String title;
|
||||
|
||||
/**
|
||||
* Creates a new DisplayableView.
|
||||
*
|
||||
* @param player The player viewing the inventories involved in this transaction.
|
||||
* @param top The upper inventory involved in this transaction.
|
||||
* @param bottom The lower inventory involved in this transaction.
|
||||
*/
|
||||
public DisplayableView(final Player player, final Displayable top, final Displayable bottom)
|
||||
{
|
||||
this.player = player;
|
||||
@ -55,15 +83,15 @@ public class DisplayableView extends InventoryView
|
||||
return title;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getOriginalTitle()
|
||||
{
|
||||
return FreedomAdventure.toPlainText(type.defaultTitle());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTitle(final @NotNull String title)
|
||||
{
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getOriginalTitle()
|
||||
{
|
||||
return FreedomAdventure.toPlainText(type.defaultTitle());
|
||||
}
|
||||
}
|
||||
|
@ -8,50 +8,108 @@ import net.kyori.adventure.title.Title;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
/**
|
||||
* A wrapper class for {@link Title}s that allows for easy display to an {@link Audience}.
|
||||
*/
|
||||
public class TitleDisplay
|
||||
{
|
||||
/**
|
||||
* The {@link Title} to display.
|
||||
*/
|
||||
private Title title;
|
||||
|
||||
/**
|
||||
* Creates a new {@link TitleDisplay} with the given {@link Title}.
|
||||
* @param title The {@link Title} to display.
|
||||
*/
|
||||
public TitleDisplay(final Title title)
|
||||
{
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A new {@link TitleBuilder} which can be used to create new {@link Title}s.
|
||||
*/
|
||||
public static TitleBuilder builder()
|
||||
{
|
||||
return new TitleBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the {@link Title} to the given {@link Audience}.
|
||||
* @param audience The {@link Audience} to display the {@link Title} to.
|
||||
*/
|
||||
public void displayTo(final Audience audience)
|
||||
{
|
||||
audience.clearTitle();
|
||||
audience.showTitle(getTitle());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The {@link Title} to display.
|
||||
*/
|
||||
public Title getTitle()
|
||||
{
|
||||
return this.title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link Title} to display.
|
||||
* @param title The {@link Title} to display.
|
||||
*/
|
||||
public void setTitle(final Title title)
|
||||
{
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the {@link Title} to the given {@link ForwardingAudience}.
|
||||
* @param forwardingAudience The {@link ForwardingAudience} to display the {@link Title} to.
|
||||
*/
|
||||
public void displayForwarded(final ForwardingAudience forwardingAudience)
|
||||
{
|
||||
forwardingAudience.clearTitle();
|
||||
forwardingAudience.showTitle(getTitle());
|
||||
}
|
||||
|
||||
private static final class TitleBuilder
|
||||
/**
|
||||
* A builder class for {@link Title}s.
|
||||
*/
|
||||
public static final class TitleBuilder
|
||||
{
|
||||
/**
|
||||
* The main title of the {@link Title}.
|
||||
*/
|
||||
private Component mainTitle;
|
||||
/**
|
||||
* The subtitle of the {@link Title}.
|
||||
*/
|
||||
private Component subTitle;
|
||||
/**
|
||||
* How long the Title should fade in for.
|
||||
*/
|
||||
private Duration fadeIn;
|
||||
/**
|
||||
* How long the Title should fade out for.
|
||||
*/
|
||||
private Duration fadeOut;
|
||||
/**
|
||||
* How long the Title should be displayed for.
|
||||
*/
|
||||
private Duration displayDuration;
|
||||
|
||||
/**
|
||||
* Creates a new {@link TitleBuilder} with default values.
|
||||
* The default values are:
|
||||
* <ul>
|
||||
* <li>Empty main title</li>
|
||||
* <li>Empty subtitle</li>
|
||||
* <li>Default fade in time</li>
|
||||
* <li>Default fade out time</li>
|
||||
* <li>Default display duration</li>
|
||||
* </ul>
|
||||
* @see Title#DEFAULT_TIMES
|
||||
*/
|
||||
public TitleBuilder()
|
||||
{
|
||||
this.mainTitle = Component.empty();
|
||||
@ -61,60 +119,111 @@ public class TitleDisplay
|
||||
this.displayDuration = Title.DEFAULT_TIMES.stay();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the main title of the {@link Title}.
|
||||
* @param title The main title of the {@link Title}.
|
||||
* @return The {@link TitleBuilder} instance.
|
||||
*/
|
||||
public TitleBuilder setMainTitle(final String title)
|
||||
{
|
||||
this.mainTitle = Component.text(title);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the main title of the {@link Title}.
|
||||
* @param title The main title of the {@link Title}.
|
||||
* @param titleColor The color of the main title.
|
||||
* @return The {@link TitleBuilder} instance.
|
||||
*/
|
||||
public TitleBuilder setMainTitle(final String title, final TextColor titleColor)
|
||||
{
|
||||
this.mainTitle = Component.text(title, titleColor);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the main title of the {@link Title}.
|
||||
* @param mainTitle The main title of the {@link Title}.
|
||||
* @return The {@link TitleBuilder} instance.
|
||||
*/
|
||||
public TitleBuilder setMainTitle(final Component mainTitle)
|
||||
{
|
||||
this.mainTitle = mainTitle;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the subtitle of the {@link Title}.
|
||||
* @param title The subtitle of the {@link Title}.
|
||||
* @return The {@link TitleBuilder} instance.
|
||||
*/
|
||||
public TitleBuilder setSubTitle(final String title)
|
||||
{
|
||||
this.subTitle = Component.text(title);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the subtitle of the {@link Title}.
|
||||
* @param title The subtitle of the {@link Title}.
|
||||
* @param titleColor The color of the subtitle.
|
||||
* @return The {@link TitleBuilder} instance.
|
||||
*/
|
||||
public TitleBuilder setSubTitle(final String title, final TextColor titleColor)
|
||||
{
|
||||
this.subTitle = Component.text(title, titleColor);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the subtitle of the {@link Title}.
|
||||
* @param subTitle The subtitle of the {@link Title}.
|
||||
* @return The {@link TitleBuilder} instance.
|
||||
*/
|
||||
public TitleBuilder setSubTitle(final Component subTitle)
|
||||
{
|
||||
this.subTitle = subTitle;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the fade in time of the {@link Title}.
|
||||
* @param duration The fade in time of the {@link Title}.
|
||||
* @return The {@link TitleBuilder} instance.
|
||||
*/
|
||||
public TitleBuilder setFadeIn(final Duration duration)
|
||||
{
|
||||
this.fadeIn = duration;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the fade out time of the {@link Title}.
|
||||
* @param duration The fade out time of the {@link Title}.
|
||||
* @return The {@link TitleBuilder} instance.
|
||||
*/
|
||||
public TitleBuilder setFadeOut(final Duration duration)
|
||||
{
|
||||
this.fadeOut = duration;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the display duration of the {@link Title}.
|
||||
* @param duration The display duration of the {@link Title}.
|
||||
* @return The {@link TitleBuilder} instance.
|
||||
*/
|
||||
public TitleBuilder setDisplayDuration(final Duration duration)
|
||||
{
|
||||
this.displayDuration = duration;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the {@link Title} with the given parameters.
|
||||
* @return The built {@link Title}.
|
||||
*/
|
||||
public Title build()
|
||||
{
|
||||
return Title.title(
|
||||
|
@ -16,7 +16,23 @@ public final class ServiceSubscription<T extends Service>
|
||||
|
||||
private boolean isActive = false;
|
||||
|
||||
ServiceSubscription(@NotNull final JavaPlugin plugin, @NotNull final T service)
|
||||
{
|
||||
this(plugin, service, 1L, false);
|
||||
}
|
||||
|
||||
ServiceSubscription(@NotNull final JavaPlugin plugin, @NotNull final T service, final boolean async)
|
||||
{
|
||||
this(plugin, service, 1L, async);
|
||||
}
|
||||
|
||||
ServiceSubscription(@NotNull final JavaPlugin plugin, @NotNull final T service, final long interval)
|
||||
{
|
||||
this(plugin, service, interval, false);
|
||||
}
|
||||
|
||||
ServiceSubscription(@NotNull final JavaPlugin plugin, @NotNull final T service,
|
||||
final long interval, final boolean async)
|
||||
{
|
||||
this.service = service;
|
||||
this.async = async;
|
||||
@ -28,7 +44,7 @@ public final class ServiceSubscription<T extends Service>
|
||||
this.executor = r ->
|
||||
{
|
||||
final BukkitTask task = Bukkit.getScheduler()
|
||||
.runTaskTimerAsynchronously(plugin, r, 0, 1);
|
||||
.runTaskTimerAsynchronously(plugin, r, 0, interval);
|
||||
tempId[0] = task.getTaskId();
|
||||
};
|
||||
} else
|
||||
@ -36,7 +52,7 @@ public final class ServiceSubscription<T extends Service>
|
||||
this.executor = r ->
|
||||
{
|
||||
final BukkitTask task = Bukkit.getScheduler()
|
||||
.runTaskTimer(plugin, r, 0, 1);
|
||||
.runTaskTimer(plugin, r, 0, interval);
|
||||
tempId[0] = task.getTaskId();
|
||||
};
|
||||
}
|
||||
|
@ -16,7 +16,16 @@ public final class SubscriptionProvider
|
||||
public static final <S extends Service> ServiceSubscription<S> syncService(@NotNull final JavaPlugin plugin,
|
||||
@NotNull final S service)
|
||||
{
|
||||
return new ServiceSubscription<>(plugin, service, false);
|
||||
return new ServiceSubscription<>(plugin, service);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Contract(value = "_,_,_ -> new", pure = false)
|
||||
public static final <S extends Service> ServiceSubscription<S> syncService(@NotNull final JavaPlugin plugin,
|
||||
final long interval,
|
||||
@NotNull final S service)
|
||||
{
|
||||
return new ServiceSubscription<>(plugin, service, interval);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@ -35,6 +44,15 @@ public final class SubscriptionProvider
|
||||
return new TaskSubscription<>(plugin, task, false);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Contract(value = "_,_,_ -> new", pure = false)
|
||||
public static final <S extends Service> ServiceSubscription<S> asyncService(@NotNull final JavaPlugin plugin,
|
||||
final long interval,
|
||||
@NotNull final S service)
|
||||
{
|
||||
return new ServiceSubscription<>(plugin, service, interval, true);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Contract(value = "_, _ -> new", pure = false)
|
||||
public static final <T extends Task> TaskSubscription<T> runAsyncTask(@NotNull final JavaPlugin plugin,
|
||||
|
@ -1,20 +1,85 @@
|
||||
package me.totalfreedom.service;
|
||||
|
||||
public interface Task extends Runnable
|
||||
import me.totalfreedom.utils.DurationTools;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
public abstract class Task extends BukkitRunnable
|
||||
{
|
||||
boolean isRunning();
|
||||
private final String name;
|
||||
private long delay;
|
||||
private long interval;
|
||||
|
||||
String getName();
|
||||
protected Task(final String name)
|
||||
{
|
||||
this(name, -1L, -1L);
|
||||
}
|
||||
|
||||
boolean isRepeating();
|
||||
protected Task(final String name, final long delay, final long interval)
|
||||
{
|
||||
this.name = name;
|
||||
this.delay = delay;
|
||||
this.interval = interval;
|
||||
}
|
||||
|
||||
void setRepeating(long interval);
|
||||
protected Task(final String name, final long delay)
|
||||
{
|
||||
this(name, delay, -1L);
|
||||
}
|
||||
|
||||
boolean isDelayed();
|
||||
protected Task(final String name, final Duration delay)
|
||||
{
|
||||
this(name, DurationTools.getTickedSeconds(delay), -1L);
|
||||
}
|
||||
|
||||
void setDelayed(long delay);
|
||||
protected Task(final String name, final Duration delay, final Duration interval)
|
||||
{
|
||||
this(name, DurationTools.getTickedSeconds(delay), DurationTools.getTickedSeconds(interval));
|
||||
}
|
||||
|
||||
long getInterval();
|
||||
protected Task(final String name, final long delay, final Duration interval)
|
||||
{
|
||||
this(name, delay, DurationTools.getTickedSeconds(interval));
|
||||
}
|
||||
|
||||
long getDelay();
|
||||
public boolean isRunning()
|
||||
{
|
||||
return !isCancelled();
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
public boolean isRepeating()
|
||||
{
|
||||
return interval != -1L;
|
||||
}
|
||||
|
||||
public void setRepeating(final long interval)
|
||||
{
|
||||
this.interval = interval;
|
||||
}
|
||||
|
||||
public boolean isDelayed()
|
||||
{
|
||||
return this.delay != -1;
|
||||
}
|
||||
|
||||
public void setDelayed(final long delay)
|
||||
{
|
||||
this.delay = delay;
|
||||
}
|
||||
|
||||
public long getInterval()
|
||||
{
|
||||
return interval;
|
||||
}
|
||||
|
||||
public long getDelay()
|
||||
{
|
||||
return delay;
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +1,25 @@
|
||||
package me.totalfreedom.shop;
|
||||
|
||||
import me.totalfreedom.display.BossBarDisplay;
|
||||
import me.totalfreedom.economy.EconomicEntity;
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public interface Reactable
|
||||
{
|
||||
String getReactionMessage();
|
||||
Component getReactionMessage();
|
||||
|
||||
Duration getReactionDuration();
|
||||
|
||||
ReactionType getReactionType();
|
||||
|
||||
long getReward();
|
||||
|
||||
void display(final Audience audience);
|
||||
|
||||
void onReact(final EconomicEntity entity);
|
||||
}
|
||||
|
69
Patchwork/src/main/java/me/totalfreedom/shop/Reaction.java
Normal file
69
Patchwork/src/main/java/me/totalfreedom/shop/Reaction.java
Normal file
@ -0,0 +1,69 @@
|
||||
package me.totalfreedom.shop;
|
||||
|
||||
import me.totalfreedom.display.BossBarDisplay;
|
||||
import net.kyori.adventure.bossbar.BossBar;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
/**
|
||||
* Represents a chat reaction that can be performed by a player.
|
||||
*/
|
||||
public abstract class Reaction implements Reactable
|
||||
{
|
||||
private final Duration reactionDuration;
|
||||
private final ReactionType reactionType;
|
||||
private final long reward;
|
||||
private Component reactionMessage = Component.empty();
|
||||
|
||||
protected Reaction(final ReactionType type)
|
||||
{
|
||||
this(50L, type);
|
||||
}
|
||||
|
||||
protected Reaction(final long reward, final ReactionType type)
|
||||
{
|
||||
this(30L, reward, type);
|
||||
}
|
||||
|
||||
protected Reaction(final long seconds, final long reward, final ReactionType reactionType)
|
||||
{
|
||||
this(Duration.ofSeconds(seconds), reward, reactionType);
|
||||
}
|
||||
|
||||
protected Reaction(final Duration duration, final long reward, final ReactionType reactionType)
|
||||
{
|
||||
this.reward = reward;
|
||||
this.reactionDuration = duration;
|
||||
this.reactionType = reactionType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getReactionMessage()
|
||||
{
|
||||
return reactionMessage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Duration getReactionDuration()
|
||||
{
|
||||
return reactionDuration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReactionType getReactionType()
|
||||
{
|
||||
return reactionType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BossBarDisplay getBossBarDisplay()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void setReactionMessage(final Component message)
|
||||
{
|
||||
this.reactionMessage = message;
|
||||
}
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
package me.totalfreedom.shop;
|
||||
|
||||
import io.papermc.paper.event.player.AsyncChatEvent;
|
||||
import me.totalfreedom.base.CommonsBase;
|
||||
import me.totalfreedom.display.BossBarDisplay;
|
||||
import me.totalfreedom.display.BossBarTimer;
|
||||
import me.totalfreedom.economy.EconomicEntity;
|
||||
import me.totalfreedom.service.Task;
|
||||
import net.kyori.adventure.bossbar.BossBar;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
public class ReactionTask extends Task implements Listener {
|
||||
private final Reaction reaction;
|
||||
private final BossBarDisplay bossBarDisplay;
|
||||
|
||||
public ReactionTask(final String name, final Reaction reaction) {
|
||||
super(name, -1L, -1);
|
||||
this.reaction = reaction;
|
||||
final BossBar bossBar = BossBarDisplay.builder()
|
||||
.setName(reaction.getReactionMessage())
|
||||
.setColor(BossBar.Color.GREEN)
|
||||
.setProgress(0.0F)
|
||||
.build();
|
||||
|
||||
this.bossBarDisplay = new BossBarDisplay(bossBar);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (isCancelled()) {
|
||||
}
|
||||
|
||||
final BossBarTimer timer = new BossBarTimer(bossBarDisplay, reaction.getReactionDuration());
|
||||
timer.runTaskTimer(CommonsBase.getInstance(), 0L, timer.getInterval());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerChat(final AsyncChatEvent event) {
|
||||
if (event.message()
|
||||
.equals(reaction.getReactionMessage())) {
|
||||
final EconomicEntity entity = CommonsBase.getInstance()
|
||||
.getRegistrations()
|
||||
.getUserRegistry()
|
||||
.getUser(event.getPlayer());
|
||||
|
||||
reaction.onReact(entity);
|
||||
}
|
||||
}
|
||||
}
|
@ -2,5 +2,5 @@ package me.totalfreedom.shop;
|
||||
|
||||
public enum ReactionType
|
||||
{
|
||||
COPYCAT, UNSCRAMBLE;
|
||||
COPYCAT, UNSCRAMBLE, MATH;
|
||||
}
|
||||
|
@ -0,0 +1,28 @@
|
||||
package me.totalfreedom.utils;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
public final class DurationTools
|
||||
{
|
||||
// One tick is 1/20th of a second which is about 50ms.
|
||||
public static final Duration TICK = Duration.ofMillis(50L);
|
||||
// One second is 20 ticks.
|
||||
public static final Duration SECOND = TICK.multipliedBy(20L);
|
||||
// One minute is 60 seconds.
|
||||
public static final Duration MINUTE = SECOND.multipliedBy(60L);
|
||||
|
||||
private DurationTools()
|
||||
{
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
public static final long getTickedSeconds(final Duration duration)
|
||||
{
|
||||
return duration.toMillis() / 50L;
|
||||
}
|
||||
|
||||
public static final Duration getTickedSeconds(final long seconds)
|
||||
{
|
||||
return SECOND.multipliedBy(seconds);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user