Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions jitpack.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
jdk:
- openjdk16

before_install:
- echo "Before Install"
- bash ensure-java-16 install
- sdk install java 16.0.1-open
- sdk use java 16.0.1-open
- sdk install maven
- mvn -v

install:
- echo "Install"
- if ! bash ensure-java-16 use; then source ~/.sdkman/bin/sdkman-init.sh; fi
- java -version
- mvn install
- mvn install -DskipTests
32 changes: 29 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,27 @@
<artifactId>skulls</artifactId>

<name>Skulls</name>
<version>3.20.0</version>
<version>3.23.0</version>
<packaging>jar</packaging>

<properties>
<author>Kiran Hart</author>
<jarName>Skulls-${project.version}</jarName>
<main.class>${project.groupId}.${project.artifactId}.${project.name}</main.class>
<java.version>16</java.version>
<flight.version>3.27.1</flight.version>
<flight.version>3.30.0</flight.version>
<flight.path>ca.tweetzy</flight.path>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<distributionManagement>
<repository>
<id>repsy</id>
<name>Tweetzy Maven Repo On Repsy</name>
<url>https://repo.repsy.io/mvn/kiran/tweetzy</url>
</repository>
</distributionManagement>

<repositories>
<repository>
<id>repsy</id>
Expand Down Expand Up @@ -59,7 +67,7 @@
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot</artifactId>
<version>1.20.4-R0.1-SNAPSHOT</version>
<version>1.21.4-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
Expand Down Expand Up @@ -186,6 +194,24 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.coderplus.maven.plugins</groupId>
<artifactId>copy-rename-maven-plugin</artifactId>
<version>1.0.1</version>
<executions>
<execution>
<id>copy-named-jar</id>
<phase>package</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<sourceFile>${project.build.directory}/${jarName}.jar</sourceFile>
<destinationFile>D:\Development\Spigot Plugins\Ready Jars\${project.name}\${project.name} - v${project.version}.jar</destinationFile>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
<resources>
<resource>
Expand Down
29 changes: 29 additions & 0 deletions src/main/java/ca/tweetzy/skulls/guis/MainGUI.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import ca.tweetzy.skulls.Skulls;
import ca.tweetzy.skulls.api.enums.BaseCategory;
import ca.tweetzy.skulls.api.enums.ViewMode;
import ca.tweetzy.skulls.api.interfaces.Skull;
import ca.tweetzy.skulls.guis.abstraction.SkullsBaseGUI;
import ca.tweetzy.skulls.model.SkullItem;
import ca.tweetzy.skulls.model.StringHelper;
Expand Down Expand Up @@ -115,6 +116,34 @@ public boolean onResult(String string) {
click.manager.showGUI(click.player, new PlayerHeadGUI(this, Skulls.getPlayerManager().findOrCreate(click.player)));
});

if (Settings.RANDOM_HEAD_BUTTON_ENABLED.getBoolean())
setButton(Settings.GUI_MAIN_ITEMS_RANDOM_HEAD_SLOT.getInt(), QuickItem.of(SkullItem.get("skulls:5171"))
.name(TranslationManager.string(Translations.GUI_MAIN_ITEMS_RANDOM_HEAD_NAME))
.lore(TranslationManager.list(Translations.GUI_MAIN_ITEMS_RANDOM_HEAD_LORE, "price", String.format("%,.2f", Settings.RANDOM_HEAD_BUTTON_PRICE.getDouble())))
.make(), click -> {

if (!Skulls.getPlayerManager().playerCanClaim(player)) {
return;
}

final double price = player.hasPermission("skulls.freeskulls") ? 0 : Settings.RANDOM_HEAD_BUTTON_PRICE.getDouble();
final Skull skull = Skulls.getSkullManager().getRandomAllowedSkull(click.player);

if (price <= 0) {
player.getInventory().addItem(skull.getItemStack());
Common.tell(player, TranslationManager.string(Translations.RECEIVED_RANDOM_SKULL, "skull_name", skull.getName())); return;
}

if (!Skulls.getEconomyManager().has(player, price)) {
Common.tell(player, TranslationManager.string(Translations.NO_MONEY));
return;
}

Skulls.getEconomyManager().withdraw(player, price);
player.getInventory().addItem(skull.getItemStack());
Common.tell(player, TranslationManager.string(Translations.RECEIVED_RANDOM_SKULL, "skull_name", skull.getName()));
});

