Compare commits

..

14 Commits

Author SHA1 Message Date
Mighty_Squid d1f6eb6b95 Update `wiki` command to new URL and add tab-completion (#23)
Reviewed-on: Minecraft/QoL#23
Co-authored-by: Mighty_Squid <103967@gmail.com>
Co-committed-by: Mighty_Squid <103967@gmail.com>
2024-08-04 15:49:05 +00:00
benamaurer 0cfb7582bf Adding alternate spelling of color as aliases for color command. (#21)
Added alternate spelling of color as aliases for color command.

- hopefully this is how you're supposed to do this...

Reviewed-on: Minecraft/QoL#21
Co-authored-by: benamaurer <ben.a.maurer@gmail.com>
Co-committed-by: benamaurer <ben.a.maurer@gmail.com>
2022-08-24 01:37:32 +00:00
Joey Hines 0c08c26854 Added Head Shop (#18)
Moved ShopkeepersAPI reference to listener

Moved head shop logic to its own listener

Move checkup command join outside shopkeeper check

Refresh player head on login

+ Cleaned up imports

Use UUID instead of display name to determine if a player is in the shop

Check if Shopkeepers is present before trying to enable it

Added Head Shop

+ Integrates with ShopKeepers
+ On login, users with the `qol.head_shop` perm have their head added to the shop, if not already added
+ The shop id and the price to charge are both configurable

Co-authored-by: Joey Hines <joey@ahines.net>
Reviewed-on: https://git.canopymc.net/Canopy/QoL/pulls/18
Reviewed-by: Etzelia <etzelia@hotmail.com>
Co-Authored-By: ZeroHD <joey@ahines.net>
Co-Committed-By: ZeroHD <joey@ahines.net>
2021-08-10 01:32:17 +00:00
Joey Hines f327f59d6c Added `discordignore` command (#17)
Small tweaks

+ Fixed permission node
+ Removed unused imports

Added `discordignore` command

+ Toggles Discord messages on/off for the user
+ Resolves #16

Co-authored-by: Joey Hines <joey@ahines.net>
Reviewed-on: https://git.canopymc.net/Canopy/QoL/pulls/17
Reviewed-by: Etzelia <etzelia@hotmail.com>
Co-Authored-By: ZeroHD <joey@ahines.net>
Co-Committed-By: ZeroHD <joey@ahines.net>
2021-08-03 02:34:17 +00:00
Mighty_Squid df292f88c5 Add moon phase command (#15)
Add moon phase command

Co-authored-by: Mighty_Squid <103967@gmail.com>
Reviewed-on: https://git.canopymc.net/Canopy/QoL/pulls/15
Reviewed-by: ZeroHD <joey@ahines.net>
Co-Authored-By: Mighty_Squid <mighty_squid@noreply.git.canopymc.net>
Co-Committed-By: Mighty_Squid <mighty_squid@noreply.git.canopymc.net>
2021-08-03 00:29:04 +00:00
Joey Hines fa2f79239e Add Config To Disable Enderman Grief (#14)
Added default config value

Bumped version number

Add config for disabling enderman grief

Co-authored-by: Joey Hines <joey@ahines.net>
Reviewed-on: https://git.canopymc.net/Canopy/QoL/pulls/14
Reviewed-by: Etzelia <etzelia@hotmail.com>
Co-Authored-By: ZeroHD <joey@ahines.net>
Co-Committed-By: ZeroHD <joey@ahines.net>
2021-07-21 00:20:25 +00:00
Mighty_Squid 2e72736571 Initial version of wiki command (#13)
Version 1.12

Initial version of wiki command

Co-authored-by: Mighty_Squid <103967@gmail.com>
Reviewed-on: https://git.canopymc.net/Canopy/QoL/pulls/13
Reviewed-by: Etzelia <etzelia@hotmail.com>
Co-Authored-By: Mighty_Squid <mighty_squid@noreply.git.canopymc.net>
Co-Committed-By: Mighty_Squid <mighty_squid@noreply.git.canopymc.net>
2021-07-19 17:30:59 +00:00
Joey Hines 3c54c249a1 Each player now gets the same reminder (#12)
Each player now gets the same reminder

+ Reminders are logged to console now
+ Fixes #11

Co-authored-by: Joey Hines <joey@ahines.net>
Reviewed-on: https://git.canopymc.net/Canopy/QoL/pulls/12
Reviewed-by: Etzelia <etzelia@hotmail.com>
Co-Authored-By: ZeroHD <joey@ahines.net>
Co-Committed-By: ZeroHD <joey@ahines.net>
2021-07-12 21:36:03 +00:00
Joey Hines 3ae415d7d0 Marked dynmap-api dependency as `provided` (#10)
Marked dynmap-api dependency as `provided`

+ Fixes #9

Co-authored-by: Joey Hines <joey@ahines.net>
Reviewed-on: https://git.canopymc.net/Canopy/QoL/pulls/10
Reviewed-by: Etzelia <etzelia@hotmail.com>
Co-Authored-By: ZeroHD <joey@ahines.net>
Co-Committed-By: ZeroHD <joey@ahines.net>
2021-07-11 16:12:13 +00:00
Joey Hines e3cf0d6d9f Switched to Spark for TPS alerts (#8)
Switched to Spark for TPS alerts

+ Currently just looks at tps, but we could hook in mspt
+ Fixes #6

Co-authored-by: Joey Hines <joey@ahines.net>
Reviewed-on: https://git.canopymc.net/Canopy/QoL/pulls/8
Reviewed-by: Etzelia <etzelia@hotmail.com>
Co-Authored-By: ZeroHD <joey@ahines.net>
Co-Committed-By: ZeroHD <joey@ahines.net>
2021-07-05 14:52:41 +00:00
Joey Hines 3c3fdc1725 Merge pull request 'Added .drone.yml' (#7) from ZeroHD/QoL:iss/5 into main
Reviewed-on: https://git.birbmc.com/Canopy/QoL/pulls/7
Reviewed-by: Etzelia <etzelia@hotmail.com>
2021-06-28 02:30:38 +00:00
Joey Hines 9c316f9fff
why do we even *need* https 2021-06-27 20:18:41 -06:00
Joey Hines e91e5ae9e5
Added .drone.yml 2021-06-27 20:13:43 -06:00
Joey Hines 684b269039 Added reminder groups (#3)
Added reminder groups

+ Multiple reminder groups can be define
+ Reminders still occur as set by the frequency
+ Each group can be configured with its own chat color and period
+ The period config defines how many reminder cycles it takes before that group's next message is used

Co-authored-by: Joey Hines <joey@ahines.net>
Reviewed-on: https://git.birbmc.com/Canopy/QoL/pulls/3
Reviewed-by: Etzelia <etzelia@hotmail.com>
Co-Authored-By: ZeroHD <joey@ahines.net>
Co-Committed-By: ZeroHD <joey@ahines.net>
2021-06-25 16:08:50 +00:00
16 changed files with 584 additions and 68 deletions

36
.drone.yml 100644
View File

@ -0,0 +1,36 @@
---
kind: pipeline
type: docker
name: compliance
steps:
- name: build
image: maven:3-openjdk-16
commands:
- mvn install
---
kind: pipeline
type: docker
name: release
trigger:
branch:
- main
event:
- push
steps:
- name: build
image: maven:3-openjdk-16
commands:
- mvn install
- name: gitea-release
pull: always
image: jolheiser/drone-gitea-main:latest
settings:
token:
from_secret: gitea_token
base: https://git.canopymc.net
files:
- "target/QoL-*.jar"

44
pom.xml
View File

@ -3,7 +3,7 @@
<groupId>xyz.etztech</groupId> <groupId>xyz.etztech</groupId>
<artifactId>QoL</artifactId> <artifactId>QoL</artifactId>
<!-- Version is used in plugin.yml --> <!-- Version is used in plugin.yml -->
<version>1.10</version> <version>1.17</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<!-- Plugin Information --> <!-- Plugin Information -->
@ -37,17 +37,13 @@
<dependency> <dependency>
<groupId>xyz.etztech</groupId> <groupId>xyz.etztech</groupId>
<artifactId>plugin-api</artifactId> <artifactId>plugin-api</artifactId>
<version>1.0.8</version> <version>1.0.7</version>
</dependency>
<dependency>
<groupId>net.ess3</groupId>
<artifactId>EssentialsX</artifactId>
<version>2.18.1</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>us.dynmap</groupId> <groupId>us.dynmap</groupId>
<artifactId>dynmap-api</artifactId> <artifactId>dynmap-api</artifactId>
<version>1.9.4</version> <version>3.5</version>
<scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>commons-lang</groupId> <groupId>commons-lang</groupId>
@ -57,7 +53,19 @@
<dependency> <dependency>
<groupId>com.discordsrv</groupId> <groupId>com.discordsrv</groupId>
<artifactId>discordsrv</artifactId> <artifactId>discordsrv</artifactId>
<version>1.19.1</version> <version>1.27.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>me.lucko</groupId>
<artifactId>spark-api</artifactId>
<version>0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.nisovin.shopkeepers</groupId>
<artifactId>ShopkeepersAPI</artifactId>
<version>2.13.3</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
</dependencies> </dependencies>
@ -72,16 +80,12 @@
<url>https://nexus.scarsz.me/content/groups/public/</url> <url>https://nexus.scarsz.me/content/groups/public/</url>
</repository> </repository>
<repository> <repository>
<id>etztech-repo</id> <id>birbmc-repo</id>
<url>http://repo.etztech.xyz</url> <url>https://mvn.jojodev.com</url>
</repository> </repository>
<repository> <repository>
<id>dynmap-repo</id> <id>dynmap-repo</id>
<url>http://repo.mikeprimm.com/</url> <url>https://repo.mikeprimm.com/</url>
</repository>
<repository>
<id>ess-repo</id>
<url>https://ci.ender.zone/plugin/repository/everything/</url>
</repository> </repository>
<repository> <repository>
<id>mvn-repo</id> <id>mvn-repo</id>
@ -95,6 +99,14 @@
<id>jitpack.io</id> <id>jitpack.io</id>
<url>https://jitpack.io</url> <url>https://jitpack.io</url>
</repository> </repository>
<repository>
<id>sonatype-snapshots</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</repository>
<repository>
<id>shopkeepers-repo</id>
<url>https://repo.projectshard.dev/repository/releases/</url>
</repository>
</repositories> </repositories>
<build> <build>

View File

@ -1,11 +1,13 @@
package xyz.etztech.qol; package xyz.etztech.qol;
import net.ess3.api.IEssentials; import com.nisovin.shopkeepers.api.ShopkeepersPlugin;
import github.scarsz.discordsrv.DiscordSRV;
import net.md_5.bungee.api.chat.BaseComponent;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.plugin.RegisteredServiceProvider;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import org.dynmap.DynmapAPI; import org.dynmap.DynmapAPI;
import org.dynmap.markers.Marker; import org.dynmap.markers.Marker;
@ -15,7 +17,9 @@ import org.dynmap.markers.MarkerSet;
import xyz.etztech.qol.commands.*; import xyz.etztech.qol.commands.*;
import xyz.etztech.qol.listeners.*; import xyz.etztech.qol.listeners.*;
import xyz.etztech.qol.other.LinkCommand; import xyz.etztech.qol.other.LinkCommand;
import xyz.etztech.qol.other.Reminder;
import xyz.etztech.qol.other.TPSRunnable; import xyz.etztech.qol.other.TPSRunnable;
import me.lucko.spark.api.Spark;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -28,7 +32,7 @@ public class QoL extends JavaPlugin {
private String qolMarkerIcon = null; private String qolMarkerIcon = null;
private static QoL instance; private static QoL instance;
private IEssentials essentials = null; private Spark spark = null;
private DynmapAPI dynmap = null; private DynmapAPI dynmap = null;
private MarkerAPI markerAPI = null; private MarkerAPI markerAPI = null;
private MarkerSet playerMarkerSet = null; private MarkerSet playerMarkerSet = null;
@ -45,16 +49,19 @@ public class QoL extends JavaPlugin {
private static List<String> audits = new ArrayList<>(); private static List<String> audits = new ArrayList<>();
private static List<LinkCommand> links = new ArrayList<>(); private static List<LinkCommand> links = new ArrayList<>();
private Reminder reminder = null;
public void onEnable() { public void onEnable() {
instance = this; instance = this;
saveDefaultConfig(); saveDefaultConfig();
reloadConfig(); reloadConfig();
saveResource("qol.png", true); saveResource("qol.png", true);
//Essentials hook //Spark hook
if (Bukkit.getPluginManager().isPluginEnabled("Essentials")) { RegisteredServiceProvider<Spark> sparkProvider = Bukkit.getServicesManager().getRegistration(Spark.class);
log("Hooked into Essentials for TPS alert."); if (sparkProvider != null) {
essentials = (IEssentials) Bukkit.getPluginManager().getPlugin("Essentials"); log("Hooked into Spark for TPS alert.");
spark = sparkProvider.getProvider();
} }
//Dynmap hook //Dynmap hook
@ -84,10 +91,17 @@ public class QoL extends JavaPlugin {
} }
} }
// DiscordSRV Hook
if (Bukkit.getPluginManager().isPluginEnabled("DiscordSRV")) { if (Bukkit.getPluginManager().isPluginEnabled("DiscordSRV")) {
new DiscordSRVListener(this); new DiscordSRVListener(this);
} }
// Shopkeepers Hook
if (Bukkit.getPluginManager().isPluginEnabled("Shopkeepers")) {
new HeadShopListener(this);
log("Hooked in Shopkeepers for the head shop");
}
if( isEnabled() ) { if( isEnabled() ) {
// Add listeners // Add listeners
@ -98,6 +112,7 @@ public class QoL extends JavaPlugin {
new BlockIgniteListener(this); new BlockIgniteListener(this);
new CommandPreprocessListener(this); new CommandPreprocessListener(this);
new DeathListener(this); new DeathListener(this);
new EntityChangeBlockListener(this);
// Add commands // Add commands
new MainCommand(this); new MainCommand(this);
@ -114,6 +129,12 @@ public class QoL extends JavaPlugin {
new DeathMuteCommand(this); new DeathMuteCommand(this);
new CheckupCommand(this); new CheckupCommand(this);
new DynmapLinkCommand(this); new DynmapLinkCommand(this);
new WikiCommand(this);
new MoonCommand(this);
if (DiscordSRV.api.isAnyHooked()) {
new DiscordIgnoreCommand(this);
}
if (dynmap != null) { if (dynmap != null) {
new MarkerCommand(this); new MarkerCommand(this);
@ -136,25 +157,17 @@ public class QoL extends JavaPlugin {
}, 0, EtzTechUtil.minutesToTicks(schedule)); }, 0, EtzTechUtil.minutesToTicks(schedule));
} }
// Reminders if (reminder != null && reminder.getFrequency() != 0) {
int frequency = config.getInt("reminders.frequency");
if (frequency > 0) {
Bukkit.getScheduler().scheduleSyncRepeatingTask(QoL.getInstance(), new Runnable() { Bukkit.getScheduler().scheduleSyncRepeatingTask(QoL.getInstance(), new Runnable() {
int idx = 0;
@Override @Override
public void run() { public void run() {
List<String> reminders = config.getStringList("reminders.messages"); BaseComponent [] msg = reminder.nextReminder();
ChatColor color = ChatColor.getByChar(config.getString("reminders.color").replace("&", ""));
if (idx >= reminders.size()) {
idx = 0;
}
for (Player player : Bukkit.getOnlinePlayers()) { for (Player player : Bukkit.getOnlinePlayers()) {
EtzTechUtil.sms(player, color + reminders.get(idx)); player.spigot().sendMessage(msg);
} }
idx++; Bukkit.getConsoleSender().spigot().sendMessage(msg);
} }
}, 0, EtzTechUtil.minutesToTicks(frequency)); }, 0, EtzTechUtil.minutesToTicks(reminder.getFrequency()));
} }
// TPS Check // TPS Check
@ -186,6 +199,8 @@ public class QoL extends JavaPlugin {
qolMarkerIcon = config.getString("dynmap.marker_icon", "blueflag"); qolMarkerIcon = config.getString("dynmap.marker_icon", "blueflag");
qolMarkerLayerShow = config.getBoolean("dynmap.marker_set_show", false); qolMarkerLayerShow = config.getBoolean("dynmap.marker_set_show", false);
qolMarkerSetLabel = config.getString("dynmap.marker_set_label", "QoL Markers"); qolMarkerSetLabel = config.getString("dynmap.marker_set_label", "QoL Markers");
reminder = Reminder.fromConfig(config.getConfigurationSection("reminders"));
} }
@ -282,8 +297,6 @@ public class QoL extends JavaPlugin {
return links; return links;
} }
public IEssentials getEssentials() { return essentials; }
public DynmapAPI getDynmap() { return dynmap; } public DynmapAPI getDynmap() { return dynmap; }
public void runTask(final String command) { public void runTask(final String command) {
@ -336,5 +349,9 @@ public class QoL extends JavaPlugin {
return marker; return marker;
} }
} }
public Spark getSpark() {
return spark;
}
} }

View File

@ -0,0 +1,55 @@
package xyz.etztech.qol.commands;
import github.scarsz.discordsrv.DiscordSRV;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.metadata.FixedMetadataValue;
import xyz.etztech.qol.EtzTechUtil;
import xyz.etztech.qol.Lang;
import xyz.etztech.qol.QoL;
public class DiscordIgnoreCommand implements CommandExecutor {
public static final String DISCORD_IGNORE_METADATA = "qol.discord_ignore";
QoL plugin;
public DiscordIgnoreCommand(QoL plugin) {
this.plugin = plugin;
plugin.getCommand("discordignore").setExecutor(this);
}
@Override
public boolean onCommand(CommandSender commandSender, Command command, String s, String[] args) {
if (!( commandSender instanceof Player)) {
EtzTechUtil.sms(commandSender, Lang.NO_CONSOLE.getDef());
return true;
}
if (!commandSender.hasPermission("qol.discordignore")) {
EtzTechUtil.sms(commandSender, Lang.NO_PERMISSION.getDef());
return true;
}
if (!DiscordSRV.api.isAnyHooked()) {
EtzTechUtil.sms(commandSender, "Command not enabled!");
return true;
}
Player player = (Player) commandSender;
boolean ignoreState = player.hasMetadata(DISCORD_IGNORE_METADATA);
String msg;
if (ignoreState) {
player.removeMetadata(DISCORD_IGNORE_METADATA, plugin);
msg = "Discord messages will now appear.";
}
else {
player.setMetadata(DISCORD_IGNORE_METADATA, new FixedMetadataValue(plugin, DISCORD_IGNORE_METADATA));
msg = "Ignoring Discord messages.";
}
EtzTechUtil.sms(commandSender, org.bukkit.ChatColor.GREEN + msg);
return true;
}
}

View File

@ -0,0 +1,51 @@
package xyz.etztech.qol.commands;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import xyz.etztech.qol.QoL;
import xyz.etztech.qol.EtzTechUtil;
import xyz.etztech.qol.Lang;
import java.util.Map;
import java.lang.*;
public class MoonCommand implements CommandExecutor {
QoL plugin;
private final Map<Integer, String> moonPhases = Map.of(
0, "Full moon",
1, "Waning gibbous",
2, "Third quarter",
3, "Waning crescent",
4, "New moon",
5, "Waxing crescent",
6, "First quarter",
7, "Waxing gibbous"
);
public MoonCommand(QoL paramQoL) {
this.plugin = paramQoL;
plugin.getCommand("moon").setExecutor(this);
}
@Override
public boolean onCommand(CommandSender commandSender, Command command, String s, String[] args) {
if (!commandSender.hasPermission("qol.moon")) {
EtzTechUtil.sms(commandSender, Lang.NO_PERMISSION.getDef());
return true;
}
String playername = commandSender.getName();
long time = commandSender.getServer().getPlayer(playername).getWorld().getFullTime();
double day = Math.floor(time / 24000);
int moonPhase = (int)(day % 8);
StringBuilder message = new StringBuilder(ChatColor.GOLD + "===== Moon Phase Utility =====");
message.append("\n" + ChatColor.GREEN + "Current moon phase: " + moonPhases.get(moonPhase) + ".");
message.append("\n" + ChatColor.GREEN + "Full moon is " + (moonPhase == 0 ? "tonight." : "in " + (8 - moonPhase) + ((moonPhase == 7) ? " day." : " days.")));
EtzTechUtil.sms(commandSender, message.toString());
return true;
}
}

View File

@ -0,0 +1,97 @@
package xyz.etztech.qol.commands;
import com.google.gson.JsonArray;
import com.google.gson.JsonParser;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.TabExecutor;
import org.bukkit.command.CommandSender;
import xyz.etztech.qol.QoL;
import xyz.etztech.qol.EtzTechUtil;
import xyz.etztech.qol.Lang;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class WikiCommand implements TabExecutor {
QoL plugin;
public WikiCommand(QoL paramQoL) {
this.plugin = paramQoL;
plugin.getCommand("wiki").setExecutor(this);
}
@Override
public boolean onCommand(CommandSender commandSender, Command command, String label, String[] args) {
if (!commandSender.hasPermission("qol.wiki")) {
EtzTechUtil.sms(commandSender, Lang.NO_PERMISSION.getDef());
return true;
}
if (args.length < 1) {
EtzTechUtil.sms(commandSender, ChatColor.RED + "Please give a search argument.");
return true;
}
String query = String.join(" ", args);
List<List<String>> result = getWikiResults(query, 1);
if (result.isEmpty())
{
EtzTechUtil.sms(commandSender, ChatColor.RED + String.format("Nothing was found on the wiki using: %s", query));
return true;
}
String message = ChatColor.GREEN + result.get(0).get(0) + ": " + ChatColor.WHITE + result.get(0).get(1);
EtzTechUtil.sms(commandSender, message);
return true;
}
@Override
public List<String> onTabComplete(CommandSender commandSender, Command command, String label, String[] args) {
String query = String.join(" ", args);
if (query.isEmpty()) return null;
List<List<String>> results = getWikiResults(query, 10);
if (results.isEmpty()) return null;
List<String> completions = new ArrayList<>();
results.forEach((result) -> completions.add(result.get(0)));
return completions;
}
private List<List<String>> getWikiResults(String query, Integer numOfResults) {
try {
InputStream response = new URL(String.format(plugin.getConfig().getString("wiki-base-url", "https://minecraft.wiki:") + "/api.php?action=opensearch&format=json&formatversion=2&search=%s&namespace=0&limit=%d", query, numOfResults)).openStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(response));
JsonArray jsonArray = new JsonParser().parse(reader.readLine()).getAsJsonArray();
JsonArray names = jsonArray.get(1).getAsJsonArray();
JsonArray links = jsonArray.get(3).getAsJsonArray();
// Check if we got any result
if (names.size() < 1)
return Collections.emptyList();
List<List<String>> results = new ArrayList<>();
for (int i = 0; i < names.size(); i++)
{
List<String> e = new ArrayList<>();
e.add(names.get(i).getAsString());
e.add(links.get(i).getAsString());
results.add(e);
}
return results;
} catch(Exception e) {
return Collections.emptyList();
}
}
}

View File

@ -6,8 +6,6 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority; import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.player.AsyncPlayerChatEvent; import org.bukkit.event.player.AsyncPlayerChatEvent;
import org.bukkit.advancement.Advancement;
import org.bukkit.Namespacedkey;
import xyz.etztech.qol.QoL; import xyz.etztech.qol.QoL;
import java.util.Arrays; import java.util.Arrays;
@ -50,16 +48,6 @@ public class AsyncPlayerChatListener implements Listener {
String chat = event.getMessage(); String chat = event.getMessage();
boolean escape = false; boolean escape = false;
//Checking if player has been awarded the chat advancement, if not, message is searched for triggers
Advancement adv = Bukkit.getAdvancement(new Namespacedkey("canopy", "chat_advancement"));
if (!player.getAdvancementProgress(adv).isDone()) {
List<String> advancementTriggerList = plugin.getConfig().getStringList("chat-advancement-triggers");
if (advancementTriggerList.stream().anyMatch(t -> chat.toLowerCase().contains(t.toLowerCase()))) {
player.getAdvancementProgress(adv).awardCriteria("win");
}
}
// Escape // Escape
if (chat.startsWith("\\")) { if (chat.startsWith("\\")) {
escape = true; escape = true;

View File

@ -1,9 +1,15 @@
package xyz.etztech.qol.listeners; package xyz.etztech.qol.listeners;
import github.scarsz.discordsrv.DiscordSRV; import github.scarsz.discordsrv.DiscordSRV;
import github.scarsz.discordsrv.api.events.DiscordGuildMessagePreBroadcastEvent;
import github.scarsz.discordsrv.api.events.GameChatMessagePreProcessEvent; import github.scarsz.discordsrv.api.events.GameChatMessagePreProcessEvent;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import xyz.etztech.qol.EtzTechUtil;
import xyz.etztech.qol.Lang;
import xyz.etztech.qol.QoL; import xyz.etztech.qol.QoL;
import github.scarsz.discordsrv.api.Subscribe; import github.scarsz.discordsrv.api.Subscribe;
import xyz.etztech.qol.commands.DiscordIgnoreCommand;
public class DiscordSRVListener { public class DiscordSRVListener {
private final QoL plugin; private final QoL plugin;
@ -20,4 +26,18 @@ public class DiscordSRVListener {
} }
} }
@Subscribe
public void discordGuildMessagePreBroadcastEvent(DiscordGuildMessagePreBroadcastEvent event) {
event.getRecipients().removeIf(recipient -> {
if (recipient instanceof Player) {
Player player = (Player) recipient;
return player.hasMetadata(DiscordIgnoreCommand.DISCORD_IGNORE_METADATA);
}
else {
return false;
}
});
}
} }

View File

@ -0,0 +1,26 @@
package xyz.etztech.qol.listeners;
import org.bukkit.entity.EntityType;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityChangeBlockEvent;
import xyz.etztech.qol.QoL;
public class EntityChangeBlockListener implements Listener {
QoL plugin;
public EntityChangeBlockListener(QoL plugin) {
this.plugin = plugin;
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
@EventHandler
public void onEntityChangeBlock(EntityChangeBlockEvent e) {
if (e.getEntity().getType() == EntityType.ENDERMAN) {
if(plugin.getConfig().getBoolean("disable-mob-grief.enderman", false)){
e.setCancelled(true);
}
}
}
}

View File

@ -0,0 +1,68 @@
package xyz.etztech.qol.listeners;
import com.nisovin.shopkeepers.api.ShopkeepersPlugin;
import com.nisovin.shopkeepers.api.shopkeeper.ShopkeeperRegistry;
import com.nisovin.shopkeepers.api.shopkeeper.admin.regular.RegularAdminShopkeeper;
import com.nisovin.shopkeepers.api.shopkeeper.offers.TradeOffer;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.SkullMeta;
import xyz.etztech.qol.QoL;
import java.util.ArrayList;
import java.util.List;
public class HeadShopListener implements Listener{
private final QoL plugin;
private final ShopkeepersPlugin shopkeepersAPI;
public HeadShopListener(QoL plugin) {
this.plugin = plugin;
plugin.getServer().getPluginManager().registerEvents(this, plugin);
this.shopkeepersAPI = ShopkeepersPlugin.getInstance();
}
@EventHandler
public void onJoin(PlayerJoinEvent event) {
final Player player = event.getPlayer();
if (shopkeepersAPI != null && player.hasPermission("qol.head_shop")) {
int shopKeeperID = plugin.getConfig().getInt("head_shop.id", -1);
if (shopKeeperID != -1) {
ShopkeeperRegistry shopkeeperRegistry = shopkeepersAPI.getShopkeeperRegistry();
RegularAdminShopkeeper donorHeadShop = (RegularAdminShopkeeper) shopkeeperRegistry.getShopkeeperById(shopKeeperID);
if (donorHeadShop != null) {
// Remove the head if it already exists. This is done to refresh the skin of the head.
List<? extends TradeOffer> tradeOffers = new ArrayList<>(donorHeadShop.getOffers());
tradeOffers.removeIf(tradeOffer -> {
SkullMeta itemOfferMeta = (SkullMeta)tradeOffer.getResultItem().getItemMeta();
return itemOfferMeta.getOwningPlayer().getUniqueId() == player.getUniqueId();
});
donorHeadShop.setOffers(tradeOffers);
// Add the head to the shop
int diamondPrice = plugin.getConfig().getInt("head_shop.price", 2);
ItemStack playerHead = new ItemStack(Material.PLAYER_HEAD);
SkullMeta skullMeta = (SkullMeta) playerHead.getItemMeta();
skullMeta.setOwningPlayer(player);
skullMeta.setDisplayName(player.getDisplayName());
playerHead.setItemMeta(skullMeta);
TradeOffer donorHeadTrade = TradeOffer.create(playerHead, new ItemStack(Material.DIAMOND, diamondPrice), null);
donorHeadShop.addOffer(donorHeadTrade);
}
}
}
}
}

View File

@ -2,13 +2,10 @@ package xyz.etztech.qol.listeners;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerLoginEvent;
import org.dynmap.markers.Marker;
import xyz.etztech.qol.QoL; import xyz.etztech.qol.QoL;
import xyz.etztech.qol.commands.CheckupCommand; import xyz.etztech.qol.commands.CheckupCommand;

View File

@ -0,0 +1,63 @@
package xyz.etztech.qol.other;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.ComponentBuilder;
import org.bukkit.configuration.ConfigurationSection;
import net.md_5.bungee.api.ChatColor;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Reminder {
private final int frequency;
private final List<ReminderList> reminderLists;
public Reminder(int frequency, List<ReminderList> reminderLists) {
this.frequency = frequency;
this.reminderLists = reminderLists;
Collections.sort(reminderLists);
}
public static Reminder fromConfig(ConfigurationSection config) {
int frequency = config.getInt("frequency");
List<ReminderList> reminderLists = new ArrayList();
ConfigurationSection reminderGroups = config.getConfigurationSection("reminder_groups");
for (String groupName: reminderGroups.getKeys(false)) {
ConfigurationSection group = reminderGroups.getConfigurationSection(groupName);
int period = group.getInt("period", 0);
ChatColor color = ChatColor.of(group.getString("color", "#3273DC"));
List<String> reminders = group.getStringList("reminders");
reminderLists.add(new ReminderList(reminders, period, color));
}
return new Reminder(frequency, reminderLists);
}
public BaseComponent[] nextReminder() {
BaseComponent[] msg = null;
boolean reminderFound = false;
for (ReminderList reminderList: reminderLists) {
if (!reminderFound && reminderList.isReady()) {
msg = new ComponentBuilder().
color(reminderList.getColor())
.append(reminderList.nextReminder())
.create();
reminderFound = true;
}
reminderList.incCount();
}
return msg;
}
public int getFrequency() {
return frequency;
}
}

View File

@ -0,0 +1,46 @@
package xyz.etztech.qol.other;
import net.md_5.bungee.api.ChatColor;
import org.jetbrains.annotations.NotNull;
import java.util.List;
public class ReminderList implements Comparable<ReminderList>{
private final List<String> reminders;
private final int period;
private final ChatColor color;
private int ndx;
private int count;
public ReminderList(List<String> reminders, int period, ChatColor color) {
this.reminders = reminders;
this.period = period;
this.color = color;
this.ndx = 0;
this.count = 0;
}
public void incCount() {
count = (count + 1) % (period + 1);
}
public boolean isReady() {
return count == period;
}
public String nextReminder() {
String nextReminder = reminders.get(ndx);
ndx = (ndx + 1) % reminders.size();
return nextReminder;
}
@Override
public int compareTo(@NotNull ReminderList o) {
return Integer.compare(o.period, this.period);
}
public ChatColor getColor() {
return color;
}
}

View File

@ -1,9 +1,11 @@
package xyz.etztech.qol.other; package xyz.etztech.qol.other;
import net.ess3.api.IEssentials; import me.lucko.spark.api.statistic.StatisticWindow;
import me.lucko.spark.api.statistic.types.DoubleStatistic;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import xyz.etztech.core.web.Http; import xyz.etztech.core.web.Http;
import xyz.etztech.qol.QoL; import xyz.etztech.qol.QoL;
import me.lucko.spark.api.Spark;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -18,13 +20,13 @@ public class TPSRunnable implements Runnable {
@Override @Override
public void run() { public void run() {
IEssentials essentials = plugin.getEssentials(); Spark spark = plugin.getSpark();
if (essentials != null) { if (spark != null) {
double tps = essentials.getTimer().getAverageTPS(); DoubleStatistic<StatisticWindow.TicksPerSecond> tps = spark.tps();
int threshold = plugin.getConfig().getInt("tps.threshold", 0); int threshold = plugin.getConfig().getInt("tps.threshold", 0);
String webhook = plugin.getConfig().getString("tps.webhook", ""); String webhook = plugin.getConfig().getString("tps.webhook", "");
String message = "@here TPS has fallen below " + threshold + "!"; String message = "@here TPS has fallen below " + threshold + "!";
if (tps < threshold) { if (tps.poll(StatisticWindow.TicksPerSecond.SECONDS_10) < threshold) {
plugin.log(message); plugin.log(message);
if (StringUtils.isNotEmpty(webhook)) { if (StringUtils.isNotEmpty(webhook)) {
Map<String, String> data = new HashMap<>(); Map<String, String> data = new HashMap<>();

View File

@ -60,10 +60,19 @@ schedule:
# To disable, set minutes to 0 # To disable, set minutes to 0
reminders: reminders:
frequency: 5 # In minutes frequency: 1 # In minutes
color: '&a' reminder_groups:
messages: standard:
- 'Check out the Discord!' color: '#3273DC'
reminders:
- '1st Standard Reminder'
- '2nd Standard Reminder'
event:
color: '#3273DC'
period: 2
reminders:
- '1st Event Reminder'
- '2nd Event Reminder'
# A list of links for link command aliases, separated by a comma between name and URL # A list of links for link command aliases, separated by a comma between name and URL
links: links:
@ -84,6 +93,9 @@ disable-fire:
ender_crystal: false ender_crystal: false
explosion: false explosion: false
disable-mob-grief:
enderman: false
# A list of commands to confirm before using if the user isn't in spectator mode # A list of commands to confirm before using if the user isn't in spectator mode
spec-confirm: spec-confirm:
- "tp" - "tp"
@ -105,6 +117,12 @@ dynmap:
map: "surface" map: "surface"
zoom: 5 zoom: 5
# A list of words/phrases which will award the chant advancement to the message author # Shopkeepers Player Head Shop
chat-advancement-triggers: head_shop:
- chat_advancment_test # Shopkeeper Shop ID, set to -1 to disable
id: -1
# Diamond price of a head in the shop, default is 2 diamonds
price: 2
# Base URL for the /wiki command. Should support a https://www.mediawiki.org/wiki/API:Opensearch request
wiki-base-url: 'https://minecraft.wiki'

View File

@ -4,13 +4,14 @@ description: ${description}
author: ${author} author: ${author}
website: ${url} website: ${url}
main: ${mainClass} main: ${mainClass}
softdepend: [Essentials, dynmap, DiscordSRV] softdepend: [spark, dynmap, DiscordSRV, Shopkeepers]
api-version: 1.13
commands: commands:
qol: qol:
description: Base command description: Base command
colors: colors:
description: See all color/formatting codes description: See all color/formatting codes
aliases: [color, c] aliases: [color, c, colour, colours]
list: list:
description: See a list of players description: See a list of players
aliases: [players, playerlist] aliases: [players, playerlist]
@ -46,6 +47,13 @@ commands:
marker: marker:
description: Dynmap marker command description: Dynmap marker command
aliases: [mark] aliases: [mark]
wiki:
description: Search the Minecraft wiki
moon:
description: Get information about the current moon phase
discordignore:
description: Mute chat messages coming from Discord
aliases: [dignore]
permissions: permissions:
qol.admin: qol.admin:
description: Ability to reload the plugin description: Ability to reload the plugin
@ -116,3 +124,15 @@ permissions:
default: op default: op
children: children:
qol.marker.limit: true qol.marker.limit: true
qol.wiki:
description: Ability to use the wiki command
default: op
qol.moon:
description: Ability to use the moon command
default: op
qol.discordignore:
description: Ability to use the use the discordignore command
default: op
qol.head_shop:
description: Controls if a player's head should be added to the head shop
default: op