Compare commits

..

18 Commits

Author SHA1 Message Date
131d131dfe Trying to fix villager spawn 2024-02-05 22:47:19 +01:00
c9dd268c14 Feat: Change way of handling voids
Only store to database when fetching scoreboard or on disconnect.
else just use the persistentStorage from players
2024-02-04 21:38:28 +01:00
a7a88bb619 Log Voids interaction
This is just in case the server would crash and not save current score.
log can be used to see what was the last score at some point
2024-02-04 21:29:03 +01:00
d92a8c6125 Seend a death message to the webhook 2024-02-04 21:28:26 +01:00
30be45065f Need thevoidmanager.score to execute /void score 2024-02-04 21:27:53 +01:00
f36e6b1aa0 Refactoring 2024-01-31 12:34:04 +01:00
629695ac21 Item drop bug 2024-01-31 12:27:38 +01:00
8bf35896f4 /void manage bring command 2024-01-29 18:25:13 +01:00
1d34a3040d Show Custom Name 2024-01-29 18:23:02 +01:00
af96c5a412 todos 2024-01-27 13:09:58 +01:00
105d564ec0 Notification on /void give 2024-01-27 00:17:47 +01:00
a7fdff2dd9 Next Item In Merchand 2024-01-27 00:17:24 +01:00
2b2683b22b Discord Binding 2024-01-26 23:47:46 +01:00
402b94a797 Check if give is not negative 2024-01-26 23:38:12 +01:00
56b7ae97ef removing uncraftable tuff stuff 2024-01-26 21:31:55 +01:00
b08fb8e5a4 Names 2024-01-26 21:25:48 +01:00
f61e6d865e Discord link 2024-01-26 20:10:45 +01:00
2f24f61b16 Unban Command 2024-01-26 19:00:03 +01:00
13 changed files with 925 additions and 56 deletions

19
TODO.md Normal file
View File

@ -0,0 +1,19 @@
# TODO list
- [x] deathBan reset
- [x] voids exchanges
- [x] /void give négatives values
- [x] Make Discord Webhoook for item changes
- [x] chest name
- [x] Show next Item
- [x] /void manage bring
- [+] /void give afficher title
- subtitle + chat
- [+] Double Check Inventory reset on die
- [+] Annonce
- [+] Find Map : 51 (250, 300)
- [+] Dupe bug (respawn)
- [-] i18n
- [ ] Events
- [ ] Command completions
- [ ] More descriptive /void commands

View File

@ -20,6 +20,23 @@ public class BanHourly implements Listener{
@EventHandler @EventHandler
public void died(PlayerDeathEvent e){ public void died(PlayerDeathEvent e){
DatabaseManager.getInstance().setDeath(e.getPlayer().getUniqueId()); DatabaseManager.getInstance().setDeath(e.getPlayer().getUniqueId());
e.setKeepInventory(true);
e.setKeepLevel(false);
e.getDrops().clear();
e.getPlayer().kick(Component.text("Vous etes mort dans la dernière heure... Patientez la prochaine!"), Cause.BANNED); e.getPlayer().kick(Component.text("Vous etes mort dans la dernière heure... Patientez la prochaine!"), Cause.BANNED);
// Send death
String link = DatabaseManager.getInstance().getConfig("discord-wh");
if(!link.equals("")){
DiscordWebhook discord = new DiscordWebhook(link);
discord.setUsername("Ange de la mort");
discord.setAvatarUrl("http://static.planetminecraft.com/files/banners/minecraft_banner_18d1g881yg5831c.png");
discord.setContent(e.getDeathMessage());
try {
discord.execute();
} catch(Exception ex){
ex.printStackTrace();
}
}
} }
} }

View File

