Migrates the entire package nomenclature to be more direct and straightforward. (#17)

Signed-off-by: Paul Reilly <pawereus@gmail.com>
This commit is contained in:
Paldiu
2023-08-01 22:34:18 -05:00
committed by GitHub
parent e1a6b5e587
commit 21463c50fe
146 changed files with 595 additions and 608 deletions

View File

@ -0,0 +1,25 @@
package fns.fossil;
import fns.fossil.trail.Trailer;
import fns.patchwork.base.Patchwork;
import fns.patchwork.base.Registration;
import fns.patchwork.service.SubscriptionProvider;
import org.bukkit.plugin.java.JavaPlugin;
public class Fossil extends JavaPlugin
{
private final Trailer trailer = new Trailer();
private final Registration registration = Patchwork.getInstance()
.getRegistrations();
@Override
public void onEnable()
{
registration.getModuleRegistry()
.addModule(this);
registration.getServiceTaskRegistry()
.registerService(
SubscriptionProvider.syncService(this, trailer));
}
}

View File

@ -0,0 +1,210 @@
package fns.fossil.bouncypads;
import com.google.errorprone.annotations.Immutable;
import java.util.SplittableRandom;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
/**
* 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);
}
}

View File

@ -0,0 +1,157 @@
package fns.fossil.bouncypads;
import fns.fossil.Fossil;
import fns.patchwork.base.Patchwork;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Stream;
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;
/**
* 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, Patchwork
.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());
}
}

View File

@ -0,0 +1,32 @@
package fns.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;
}

View File

@ -0,0 +1,64 @@
/*
* Copyright (c) 2023 TotalFreedom
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this
* software and associated documentation files (the “Software”), to deal in the Software
* without restriction, including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to
* whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package fns.fossil.cmd;
import fns.patchwork.command.Commander;
import fns.patchwork.command.annotation.Base;
import fns.patchwork.command.annotation.Info;
import fns.patchwork.command.annotation.Permissive;
import fns.patchwork.utils.kyori.FreedomMiniMessage;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.command.CommandSender;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
@Info(name = "cake", description = "Gives everyone cake and broadcasts a message.", usage = "/cake")
@Permissive(perm = "fossil.cake")
public class CakeCommand extends Commander
{
protected CakeCommand(final @NotNull JavaPlugin plugin)
{
super(plugin);
}
@Base
public void broadcastCake(final CommandSender sender)
{
Bukkit.getServer().sendMessage(FreedomMiniMessage.deserialize(true,
"<rainbow>But there's no sense crying over " +
"every mistake. You just keep on trying " +
"till you run out of " +
"cake.</rainbow>"));
final ItemStack stack = new ItemStack(Material.CAKE, 1);
final ItemMeta meta = stack.getItemMeta();
meta.displayName(FreedomMiniMessage.deserialize(true, "<dark_gray>The <white>Lie"));
stack.setItemMeta(meta);
Bukkit.getOnlinePlayers()
.forEach(player -> player.getInventory()
.addItem(stack));
}
}

View File

@ -0,0 +1,47 @@
package fns.fossil.economy;
import fns.patchwork.economy.CompletedTransaction;
import fns.patchwork.economy.EconomicEntity;
import fns.patchwork.economy.Transaction;
import fns.patchwork.economy.TransactionResult;
public class SimpleCompletedTransaction implements CompletedTransaction
{
private final TransactionResult transactionResult;
private final EconomicEntity source;
private final EconomicEntity destination;
private final long balance;
public SimpleCompletedTransaction(final Transaction transaction, final TransactionResult transactionResult)
{
this.source = transaction.getSource();
this.destination = transaction.getDestination();
this.balance = transaction.getBalance();
this.transactionResult = transactionResult;
}
@Override
public TransactionResult getResult()
{
return transactionResult;
}
@Override
public EconomicEntity getSource()
{
return source;
}
@Override
public EconomicEntity getDestination()
{
return destination;
}
@Override
public long getBalance()
{
return balance;
}
}

View File

@ -0,0 +1,37 @@
package fns.fossil.economy;
import fns.patchwork.economy.CompletedTransaction;
import fns.patchwork.economy.MutableTransaction;
import fns.patchwork.economy.TransactionLogger;
import fns.patchwork.economy.Transactor;
public class SimpleLoggedTransactor implements Transactor
{
private final Transactor transactor;
private final TransactionLogger transactionLogger;
public SimpleLoggedTransactor()
{
this(new SimpleTransactor(), new SimpleTransactionLogger());
}
public SimpleLoggedTransactor(final Transactor transactor, final TransactionLogger transactionLogger)
{
this.transactor = transactor;
this.transactionLogger = transactionLogger;
}
@Override
public CompletedTransaction handleTransaction(final MutableTransaction transaction)
{
final CompletedTransaction completedTransaction = transactor.handleTransaction(transaction);
transactionLogger.logTransaction(completedTransaction);
return completedTransaction;
}
public TransactionLogger getTransactionLogger()
{
return this.transactionLogger;
}
}

View File

@ -0,0 +1,30 @@
package fns.fossil.economy;
import fns.patchwork.economy.EconomicEntity;
import fns.patchwork.economy.MutableTransaction;
public class SimpleMutableTransaction extends SimpleTransaction implements MutableTransaction
{
public SimpleMutableTransaction(final EconomicEntity source, final EconomicEntity destination, final long balance)
{
super(source, destination, balance);
}
@Override
public long addToBalance(final long amount)
{
return balance.addAndGet(amount);
}
@Override
public long removeFromBalance(final long amount)
{
return this.addToBalance(-amount);
}
@Override
public void setBalance(final long newBalance)
{
balance.set(newBalance);
}
}

View File

@ -0,0 +1,37 @@
package fns.fossil.economy;
import fns.patchwork.economy.EconomicEntity;
import fns.patchwork.economy.Transaction;
import java.util.concurrent.atomic.AtomicLong;
public class SimpleTransaction implements Transaction
{
protected final AtomicLong balance;
private final EconomicEntity source;
private final EconomicEntity destination;
public SimpleTransaction(final EconomicEntity source, final EconomicEntity destination, final long balance)
{
this.source = source;
this.destination = destination;
this.balance = new AtomicLong(balance);
}
@Override
public EconomicEntity getSource()
{
return source;
}
@Override
public EconomicEntity getDestination()
{
return destination;
}
@Override
public long getBalance()
{
return balance.get();
}
}

View File

@ -0,0 +1,50 @@
package fns.fossil.economy;
import fns.patchwork.audience.MutableAudienceForwarder;
import fns.patchwork.economy.CompletedTransaction;
import fns.patchwork.economy.EconomicEntity;
import fns.patchwork.economy.TransactionLogger;
import fns.patchwork.economy.TransactionResult;
import fns.patchwork.utils.logging.FreedomLogger;
import net.kyori.adventure.text.Component;
public class SimpleTransactionLogger implements TransactionLogger
{
private final MutableAudienceForwarder audience = MutableAudienceForwarder.from(FreedomLogger.getLogger("Fossil"));
@Override
public void logTransaction(final CompletedTransaction completedTransaction)
{
final StringBuilder transactionLoggingStatementBuilder = new StringBuilder();
final TransactionResult result = completedTransaction.getResult();
final boolean resultSuccess = result.isSuccessful();
final String resultMessage = result.getMessage();
final EconomicEntity source = completedTransaction.getSource();
final EconomicEntity destination = completedTransaction.getDestination();
final long transactionAmount = completedTransaction.getBalance();
transactionLoggingStatementBuilder.append(resultSuccess
? "Successful"
: "Unsuccessful")
.append(" (")
.append(resultMessage)
.append(") ")
.append(" transaction between ")
.append(source.getName())
.append(" ")
.append(destination.getName())
.append(" where the volume of currency transferred was $")
.append(transactionAmount)
.append(".");
final Component message = Component.text(transactionLoggingStatementBuilder.toString());
audience.sendMessage(message);
}
public MutableAudienceForwarder getAudienceForwarder()
{
return audience;
}
}

View File

@ -0,0 +1,51 @@
package fns.fossil.economy;
import fns.patchwork.economy.TransactionResult;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
public class SimpleTransactionResult implements TransactionResult
{
public static final TransactionResult SUCCESSFUL = new SimpleTransactionResult("Successful transaction.", true);
public static final TransactionResult UNAUTHORIZED = new SimpleTransactionResult("Unauthorized transaction.",
false);
public static final TransactionResult AMOUNT_TOO_SMALL = new SimpleTransactionResult(
"Transaction balance too small.", false);
public static final TransactionResult INSUFFICIENT_FUNDS = new SimpleTransactionResult(
"The source has an insufficient balance to carry out this transaction.", false);
private final String message;
private final Component component;
private final boolean isSuccessful;
public SimpleTransactionResult(final String message, final boolean isSuccessful)
{
this(message, Component.text(message, isSuccessful
? NamedTextColor.GREEN
: NamedTextColor.RED), isSuccessful);
}
public SimpleTransactionResult(final String message, final Component component, final boolean isSuccessful)
{
this.message = message;
this.component = component;
this.isSuccessful = isSuccessful;
}
@Override
public String getMessage()
{
return message;
}
@Override
public boolean isSuccessful()
{
return isSuccessful;
}
@Override
public Component getComponent()
{
return component;
}
}

View File

@ -0,0 +1,50 @@
package fns.fossil.economy;
import fns.patchwork.economy.CompletedTransaction;
import fns.patchwork.economy.EconomicEntity;
import fns.patchwork.economy.EconomicEntityData;
import fns.patchwork.economy.MutableTransaction;
import fns.patchwork.economy.Transactor;
public class SimpleTransactor implements Transactor
{
@Override
public CompletedTransaction handleTransaction(final MutableTransaction transaction)
{
final EconomicEntity source = transaction.getSource();
final EconomicEntityData sourceData = source.getEconomicData();
if (sourceData.areTransactionsFrozen())
{
return new SimpleCompletedTransaction(transaction, SimpleTransactionResult.UNAUTHORIZED);
}
final long transactionAmount = transaction.getBalance();
if (transactionAmount >= 0)
{
return new SimpleCompletedTransaction(transaction, SimpleTransactionResult.AMOUNT_TOO_SMALL);
}
final long sourceBalance = sourceData.getBalance();
final long diff = sourceBalance - transactionAmount;
if (diff > 0)
{
return new SimpleCompletedTransaction(transaction, SimpleTransactionResult.INSUFFICIENT_FUNDS);
}
final EconomicEntity destination = transaction.getDestination();
final EconomicEntityData destinationData = destination.getEconomicData();
if (destinationData.areTransactionsFrozen())
{
return new SimpleCompletedTransaction(transaction, SimpleTransactionResult.UNAUTHORIZED);
}
sourceData.removeFromBalance(transactionAmount);
destinationData.addToBalance(transactionAmount);
return new SimpleCompletedTransaction(transaction, SimpleTransactionResult.SUCCESSFUL);
}
}

View File

@ -0,0 +1,30 @@
package fns.fossil.items;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public final class ClownfishItem extends ShopItem
{
public ClownfishItem()
{
super(Material.TROPICAL_FISH);
}
@Override
public void runAction(final @NotNull Player user, final @Nullable Entity target)
{
if (target == null) return;
final Location location = user.getEyeLocation()
.clone();
final Vector vector = location.getDirection()
.multiply(2);
target.setVelocity(vector);
}
}

View File

@ -0,0 +1,34 @@
package fns.fossil.items;
import org.bukkit.Material;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public abstract class ShopItem
{
private final ItemStack item;
private final ItemMeta meta;
protected ShopItem(final Material material)
{
this.item = new ItemStack(material, 1);
this.meta = this.item.getItemMeta();
}
public abstract void runAction(@NotNull final Player user, @Nullable final Entity target);
public ItemStack getItem()
{
return this.item;
}
public ItemMeta getMeta()
{
return this.meta;
}
}

View File

@ -0,0 +1,21 @@
package fns.fossil.items;
import org.bukkit.Material;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public final class TrailItem extends ShopItem
{
public TrailItem()
{
super(Material.LINGERING_POTION);
}
@Override
public void runAction(final @NotNull Player user, final @Nullable Entity target)
{
}
}

View File

@ -0,0 +1,59 @@
package fns.fossil.reactions;
import fns.patchwork.display.BossBarDisplay;
import fns.patchwork.economy.EconomicEntity;
import fns.patchwork.shop.Reaction;
import fns.patchwork.shop.ReactionType;
import java.util.SplittableRandom;
import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.bossbar.BossBar;
/**
* 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 display(final Audience audience)
{
final BossBar bossBar = BossBarDisplay.builder()
.setName(getRandomCharacterString())
.setProgress(0.0F)
.build();
}
@Override
public void onReact(final EconomicEntity entity)
{
//
}
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();
}
}

View File

@ -0,0 +1,5 @@
package fns.fossil.shop;
public class Shoppe
{
}

View File

@ -0,0 +1,11 @@
package fns.fossil.shop.menus;
import fns.patchwork.display.AbstractMenu;
public final class MainMenu extends AbstractMenu
{
protected MainMenu(final int size)
{
super(size);
}
}

View File

@ -0,0 +1,36 @@
package fns.fossil.trail;
import fns.patchwork.particle.Trail;
import fns.patchwork.service.Service;
import java.util.ArrayList;
import java.util.List;
public class Trailer extends Service
{
private final List<Trail> activeTrails = new ArrayList<>();
// Cannot be async due to interaction with the world, and API interactions MUST be synchronized.
public Trailer()
{
super("trailer_service");
}
public void addTrail(final Trail trail)
{
this.activeTrails.add(trail);
}
public void removeTrail(final Trail trail)
{
this.activeTrails.remove(trail);
}
@Override
public void tick()
{
for (final Trail trail : activeTrails)
{
trail.spawnParticle();
}
}
}

View File

@ -0,0 +1,33 @@
package fns.fossil.trail.types;
import fns.patchwork.particle.TrailType;
import org.bukkit.Color;
import org.bukkit.Location;
import org.bukkit.Particle;
import org.bukkit.entity.Player;
public final class BasicTrail extends SimpleTrail
{
protected BasicTrail(final Player player)
{
super(player, TrailType.DEFAULT);
super.setColor(Color.RED);
}
@Override
public void spawnParticle()
{
// Exit immediately if either condition is false.
if (!isActive() || !getAssociatedPlayer().isOnline()) return;
// Trail is active and the player is online.
final Particle particle = getTrailType().getType();
final Particle.DustOptions options = new Particle.DustOptions(getColor(), 3);
final Player player = (Player) getAssociatedPlayer();
final Location location = player.getLocation()
.clone()
.subtract(0, 1, 0);
location.getWorld()
.spawnParticle(particle, location, 1, 0.0, 0.5, 0.0, options);
}
}

View File

@ -0,0 +1,29 @@
package fns.fossil.trail.types;
import fns.patchwork.particle.TrailType;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
public final class FlameTrail extends SimpleTrail
{
public FlameTrail(final Player player)
{
super(player, TrailType.FLAME);
}
@Override
public void spawnParticle()
{
if (!getAssociatedPlayer().isOnline() || !isActive()) return;
final Player player = (Player) getAssociatedPlayer();
final Location location = player.getLocation()
.clone()
.subtract(0, 1, 0);
final Vector direction = location.getDirection();
location.getWorld()
.spawnParticle(getTrailType().getType(), location, 0, direction.getX(), direction.getY(),
direction.getZ(), 0.1);
}
}

View File

@ -0,0 +1,26 @@
package fns.fossil.trail.types;
import fns.patchwork.particle.TrailType;
import org.bukkit.Location;
import org.bukkit.entity.Player;
public final class HeartTrail extends SimpleTrail
{
public HeartTrail(final Player player)
{
super(player, TrailType.HEART);
}
@Override
public void spawnParticle()
{
if (!getAssociatedPlayer().isOnline() || !isActive()) return;
final Player player = (Player) getAssociatedPlayer();
final Location location = player.getLocation()
.clone()
.subtract(0, 1, 0);
location.getWorld()
.spawnParticle(getTrailType().getType(), location, 1, 0.0, 0.5, 0.0);
}
}

View File

@ -0,0 +1,45 @@
package fns.fossil.trail.types;
import fns.patchwork.particle.TrailType;
import fns.patchwork.utils.InterpolationUtils;
import java.util.Iterator;
import org.bukkit.Color;
import org.bukkit.Location;
import org.bukkit.Particle;
import org.bukkit.entity.Player;
public final class RainbowTrail extends SimpleTrail
{
private Iterator<Color> currentColor;
protected RainbowTrail(final Player player)
{
super(player, TrailType.DEFAULT);
setColors(InterpolationUtils.rainbow(40 % 7));
this.currentColor = getColors().iterator();
}
@Override
public void spawnParticle()
{
// Exit immediately if either case is false.
if (!isActive() || !getAssociatedPlayer().isOnline()) return;
// Re-initialize the color iterator if the iterator has previously reached the end of its index.
if (!currentColor.hasNext())
{
this.currentColor = getColors().iterator();
}
final Color color = currentColor.next();
final Player player = (Player) getAssociatedPlayer();
final Particle particle = getTrailType().getType();
final Particle.DustOptions options = new Particle.DustOptions(color, 3F);
final Location location = player.getLocation()
.clone()
.subtract(0, 1, 0);
location.getWorld()
.spawnParticle(particle, location, 1, 0.0, 0.5, 0.0, options);
}
}

View File

@ -0,0 +1,90 @@
package fns.fossil.trail.types;
import fns.patchwork.particle.Trail;
import fns.patchwork.particle.TrailType;
import java.util.Set;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.Color;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public abstract class SimpleTrail implements Trail
{
private final UUID associatedPlayerUUID;
private final TrailType trailType;
private Color staticColor = null;
private Set<Color> gradientColor = null;
private boolean active = false;
protected SimpleTrail(final Player player, final TrailType trailType)
{
this.associatedPlayerUUID = player.getUniqueId();
this.trailType = trailType;
}
@Override
public @NotNull UUID getAssociatedPlayerUUID()
{
return associatedPlayerUUID;
}
@Override
public @NotNull OfflinePlayer getAssociatedPlayer()
{
return Bukkit.getOfflinePlayer(getAssociatedPlayerUUID());
}
@Override
public @NotNull TrailType getTrailType()
{
return trailType;
}
@Override
public @Nullable Color getColor()
{
return staticColor;
}
@Override
public void setColor(@NotNull final Color color)
{
this.gradientColor = null;
this.staticColor = color;
}
@Override
public @Nullable Set<Color> getColors()
{
return this.gradientColor;
}
@Override
public void setColors(@NotNull final Set<Color> colors)
{
this.staticColor = null;
this.gradientColor = colors;
}
@Override
public boolean isGradient()
{
return gradientColor != null;
}
@Override
public boolean isActive()
{
return active;
}
@Override
public void setActive(final boolean active)
{
this.active = active;
}
}

View File

@ -0,0 +1,31 @@
package fns.fossil.trail.types;
import fns.patchwork.particle.TrailType;
import org.bukkit.Color;
import org.bukkit.Location;
import org.bukkit.Particle;
import org.bukkit.entity.Player;
public final class StrobeTrail extends SimpleTrail
{
private final Particle.DustTransition dustTransition;
public StrobeTrail(final Player player, final Color from, final Color to)
{
super(player, TrailType.STROBE);
this.dustTransition = new Particle.DustTransition(from, to, 3F);
}
@Override
public void spawnParticle()
{
if (!getAssociatedPlayer().isOnline() || !isActive()) return;
final Player player = (Player) getAssociatedPlayer();
final Location location = player.getLocation()
.clone()
.subtract(0, 1, 0);
location.getWorld()
.spawnParticle(getTrailType().getType(), location, 1, 0.0, 0.5, 0.0, dustTransition);
}
}

View File

@ -0,0 +1,12 @@
package fns.fossil.trail.types;
import org.bukkit.entity.Player;
public final class TrailProvider
{
public BasicTrail basicTrail(final Player player)
{
return new BasicTrail(player);
}
}