This commit is contained in:
Paul Reilly 2023-06-04 21:30:17 -05:00
parent ef3acca330
commit 27dafd69e6
27 changed files with 770 additions and 155 deletions

View File

@ -0,0 +1,43 @@
package me.totalfreedom.corvo.listener;
import io.papermc.paper.event.block.BlockBreakBlockEvent;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.event.inventory.InventoryOpenEvent;
import org.bukkit.event.player.PlayerInteractEvent;
public class PlayerInteractionListener implements Listener
{
@EventHandler
public void playerBreakBlock(final BlockBreakEvent event)
{
}
@EventHandler
public void blockBreakBlock(final BlockBreakBlockEvent event)
{
}
@EventHandler
public void playerOpenContainer(final InventoryOpenEvent event)
{
}
@EventHandler
public void playerCloseContainer(final InventoryCloseEvent event)
{
}
@EventHandler
public void playerInteraction(final PlayerInteractEvent event)
{
}
}

View File

@ -1,7 +1,7 @@
package me.totalfreedom.datura.perms;
import me.totalfreedom.security.perm.Node;
import me.totalfreedom.security.perm.NodeType;
import me.totalfreedom.security.Node;
import me.totalfreedom.security.NodeType;
public class DefaultNodes
{

View File

@ -1,8 +1,8 @@
package me.totalfreedom.datura.perms;
import me.totalfreedom.base.CommonsBase;
import me.totalfreedom.security.perm.Group;
import me.totalfreedom.security.perm.Node;
import me.totalfreedom.security.Group;
import me.totalfreedom.security.Node;
import net.kyori.adventure.text.Component;
import org.bukkit.permissions.Permission;
import org.bukkit.permissions.PermissionAttachment;

View File

@ -3,7 +3,7 @@ package me.totalfreedom.datura.perms;
import me.totalfreedom.base.CommonsBase;
import me.totalfreedom.datura.Datura;
import me.totalfreedom.datura.user.SimpleUserData;
import me.totalfreedom.security.perm.Node;
import me.totalfreedom.security.Node;
import me.totalfreedom.user.User;
import me.totalfreedom.user.UserData;
import net.kyori.adventure.text.Component;

View File

@ -1,7 +1,7 @@
package me.totalfreedom.datura.perms;
import me.totalfreedom.security.perm.Node;
import me.totalfreedom.security.perm.NodeType;
import me.totalfreedom.security.Node;
import me.totalfreedom.security.NodeType;
import org.bukkit.permissions.Permission;
import org.bukkit.permissions.PermissionDefault;

View File

@ -1,8 +1,8 @@
package me.totalfreedom.datura.perms;
import me.totalfreedom.security.perm.Node;
import me.totalfreedom.security.perm.NodeBuilder;
import me.totalfreedom.security.perm.NodeType;
import me.totalfreedom.security.Node;
import me.totalfreedom.security.NodeBuilder;
import me.totalfreedom.security.NodeType;
public class PermissionNodeBuilder implements NodeBuilder
{

View File

@ -0,0 +1,53 @@
package me.totalfreedom.datura.user;
import me.totalfreedom.economy.EconomicEntity;
import me.totalfreedom.economy.EconomicEntityData;
public class ServerEconomyHolder implements EconomicEntity, EconomicEntityData
{
private long balance = Long.MAX_VALUE;
@Override
public EconomicEntityData getEconomicData()
{
return this;
}
@Override
public String getName()
{
return "TotalFreedom-Bank";
}
@Override
public boolean areTransactionsFrozen()
{
return false;
}
@Override
public long getBalance()
{
return balance;
}
@Override
public void setBalance(final long newBalance)
{
balance = newBalance;
}
@Override
public long addToBalance(final long amount)
{
balance += amount;
return balance;
}
@Override
public long removeFromBalance(final long amount)
{
balance -= amount;
return balance;
}
}

View File

@ -3,7 +3,7 @@ package me.totalfreedom.datura.user;
import me.totalfreedom.base.CommonsBase;
import me.totalfreedom.datura.event.UserDataUpdateEvent;
import me.totalfreedom.datura.perms.FreedomUser;
import me.totalfreedom.security.perm.Group;
import me.totalfreedom.security.Group;
import me.totalfreedom.sql.SQL;
import me.totalfreedom.user.User;
import me.totalfreedom.user.UserData;

View File

@ -1,6 +1,6 @@
package me.totalfreedom.data;
import me.totalfreedom.security.perm.Group;
import me.totalfreedom.security.Group;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
import java.util.ArrayList;

View File

@ -2,6 +2,7 @@ package me.totalfreedom.data;
import me.totalfreedom.user.User;
import me.totalfreedom.user.UserData;
import org.bukkit.entity.Player;
import java.util.HashMap;
import java.util.Map;
@ -20,6 +21,15 @@ public class UserRegistry
return userDataMap.get(user);
}
public UserData fromPlayer(final Player player) {
return userDataMap.entrySet()
.stream()
.filter(entry -> entry.getKey().getUniqueId().equals(player.getUniqueId()))
.findFirst()
.map(Map.Entry::getValue)
.orElse(null);
}
public void registerUserData(final User user, final UserData userData)
{
userDataMap.put(user, userData);

View File

@ -0,0 +1,204 @@
package me.totalfreedom.display;
import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.audience.ForwardingAudience;
import net.kyori.adventure.bossbar.BossBar;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.TextColor;
import org.jetbrains.annotations.Range;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class BossBarDisplay
{
private BossBar bossBar;
public BossBarDisplay(final BossBar bossBar)
{
this.bossBar = bossBar;
}
public static BossBarBuilder builder()
{
return new BossBarBuilder();
}
public void changeColor(final BossBar.Color color)
{
this.bossBar.color(color);
}
public void changeOverlay(final BossBar.Overlay overlay)
{
this.bossBar.overlay(overlay);
}
public void changeName(final Component name)
{
this.bossBar.name(name);
}
public void changeName(final String name, final TextColor color)
{
this.bossBar.name(Component.text(name, color));
}
public void changeName(final String name)
{
this.bossBar.name(Component.text(name));
}
public void showTo(final Audience audience)
{
audience.showBossBar(getBossBar());
}
public BossBar getBossBar()
{
return this.bossBar;
}
public void setBossBar(final BossBar bossBar)
{
this.bossBar = bossBar;
}
public void hideFrom(final Audience audience)
{
audience.hideBossBar(getBossBar());
}
public void incrementProgress(final @Range(from = 0, to = 100) float progress)
{
final float currentProgress = this.bossBar.progress();
final float newProgress = currentProgress + (progress / 100.0F);
if (newProgress > 1) this.bossBar.progress(1.0F);
else this.bossBar.progress(newProgress);
}
public void decrementProgress(final @Range(from = 0, to = 100) float progress)
{
final float currentProgress = this.bossBar.progress();
final float newProgress = currentProgress - (progress / 100.0F);
if (newProgress < 0) this.bossBar.progress(0.0F);
else this.bossBar.progress(newProgress);
}
public void maximumProgress()
{
this.bossBar.progress(1.0F);
}
public void halfProgress()
{
this.bossBar.progress(0.5F);
}
public void minimumProgress()
{
this.bossBar.progress(0.0F);
}
public void showForwarded(final ForwardingAudience forwardingAudience)
{
forwardingAudience.showBossBar(getBossBar());
}
public void hideForwarded(final ForwardingAudience forwardingAudience)
{
forwardingAudience.hideBossBar(getBossBar());
}
private static final class BossBarBuilder
{
private final Set<BossBar.Flag> flags = new HashSet<>();
private Component name;
private BossBar.Color color;
private BossBar.Overlay overlay;
@Range(from = 0, to = 1)
private float progress;
public BossBarBuilder()
{
this.name = Component.empty();
this.color = BossBar.Color.GREEN;
this.overlay = BossBar.Overlay.PROGRESS;
this.progress = 0.0F;
}
public BossBarBuilder setName(final Component name)
{
this.name = name;
return this;
}
public BossBarBuilder setName(final String name, final TextColor color)
{
this.name = Component.text(name, color);
return this;
}
public BossBarBuilder setName(final String name)
{
this.name = Component.text(name);
return this;
}
public BossBarBuilder addFlag(final BossBar.Flag flag)
{
this.flags.add(flag);
return this;
}
public BossBarBuilder addFlags(final BossBar.Flag... flags)
{
this.flags.addAll(List.of(flags));
return this;
}
public BossBarBuilder removeFlag(final BossBar.Flag flag)
{
this.flags.remove(flag);
return this;
}
public BossBarBuilder removeFlags(final BossBar.Flag... flags)
{
this.flags.removeAll(List.of(flags));
return this;
}
public BossBarBuilder clearFlags()
{
this.flags.clear();
return this;
}
public BossBarBuilder setColor(final BossBar.Color color)
{
this.color = color;
return this;
}
public BossBarBuilder setOverlay(final BossBar.Overlay overlay)
{
this.overlay = overlay;
return this;
}
public BossBarBuilder setProgress(final @Range(from = 0, to = 100) float progress)
{
this.progress = progress / 100.0F;
return this;
}
public BossBar build()
{
return BossBar.bossBar(this.name, this.progress, this.color, this.overlay, this.flags);
}
}
}

View File

@ -0,0 +1,127 @@
package me.totalfreedom.display;
import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.audience.ForwardingAudience;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.TextColor;
import net.kyori.adventure.title.Title;
import java.time.Duration;
public class TitleDisplay
{
private Title title;
public TitleDisplay(final Title title)
{
this.title = title;
}
public static TitleBuilder builder()
{
return new TitleBuilder();
}
public void displayTo(final Audience audience)
{
audience.clearTitle();
audience.showTitle(getTitle());
}
public Title getTitle()
{
return this.title;
}
public void setTitle(final Title title)
{
this.title = title;
}
public void displayForwarded(final ForwardingAudience forwardingAudience)
{
forwardingAudience.clearTitle();
forwardingAudience.showTitle(getTitle());
}
private static final class TitleBuilder
{
private Component mainTitle;
private Component subTitle;
private Duration fadeIn;
private Duration fadeOut;
private Duration displayDuration;
public TitleBuilder()
{
this.mainTitle = Component.empty();
this.subTitle = Component.empty();
this.fadeIn = Title.DEFAULT_TIMES.fadeIn();
this.fadeOut = Title.DEFAULT_TIMES.fadeOut();
this.displayDuration = Title.DEFAULT_TIMES.stay();
}
public TitleBuilder setMainTitle(final String title)
{
this.mainTitle = Component.text(title);
return this;
}
public TitleBuilder setMainTitle(final String title, final TextColor titleColor)
{
this.mainTitle = Component.text(title, titleColor);
return this;
}
public TitleBuilder setMainTitle(final Component mainTitle)
{
this.mainTitle = mainTitle;
return this;
}
public TitleBuilder setSubTitle(final String title)
{
this.subTitle = Component.text(title);
return this;
}
public TitleBuilder setSubTitle(final String title, final TextColor titleColor)
{
this.subTitle = Component.text(title, titleColor);
return this;
}
public TitleBuilder setSubTitle(final Component subTitle)
{
this.subTitle = subTitle;
return this;
}
public TitleBuilder setFadeIn(final Duration duration)
{
this.fadeIn = duration;
return this;
}
public TitleBuilder setFadeOut(final Duration duration)
{
this.fadeOut = duration;
return this;
}
public TitleBuilder setDisplayDuration(final Duration duration)
{
this.displayDuration = duration;
return this;
}
public Title build()
{
return Title.title(
this.mainTitle,
this.subTitle,
Title.Times.times(this.fadeIn, this.displayDuration, this.fadeOut)
);
}
}
}

View File

@ -0,0 +1,57 @@
package me.totalfreedom.logging;
import org.bukkit.Location;
import org.bukkit.block.data.BlockData;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.time.Instant;
import java.util.UUID;
public final class BlockInteraction implements Interaction<BlockData>
{
private final Location location;
private final UUID whoClicked;
private final Instant when;
private final BlockData originalState;
private final BlockData newState;
public BlockInteraction(final Player player, final BlockData originalState, final BlockData newState)
{
this.location = player.getLocation();
this.whoClicked = player.getUniqueId();
this.when = Instant.now();
this.originalState = originalState;
this.newState = newState;
}
@Override
public @NotNull UUID getWhoClicked()
{
return whoClicked;
}
@Override
public @NotNull BlockData getOriginalState()
{
return originalState;
}
@Override
public @NotNull BlockData getNewState()
{
return newState;
}
@Override
public @NotNull Instant getWhen()
{
return when;
}
@Override
public @NotNull Location getLocation()
{
return location;
}
}

View File

@ -0,0 +1,63 @@
package me.totalfreedom.logging;
import org.bukkit.Location;
import org.bukkit.block.Container;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.time.Instant;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
public final class ContainerInteraction implements Interaction<List<ItemStack>>
{
private final UUID whoClicked;
private final List<ItemStack> originalState;
private final List<ItemStack> newState;
private final Instant when;
private final Location location;
public ContainerInteraction(final Player player, final Container originalState, final Container newState)
{
this.whoClicked = player.getUniqueId();
this.originalState = Collections.unmodifiableList(Arrays.asList(originalState.getInventory()
.getContents()));
this.newState = Collections.unmodifiableList(Arrays.asList(newState.getInventory()
.getContents()));
this.location = originalState.getLocation();
this.when = Instant.now();
}
@Override
public @NotNull UUID getWhoClicked()
{
return whoClicked;
}
@Override
public @NotNull List<ItemStack> getOriginalState()
{
return originalState;
}
@Override
public @NotNull List<ItemStack> getNewState()
{
return newState;
}
@Override
public @NotNull Instant getWhen()
{
return when;
}
@Override
public @NotNull Location getLocation()
{
return location;
}
}

View File

@ -0,0 +1,33 @@
package me.totalfreedom.logging;
import com.google.errorprone.annotations.Immutable;
import org.bukkit.Location;
import org.jetbrains.annotations.NotNull;
import java.time.Instant;
import java.util.UUID;
@Immutable
public interface Interaction<T>
{
@NotNull
static String format(@NotNull final Interaction<?> interaction)
{
return new InteractionFormatter().formatInteraction(interaction);
}
@NotNull
UUID getWhoClicked();
@NotNull
T getOriginalState();
@NotNull
T getNewState();
@NotNull
Instant getWhen();
@NotNull
Location getLocation();
}

View File

@ -0,0 +1,139 @@
package me.totalfreedom.logging;
import me.totalfreedom.sql.SQL;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.inventory.ItemStack;
import java.time.Instant;
public final class InteractionFormatter
{
public String formatInteraction(final Interaction<?> interaction)
{
final String location = formatLocation(interaction.getLocation());
final String world = formatWorld(interaction.getLocation()
.getWorld());
final String player = interaction.getWhoClicked()
.toString();
final String block = formatBlock(interaction.getLocation()
.getBlock());
final String when = formatTime(interaction.getWhen());
if (interaction instanceof ContainerInteraction container)
{
final StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("Container ")
.append(block)
.append(" at location ")
.append(location)
.append(" in world ")
.append(world)
.append(" was opened by ")
.append(player)
.append(" at ")
.append(when)
.append("\nHere is a list of items changed:\n");
container.getOriginalState()
.stream()
.filter(item ->
{
final ItemStack newItem = container.getNewState()
.stream()
.filter(item2 -> item2.isSimilar(item))
.findFirst()
.orElse(null);
return newItem == null || newItem.getAmount() != item.getAmount();
})
.forEach(item ->
{
final ItemStack newItem = container.getNewState()
.stream()
.filter(item2 -> item2.isSimilar(item))
.findFirst()
.orElse(null);
stringBuilder.append("Item ")
.append(formatItemStack(item))
.append(" was changed to ")
.append(formatItemStack(newItem))
.append("\n");
});
stringBuilder.append(".");
return stringBuilder.toString();
} else if (interaction instanceof BlockInteraction blockData)
{
final StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("Block ")
.append(block)
.append(" at location ")
.append(location)
.append(" in world ")
.append(world)
.append(" was changed by ")
.append(player)
.append(" at ")
.append(when)
.append("\nBlock was changed from ")
.append(blockData.getOriginalState()
.getAsString())
.append(" to ")
.append(blockData.getNewState()
.getAsString())
.append(".");
return stringBuilder.toString();
} else
{
throw new IllegalArgumentException("Unknown interaction type: " + interaction.getClass()
.getName());
}
}
// Format: <x>,<y>,<z>
public String formatLocation(final Location location)
{
return String.format("%s,%s,%s", location.getBlockX(), location.getBlockY(), location.getBlockZ());
}
// Format: <world>
public String formatWorld(final World world)
{
return world.getName();
}
// Format: <material>
public String formatBlock(final Block block)
{
return block.getType()
.toString()
.toLowerCase();
}
public String formatTime(final Instant instant)
{
final String trimmed = instant.toString()
.replaceAll("[TZ]", " ");
final int dotIndex = trimmed.indexOf('.');
return (dotIndex != -1)
? trimmed.substring(0, dotIndex)
: trimmed;
}
// Format: <item>,<amount>
public String formatItemStack(final ItemStack stack)
{
if (stack == null)
{
return String.format("%s,%s", "empty", "0");
}
return String.format("%s,%s", stack.getType()
.toString()
.toLowerCase(), stack.getAmount());
}
}

View File

@ -1,4 +1,4 @@
package me.totalfreedom.security.perm;
package me.totalfreedom.security;
import net.kyori.adventure.text.Component;

View File

@ -1,4 +1,4 @@
package me.totalfreedom.security.perm;
package me.totalfreedom.security;
import org.bukkit.permissions.Permission;

View File

@ -1,4 +1,4 @@
package me.totalfreedom.security.perm;
package me.totalfreedom.security;
public interface NodeBuilder
{

View File

@ -1,4 +1,4 @@
package me.totalfreedom.security.perm;
package me.totalfreedom.security;
public enum NodeType
{

View File

@ -1,4 +1,4 @@
package me.totalfreedom.security.perm;
package me.totalfreedom.security;
import org.bukkit.permissions.Permissible;

View File

@ -1,78 +0,0 @@
package me.totalfreedom.security.ban;
import org.jetbrains.annotations.Nullable;
import java.time.Instant;
import java.util.UUID;
/**
* Represents a physical ban entry. This is used to store information about a ban,
* such as the player who was banned, the reason for why they were banned, the individual who issued the ban,
* when the ban expires, and when the ban was created.
* <br>
* Ban information is stored in the Database with the {@link BanID} as the PRIMARY KEY.
*/
public interface Ban
{
/**
* Gets the ID of this ban. This is an object which represents a string prefixed with either a T or a P,
* and suffixed with a 6-10 digit numerical code. This is used to identify the ban in the database, and for
* easier ban referencing.
*
* @return The ID of this ban.
*/
BanID getBanID();
/**
* Gets the UUID of the player who was banned. This is formatted as a UUID
* which allows us to retrieve the particular player instance, if applicable, and also
* have a true identifier to check against user logins.
*
* @return The UUID of the player who was banned.
*/
UUID getOffenderID();
/**
* Gets the reason that the player was banned for. Typically, the default reason is "You are banned!".
* We've forced implementations to require a reason, as it's important to know why a player was banned.
*
* @return The reason that the player was banned for.
*/
String getReason();
/**
* Gets the username of the individual who issued the ban. This is not a reliable way to store data, but
* in our case, we should not need to interact with the ban issuer from the code. This is simply for
* reference purposes.
*
* @return The username of the individual who issued the ban.
*/
String getBanIssuer();
/**
* Gets the {@link Instant} which this ban was created.
*
* @return The ban's creation time.
*/
Instant getCreationTime();
/**
* Gets the {@link Instant} which this ban is due to expire, if applicable.
* This method is annotated as {@link Nullable}, as permanent bans do not have an expiry date.
*
* @return The ban's expiry time, or null if the ban is permanent.
*/
@Nullable
Instant getExpiry();
/**
* Checks if the ban has expired. This will return false if:
* <ul>
* <li>The {@link Instant} returned by {@link #getExpiry()} is null.</li>
* <li>The {@link Instant} returned by {@link #getExpiry()} is after the current time.</li>
* </ul>
*
* @return True if the ban has expired, false otherwise.
*/
boolean isExpired();
}

View File

@ -1,54 +0,0 @@
package me.totalfreedom.security.ban;
/**
* Represents an ID for a ban. These are formatted either as:
* <p>
* P-00129381
* <br>
* T-00128381
* <br>
* </p>
* Where P marks a ban as permanent, and T marks a ban as temporary.
*/
public interface BanID
{
/**
* This method returns the full Ban ID.
*
* @return The actual ID.
*/
String getID();
/**
* Checks the prefix of the Ban ID to see whether if it is permanent.
*
* @return true if the Ban ID is prefixed with a P, false otherwise.
*/
boolean isPermanent();
default boolean matches(BanID other)
{
if (other == null)
{
return false;
}
return (getIDPrefix() == other.getIDPrefix())
&& (getNumericalTag() == other.getNumericalTag());
}
/**
* This method returns the ban type denominator character for the Ban ID.
* This would either be T or P, where T = temporary and P = permanent.
*
* @return The ban type denominator character for the Ban ID.
*/
char getIDPrefix();
/**
* Gets the numerical tag of this ban ID.
* This would be the numerical section of the full Ban ID.
*
* @return The numerical tag of this ban ID.
*/
int getNumericalTag();
}

View File

@ -0,0 +1,16 @@
package me.totalfreedom.shop;
import me.totalfreedom.economy.EconomicEntity;
import java.time.Duration;
public interface Reactable
{
String getReactionMessage();
Duration getReactionDuration();
ReactionType getReactionType();
void onReact(final EconomicEntity entity);
}

View File

@ -0,0 +1,6 @@
package me.totalfreedom.shop;
public enum ReactionType
{
COPYCAT, UNSCRAMBLE;
}

View File

@ -2,7 +2,7 @@ package me.totalfreedom.user;
import me.totalfreedom.economy.EconomicEntity;
import me.totalfreedom.economy.EconomicEntityData;
import me.totalfreedom.security.perm.PermissionHolder;
import me.totalfreedom.security.PermissionHolder;
import net.kyori.adventure.text.Component;
public interface User extends PermissionHolder, EconomicEntity

View File

@ -1,7 +1,7 @@
package me.totalfreedom.user;
import me.totalfreedom.economy.EconomicEntityData;
import me.totalfreedom.security.perm.Group;
import me.totalfreedom.security.Group;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@ -27,10 +27,6 @@ public interface UserData extends EconomicEntityData
void resetPlaytime();
boolean isFrozen();
void setFrozen(boolean frozen);
boolean canInteract();
void setInteractionState(boolean canInteract);