@ -67,6 +67,7 @@ public class DatabaseManager {
} }
public void setVoids(UUID uuid, int amount) { public void setVoids(UUID uuid, int amount) {
Bukkit.getLogger().info("[VOIDS] -> " + uuid.toString() + " to " + amount);
try { try {
Statement st = con.createStatement(); Statement st = con.createStatement();
String query = "INSERT OR REPLACE INTO voids (uuid, amount) VALUES (?, ?)"; String query = "INSERT OR REPLACE INTO voids (uuid, amount) VALUES (?, ?)";
@ -176,6 +177,18 @@ public class DatabaseManager {
return false; return false;
} }
public void unban(UUID uuid) {
try {
Statement st = con.createStatement();
String query = "INSERT OR REPLACE INTO deaths (uuid, lastDeath) SELECT uuid, lastDeath - 1 FROM deaths WHERE uuid = ?";
PreparedStatement p = con.prepareStatement(query);
p.setString(1, uuid.toString());
p.execute();
st.close();
} catch(Exception e){
e.printStackTrace();
}
}
public void close(){ public void close(){
try { try {

View File

@ -0,0 +1,392 @@
package ovh.herisson.thevoidroad;
import javax.net.ssl.HttpsURLConnection;
import java.awt.Color;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Array;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Class used to execute Discord Webhooks with low effort
* @source https://gist.github.com/k3kdude/fba6f6b37594eae3d6f9475330733bdb
*/
public class DiscordWebhook {
private final String url;
private String content;
private String username;
private String avatarUrl;
private boolean tts;
private List<EmbedObject> embeds = new ArrayList<>();
/**
* Constructs a new DiscordWebhook instance
*
* @param url The webhook URL obtained in Discord
*/
public DiscordWebhook(String url) {
this.url = url;
}
public void setContent(String content) {
this.content = content;
}
public void setUsername(String username) {
this.username = username;
}
public void setAvatarUrl(String avatarUrl) {
this.avatarUrl = avatarUrl;
}
public void setTts(boolean tts) {
this.tts = tts;
}
public void addEmbed(EmbedObject embed) {
this.embeds.add(embed);
}
public void execute() throws IOException {
if (this.content == null && this.embeds.isEmpty()) {
throw new IllegalArgumentException("Set content or add at least one EmbedObject");
}
JSONObject json = new JSONObject();
json.put("content", this.content);
json.put("username", this.username);
json.put("avatar_url", this.avatarUrl);
json.put("tts", this.tts);
if (!this.embeds.isEmpty()) {
List<JSONObject> embedObjects = new ArrayList<>();
for (EmbedObject embed : this.embeds) {
JSONObject jsonEmbed = new JSONObject();
jsonEmbed.put("title", embed.getTitle());
jsonEmbed.put("description", embed.getDescription());
jsonEmbed.put("url", embed.getUrl());
if (embed.getColor() != null) {
Color color = embed.getColor();
int rgb = color.getRed();
rgb = (rgb << 8) + color.getGreen();
rgb = (rgb << 8) + color.getBlue();
jsonEmbed.put("color", rgb);
}
EmbedObject.Footer footer = embed.getFooter();
EmbedObject.Image image = embed.getImage();
EmbedObject.Thumbnail thumbnail = embed.getThumbnail();
EmbedObject.Author author = embed.getAuthor();
List<EmbedObject.Field> fields = embed.getFields();
if (footer != null) {
JSONObject jsonFooter = new JSONObject();
jsonFooter.put("text", footer.getText());
jsonFooter.put("icon_url", footer.getIconUrl());
jsonEmbed.put("footer", jsonFooter);
}
if (image != null) {
JSONObject jsonImage = new JSONObject();
jsonImage.put("url", image.getUrl());
jsonEmbed.put("image", jsonImage);
}
if (thumbnail != null) {
JSONObject jsonThumbnail = new JSONObject();
jsonThumbnail.put("url", thumbnail.getUrl());
jsonEmbed.put("thumbnail", jsonThumbnail);
}
if (author != null) {
JSONObject jsonAuthor = new JSONObject();
jsonAuthor.put("name", author.getName());
jsonAuthor.put("url", author.getUrl());
jsonAuthor.put("icon_url", author.getIconUrl());
jsonEmbed.put("author", jsonAuthor);
}
List<JSONObject> jsonFields = new ArrayList<>();
for (EmbedObject.Field field : fields) {
JSONObject jsonField = new JSONObject();
jsonField.put("name", field.getName());
jsonField.put("value", field.getValue());
jsonField.put("inline", field.isInline());
jsonFields.add(jsonField);
}
jsonEmbed.put("fields", jsonFields.toArray());
embedObjects.add(jsonEmbed);
}
json.put("embeds", embedObjects.toArray());
}
URL url = new URL(this.url);
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
connection.addRequestProperty("Content-Type", "application/json");
connection.addRequestProperty("User-Agent", "Java-DiscordWebhook-BY-Gelox_");
connection.setDoOutput(true);
connection.setRequestMethod("POST");
OutputStream stream = connection.getOutputStream();
stream.write(json.toString().getBytes());
stream.flush();
stream.close();
connection.getInputStream().close(); //I'm not sure why but it doesn't work without getting the InputStream
connection.disconnect();
}
public static class EmbedObject {
private String title;
private String description;
private String url;
private Color color;
private Footer footer;
private Thumbnail thumbnail;
private Image image;
private Author author;
private List<Field> fields = new ArrayList<>();
public String getTitle() {
return title;
}
public String getDescription() {
return description;
}
public String getUrl() {
return url;
}
public Color getColor() {
return color;
}
public Footer getFooter() {
return footer;
}
public Thumbnail getThumbnail() {
return thumbnail;
}
public Image getImage() {
return image;
}
public Author getAuthor() {
return author;
}
public List<Field> getFields() {
return fields;
}
public EmbedObject setTitle(String title) {
this.title = title;
return this;
}
public EmbedObject setDescription(String description) {
this.description = description;
return this;
}
public EmbedObject setUrl(String url) {
this.url = url;
return this;
}
public EmbedObject setColor(Color color) {
this.color = color;
return this;
}
public EmbedObject setFooter(String text, String icon) {
this.footer = new Footer(text, icon);
return this;
}
public EmbedObject setThumbnail(String url) {
this.thumbnail = new Thumbnail(url);
return this;
}
public EmbedObject setImage(String url) {
this.image = new Image(url);
return this;
}
public EmbedObject setAuthor(String name, String url, String icon) {
this.author = new Author(name, url, icon);
return this;
}
public EmbedObject addField(String name, String value, boolean inline) {
this.fields.add(new Field(name, value, inline));
return this;
}
private class Footer {
private String text;
private String iconUrl;
private Footer(String text, String iconUrl) {
this.text = text;
this.iconUrl = iconUrl;
}
private String getText() {
return text;
}
private String getIconUrl() {
return iconUrl;
}
}
private class Thumbnail {
private String url;
private Thumbnail(String url) {
this.url = url;
}
private String getUrl() {
return url;
}
}
private class Image {
private String url;
private Image(String url) {
this.url = url;
}
private String getUrl() {
return url;
}
}
private class Author {
private String name;
private String url;
private String iconUrl;
private Author(String name, String url, String iconUrl) {
this.name = name;
this.url = url;
this.iconUrl = iconUrl;
}
private String getName() {
return name;
}
private String getUrl() {
return url;
}
private String getIconUrl() {
return iconUrl;
}
}
private class Field {
private String name;
private String value;
private boolean inline;
private Field(String name, String value, boolean inline) {
this.name = name;
this.value = value;
this.inline = inline;
}
private String getName() {
return name;
}
private String getValue() {
return value;
}
private boolean isInline() {
return inline;
}
}
}
private class JSONObject {
private final HashMap<String, Object> map = new HashMap<>();
void put(String key, Object value) {
if (value != null) {
map.put(key, value);
}
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
Set<Map.Entry<String, Object>> entrySet = map.entrySet();
builder.append("{");
int i = 0;
for (Map.Entry<String, Object> entry : entrySet) {
Object val = entry.getValue();
builder.append(quote(entry.getKey())).append(":");
if (val instanceof String) {
builder.append(quote(String.valueOf(val)));
} else if (val instanceof Integer) {
builder.append(Integer.valueOf(String.valueOf(val)));
} else if (val instanceof Boolean) {
builder.append(val);
} else if (val instanceof JSONObject) {
builder.append(val.toString());
} else if (val.getClass().isArray()) {
builder.append("[");
int len = Array.getLength(val);
for (int j = 0; j < len; j++) {
builder.append(Array.get(val, j).toString()).append(j != len - 1 ? "," : "");
}
builder.append("]");
}
builder.append(++i == entrySet.size() ? "}" : ",");
}
return builder.toString();
}
private String quote(String string) {
return "\"" + string + "\"";
}
}
}

View File

@ -1,4 +1,4 @@
package ovh.herisson.thevoidroad.Event; package ovh.herisson.thevoidroad;
import java.time.LocalTime; import java.time.LocalTime;

View File

@ -1,4 +1,4 @@
package ovh.herisson.thevoidroad.Entity; package ovh.herisson.thevoidroad;
import java.io.File; import java.io.File;
import java.nio.file.Files; import java.nio.file.Files;
@ -15,9 +15,7 @@ import org.bukkit.entity.Player;
import org.bukkit.entity.Villager; import org.bukkit.entity.Villager;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryAction;
import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryInteractEvent;
import org.bukkit.event.player.PlayerInteractEntityEvent; import org.bukkit.event.player.PlayerInteractEntityEvent;
import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.world.EntitiesLoadEvent; import org.bukkit.event.world.EntitiesLoadEvent;
@ -26,18 +24,14 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.persistence.PersistentDataType; import org.bukkit.persistence.PersistentDataType;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import ovh.herisson.thevoidroad.DatabaseManager;
import ovh.herisson.thevoidroad.TheVoidRoad;
import ovh.herisson.thevoidroad.Voids;
import ovh.herisson.thevoidroad.Event.HourEvent;
import ovh.herisson.thevoidroad.util.Tuple;
//Unique, so singleton patern //Unique, so singleton patern
public class Merchand implements Listener{ public class Merchand implements Listener{
public static Tuple<Material, Integer> current, next; public static Tuple<Material, Integer> current, next;
private static Merchand instance; private static Merchand instance;
private static final ArrayList<Material> mat = new ArrayList<>(); private static final ArrayList<Material> mat = new ArrayList<>();
private final Inventory inv; private static final ArrayList<String> names = new ArrayList<>();
private static Inventory inv;
private Villager m ; private Villager m ;
private static final NamespacedKey tagger = new NamespacedKey(TheVoidRoad.instance, "merchand") ; private static final NamespacedKey tagger = new NamespacedKey(TheVoidRoad.instance, "merchand") ;
@ -49,7 +43,8 @@ public class Merchand implements Listener{
} }
private Merchand() { private Merchand() {
inv = Bukkit.createInventory(null, 9);
//Get file materials
File f = new File(TheVoidRoad.instance.getDataFolder(), "materials.txt"); File f = new File(TheVoidRoad.instance.getDataFolder(), "materials.txt");
try { try {
for (String s : Files.readAllLines(f.toPath())) { for (String s : Files.readAllLines(f.toPath())) {
@ -58,22 +53,38 @@ public class Merchand implements Listener{
} catch(Exception e){ } catch(Exception e){
e.printStackTrace(); e.printStackTrace();
} }
f = new File(TheVoidRoad.instance.getDataFolder(), "names.txt");
try {
for (String s : Files.readAllLines(f.toPath())) {
names.add(s);
}
} catch(Exception e){
e.printStackTrace();
}
//Is the game inited
if(DatabaseManager.getInstance().getConfig("init") != null && if(DatabaseManager.getInstance().getConfig("init") != null &&
DatabaseManager.getInstance().getConfig("init").equalsIgnoreCase("true")){ DatabaseManager.getInstance().getConfig("init").equalsIgnoreCase("true")){
regenerate(); regenerate();
} }
//Webhook connection
} }
public void regenerate(){ public void regenerate(){
if(m != null){ m.remove(); } if(m != null){ m.remove(); }
current = genTrade(System.currentTimeMillis() / (1000 * 60 * 60)); current = genTrade(System.currentTimeMillis() / (1000 * 60 * 60));
next = genTrade(1 + System.currentTimeMillis() / (1000 * 60 * 60));
Location center = Bukkit.getWorld("world").getWorldBorder().getCenter(); Location center = Bukkit.getWorld("world").getWorldBorder().getCenter();
double brdSize = Bukkit.getWorld("world").getWorldBorder().getSize(); double brdSize = Bukkit.getWorld("world").getWorldBorder().getSize() - 1;
double x = new Random().nextDouble(brdSize) - brdSize/2, z = new Random().nextDouble(brdSize) - brdSize/2; double x = new Random().nextDouble(brdSize) - brdSize/2, z = new Random().nextDouble(brdSize) - brdSize/2;
m = (Villager) Bukkit.getWorld("world").spawnEntity(center.add(x, 100, z), EntityType.VILLAGER); m = (Villager) Bukkit.getWorld("world").spawnEntity(center.add(x, 200, z), EntityType.VILLAGER);
m.getPersistentDataContainer().set(tagger, PersistentDataType.BOOLEAN, true); m.getPersistentDataContainer().set(tagger, PersistentDataType.BOOLEAN, true);
m.setGlowing(true); m.setGlowing(true);
m.setInvulnerable(true); m.setInvulnerable(true);
m.customName(Component.text(names.get(new Random().nextInt(names.size()))));
m.setCustomNameVisible(true);
inv = Bukkit.createInventory(null, 9, Component.text(m.getName()));
Bukkit.getServer().forEachAudience((a) -> { Bukkit.getServer().forEachAudience((a) -> {
if(a instanceof Player ply){ if(a instanceof Player ply){
ply.setCompassTarget(m.getLocation()); ply.setCompassTarget(m.getLocation());
@ -106,6 +117,17 @@ public class Merchand implements Listener{
public void onHour(HourEvent e){ public void onHour(HourEvent e){
current = genTrade(e.unixhour); current = genTrade(e.unixhour);
next = genTrade(e.unixhour + 1); next = genTrade(e.unixhour + 1);
String link = DatabaseManager.getInstance().getConfig("discord-wh");
if(!link.equals("")){
DiscordWebhook discord = new DiscordWebhook(link);
discord.setUsername(m.getName());
discord.setContent("Salut, Je vend actuellement `" + current.x + "` au prix de " + current.y + TheVoidRoad.CoinGlyph);
try {
discord.execute();
} catch(Exception ex){
ex.printStackTrace();
}
}
regenerate(); regenerate();
} }
@ -115,6 +137,9 @@ public class Merchand implements Listener{
e.setCancelled(true); e.setCancelled(true);
inv.clear(); inv.clear();
inv.setItem(4, new ItemStack(current.x, current.y)); inv.setItem(4, new ItemStack(current.x, current.y));
ItemStack nextItem = new ItemStack(next.x,next.y);
nextItem.editMeta(m ->{ m.setDisplayName("Prochain item en vente"); });
inv.setItem(8, nextItem);
e.getPlayer().openInventory(inv); e.getPlayer().openInventory(inv);
} }
} }
@ -138,7 +163,7 @@ public class Merchand implements Listener{
//Do we have the item and if so remove them //Do we have the item and if so remove them
if(ply.getInventory().contains(current.x)){ if(ply.getInventory().contains(current.x)){
for (ItemStack i : ply.getInventory().getContents()) { for (ItemStack i : ply.getInventory().getContents()) {
if(i.getType() == current.x){ if(i != null && i.getType() == current.x){
i.subtract(1); i.subtract(1);
Voids.add(ply, current.y); Voids.add(ply, current.y);
return; return;
@ -147,4 +172,8 @@ public class Merchand implements Listener{
} }
} }
} }
public void teleport(Location location) {
m.teleport(location);
}
} }

View File

@ -2,9 +2,9 @@ package ovh.herisson.thevoidroad;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import ovh.herisson.thevoidroad.Commands.VoidCommands; import ovh.herisson.thevoidroad.VoidCommands;
import ovh.herisson.thevoidroad.Entity.Merchand; import ovh.herisson.thevoidroad.Merchand;
import ovh.herisson.thevoidroad.Event.HourEvent; import ovh.herisson.thevoidroad.HourEvent;
public class TheVoidRoad extends JavaPlugin{ public class TheVoidRoad extends JavaPlugin{
@ -21,6 +21,7 @@ public class TheVoidRoad extends JavaPlugin{
public void onEnable(){ public void onEnable(){
saveResource("materials.txt", false); saveResource("materials.txt", false);
saveResource("names.txt", false);
//Commands //Commands
getCommand("void").setExecutor(new VoidCommands()); getCommand("void").setExecutor(new VoidCommands());

View File

@ -1,4 +1,4 @@
package ovh.herisson.thevoidroad.util; package ovh.herisson.thevoidroad;
public class Tuple<X, Y> { public class Tuple<X, Y> {
public final X x; public final X x;

View File

@ -1,7 +1,8 @@
package ovh.herisson.thevoidroad.Commands; package ovh.herisson.thevoidroad;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.UUID;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
@ -13,10 +14,6 @@ import org.bukkit.command.TabCompleter;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import ovh.herisson.thevoidroad.DatabaseManager;
import ovh.herisson.thevoidroad.TheVoidRoad;
import ovh.herisson.thevoidroad.Voids;
import ovh.herisson.thevoidroad.Entity.Merchand;
public class VoidCommands implements CommandExecutor, TabCompleter{ public class VoidCommands implements CommandExecutor, TabCompleter{
private final Merchand m = Merchand.getInstance(); private final Merchand m = Merchand.getInstance();
@ -35,13 +32,19 @@ public class VoidCommands implements CommandExecutor, TabCompleter{
} }
switch (args[0]) { switch (args[0]) {
case "score": case "score":
Voids.scoreboard().forEach((p, a) -> { if(!sender.hasPermission("void.score")){
sender.sendMessage(p + " : " + a); Voids.scoreboard().forEach((p, a) -> {
}); sender.sendMessage(p + " : " + a);
return true; });
return true;
}
return false;
case "give": case "give":
//TODO(Balance): Give to a player if(args.length < 2) return false;
return true; Player target = Bukkit.getPlayer(args[1]);
if(target != null && sender instanceof Player ply && Integer.parseInt(args[2]) > 0)
Voids.give(ply,target, Integer.parseInt(args[2]));
break;
case "event": case "event":
//TODO(event) manage event //TODO(event) manage event
return true; return true;
@ -58,6 +61,10 @@ public class VoidCommands implements CommandExecutor, TabCompleter{
case "reset": case "reset":
DatabaseManager.getInstance().setConfig("init", "false"); DatabaseManager.getInstance().setConfig("init", "false");
break; break;
case "unban":
UUID target_uuid = Bukkit.getPlayerUniqueId(args[2]);
DatabaseManager.getInstance().unban(target_uuid);
return true;
case "skip": case "skip":
//TODO(Merchand): Skip trade //TODO(Merchand): Skip trade
break; break;
@ -68,16 +75,21 @@ public class VoidCommands implements CommandExecutor, TabCompleter{
sender.sendMessage("You can't teleport!"); sender.sendMessage("You can't teleport!");
} }
break; break;
case "bring":
if(sender instanceof Player ply && m.getLocation() != null){
m.teleport(ply.getLocation());
}else{
return false;
}
break;
case "balance": case "balance":
if(args.length < 5) return false; if(args.length < 5) return false;
switch (args[2]) { switch (args[2]) {
case "set": case "set":
Player target = Bukkit.getPlayer(args[3]); Player target_ = Bukkit.getPlayer(args[3]);
Voids.set(target, Integer.parseInt(args[4])); Voids.set(target_, Integer.parseInt(args[4]));
return true; return true;
case "add":
case "sub":
sender.sendMessage("TODO"); //TODO
} }
return false; return false;
} }
@ -100,14 +112,17 @@ public class VoidCommands implements CommandExecutor, TabCompleter{
} }
@Override @Override
public List<String> onTabComplete(CommandSender sender, Command command, String label, String[] args) { public List<String> onTabComplete(CommandSender sender, Command command, String label, String[] args) { //TODO: add all commands
ArrayList<String> list = new ArrayList<>(); ArrayList<String> list = new ArrayList<>();
if(args.length == 1){ if(args.length == 1){
list.addAll(List.of("give","event", "score")); list.addAll(List.of("give","event"));
if(sender.hasPermission("void.manage")){ if(sender.hasPermission("void.manage")){
list.add("manage"); list.add("manage");
} }
if(sender.hasPermission("void.score")){
list.add("score");
}
} }
if(args.length >= 2){ if(args.length >= 2){
switch (args[0]) { switch (args[0]) {
@ -117,7 +132,7 @@ public class VoidCommands implements CommandExecutor, TabCompleter{
return list; return list;
case "manage": case "manage":
if(sender.hasPermission("void.manage")){ if(sender.hasPermission("void.manage")){
if(args[1] == "balance"){ if(args[1] == "balance" && args.length <= 3){
list.addAll(List.of("set", "add", "sub")); list.addAll(List.of("set", "add", "sub"));
return list; return list;
} }

View File

@ -5,57 +5,74 @@ import java.util.HashMap;
import java.util.UUID; import java.util.UUID;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.NamespacedKey;
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.PlayerQuitEvent;
import org.bukkit.persistence.PersistentDataType;
import org.bukkit.scoreboard.Criteria; import org.bukkit.scoreboard.Criteria;
import org.bukkit.scoreboard.DisplaySlot; import org.bukkit.scoreboard.DisplaySlot;
import org.bukkit.scoreboard.Objective; import org.bukkit.scoreboard.Objective;
import org.bukkit.scoreboard.RenderType;
import org.bukkit.scoreboard.Score; import org.bukkit.scoreboard.Score;
import org.bukkit.scoreboard.Scoreboard; import org.bukkit.scoreboard.Scoreboard;
import org.bukkit.scoreboard.ScoreboardManager;
import net.kyori.adventure.bossbar.BossBar; import net.kyori.adventure.bossbar.BossBar;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.title.Title;
public final class Voids implements Listener{ public final class Voids implements Listener{
private static HashMap<Player, BossBar> bossbars = new HashMap<>(); private static HashMap<Player, BossBar> bossbars = new HashMap<>();
private static final NamespacedKey voids = new NamespacedKey(TheVoidRoad.instance, "voids");
public static int get(Player ply){ public static int get(Player ply){
if(ply.getPersistentDataContainer().has(voids)){
return ply.getPersistentDataContainer().get(voids, PersistentDataType.INTEGER);
}
return TheVoidRoad.db.getVoids(ply.getUniqueId()); return TheVoidRoad.db.getVoids(ply.getUniqueId());
} }
public static void set(Player ply, int amount){ public static void set(Player ply, int amount){
TheVoidRoad.db.setVoids(ply.getUniqueId(), amount); ply.getPersistentDataContainer().set(voids, PersistentDataType.INTEGER, amount);
UpdateVoids(ply); UpdateVoids(ply);
} }
public static void add(Player ply, int amount){ public static void add(Player ply, int amount){
int curr = DatabaseManager.getInstance().getVoids(ply.getUniqueId()); int curr = get(ply);
DatabaseManager.getInstance().setVoids(ply.getUniqueId(), curr + amount); set(ply, curr + amount);
UpdateVoids(ply); UpdateVoids(ply);
} }
public static boolean subtract(Player ply, int amount, boolean force){ public static boolean subtract(Player ply, int amount, boolean force){
int curr = TheVoidRoad.db.getVoids(ply.getUniqueId()); int curr = get(ply);
if(curr - amount < 0 && !force) return false; if(curr - amount < 0 && !force) return false;
TheVoidRoad.db.setVoids(ply.getUniqueId(), curr - amount); set(ply, curr - amount);
UpdateVoids(ply); UpdateVoids(ply);
return true; return true;
} }
public static boolean give(Player giver, Player receiver, int amount){ public static boolean give(Player giver, Player receiver, int amount){
if(subtract(giver, amount, false)){ if( amount < 0 || !subtract(giver, amount, false))
add(receiver, amount); return false;
return true; add(receiver, amount);
} giver.sendMessage("Vous avez donné " + amount + TheVoidRoad.CoinGlyph + " à " + receiver.getName());
return false; receiver.sendMessage("Vous avez reçu " + amount + TheVoidRoad.CoinGlyph + " de " + giver.getName());
receiver.showTitle(Title.title(Component.empty(), Component.text("+" + amount + TheVoidRoad.CoinGlyph + " from " + giver.getName()).color(NamedTextColor.GREEN)));
return true;
}
public static void save(Player ply){
int curr = get(ply);
TheVoidRoad.db.setVoids(ply.getUniqueId(), curr);
} }
public static HashMap<Player, Integer> scoreboard(){ public static HashMap<Player, Integer> scoreboard(){
Bukkit.getServer().forEachAudience(a -> {
if(a instanceof Player ply) save(ply);
});
HashMap<Player, Integer> ret = new HashMap<>(); HashMap<Player, Integer> ret = new HashMap<>();
try { try {
HashMap<UUID, Integer> scores_uuid = TheVoidRoad.db.getVoidsScoreboard(); HashMap<UUID, Integer> scores_uuid = TheVoidRoad.db.getVoidsScoreboard();
@ -91,4 +108,9 @@ public final class Voids implements Listener{
public void UpdateVoids(PlayerJoinEvent e){ public void UpdateVoids(PlayerJoinEvent e){
UpdateVoids(e.getPlayer()); UpdateVoids(e.getPlayer());
} }
@EventHandler
public void SaveToDbBeforeQuit(PlayerQuitEvent e){
save(e.getPlayer());
}
} }

View File

@ -10,13 +10,6 @@ COBBLED_DEEPSLATE
POLISHED_DEEPSLATE POLISHED_DEEPSLATE
CALCITE CALCITE
TUFF TUFF
TUFF_WALL
CHISELED_TUFF
POLISHED_TUFF
POLISHED_TUFF_WALL
TUFF_BRICKS
TUFF_BRICK_WALL
CHISELED_TUFF_BRICKS
DRIPSTONE_BLOCK DRIPSTONE_BLOCK
GRASS_BLOCK GRASS_BLOCK
DIRT DIRT

View File

@ -0,0 +1,365 @@
Ave
Civi
Denni
Gen
Genner
Gennie
Habbie
Nary
Norm
Norma
Norman
Ordie
Reg
Reggie
Ressie
Settler
Sitti
Sity
Stan
Standa
Unem
Urbie
Verage
Aegis
Armsworth
Bell
Boots
Bootsmith
Buckle
Buckler
Bullwark
Busby
Chains
Chestington
Coal
Cole
Diamonds
Feaver
Gow
Guard
Helms
Helmut
Ingot
Irons
Koval
Kowal
Lava
Magma
Mails
Schmits
Shieldrick
Shields
Ward
Barry
Beefs
Berry
Bones
Boucher
Brawn
Brawnworth
Brew
Butch
Chows
Cole
Fleischer
Grubs
Hash
Kelps
Metzner
Porkington
Rabbits
Rations
Slager
Stewie
Stews
Atlas
Banner
Bannerman
Banners
Compass
Discovery
Entrepid
Explorer
Geo
Glaser
Glass
Glazer
Globetrots
Globetrotter
Journeyman
Journeys
Path
Paths
Pioneer
Roamer
Strider
Tracer
Trailer
Trails
Trekker
Treks
Trips
Voyage
Voyager
Wander
Wayfare
Chapman
Clark
Docs
Ender
Enders
Foot
Foots
Glaser
Glass
Glazer
Glow
Heals
Ingot
Ingots
Lapis
Lazuli
Mendings
Mends
Patches
Rot
Rott
Salve
Scute
Scutes
Soothe
Warts
Akkerman
Apple
Appleton
Beetington
Beets
Boer
Carrots
Cookie
Cowman
Crops
Gorter
Grows
Harrow
Harvester
Harvests
Koeman
Landman
Miller
Morar
Moraru
Mulder
Plants
Plower
Plowright
Pumpkin
Pumpking
Ranch
Rancher
Reaper
Seeds
Sow
Tater
Taters
Tender
Till
Tiller
Tots
Wheats
Angle
Angler
Angles
Baits
Baitsman
Boatman
Boatwright
Bob
Cast
Casts
Chum
Coal
Cod
Cole
Fisch
Fisher
Haul
Lure
Marin
Marine
Net
Nets
Piscator
Pisces
Puff
Puffer
Rod
Rodman
Rods
Strings
Trawler
Trawlie
Waters
Wave
Archer
Arrowsmith
Bo
Bolt
Bowman
Bows
Bowyer
Bullseye
Dart
Feathers
Flint
Hook
Hooks
Plume
Quiver
Sticks
Trips
Attire
Boots
Cap
Caps
Flint
Garb
Glover
Hide
Hides
Hyde
Leatherman
Pantington
Raggers
Rags
Riggings
Sadler
Sandler
Scute
Shoemaker
Skinner
Skins
Tailor
Tan
Tanner
Threads
Tunics
Book
Books
Clocks
Compass
Dinter
Glass
Ink
Inkworth
Lerner
Page
Papers
Quill
Quills
Reads
Scriver
Shriver
Andy
Baumann
Boulder
Brick
Bricks
Brock
Chisel
Chisels
Clay
Claye
Cotta
Dio
Granite
Mason
Pebble
Pillars
Quartz
Rock
Rocky
Stone
Terra
Tyler
Blockhead
Bonehead
Dimdim
Dimwit
Dingbat
Dolt
Doofus
Dope
Dumbbell
Dummydum
Dummydumdum
Dunce
Ignoramus
Loony
Muttonhead
Nincompoop
Nitty
Nutters
Pinhead
Simpleton
Simpleton II
Slowpoke
Tomfool
Beds
Color
Dye
Dyer
Fuller
Paint
Paints
Pigment
Shear
Shears
Sleep
Sleeps
Wool
Wools
Woolsworth
Apparatus
Ax
Axington
Carpenter
Flint
Gizmo
Hammer
Hammers
Hatchet
Ingot
Ingots
Iron
Irons
Pick
Steels
Tools
Toolsworth
Arm
Arming
Arms
Axe
Bell
Blade
Blades
Brand
Claymore
Coal
Cole
Dirk
Edge
Epee
Falchio
Falchion
Glaive
Glaives
Hatchet
Ingot
Kris
Saber
Shank
Swords
Swordsmith

View File

@ -16,6 +16,9 @@ permissions:
void.manage: void.manage:
description: "GameMaster's command" description: "GameMaster's command"
default: op default: op
void.score:
description: "score the voids"
default: op
void.balance: void.balance:
description: "User of thevoidroad" description: "User of thevoidroad"
default: not op default: not op