setButton(Settings.GUI_MAIN_ITEMS_FAVOURITES_SLOT.getInt(), QuickItem.of(SkullItem.get("skulls:39696"))
.name(TranslationManager.string(Translations.GUI_MAIN_ITEMS_FAVOURITES_NAME))
.lore(TranslationManager.list(Translations.GUI_MAIN_ITEMS_FAVOURITES_LORE))
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/ca/tweetzy/skulls/guis/SettingsGUI.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ protected void draw() {
setButton(1, 2, QuickItem.of(CompMaterial.GOLD_NUGGET).name("&e&lForce Sync Prices").lore("&7Clicking this will force update all the prices", "&7for all skulls to the default category price", "&7set within the configuration file.").make(), click -> {
AtomicInteger total = new AtomicInteger(0);

Skulls.getSkullManager().getSkulls().forEach(skull -> {
Skulls.getSkullManager().getSkulls().values().forEach(skull -> {
final BaseCategory category = BaseCategory.getById(skull.getCategory());
if (skull.getPrice() != category.getDefaultPrice()) {
skull.setPrice(category.getDefaultPrice());
Expand Down
7 changes: 6 additions & 1 deletion src/main/java/ca/tweetzy/skulls/guis/SkullsViewGUI.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public SkullsViewGUI(final Gui parent, final SkullUser skullPlayer, final String
Bukkit.getPlayer(skullPlayer.getUUID()),
viewMode == ViewMode.SEARCH ? TranslationManager.string(Translations.GUI_SKULLS_LIST_TITLE_SEARCH, "search_phrase", category) : viewMode == ViewMode.FAVOURITE ? TranslationManager.string(Translations.GUI_SKULLS_LIST_TITLE_FAVOURITES) : TranslationManager.string(Translations.GUI_SKULLS_LIST_TITLE_CATEGORY, "category_name", category),
6,
viewMode == ViewMode.SEARCH ? new ArrayList<>() : viewMode == ViewMode.FAVOURITE ? Skulls.getSkullManager().getSkulls(skullPlayer.getFavourites()) : Skulls.getSkullManager().getSkulls(category)
new ArrayList<>()
);

this.category = category;
Expand All @@ -70,6 +70,11 @@ public SkullsViewGUI(final Gui parent, final SkullUser skullPlayer, final String
protected void prePopulate() {
if (this.viewMode == ViewMode.SEARCH)
this.items = Skulls.getSkullManager().getSkullsBySearch(this.player, category);

else if (viewMode == ViewMode.FAVOURITE)
this.items = Skulls.getSkullManager().getSkulls(skullPlayer.getFavourites());
else
this.items= Skulls.getSkullManager().getSkulls(category);
}

@Override
Expand Down
91 changes: 49 additions & 42 deletions src/main/java/ca/tweetzy/skulls/manager/SkullManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import lombok.Setter;
import org.apache.commons.lang.math.NumberUtils;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
Expand Down Expand Up @@ -71,10 +72,10 @@ public final class SkullManager implements Manager {
private boolean loading = false;

@Getter
private final List<Skull> skulls = Collections.synchronizedList(new ArrayList<>());
private final ConcurrentHashMap<Integer, Skull> skulls = new ConcurrentHashMap<>();

@Getter
private final List<Integer> idList = Collections.synchronizedList(new ArrayList<>());
private final Set<Integer> idList = Collections.synchronizedSet(new HashSet<>());

@Getter
private final Map<Location, PlacedSkull> placedSkulls = new ConcurrentHashMap<>();
Expand All @@ -90,58 +91,61 @@ public List<OfflinePlayer> getOnlineOfflinePlayers() {
}

public Skull getSkull(final int id) {
synchronized (this.skulls) {
return this.skulls.stream().filter(skull -> skull.getId() == id).findFirst().orElse(null);
}
return this.skulls.getOrDefault(id, null);
}

public List<Skull> getSkulls(BaseCategory category) {
synchronized (this.skulls) {
return this.skulls.stream().filter(skull -> skull.getCategory().equalsIgnoreCase(category.getId())).collect(Collectors.toList());
}
return this.skulls.values().stream().filter(skull -> skull.getCategory().equalsIgnoreCase(category.getId())).collect(Collectors.toList());
}

public List<Skull> getSkulls(String category) {
synchronized (this.skulls) {
if (BaseCategory.getById(category) != null)
if (BaseCategory.getById(category) != null)

return this.skulls.stream().filter(skull -> skull.getCategory().equalsIgnoreCase(category)).collect(Collectors.toList());
return this.skulls.values().stream().filter(skull -> skull.getCategory().equalsIgnoreCase(category)).collect(Collectors.toList());

return this.skulls.stream().filter(skull -> Skulls.getCategoryManager().findCategory(category).getSkulls().contains(skull.getId())).collect(Collectors.toList());
}
return this.skulls.values().stream().filter(skull -> Skulls.getCategoryManager().findCategory(category).getSkulls().contains(skull.getId())).collect(Collectors.toList());
}

public Skull getRandomSkull() {
final List<Skull> enabledSkulls = getSkulls().stream().filter(skull -> BaseCategory.getById(skull.getCategory()).isEnabled()).collect(Collectors.toList());
final List<Skull> enabledSkulls = getSkulls().values().stream().filter(skull -> BaseCategory.getById(skull.getCategory()).isEnabled()).toList();
return enabledSkulls.get(random.nextInt(enabledSkulls.size()));
}

public List<Skull> getSkullsBySearch(Player player, String phrase) {
synchronized (this.skulls) {
int id = -1;
if (phrase.startsWith("id:")) {
if (NumberUtils.isNumber(phrase.split(":")[1])) {
id = Integer.parseInt(phrase.split(":")[1]);
}
}
public Skull getRandomAllowedSkull(Player player) {
final List<Skull> enabledSkulls = getSkulls().values().stream().filter(skull -> player.hasPermission("skulls.category." + BaseCategory.getById(skull.getCategory()).getId().toLowerCase().replace(" ", "").replace("&", "")) && BaseCategory.getById(skull.getCategory()).isEnabled() && !skull.isBlocked()).toList();
return enabledSkulls.get(random.nextInt(enabledSkulls.size()));
}

if (id != -1)
return Collections.singletonList(getSkull(id));
public List<Skull> getSkullsBySearch(Player player, String phraseOriginal) {
String phrase = ChatColor.stripColor(phraseOriginal);

return this.skulls.stream().filter(skull -> player.hasPermission("skulls.category." + BaseCategory.getById(skull.getCategory()).getId().toLowerCase().replace(" ", "").replace("&", "")) && BaseCategory.getById(skull.getCategory()).isEnabled() && (Common.match(phrase, skull.getName()) || Common.match(phrase, skull.getCategory()) || skull.getTags().stream().anyMatch(tag -> Common.match(phrase, tag)))).collect(Collectors.toList());
int id = -1;
if (phrase.startsWith("id:")) {
if (NumberUtils.isNumber(phrase.split(":")[1])) {
id = Integer.parseInt(phrase.split(":")[1]);
}
}

if (id != -1)
return Collections.singletonList(getSkull(id));

return this.skulls.values().stream().filter(skull -> player.hasPermission("skulls.category." + BaseCategory.getById(skull.getCategory()).getId().toLowerCase().replace(" ", "").replace("&", "")) && BaseCategory.getById(skull.getCategory()).isEnabled() && (Common.match(phrase, skull.getName()) || Common.match(phrase, skull.getCategory()) || skull.getTags().stream().anyMatch(tag -> Common.match(phrase, tag)))).collect(Collectors.toList());
}

public List<Skull> getSkulls(List<Integer> ids) {
synchronized (this.skulls) {
return this.skulls.stream().filter(skull -> ids.contains(skull.getId())).collect(Collectors.toList());
final List<Skull> results = new ArrayList<>();

for (Integer id : ids) {
final Skull found = this.skulls.getOrDefault(id, null);
if (found != null)
results.add(found);
}

return results;
}

public long getSkullCount(String category) {
synchronized (this.skulls) {
return this.skulls.stream().filter(skull -> skull.getCategory().equalsIgnoreCase(category)).count();
}
return this.skulls.values().stream().filter(skull -> skull.getCategory().equalsIgnoreCase(category)).count();
}

public ItemStack getSkullItem(final int id) {
Expand Down Expand Up @@ -171,22 +175,25 @@ public void removePlacedSkull(@NonNull final PlacedSkull placedSkull) {

private void checkAndFixDatabase() {
Bukkit.getServer().getScheduler().runTaskAsynchronously(Skulls.getInstance(), () -> {
final Set<Skull> heads = new HashSet<>();
final Map<Integer, Skull> heads = new HashMap<>();

Common.log("&r&aRunning database check :)");

final List<Skull> downloaded = performHeadDownload(true);
downloaded.forEach(skull -> {
if (this.skulls.contains(skull)) return;
heads.add(skull);
if (!this.skulls.containsKey(skull.getId()))
heads.put(skull.getId(),skull);
});

if (this.skulls.size() < heads.size()) {
Common.log("&r&eFound some missing heads, downloading/inserting them now!");
int oldSize = this.skulls.size();
this.skulls.putAll(heads);
int newSize = this.skulls.size();

this.skulls.addAll(heads);
this.idList.addAll(heads.stream().map(Skull::getId).toList());
Skulls.getDataManager().insertSkulls(new ArrayList<>(heads));
if (newSize > oldSize) {
Skulls.getDataManager().insertSkulls(new ArrayList<>(heads.values()));
Common.log("&r&eFound some new skulls, saving them now :D");
} else {
Common.log("&r&aEverything looks up-to-date, no issues found. Enjoy!");
}
});
}
Expand All @@ -198,8 +205,8 @@ public void downloadHeads() {

final List<Skull> heads = new ArrayList<>(performHeadDownload(false));

this.skulls.addAll(heads);
this.idList.addAll(heads.stream().map(Skull::getId).toList());
heads.forEach(skull -> this.skulls.putIfAbsent(skull.getId(), skull));
// this.idList.addAll(heads.stream().map(Skull::getId).toList());
Skulls.getDataManager().insertSkulls(heads);
});
}
Expand Down Expand Up @@ -277,8 +284,8 @@ public void load() {
return;
}

this.skulls.addAll(all);
this.idList.addAll(all.stream().map(Skull::getId).toList());
all.forEach(skull -> this.skulls.put(skull.getId(), skull));
// this.idList.addAll(all.stream().map(Skull::getId).toList());

if (this.skulls.isEmpty()) {
Common.log("&cCould not find any skulls, attempting to redownload them!");
Expand Down
5 changes: 4 additions & 1 deletion src/main/java/ca/tweetzy/skulls/settings/Settings.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ public final class Settings extends FlightSettings {
public static final ConfigEntry GENERAL_USAGE_REQUIRES_NO_PERM = create("general usage requires no permission", false, "If true, no permission is required to use except for admin stuff");
public static final ConfigEntry TELL_OP_PATREON_LINK = create("tell ops patron on join", true);
public static final ConfigEntry SKULL_TRACKING = create("track skull placement", true, "If disabled skulls will no longer drop in creative");
public static final ConfigEntry RANDOM_HEAD_BUTTON_ENABLED = create("random head button.enabled", false, "If enabled players can click to receive a random head (only from categories they have access too)");
public static final ConfigEntry RANDOM_HEAD_BUTTON_PRICE = create("random head button.price", 1.0, "The price for using the random head button");

public static final ConfigEntry CATEGORIES_ALPHABET_ENABLED = create("enabled categories.alphabet", true);
public static final ConfigEntry CATEGORIES_ANIMALS_ENABLED = create("enabled categories.animals", true);
Expand All @@ -57,6 +59,7 @@ public final class Settings extends FlightSettings {
public static final ConfigEntry CATEGORIES_PLANTS_ENABLED = create("enabled categories.plants", true);
public static final ConfigEntry CATEGORIES_PLAYER_HEADS_ENABLED = create("enabled categories.player heads", false);


public static final ConfigEntry PLAYER_HEAD_NAME = create("player head.name", "&e%player_name%");
public static final ConfigEntry PLAYER_HEAD_DROP = create("player head.drop enabled", true);
public static final ConfigEntry PLAYER_HEAD_DROP_CHANCE = create("player head.drop chance", 50);
Expand All @@ -79,7 +82,7 @@ public final class Settings extends FlightSettings {
public static final ConfigEntry GUI_MAIN_ITEMS_SEARCH_SLOT = create("gui.main.items.search.slot", 41, "-1 to disable it");
public static final ConfigEntry GUI_MAIN_ITEMS_CUSTOM_CATEGORIES_SLOT = create("gui.main.items.custom categories.slot", 38, "-1 to disable it");
public static final ConfigEntry GUI_MAIN_ITEMS_PLAYER_HEADS_SLOT = create("gui.main.items.player heads.slot", 39, "-1 to disable it");

public static final ConfigEntry GUI_MAIN_ITEMS_RANDOM_HEAD_SLOT = create("gui.main.items.random head.slot", 40, "-1 to disable or turn off completely under 'random head button'");

public static final ConfigEntry GUI_MAIN_ITEMS_ALPHABET_SLOT = create("gui.main.items.alphabet.slot", 11);
public static final ConfigEntry GUI_MAIN_ITEMS_ANIMALS_SLOT = create("gui.main.items.animals.slot", 12);
Expand Down
13 changes: 12 additions & 1 deletion src/main/java/ca/tweetzy/skulls/settings/Translations.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ public Translations(@NonNull JavaPlugin plugin) {
public static final TranslationEntry NO_SKULL_INFO = create("misc.no skull info", "&cCould not determine ID of that skull");
public static final TranslationEntry SKULL_TITLE = create("skull.name", "&e%skull_name%");
public static final TranslationEntry ID_TAKEN = create("misc.id taken", "&cThat category id is already in use!");
public static final TranslationEntry LOADING = create("misc.loading", "&cPlease wait a bit longer, still loading heads.");
public static final TranslationEntry CLAIM_DELAY = create("misc.claim delay", "&cYou can claim another head in &7(&e%time_difference%&7)");
public static final TranslationEntry RECEIVED_RANDOM_SKULL = create("misc.received random skull", "&aYou received a random skull &F(&E%skull_name%&f)");


public static final TranslationEntry ALPHABET = create("categories.alphabet", "Alphabet");
Expand Down Expand Up @@ -174,6 +174,17 @@ public Translations(@NonNull JavaPlugin plugin) {
"&e&lClick &8» &7To view your favourites"
);

public static final TranslationEntry GUI_MAIN_ITEMS_RANDOM_HEAD_NAME = create("gui.main.items.random head.name", "<GRADIENT:DD5E89>&lRandom Head</GRADIENT:fbc7d4>");

public static final TranslationEntry GUI_MAIN_ITEMS_RANDOM_HEAD_LORE = create("gui.main.items.random head.lore",
"&7Used to receive a random head from",
"&7a random category that you have access too.",
"",
"&7Cost: &a$%price%",
"",
"&e&lClick &8» &7To receive a random head"
);

public static final TranslationEntry GUI_MAIN_ITEMS_SEARCH_NAME = create("gui.main.items.search.name", "<GRADIENT:DD5E89>&lSearch</GRADIENT:fbc7d4>");

public static final TranslationEntry GUI_MAIN_ITEMS_SEARCH_LORE = create("gui.main.items.search.lore",
Expand Down
Loading